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