Source file src/pkg/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 package image
23
24 import (
25 "image/color"
26 )
27
28
29 type Config struct {
30 ColorModel color.Model
31 Width, Height int
32 }
33
34
35
36 type Image interface {
37
38 ColorModel() color.Model
39
40
41 Bounds() Rectangle
42
43
44
45 At(x, y int) color.Color
46 }
47
48
49
50
51
52
53 type PalettedImage interface {
54
55 ColorIndexAt(x, y int) uint8
56 Image
57 }
58
59
60 type RGBA struct {
61
62
63 Pix []uint8
64
65 Stride int
66
67 Rect Rectangle
68 }
69
70 func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
71
72 func (p *RGBA) Bounds() Rectangle { return p.Rect }
73
74 func (p *RGBA) At(x, y int) color.Color {
75 return p.RGBAAt(x, y)
76 }
77
78 func (p *RGBA) RGBAAt(x, y int) color.RGBA {
79 if !(Point{x, y}.In(p.Rect)) {
80 return color.RGBA{}
81 }
82 i := p.PixOffset(x, y)
83 s := p.Pix[i : i+4 : i+4]
84 return color.RGBA{s[0], s[1], s[2], s[3]}
85 }
86
87
88
89 func (p *RGBA) PixOffset(x, y int) int {
90 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
91 }
92
93 func (p *RGBA) Set(x, y int, c color.Color) {
94 if !(Point{x, y}.In(p.Rect)) {
95 return
96 }
97 i := p.PixOffset(x, y)
98 c1 := color.RGBAModel.Convert(c).(color.RGBA)
99 s := p.Pix[i : i+4 : i+4]
100 s[0] = c1.R
101 s[1] = c1.G
102 s[2] = c1.B
103 s[3] = c1.A
104 }
105
106 func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
107 if !(Point{x, y}.In(p.Rect)) {
108 return
109 }
110 i := p.PixOffset(x, y)
111 s := p.Pix[i : i+4 : i+4]
112 s[0] = c.R
113 s[1] = c.G
114 s[2] = c.B
115 s[3] = c.A
116 }
117
118
119
120 func (p *RGBA) SubImage(r Rectangle) Image {
121 r = r.Intersect(p.Rect)
122
123
124
125 if r.Empty() {
126 return &RGBA{}
127 }
128 i := p.PixOffset(r.Min.X, r.Min.Y)
129 return &RGBA{
130 Pix: p.Pix[i:],
131 Stride: p.Stride,
132 Rect: r,
133 }
134 }
135
136
137 func (p *RGBA) Opaque() bool {
138 if p.Rect.Empty() {
139 return true
140 }
141 i0, i1 := 3, p.Rect.Dx()*4
142 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
143 for i := i0; i < i1; i += 4 {
144 if p.Pix[i] != 0xff {
145 return false
146 }
147 }
148 i0 += p.Stride
149 i1 += p.Stride
150 }
151 return true
152 }
153
154
155 func NewRGBA(r Rectangle) *RGBA {
156 w, h := r.Dx(), r.Dy()
157 buf := make([]uint8, 4*w*h)
158 return &RGBA{buf, 4 * w, r}
159 }
160
161
162 type RGBA64 struct {
163
164
165 Pix []uint8
166
167 Stride int
168
169 Rect Rectangle
170 }
171
172 func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
173
174 func (p *RGBA64) Bounds() Rectangle { return p.Rect }
175
176 func (p *RGBA64) At(x, y int) color.Color {
177 return p.RGBA64At(x, y)
178 }
179
180 func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
181 if !(Point{x, y}.In(p.Rect)) {
182 return color.RGBA64{}
183 }
184 i := p.PixOffset(x, y)
185 s := p.Pix[i : i+8 : i+8]
186 return color.RGBA64{
187 uint16(s[0])<<8 | uint16(s[1]),
188 uint16(s[2])<<8 | uint16(s[3]),
189 uint16(s[4])<<8 | uint16(s[5]),
190 uint16(s[6])<<8 | uint16(s[7]),
191 }
192 }
193
194
195
196 func (p *RGBA64) PixOffset(x, y int) int {
197 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
198 }
199
200 func (p *RGBA64) Set(x, y int, c color.Color) {
201 if !(Point{x, y}.In(p.Rect)) {
202 return
203 }
204 i := p.PixOffset(x, y)
205 c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
206 s := p.Pix[i : i+8 : i+8]
207 s[0] = uint8(c1.R >> 8)
208 s[1] = uint8(c1.R)
209 s[2] = uint8(c1.G >> 8)
210 s[3] = uint8(c1.G)
211 s[4] = uint8(c1.B >> 8)
212 s[5] = uint8(c1.B)
213 s[6] = uint8(c1.A >> 8)
214 s[7] = uint8(c1.A)
215 }
216
217 func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
218 if !(Point{x, y}.In(p.Rect)) {
219 return
220 }
221 i := p.PixOffset(x, y)
222 s := p.Pix[i : i+8 : i+8]
223 s[0] = uint8(c.R >> 8)
224 s[1] = uint8(c.R)
225 s[2] = uint8(c.G >> 8)
226 s[3] = uint8(c.G)
227 s[4] = uint8(c.B >> 8)
228 s[5] = uint8(c.B)
229 s[6] = uint8(c.A >> 8)
230 s[7] = uint8(c.A)
231 }
232
233
234
235 func (p *RGBA64) SubImage(r Rectangle) Image {
236 r = r.Intersect(p.Rect)
237
238
239
240 if r.Empty() {
241 return &RGBA64{}
242 }
243 i := p.PixOffset(r.Min.X, r.Min.Y)
244 return &RGBA64{
245 Pix: p.Pix[i:],
246 Stride: p.Stride,
247 Rect: r,
248 }
249 }
250
251
252 func (p *RGBA64) Opaque() bool {
253 if p.Rect.Empty() {
254 return true
255 }
256 i0, i1 := 6, p.Rect.Dx()*8
257 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
258 for i := i0; i < i1; i += 8 {
259 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
260 return false
261 }
262 }
263 i0 += p.Stride
264 i1 += p.Stride
265 }
266 return true
267 }
268
269
270 func NewRGBA64(r Rectangle) *RGBA64 {
271 w, h := r.Dx(), r.Dy()
272 pix := make([]uint8, 8*w*h)
273 return &RGBA64{pix, 8 * w, r}
274 }
275
276
277 type NRGBA struct {
278
279
280 Pix []uint8
281
282 Stride int
283
284 Rect Rectangle
285 }
286
287 func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
288
289 func (p *NRGBA) Bounds() Rectangle { return p.Rect }
290
291 func (p *NRGBA) At(x, y int) color.Color {
292 return p.NRGBAAt(x, y)
293 }
294
295 func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
296 if !(Point{x, y}.In(p.Rect)) {
297 return color.NRGBA{}
298 }
299 i := p.PixOffset(x, y)
300 s := p.Pix[i : i+4 : i+4]
301 return color.NRGBA{s[0], s[1], s[2], s[3]}
302 }
303
304
305
306 func (p *NRGBA) PixOffset(x, y int) int {
307 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
308 }
309
310 func (p *NRGBA) Set(x, y int, c color.Color) {
311 if !(Point{x, y}.In(p.Rect)) {
312 return
313 }
314 i := p.PixOffset(x, y)
315 c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
316 s := p.Pix[i : i+4 : i+4]
317 s[0] = c1.R
318 s[1] = c1.G
319 s[2] = c1.B
320 s[3] = c1.A
321 }
322
323 func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
324 if !(Point{x, y}.In(p.Rect)) {
325 return
326 }
327 i := p.PixOffset(x, y)
328 s := p.Pix[i : i+4 : i+4]
329 s[0] = c.R
330 s[1] = c.G
331 s[2] = c.B
332 s[3] = c.A
333 }
334
335
336
337 func (p *NRGBA) SubImage(r Rectangle) Image {
338 r = r.Intersect(p.Rect)
339
340
341
342 if r.Empty() {
343 return &NRGBA{}
344 }
345 i := p.PixOffset(r.Min.X, r.Min.Y)
346 return &NRGBA{
347 Pix: p.Pix[i:],
348 Stride: p.Stride,
349 Rect: r,
350 }
351 }
352
353
354 func (p *NRGBA) Opaque() bool {
355 if p.Rect.Empty() {
356 return true
357 }
358 i0, i1 := 3, p.Rect.Dx()*4
359 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
360 for i := i0; i < i1; i += 4 {
361 if p.Pix[i] != 0xff {
362 return false
363 }
364 }
365 i0 += p.Stride
366 i1 += p.Stride
367 }
368 return true
369 }
370
371
372 func NewNRGBA(r Rectangle) *NRGBA {
373 w, h := r.Dx(), r.Dy()
374 pix := make([]uint8, 4*w*h)
375 return &NRGBA{pix, 4 * w, r}
376 }
377
378
379 type NRGBA64 struct {
380
381
382 Pix []uint8
383
384 Stride int
385
386 Rect Rectangle
387 }
388
389 func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
390
391 func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
392
393 func (p *NRGBA64) At(x, y int) color.Color {
394 return p.NRGBA64At(x, y)
395 }
396
397 func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
398 if !(Point{x, y}.In(p.Rect)) {
399 return color.NRGBA64{}
400 }
401 i := p.PixOffset(x, y)
402 s := p.Pix[i : i+8 : i+8]
403 return color.NRGBA64{
404 uint16(s[0])<<8 | uint16(s[1]),
405 uint16(s[2])<<8 | uint16(s[3]),
406 uint16(s[4])<<8 | uint16(s[5]),
407 uint16(s[6])<<8 | uint16(s[7]),
408 }
409 }
410
411
412
413 func (p *NRGBA64) PixOffset(x, y int) int {
414 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
415 }
416
417 func (p *NRGBA64) Set(x, y int, c color.Color) {
418 if !(Point{x, y}.In(p.Rect)) {
419 return
420 }
421 i := p.PixOffset(x, y)
422 c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
423 s := p.Pix[i : i+8 : i+8]
424 s[0] = uint8(c1.R >> 8)
425 s[1] = uint8(c1.R)
426 s[2] = uint8(c1.G >> 8)
427 s[3] = uint8(c1.G)
428 s[4] = uint8(c1.B >> 8)
429 s[5] = uint8(c1.B)
430 s[6] = uint8(c1.A >> 8)
431 s[7] = uint8(c1.A)
432 }
433
434 func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
435 if !(Point{x, y}.In(p.Rect)) {
436 return
437 }
438 i := p.PixOffset(x, y)
439 s := p.Pix[i : i+8 : i+8]
440 s[0] = uint8(c.R >> 8)
441 s[1] = uint8(c.R)
442 s[2] = uint8(c.G >> 8)
443 s[3] = uint8(c.G)
444 s[4] = uint8(c.B >> 8)
445 s[5] = uint8(c.B)
446 s[6] = uint8(c.A >> 8)
447 s[7] = uint8(c.A)
448 }
449
450
451
452 func (p *NRGBA64) SubImage(r Rectangle) Image {
453 r = r.Intersect(p.Rect)
454
455
456
457 if r.Empty() {
458 return &NRGBA64{}
459 }
460 i := p.PixOffset(r.Min.X, r.Min.Y)
461 return &NRGBA64{
462 Pix: p.Pix[i:],
463 Stride: p.Stride,
464 Rect: r,
465 }
466 }
467
468
469 func (p *NRGBA64) Opaque() bool {
470 if p.Rect.Empty() {
471 return true
472 }
473 i0, i1 := 6, p.Rect.Dx()*8
474 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
475 for i := i0; i < i1; i += 8 {
476 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
477 return false
478 }
479 }
480 i0 += p.Stride
481 i1 += p.Stride
482 }
483 return true
484 }
485
486
487 func NewNRGBA64(r Rectangle) *NRGBA64 {
488 w, h := r.Dx(), r.Dy()
489 pix := make([]uint8, 8*w*h)
490 return &NRGBA64{pix, 8 * w, r}
491 }
492
493
494 type Alpha struct {
495
496
497 Pix []uint8
498
499 Stride int
500
501 Rect Rectangle
502 }
503
504 func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
505
506 func (p *Alpha) Bounds() Rectangle { return p.Rect }
507
508 func (p *Alpha) At(x, y int) color.Color {
509 return p.AlphaAt(x, y)
510 }
511
512 func (p *Alpha) AlphaAt(x, y int) color.Alpha {
513 if !(Point{x, y}.In(p.Rect)) {
514 return color.Alpha{}
515 }
516 i := p.PixOffset(x, y)
517 return color.Alpha{p.Pix[i]}
518 }
519
520
521
522 func (p *Alpha) PixOffset(x, y int) int {
523 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
524 }
525
526 func (p *Alpha) Set(x, y int, c color.Color) {
527 if !(Point{x, y}.In(p.Rect)) {
528 return
529 }
530 i := p.PixOffset(x, y)
531 p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
532 }
533
534 func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
535 if !(Point{x, y}.In(p.Rect)) {
536 return
537 }
538 i := p.PixOffset(x, y)
539 p.Pix[i] = c.A
540 }
541
542
543
544 func (p *Alpha) SubImage(r Rectangle) Image {
545 r = r.Intersect(p.Rect)
546
547
548
549 if r.Empty() {
550 return &Alpha{}
551 }
552 i := p.PixOffset(r.Min.X, r.Min.Y)
553 return &Alpha{
554 Pix: p.Pix[i:],
555 Stride: p.Stride,
556 Rect: r,
557 }
558 }
559
560
561 func (p *Alpha) Opaque() bool {
562 if p.Rect.Empty() {
563 return true
564 }
565 i0, i1 := 0, p.Rect.Dx()
566 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
567 for i := i0; i < i1; i++ {
568 if p.Pix[i] != 0xff {
569 return false
570 }
571 }
572 i0 += p.Stride
573 i1 += p.Stride
574 }
575 return true
576 }
577
578
579 func NewAlpha(r Rectangle) *Alpha {
580 w, h := r.Dx(), r.Dy()
581 pix := make([]uint8, 1*w*h)
582 return &Alpha{pix, 1 * w, r}
583 }
584
585
586 type Alpha16 struct {
587
588
589 Pix []uint8
590
591 Stride int
592
593 Rect Rectangle
594 }
595
596 func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
597
598 func (p *Alpha16) Bounds() Rectangle { return p.Rect }
599
600 func (p *Alpha16) At(x, y int) color.Color {
601 return p.Alpha16At(x, y)
602 }
603
604 func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
605 if !(Point{x, y}.In(p.Rect)) {
606 return color.Alpha16{}
607 }
608 i := p.PixOffset(x, y)
609 return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
610 }
611
612
613
614 func (p *Alpha16) PixOffset(x, y int) int {
615 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
616 }
617
618 func (p *Alpha16) Set(x, y int, c color.Color) {
619 if !(Point{x, y}.In(p.Rect)) {
620 return
621 }
622 i := p.PixOffset(x, y)
623 c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
624 p.Pix[i+0] = uint8(c1.A >> 8)
625 p.Pix[i+1] = uint8(c1.A)
626 }
627
628 func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
629 if !(Point{x, y}.In(p.Rect)) {
630 return
631 }
632 i := p.PixOffset(x, y)
633 p.Pix[i+0] = uint8(c.A >> 8)
634 p.Pix[i+1] = uint8(c.A)
635 }
636
637
638
639 func (p *Alpha16) SubImage(r Rectangle) Image {
640 r = r.Intersect(p.Rect)
641
642
643
644 if r.Empty() {
645 return &Alpha16{}
646 }
647 i := p.PixOffset(r.Min.X, r.Min.Y)
648 return &Alpha16{
649 Pix: p.Pix[i:],
650 Stride: p.Stride,
651 Rect: r,
652 }
653 }
654
655
656 func (p *Alpha16) Opaque() bool {
657 if p.Rect.Empty() {
658 return true
659 }
660 i0, i1 := 0, p.Rect.Dx()*2
661 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
662 for i := i0; i < i1; i += 2 {
663 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
664 return false
665 }
666 }
667 i0 += p.Stride
668 i1 += p.Stride
669 }
670 return true
671 }
672
673
674 func NewAlpha16(r Rectangle) *Alpha16 {
675 w, h := r.Dx(), r.Dy()
676 pix := make([]uint8, 2*w*h)
677 return &Alpha16{pix, 2 * w, r}
678 }
679
680
681 type Gray struct {
682
683
684 Pix []uint8
685
686 Stride int
687
688 Rect Rectangle
689 }
690
691 func (p *Gray) ColorModel() color.Model { return color.GrayModel }
692
693 func (p *Gray) Bounds() Rectangle { return p.Rect }
694
695 func (p *Gray) At(x, y int) color.Color {
696 return p.GrayAt(x, y)
697 }
698
699 func (p *Gray) GrayAt(x, y int) color.Gray {
700 if !(Point{x, y}.In(p.Rect)) {
701 return color.Gray{}
702 }
703 i := p.PixOffset(x, y)
704 return color.Gray{p.Pix[i]}
705 }
706
707
708
709 func (p *Gray) PixOffset(x, y int) int {
710 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
711 }
712
713 func (p *Gray) Set(x, y int, c color.Color) {
714 if !(Point{x, y}.In(p.Rect)) {
715 return
716 }
717 i := p.PixOffset(x, y)
718 p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
719 }
720
721 func (p *Gray) SetGray(x, y int, c color.Gray) {
722 if !(Point{x, y}.In(p.Rect)) {
723 return
724 }
725 i := p.PixOffset(x, y)
726 p.Pix[i] = c.Y
727 }
728
729
730
731 func (p *Gray) SubImage(r Rectangle) Image {
732 r = r.Intersect(p.Rect)
733
734
735
736 if r.Empty() {
737 return &Gray{}
738 }
739 i := p.PixOffset(r.Min.X, r.Min.Y)
740 return &Gray{
741 Pix: p.Pix[i:],
742 Stride: p.Stride,
743 Rect: r,
744 }
745 }
746
747
748 func (p *Gray) Opaque() bool {
749 return true
750 }
751
752
753 func NewGray(r Rectangle) *Gray {
754 w, h := r.Dx(), r.Dy()
755 pix := make([]uint8, 1*w*h)
756 return &Gray{pix, 1 * w, r}
757 }
758
759
760 type Gray16 struct {
761
762
763 Pix []uint8
764
765 Stride int
766
767 Rect Rectangle
768 }
769
770 func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
771
772 func (p *Gray16) Bounds() Rectangle { return p.Rect }
773
774 func (p *Gray16) At(x, y int) color.Color {
775 return p.Gray16At(x, y)
776 }
777
778 func (p *Gray16) Gray16At(x, y int) color.Gray16 {
779 if !(Point{x, y}.In(p.Rect)) {
780 return color.Gray16{}
781 }
782 i := p.PixOffset(x, y)
783 return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
784 }
785
786
787
788 func (p *Gray16) PixOffset(x, y int) int {
789 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
790 }
791
792 func (p *Gray16) Set(x, y int, c color.Color) {
793 if !(Point{x, y}.In(p.Rect)) {
794 return
795 }
796 i := p.PixOffset(x, y)
797 c1 := color.Gray16Model.Convert(c).(color.Gray16)
798 p.Pix[i+0] = uint8(c1.Y >> 8)
799 p.Pix[i+1] = uint8(c1.Y)
800 }
801
802 func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
803 if !(Point{x, y}.In(p.Rect)) {
804 return
805 }
806 i := p.PixOffset(x, y)
807 p.Pix[i+0] = uint8(c.Y >> 8)
808 p.Pix[i+1] = uint8(c.Y)
809 }
810
811
812
813 func (p *Gray16) SubImage(r Rectangle) Image {
814 r = r.Intersect(p.Rect)
815
816
817
818 if r.Empty() {
819 return &Gray16{}
820 }
821 i := p.PixOffset(r.Min.X, r.Min.Y)
822 return &Gray16{
823 Pix: p.Pix[i:],
824 Stride: p.Stride,
825 Rect: r,
826 }
827 }
828
829
830 func (p *Gray16) Opaque() bool {
831 return true
832 }
833
834
835 func NewGray16(r Rectangle) *Gray16 {
836 w, h := r.Dx(), r.Dy()
837 pix := make([]uint8, 2*w*h)
838 return &Gray16{pix, 2 * w, r}
839 }
840
841
842 type CMYK struct {
843
844
845 Pix []uint8
846
847 Stride int
848
849 Rect Rectangle
850 }
851
852 func (p *CMYK) ColorModel() color.Model { return color.CMYKModel }
853
854 func (p *CMYK) Bounds() Rectangle { return p.Rect }
855
856 func (p *CMYK) At(x, y int) color.Color {
857 return p.CMYKAt(x, y)
858 }
859
860 func (p *CMYK) CMYKAt(x, y int) color.CMYK {
861 if !(Point{x, y}.In(p.Rect)) {
862 return color.CMYK{}
863 }
864 i := p.PixOffset(x, y)
865 s := p.Pix[i : i+4 : i+4]
866 return color.CMYK{s[0], s[1], s[2], s[3]}
867 }
868
869
870
871 func (p *CMYK) PixOffset(x, y int) int {
872 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
873 }
874
875 func (p *CMYK) Set(x, y int, c color.Color) {
876 if !(Point{x, y}.In(p.Rect)) {
877 return
878 }
879 i := p.PixOffset(x, y)
880 c1 := color.CMYKModel.Convert(c).(color.CMYK)
881 s := p.Pix[i : i+4 : i+4]
882 s[0] = c1.C
883 s[1] = c1.M
884 s[2] = c1.Y
885 s[3] = c1.K
886 }
887
888 func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
889 if !(Point{x, y}.In(p.Rect)) {
890 return
891 }
892 i := p.PixOffset(x, y)
893 s := p.Pix[i : i+4 : i+4]
894 s[0] = c.C
895 s[1] = c.M
896 s[2] = c.Y
897 s[3] = c.K
898 }
899
900
901
902 func (p *CMYK) SubImage(r Rectangle) Image {
903 r = r.Intersect(p.Rect)
904
905
906
907 if r.Empty() {
908 return &CMYK{}
909 }
910 i := p.PixOffset(r.Min.X, r.Min.Y)
911 return &CMYK{
912 Pix: p.Pix[i:],
913 Stride: p.Stride,
914 Rect: r,
915 }
916 }
917
918
919 func (p *CMYK) Opaque() bool {
920 return true
921 }
922
923
924 func NewCMYK(r Rectangle) *CMYK {
925 w, h := r.Dx(), r.Dy()
926 buf := make([]uint8, 4*w*h)
927 return &CMYK{buf, 4 * w, r}
928 }
929
930
931 type Paletted struct {
932
933
934 Pix []uint8
935
936 Stride int
937
938 Rect Rectangle
939
940 Palette color.Palette
941 }
942
943 func (p *Paletted) ColorModel() color.Model { return p.Palette }
944
945 func (p *Paletted) Bounds() Rectangle { return p.Rect }
946
947 func (p *Paletted) At(x, y int) color.Color {
948 if len(p.Palette) == 0 {
949 return nil
950 }
951 if !(Point{x, y}.In(p.Rect)) {
952 return p.Palette[0]
953 }
954 i := p.PixOffset(x, y)
955 return p.Palette[p.Pix[i]]
956 }
957
958
959
960 func (p *Paletted) PixOffset(x, y int) int {
961 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
962 }
963
964 func (p *Paletted) Set(x, y int, c color.Color) {
965 if !(Point{x, y}.In(p.Rect)) {
966 return
967 }
968 i := p.PixOffset(x, y)
969 p.Pix[i] = uint8(p.Palette.Index(c))
970 }
971
972 func (p *Paletted) ColorIndexAt(x, y int) uint8 {
973 if !(Point{x, y}.In(p.Rect)) {
974 return 0
975 }
976 i := p.PixOffset(x, y)
977 return p.Pix[i]
978 }
979
980 func (p *Paletted) SetColorIndex(x, y int, index uint8) {
981 if !(Point{x, y}.In(p.Rect)) {
982 return
983 }
984 i := p.PixOffset(x, y)
985 p.Pix[i] = index
986 }
987
988
989
990 func (p *Paletted) SubImage(r Rectangle) Image {
991 r = r.Intersect(p.Rect)
992
993
994
995 if r.Empty() {
996 return &Paletted{
997 Palette: p.Palette,
998 }
999 }
1000 i := p.PixOffset(r.Min.X, r.Min.Y)
1001 return &Paletted{
1002 Pix: p.Pix[i:],
1003 Stride: p.Stride,
1004 Rect: p.Rect.Intersect(r),
1005 Palette: p.Palette,
1006 }
1007 }
1008
1009
1010 func (p *Paletted) Opaque() bool {
1011 var present [256]bool
1012 i0, i1 := 0, p.Rect.Dx()
1013 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
1014 for _, c := range p.Pix[i0:i1] {
1015 present[c] = true
1016 }
1017 i0 += p.Stride
1018 i1 += p.Stride
1019 }
1020 for i, c := range p.Palette {
1021 if !present[i] {
1022 continue
1023 }
1024 _, _, _, a := c.RGBA()
1025 if a != 0xffff {
1026 return false
1027 }
1028 }
1029 return true
1030 }
1031
1032
1033
1034 func NewPaletted(r Rectangle, p color.Palette) *Paletted {
1035 w, h := r.Dx(), r.Dy()
1036 pix := make([]uint8, 1*w*h)
1037 return &Paletted{pix, 1 * w, r, p}
1038 }
1039
View as plain text