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