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