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