Source file
src/image/image.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 package image
41
42 import (
43 "image/color"
44 )
45
46
47 type Config struct {
48 ColorModel color.Model
49 Width, Height int
50 }
51
52
53
54 type Image interface {
55
56 ColorModel() color.Model
57
58
59 Bounds() Rectangle
60
61
62
63 At(x, y int) color.Color
64 }
65
66
67
68 type RGBA64Image interface {
69
70
71
72
73 RGBA64At(x, y int) color.RGBA64
74 Image
75 }
76
77
78
79
80
81
82 type PalettedImage interface {
83
84 ColorIndexAt(x, y int) uint8
85 Image
86 }
87
88
89
90
91
92
93
94
95 func pixelBufferLength(bytesPerPixel int, r Rectangle, imageTypeName string) int {
96 totalLength := mul3NonNeg(bytesPerPixel, r.Dx(), r.Dy())
97 if totalLength < 0 {
98 panic("image: New" + imageTypeName + " Rectangle has huge or negative dimensions")
99 }
100 return totalLength
101 }
102
103
104 type RGBA struct {
105
106
107 Pix []uint8
108
109 Stride int
110
111 Rect Rectangle
112 }
113
114 func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
115
116 func (p *RGBA) Bounds() Rectangle { return p.Rect }
117
118 func (p *RGBA) At(x, y int) color.Color {
119 return p.RGBAAt(x, y)
120 }
121
122 func (p *RGBA) RGBA64At(x, y int) color.RGBA64 {
123 if !(Point{x, y}.In(p.Rect)) {
124 return color.RGBA64{}
125 }
126 i := p.PixOffset(x, y)
127 s := p.Pix[i : i+4 : i+4]
128 r := uint16(s[0])
129 g := uint16(s[1])
130 b := uint16(s[2])
131 a := uint16(s[3])
132 return color.RGBA64{
133 (r << 8) | r,
134 (g << 8) | g,
135 (b << 8) | b,
136 (a << 8) | a,
137 }
138 }
139
140 func (p *RGBA) RGBAAt(x, y int) color.RGBA {
141 if !(Point{x, y}.In(p.Rect)) {
142 return color.RGBA{}
143 }
144 i := p.PixOffset(x, y)
145 s := p.Pix[i : i+4 : i+4]
146 return color.RGBA{s[0], s[1], s[2], s[3]}
147 }
148
149
150
151 func (p *RGBA) PixOffset(x, y int) int {
152 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
153 }
154
155 func (p *RGBA) Set(x, y int, c color.Color) {
156 if !(Point{x, y}.In(p.Rect)) {
157 return
158 }
159 i := p.PixOffset(x, y)
160 c1 := color.RGBAModel.Convert(c).(color.RGBA)
161 s := p.Pix[i : i+4 : i+4]
162 s[0] = c1.R
163 s[1] = c1.G
164 s[2] = c1.B
165 s[3] = c1.A
166 }
167
168 func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) {
169 if !(Point{x, y}.In(p.Rect)) {
170 return
171 }
172 i := p.PixOffset(x, y)
173 s := p.Pix[i : i+4 : i+4]
174 s[0] = uint8(c.R >> 8)
175 s[1] = uint8(c.G >> 8)
176 s[2] = uint8(c.B >> 8)
177 s[3] = uint8(c.A >> 8)
178 }
179
180 func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
181 if !(Point{x, y}.In(p.Rect)) {
182 return
183 }
184 i := p.PixOffset(x, y)
185 s := p.Pix[i : i+4 : i+4]
186 s[0] = c.R
187 s[1] = c.G
188 s[2] = c.B
189 s[3] = c.A
190 }
191
192
193
194 func (p *RGBA) SubImage(r Rectangle) Image {
195 r = r.Intersect(p.Rect)
196
197
198
199 if r.Empty() {
200 return &RGBA{}
201 }
202 i := p.PixOffset(r.Min.X, r.Min.Y)
203 return &RGBA{
204 Pix: p.Pix[i:],
205 Stride: p.Stride,
206 Rect: r,
207 }
208 }
209
210
211 func (p *RGBA) Opaque() bool {
212 if p.Rect.Empty() {
213 return true
214 }
215 i0, i1 := 3, p.Rect.Dx()*4
216 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
217 for i := i0; i < i1; i += 4 {
218 if p.Pix[i] != 0xff {
219 return false
220 }
221 }
222 i0 += p.Stride
223 i1 += p.Stride
224 }
225 return true
226 }
227
228
229 func NewRGBA(r Rectangle) *RGBA {
230 return &RGBA{
231 Pix: make([]uint8, pixelBufferLength(4, r, "RGBA")),
232 Stride: 4 * r.Dx(),
233 Rect: r,
234 }
235 }
236
237
238 type RGBA64 struct {
239
240
241 Pix []uint8
242
243 Stride int
244
245 Rect Rectangle
246 }
247
248 func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
249
250 func (p *RGBA64) Bounds() Rectangle { return p.Rect }
251
252 func (p *RGBA64) At(x, y int) color.Color {
253 return p.RGBA64At(x, y)
254 }
255
256 func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
257 if !(Point{x, y}.In(p.Rect)) {
258 return color.RGBA64{}
259 }
260 i := p.PixOffset(x, y)
261 s := p.Pix[i : i+8 : i+8]
262 return color.RGBA64{
263 uint16(s[0])<<8 | uint16(s[1]),
264 uint16(s[2])<<8 | uint16(s[3]),
265 uint16(s[4])<<8 | uint16(s[5]),
266 uint16(s[6])<<8 | uint16(s[7]),
267 }
268 }
269
270
271
272 func (p *RGBA64) PixOffset(x, y int) int {
273 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
274 }
275
276 func (p *RGBA64) Set(x, y int, c color.Color) {
277 if !(Point{x, y}.In(p.Rect)) {
278 return
279 }
280 i := p.PixOffset(x, y)
281 c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
282 s := p.Pix[i : i+8 : i+8]
283 s[0] = uint8(c1.R >> 8)
284 s[1] = uint8(c1.R)
285 s[2] = uint8(c1.G >> 8)
286 s[3] = uint8(c1.G)
287 s[4] = uint8(c1.B >> 8)
288 s[5] = uint8(c1.B)
289 s[6] = uint8(c1.A >> 8)
290 s[7] = uint8(c1.A)
291 }
292
293 func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
294 if !(Point{x, y}.In(p.Rect)) {
295 return
296 }
297 i := p.PixOffset(x, y)
298 s := p.Pix[i : i+8 : i+8]
299 s[0] = uint8(c.R >> 8)
300 s[1] = uint8(c.R)
301 s[2] = uint8(c.G >> 8)
302 s[3] = uint8(c.G)
303 s[4] = uint8(c.B >> 8)
304 s[5] = uint8(c.B)
305 s[6] = uint8(c.A >> 8)
306 s[7] = uint8(c.A)
307 }
308
309
310
311 func (p *RGBA64) SubImage(r Rectangle) Image {
312 r = r.Intersect(p.Rect)
313
314
315
316 if r.Empty() {
317 return &RGBA64{}
318 }
319 i := p.PixOffset(r.Min.X, r.Min.Y)
320 return &RGBA64{
321 Pix: p.Pix[i:],
322 Stride: p.Stride,
323 Rect: r,
324 }
325 }
326
327
328 func (p *RGBA64) Opaque() bool {
329 if p.Rect.Empty() {
330 return true
331 }
332 i0, i1 := 6, p.Rect.Dx()*8
333 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
334 for i := i0; i < i1; i += 8 {
335 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
336 return false
337 }
338 }
339 i0 += p.Stride
340 i1 += p.Stride
341 }
342 return true
343 }
344
345
346 func NewRGBA64(r Rectangle) *RGBA64 {
347 return &RGBA64{
348 Pix: make([]uint8, pixelBufferLength(8, r, "RGBA64")),
349 Stride: 8 * r.Dx(),
350 Rect: r,
351 }
352 }
353
354
355 type NRGBA struct {
356
357
358 Pix []uint8
359
360 Stride int
361
362 Rect Rectangle
363 }
364
365 func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
366
367 func (p *NRGBA) Bounds() Rectangle { return p.Rect }
368
369 func (p *NRGBA) At(x, y int) color.Color {
370 return p.NRGBAAt(x, y)
371 }
372
373 func (p *NRGBA) RGBA64At(x, y int) color.RGBA64 {
374 r, g, b, a := p.NRGBAAt(x, y).RGBA()
375 return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
376 }
377
378 func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
379 if !(Point{x, y}.In(p.Rect)) {
380 return color.NRGBA{}
381 }
382 i := p.PixOffset(x, y)
383 s := p.Pix[i : i+4 : i+4]
384 return color.NRGBA{s[0], s[1], s[2], s[3]}
385 }
386
387
388
389 func (p *NRGBA) PixOffset(x, y int) int {
390 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
391 }
392
393 func (p *NRGBA) Set(x, y int, c color.Color) {
394 if !(Point{x, y}.In(p.Rect)) {
395 return
396 }
397 i := p.PixOffset(x, y)
398 c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
399 s := p.Pix[i : i+4 : i+4]
400 s[0] = c1.R
401 s[1] = c1.G
402 s[2] = c1.B
403 s[3] = c1.A
404 }
405
406 func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) {
407 if !(Point{x, y}.In(p.Rect)) {
408 return
409 }
410 r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
411 if (a != 0) && (a != 0xffff) {
412 r = (r * 0xffff) / a
413 g = (g * 0xffff) / a
414 b = (b * 0xffff) / a
415 }
416 i := p.PixOffset(x, y)
417 s := p.Pix[i : i+4 : i+4]
418 s[0] = uint8(r >> 8)
419 s[1] = uint8(g >> 8)
420 s[2] = uint8(b >> 8)
421 s[3] = uint8(a >> 8)
422 }
423
424 func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
425 if !(Point{x, y}.In(p.Rect)) {
426 return
427 }
428 i := p.PixOffset(x, y)
429 s := p.Pix[i : i+4 : i+4]
430 s[0] = c.R
431 s[1] = c.G
432 s[2] = c.B
433 s[3] = c.A
434 }
435
436
437
438 func (p *NRGBA) SubImage(r Rectangle) Image {
439 r = r.Intersect(p.Rect)
440
441
442
443 if r.Empty() {
444 return &NRGBA{}
445 }
446 i := p.PixOffset(r.Min.X, r.Min.Y)
447 return &NRGBA{
448 Pix: p.Pix[i:],
449 Stride: p.Stride,
450 Rect: r,
451 }
452 }
453
454
455 func (p *NRGBA) Opaque() bool {
456 if p.Rect.Empty() {
457 return true
458 }
459 i0, i1 := 3, p.Rect.Dx()*4
460 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
461 for i := i0; i < i1; i += 4 {
462 if p.Pix[i] != 0xff {
463 return false
464 }
465 }
466 i0 += p.Stride
467 i1 += p.Stride
468 }
469 return true
470 }
471
472
473 func NewNRGBA(r Rectangle) *NRGBA {
474 return &NRGBA{
475 Pix: make([]uint8, pixelBufferLength(4, r, "NRGBA")),
476 Stride: 4 * r.Dx(),
477 Rect: r,
478 }
479 }
480
481
482 type NRGBA64 struct {
483
484
485 Pix []uint8
486
487 Stride int
488
489 Rect Rectangle
490 }
491
492 func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
493
494 func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
495
496 func (p *NRGBA64) At(x, y int) color.Color {
497 return p.NRGBA64At(x, y)
498 }
499
500 func (p *NRGBA64) RGBA64At(x, y int) color.RGBA64 {
501 r, g, b, a := p.NRGBA64At(x, y).RGBA()
502 return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
503 }
504
505 func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
506 if !(Point{x, y}.In(p.Rect)) {
507 return color.NRGBA64{}
508 }
509 i := p.PixOffset(x, y)
510 s := p.Pix[i : i+8 : i+8]
511 return color.NRGBA64{
512 uint16(s[0])<<8 | uint16(s[1]),
513 uint16(s[2])<<8 | uint16(s[3]),
514 uint16(s[4])<<8 | uint16(s[5]),
515 uint16(s[6])<<8 | uint16(s[7]),
516 }
517 }
518
519
520
521 func (p *NRGBA64) PixOffset(x, y int) int {
522 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
523 }
524
525 func (p *NRGBA64) Set(x, y int, c color.Color) {
526 if !(Point{x, y}.In(p.Rect)) {
527 return
528 }
529 i := p.PixOffset(x, y)
530 c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
531 s := p.Pix[i : i+8 : i+8]
532 s[0] = uint8(c1.R >> 8)
533 s[1] = uint8(c1.R)
534 s[2] = uint8(c1.G >> 8)
535 s[3] = uint8(c1.G)
536 s[4] = uint8(c1.B >> 8)
537 s[5] = uint8(c1.B)
538 s[6] = uint8(c1.A >> 8)
539 s[7] = uint8(c1.A)
540 }
541
542 func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) {
543 if !(Point{x, y}.In(p.Rect)) {
544 return
545 }
546 r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
547 if (a != 0) && (a != 0xffff) {
548 r = (r * 0xffff) / a
549 g = (g * 0xffff) / a
550 b = (b * 0xffff) / a
551 }
552 i := p.PixOffset(x, y)
553 s := p.Pix[i : i+8 : i+8]
554 s[0] = uint8(r >> 8)
555 s[1] = uint8(r)
556 s[2] = uint8(g >> 8)
557 s[3] = uint8(g)
558 s[4] = uint8(b >> 8)
559 s[5] = uint8(b)
560 s[6] = uint8(a >> 8)
561 s[7] = uint8(a)
562 }
563
564 func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
565 if !(Point{x, y}.In(p.Rect)) {
566 return
567 }
568 i := p.PixOffset(x, y)
569 s := p.Pix[i : i+8 : i+8]
570 s[0] = uint8(c.R >> 8)
571 s[1] = uint8(c.R)
572 s[2] = uint8(c.G >> 8)
573 s[3] = uint8(c.G)
574 s[4] = uint8(c.B >> 8)
575 s[5] = uint8(c.B)
576 s[6] = uint8(c.A >> 8)
577 s[7] = uint8(c.A)
578 }
579
580
581
582 func (p *NRGBA64) SubImage(r Rectangle) Image {
583 r = r.Intersect(p.Rect)
584
585
586
587 if r.Empty() {
588 return &NRGBA64{}
589 }
590 i := p.PixOffset(r.Min.X, r.Min.Y)
591 return &NRGBA64{
592 Pix: p.Pix[i:],
593 Stride: p.Stride,
594 Rect: r,
595 }
596 }
597
598
599 func (p *NRGBA64) Opaque() bool {
600 if p.Rect.Empty() {
601 return true
602 }
603 i0, i1 := 6, p.Rect.Dx()*8
604 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
605 for i := i0; i < i1; i += 8 {
606 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
607 return false
608 }
609 }
610 i0 += p.Stride
611 i1 += p.Stride
612 }
613 return true
614 }
615
616
617 func NewNRGBA64(r Rectangle) *NRGBA64 {
618 return &NRGBA64{
619 Pix: make([]uint8, pixelBufferLength(8, r, "NRGBA64")),
620 Stride: 8 * r.Dx(),
621 Rect: r,
622 }
623 }
624
625
626 type Alpha struct {
627
628
629 Pix []uint8
630
631 Stride int
632
633 Rect Rectangle
634 }
635
636 func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
637
638 func (p *Alpha) Bounds() Rectangle { return p.Rect }
639
640 func (p *Alpha) At(x, y int) color.Color {
641 return p.AlphaAt(x, y)
642 }
643
644 func (p *Alpha) RGBA64At(x, y int) color.RGBA64 {
645 a := uint16(p.AlphaAt(x, y).A)
646 a |= a << 8
647 return color.RGBA64{a, a, a, a}
648 }
649
650 func (p *Alpha) AlphaAt(x, y int) color.Alpha {
651 if !(Point{x, y}.In(p.Rect)) {
652 return color.Alpha{}
653 }
654 i := p.PixOffset(x, y)
655 return color.Alpha{p.Pix[i]}
656 }
657
658
659
660 func (p *Alpha) PixOffset(x, y int) int {
661 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
662 }
663
664 func (p *Alpha) Set(x, y int, c color.Color) {
665 if !(Point{x, y}.In(p.Rect)) {
666 return
667 }
668 i := p.PixOffset(x, y)
669 p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
670 }
671
672 func (p *Alpha) SetRGBA64(x, y int, c color.RGBA64) {
673 if !(Point{x, y}.In(p.Rect)) {
674 return
675 }
676 i := p.PixOffset(x, y)
677 p.Pix[i] = uint8(c.A >> 8)
678 }
679
680 func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
681 if !(Point{x, y}.In(p.Rect)) {
682 return
683 }
684 i := p.PixOffset(x, y)
685 p.Pix[i] = c.A
686 }
687
688
689
690 func (p *Alpha) SubImage(r Rectangle) Image {
691 r = r.Intersect(p.Rect)
692
693
694
695 if r.Empty() {
696 return &Alpha{}
697 }
698 i := p.PixOffset(r.Min.X, r.Min.Y)
699 return &Alpha{
700 Pix: p.Pix[i:],
701 Stride: p.Stride,
702 Rect: r,
703 }
704 }
705
706
707 func (p *Alpha) Opaque() bool {
708 if p.Rect.Empty() {
709 return true
710 }
711 i0, i1 := 0, p.Rect.Dx()
712 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
713 for i := i0; i < i1; i++ {
714 if p.Pix[i] != 0xff {
715 return false
716 }
717 }
718 i0 += p.Stride
719 i1 += p.Stride
720 }
721 return true
722 }
723
724
725 func NewAlpha(r Rectangle) *Alpha {
726 return &Alpha{
727 Pix: make([]uint8, pixelBufferLength(1, r, "Alpha")),
728 Stride: 1 * r.Dx(),
729 Rect: r,
730 }
731 }
732
733
734 type Alpha16 struct {
735
736
737 Pix []uint8
738
739 Stride int
740
741 Rect Rectangle
742 }
743
744 func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
745
746 func (p *Alpha16) Bounds() Rectangle { return p.Rect }
747
748 func (p *Alpha16) At(x, y int) color.Color {
749 return p.Alpha16At(x, y)
750 }
751
752 func (p *Alpha16) RGBA64At(x, y int) color.RGBA64 {
753 a := p.Alpha16At(x, y).A
754 return color.RGBA64{a, a, a, a}
755 }
756
757 func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
758 if !(Point{x, y}.In(p.Rect)) {
759 return color.Alpha16{}
760 }
761 i := p.PixOffset(x, y)
762 return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
763 }
764
765
766
767 func (p *Alpha16) PixOffset(x, y int) int {
768 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
769 }
770
771 func (p *Alpha16) Set(x, y int, c color.Color) {
772 if !(Point{x, y}.In(p.Rect)) {
773 return
774 }
775 i := p.PixOffset(x, y)
776 c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
777 p.Pix[i+0] = uint8(c1.A >> 8)
778 p.Pix[i+1] = uint8(c1.A)
779 }
780
781 func (p *Alpha16) SetRGBA64(x, y int, c color.RGBA64) {
782 if !(Point{x, y}.In(p.Rect)) {
783 return
784 }
785 i := p.PixOffset(x, y)
786 p.Pix[i+0] = uint8(c.A >> 8)
787 p.Pix[i+1] = uint8(c.A)
788 }
789
790 func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
791 if !(Point{x, y}.In(p.Rect)) {
792 return
793 }
794 i := p.PixOffset(x, y)
795 p.Pix[i+0] = uint8(c.A >> 8)
796 p.Pix[i+1] = uint8(c.A)
797 }
798
799
800
801 func (p *Alpha16) SubImage(r Rectangle) Image {
802 r = r.Intersect(p.Rect)
803
804
805
806 if r.Empty() {
807 return &Alpha16{}
808 }
809 i := p.PixOffset(r.Min.X, r.Min.Y)
810 return &Alpha16{
811 Pix: p.Pix[i:],
812 Stride: p.Stride,
813 Rect: r,
814 }
815 }
816
817
818 func (p *Alpha16) Opaque() bool {
819 if p.Rect.Empty() {
820 return true
821 }
822 i0, i1 := 0, p.Rect.Dx()*2
823 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
824 for i := i0; i < i1; i += 2 {
825 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
826 return false
827 }
828 }
829 i0 += p.Stride
830 i1 += p.Stride
831 }
832 return true
833 }
834
835
836 func NewAlpha16(r Rectangle) *Alpha16 {
837 return &Alpha16{
838 Pix: make([]uint8, pixelBufferLength(2, r, "Alpha16")),
839 Stride: 2 * r.Dx(),
840 Rect: r,
841 }
842 }
843
844
845 type Gray struct {
846
847
848 Pix []uint8
849
850 Stride int
851
852 Rect Rectangle
853 }
854
855 func (p *Gray) ColorModel() color.Model { return color.GrayModel }
856
857 func (p *Gray) Bounds() Rectangle { return p.Rect }
858
859 func (p *Gray) At(x, y int) color.Color {
860 return p.GrayAt(x, y)
861 }
862
863 func (p *Gray) RGBA64At(x, y int) color.RGBA64 {
864 gray := uint16(p.GrayAt(x, y).Y)
865 gray |= gray << 8
866 return color.RGBA64{gray, gray, gray, 0xffff}
867 }
868
869 func (p *Gray) GrayAt(x, y int) color.Gray {
870 if !(Point{x, y}.In(p.Rect)) {
871 return color.Gray{}
872 }
873 i := p.PixOffset(x, y)
874 return color.Gray{p.Pix[i]}
875 }
876
877
878
879 func (p *Gray) PixOffset(x, y int) int {
880 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
881 }
882
883 func (p *Gray) Set(x, y int, c color.Color) {
884 if !(Point{x, y}.In(p.Rect)) {
885 return
886 }
887 i := p.PixOffset(x, y)
888 p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
889 }
890
891 func (p *Gray) SetRGBA64(x, y int, c color.RGBA64) {
892 if !(Point{x, y}.In(p.Rect)) {
893 return
894 }
895
896 gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 24
897 i := p.PixOffset(x, y)
898 p.Pix[i] = uint8(gray)
899 }
900
901 func (p *Gray) SetGray(x, y int, c color.Gray) {
902 if !(Point{x, y}.In(p.Rect)) {
903 return
904 }
905 i := p.PixOffset(x, y)
906 p.Pix[i] = c.Y
907 }
908
909
910
911 func (p *Gray) SubImage(r Rectangle) Image {
912 r = r.Intersect(p.Rect)
913
914
915
916 if r.Empty() {
917 return &Gray{}
918 }
919 i := p.PixOffset(r.Min.X, r.Min.Y)
920 return &Gray{
921 Pix: p.Pix[i:],
922 Stride: p.Stride,
923 Rect: r,
924 }
925 }
926
927
928 func (p *Gray) Opaque() bool {
929 return true
930 }
931
932
933 func NewGray(r Rectangle) *Gray {
934 return &Gray{
935 Pix: make([]uint8, pixelBufferLength(1, r, "Gray")),
936 Stride: 1 * r.Dx(),
937 Rect: r,
938 }
939 }
940
941
942 type Gray16 struct {
943
944
945 Pix []uint8
946
947 Stride int
948
949 Rect Rectangle
950 }
951
952 func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
953
954 func (p *Gray16) Bounds() Rectangle { return p.Rect }
955
956 func (p *Gray16) At(x, y int) color.Color {
957 return p.Gray16At(x, y)
958 }
959
960 func (p *Gray16) RGBA64At(x, y int) color.RGBA64 {
961 gray := p.Gray16At(x, y).Y
962 return color.RGBA64{gray, gray, gray, 0xffff}
963 }
964
965 func (p *Gray16) Gray16At(x, y int) color.Gray16 {
966 if !(Point{x, y}.In(p.Rect)) {
967 return color.Gray16{}
968 }
969 i := p.PixOffset(x, y)
970 return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
971 }
972
973
974
975 func (p *Gray16) PixOffset(x, y int) int {
976 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
977 }
978
979 func (p *Gray16) Set(x, y int, c color.Color) {
980 if !(Point{x, y}.In(p.Rect)) {
981 return
982 }
983 i := p.PixOffset(x, y)
984 c1 := color.Gray16Model.Convert(c).(color.Gray16)
985 p.Pix[i+0] = uint8(c1.Y >> 8)
986 p.Pix[i+1] = uint8(c1.Y)
987 }
988
989 func (p *Gray16) SetRGBA64(x, y int, c color.RGBA64) {
990 if !(Point{x, y}.In(p.Rect)) {
991 return
992 }
993
994 gray := (19595*uint32(c.R) + 38470*uint32(c.G) + 7471*uint32(c.B) + 1<<15) >> 16
995 i := p.PixOffset(x, y)
996 p.Pix[i+0] = uint8(gray >> 8)
997 p.Pix[i+1] = uint8(gray)
998 }
999
1000 func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
1001 if !(Point{x, y}.In(p.Rect)) {
1002 return
1003 }
1004 i := p.PixOffset(x, y)
1005 p.Pix[i+0] = uint8(c.Y >> 8)
1006 p.Pix[i+1] = uint8(c.Y)
1007 }
1008
1009
1010
1011 func (p *Gray16) SubImage(r Rectangle) Image {
1012 r = r.Intersect(p.Rect)
1013
1014
1015
1016 if r.Empty() {
1017 return &Gray16{}
1018 }
1019 i := p.PixOffset(r.Min.X, r.Min.Y)
1020 return &Gray16{
1021 Pix: p.Pix[i:],
1022 Stride: p.Stride,
1023 Rect: r,
1024 }
1025 }
1026
1027
1028 func (p *Gray16) Opaque() bool {
1029 return true
1030 }
1031
1032
1033 func NewGray16(r Rectangle) *Gray16 {
1034 return &Gray16{
1035 Pix: make([]uint8, pixelBufferLength(2, r, "Gray16")),
1036 Stride: 2 * r.Dx(),
1037 Rect: r,
1038 }
1039 }
1040
1041
1042 type CMYK struct {
1043
1044
1045 Pix []uint8
1046
1047 Stride int
1048
1049 Rect Rectangle
1050 }
1051
1052 func (p *CMYK) ColorModel() color.Model { return color.CMYKModel }
1053
1054 func (p *CMYK) Bounds() Rectangle { return p.Rect }
1055
1056 func (p *CMYK) At(x, y int) color.Color {
1057 return p.CMYKAt(x, y)
1058 }
1059
1060 func (p *CMYK) RGBA64At(x, y int) color.RGBA64 {
1061 r, g, b, a := p.CMYKAt(x, y).RGBA()
1062 return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
1063 }
1064
1065 func (p *CMYK) CMYKAt(x, y int) color.CMYK {
1066 if !(Point{x, y}.In(p.Rect)) {
1067 return color.CMYK{}
1068 }
1069 i := p.PixOffset(x, y)
1070 s := p.Pix[i : i+4 : i+4]
1071 return color.CMYK{s[0], s[1], s[2], s[3]}
1072 }
1073
1074
1075
1076 func (p *CMYK) PixOffset(x, y int) int {
1077 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
1078 }
1079
1080 func (p *CMYK) Set(x, y int, c color.Color) {
1081 if !(Point{x, y}.In(p.Rect)) {
1082 return
1083 }
1084 i := p.PixOffset(x, y)
1085 c1 := color.CMYKModel.Convert(c).(color.CMYK)
1086 s := p.Pix[i : i+4 : i+4]
1087 s[0] = c1.C
1088 s[1] = c1.M
1089 s[2] = c1.Y
1090 s[3] = c1.K
1091 }
1092
1093 func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) {
1094 if !(Point{x, y}.In(p.Rect)) {
1095 return
1096 }
1097 cc, mm, yy, kk := color.RGBToCMYK(uint8(c.R>>8), uint8(c.G>>8), uint8(c.B>>8))
1098 i := p.PixOffset(x, y)
1099 s := p.Pix[i : i+4 : i+4]
1100 s[0] = cc
1101 s[1] = mm
1102 s[2] = yy
1103 s[3] = kk
1104 }
1105
1106 func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
1107 if !(Point{x, y}.In(p.Rect)) {
1108 return
1109 }
1110 i := p.PixOffset(x, y)
1111 s := p.Pix[i : i+4 : i+4]
1112 s[0] = c.C
1113 s[1] = c.M
1114 s[2] = c.Y
1115 s[3] = c.K
1116 }
1117
1118
1119
1120 func (p *CMYK) SubImage(r Rectangle) Image {
1121 r = r.Intersect(p.Rect)
1122
1123
1124
1125 if r.Empty() {
1126 return &CMYK{}
1127 }
1128 i := p.PixOffset(r.Min.X, r.Min.Y)
1129 return &CMYK{
1130 Pix: p.Pix[i:],
1131 Stride: p.Stride,
1132 Rect: r,
1133 }
1134 }
1135
1136
1137 func (p *CMYK) Opaque() bool {
1138 return true
1139 }
1140
1141
1142 func NewCMYK(r Rectangle) *CMYK {
1143 return &CMYK{
1144 Pix: make([]uint8, pixelBufferLength(4, r, "CMYK")),
1145 Stride: 4 * r.Dx(),
1146 Rect: r,
1147 }
1148 }
1149
1150
1151 type Paletted struct {
1152
1153
1154 Pix []uint8
1155
1156 Stride int
1157
1158 Rect Rectangle
1159
1160 Palette color.Palette
1161 }
1162
1163 func (p *Paletted) ColorModel() color.Model { return p.Palette }
1164
1165 func (p *Paletted) Bounds() Rectangle { return p.Rect }
1166
1167 func (p *Paletted) At(x, y int) color.Color {
1168 if len(p.Palette) == 0 {
1169 return nil
1170 }
1171 if !(Point{x, y}.In(p.Rect)) {
1172 return p.Palette[0]
1173 }
1174 i := p.PixOffset(x, y)
1175 return p.Palette[p.Pix[i]]
1176 }
1177
1178 func (p *Paletted) RGBA64At(x, y int) color.RGBA64 {
1179 if len(p.Palette) == 0 {
1180 return color.RGBA64{}
1181 }
1182 c := color.Color(nil)
1183 if !(Point{x, y}.In(p.Rect)) {
1184 c = p.Palette[0]
1185 } else {
1186 i := p.PixOffset(x, y)
1187 c = p.Palette[p.Pix[i]]
1188 }
1189 r, g, b, a := c.RGBA()
1190 return color.RGBA64{
1191 uint16(r),
1192 uint16(g),
1193 uint16(b),
1194 uint16(a),
1195 }
1196 }
1197
1198
1199
1200 func (p *Paletted) PixOffset(x, y int) int {
1201 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
1202 }
1203
1204 func (p *Paletted) Set(x, y int, c color.Color) {
1205 if !(Point{x, y}.In(p.Rect)) {
1206 return
1207 }
1208 i := p.PixOffset(x, y)
1209 p.Pix[i] = uint8(p.Palette.Index(c))
1210 }
1211
1212 func (p *Paletted) SetRGBA64(x, y int, c color.RGBA64) {
1213 if !(Point{x, y}.In(p.Rect)) {
1214 return
1215 }
1216 i := p.PixOffset(x, y)
1217 p.Pix[i] = uint8(p.Palette.Index(c))
1218 }
1219
1220 func (p *Paletted) ColorIndexAt(x, y int) uint8 {
1221 if !(Point{x, y}.In(p.Rect)) {
1222 return 0
1223 }
1224 i := p.PixOffset(x, y)
1225 return p.Pix[i]
1226 }
1227
1228 func (p *Paletted) SetColorIndex(x, y int, index uint8) {
1229 if !(Point{x, y}.In(p.Rect)) {
1230 return
1231 }
1232 i := p.PixOffset(x, y)
1233 p.Pix[i] = index
1234 }
1235
1236
1237
1238 func (p *Paletted) SubImage(r Rectangle) Image {
1239 r = r.Intersect(p.Rect)
1240
1241
1242
1243 if r.Empty() {
1244 return &Paletted{
1245 Palette: p.Palette,
1246 }
1247 }
1248 i := p.PixOffset(r.Min.X, r.Min.Y)
1249 return &Paletted{
1250 Pix: p.Pix[i:],
1251 Stride: p.Stride,
1252 Rect: p.Rect.Intersect(r),
1253 Palette: p.Palette,
1254 }
1255 }
1256
1257
1258 func (p *Paletted) Opaque() bool {
1259 var present [256]bool
1260 i0, i1 := 0, p.Rect.Dx()
1261 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
1262 for _, c := range p.Pix[i0:i1] {
1263 present[c] = true
1264 }
1265 i0 += p.Stride
1266 i1 += p.Stride
1267 }
1268 for i, c := range p.Palette {
1269 if !present[i] {
1270 continue
1271 }
1272 _, _, _, a := c.RGBA()
1273 if a != 0xffff {
1274 return false
1275 }
1276 }
1277 return true
1278 }
1279
1280
1281
1282 func NewPaletted(r Rectangle, p color.Palette) *Paletted {
1283 return &Paletted{
1284 Pix: make([]uint8, pixelBufferLength(1, r, "Paletted")),
1285 Stride: 1 * r.Dx(),
1286 Rect: r,
1287 Palette: p,
1288 }
1289 }
1290
View as plain text