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