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