PR tree-optimization/82929
[official-gcc.git] / libgo / go / image / image.go
blobbebb9f70fa65e03dc41057bf5a66b7ff8d3bba5e
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package image implements a basic 2-D image library.
6 //
7 // The fundamental interface is called Image. An Image contains colors, which
8 // are described in the image/color package.
9 //
10 // Values of the Image interface are created either by calling functions such
11 // as NewRGBA and NewPaletted, or by calling Decode on an io.Reader containing
12 // image data in a format such as GIF, JPEG or PNG. Decoding any particular
13 // image format requires the prior registration of a decoder function.
14 // Registration is typically automatic as a side effect of initializing that
15 // format's package so that, to decode a PNG image, it suffices to have
16 // import _ "image/png"
17 // in a program's main package. The _ means to import a package purely for its
18 // initialization side effects.
20 // See "The Go image package" for more details:
21 // https://golang.org/doc/articles/image_package.html
22 package image
24 import (
25 "image/color"
28 // Config holds an image's color model and dimensions.
29 type Config struct {
30 ColorModel color.Model
31 Width, Height int
34 // Image is a finite rectangular grid of color.Color values taken from a color
35 // model.
36 type Image interface {
37 // ColorModel returns the Image's color model.
38 ColorModel() color.Model
39 // Bounds returns the domain for which At can return non-zero color.
40 // The bounds do not necessarily contain the point (0, 0).
41 Bounds() Rectangle
42 // At returns the color of the pixel at (x, y).
43 // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
44 // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
45 At(x, y int) color.Color
48 // PalettedImage is an image whose colors may come from a limited palette.
49 // If m is a PalettedImage and m.ColorModel() returns a color.Palette p,
50 // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
51 // color model is not a color.Palette, then ColorIndexAt's behavior is
52 // undefined.
53 type PalettedImage interface {
54 // ColorIndexAt returns the palette index of the pixel at (x, y).
55 ColorIndexAt(x, y int) uint8
56 Image
59 // RGBA is an in-memory image whose At method returns color.RGBA values.
60 type RGBA struct {
61 // Pix holds the image's pixels, in R, G, B, A order. The pixel at
62 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
63 Pix []uint8
64 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
65 Stride int
66 // Rect is the image's bounds.
67 Rect Rectangle
70 func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
72 func (p *RGBA) Bounds() Rectangle { return p.Rect }
74 func (p *RGBA) At(x, y int) color.Color {
75 return p.RGBAAt(x, y)
78 func (p *RGBA) RGBAAt(x, y int) color.RGBA {
79 if !(Point{x, y}.In(p.Rect)) {
80 return color.RGBA{}
82 i := p.PixOffset(x, y)
83 return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
86 // PixOffset returns the index of the first element of Pix that corresponds to
87 // the pixel at (x, y).
88 func (p *RGBA) PixOffset(x, y int) int {
89 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
92 func (p *RGBA) Set(x, y int, c color.Color) {
93 if !(Point{x, y}.In(p.Rect)) {
94 return
96 i := p.PixOffset(x, y)
97 c1 := color.RGBAModel.Convert(c).(color.RGBA)
98 p.Pix[i+0] = c1.R
99 p.Pix[i+1] = c1.G
100 p.Pix[i+2] = c1.B
101 p.Pix[i+3] = c1.A
104 func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
105 if !(Point{x, y}.In(p.Rect)) {
106 return
108 i := p.PixOffset(x, y)
109 p.Pix[i+0] = c.R
110 p.Pix[i+1] = c.G
111 p.Pix[i+2] = c.B
112 p.Pix[i+3] = c.A
115 // SubImage returns an image representing the portion of the image p visible
116 // through r. The returned value shares pixels with the original image.
117 func (p *RGBA) SubImage(r Rectangle) Image {
118 r = r.Intersect(p.Rect)
119 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
120 // either r1 or r2 if the intersection is empty. Without explicitly checking for
121 // this, the Pix[i:] expression below can panic.
122 if r.Empty() {
123 return &RGBA{}
125 i := p.PixOffset(r.Min.X, r.Min.Y)
126 return &RGBA{
127 Pix: p.Pix[i:],
128 Stride: p.Stride,
129 Rect: r,
133 // Opaque scans the entire image and reports whether it is fully opaque.
134 func (p *RGBA) Opaque() bool {
135 if p.Rect.Empty() {
136 return true
138 i0, i1 := 3, p.Rect.Dx()*4
139 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
140 for i := i0; i < i1; i += 4 {
141 if p.Pix[i] != 0xff {
142 return false
145 i0 += p.Stride
146 i1 += p.Stride
148 return true
151 // NewRGBA returns a new RGBA image with the given bounds.
152 func NewRGBA(r Rectangle) *RGBA {
153 w, h := r.Dx(), r.Dy()
154 buf := make([]uint8, 4*w*h)
155 return &RGBA{buf, 4 * w, r}
158 // RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
159 type RGBA64 struct {
160 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
161 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
162 Pix []uint8
163 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
164 Stride int
165 // Rect is the image's bounds.
166 Rect Rectangle
169 func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
171 func (p *RGBA64) Bounds() Rectangle { return p.Rect }
173 func (p *RGBA64) At(x, y int) color.Color {
174 return p.RGBA64At(x, y)
177 func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
178 if !(Point{x, y}.In(p.Rect)) {
179 return color.RGBA64{}
181 i := p.PixOffset(x, y)
182 return color.RGBA64{
183 uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
184 uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
185 uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
186 uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
190 // PixOffset returns the index of the first element of Pix that corresponds to
191 // the pixel at (x, y).
192 func (p *RGBA64) PixOffset(x, y int) int {
193 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
196 func (p *RGBA64) Set(x, y int, c color.Color) {
197 if !(Point{x, y}.In(p.Rect)) {
198 return
200 i := p.PixOffset(x, y)
201 c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
202 p.Pix[i+0] = uint8(c1.R >> 8)
203 p.Pix[i+1] = uint8(c1.R)
204 p.Pix[i+2] = uint8(c1.G >> 8)
205 p.Pix[i+3] = uint8(c1.G)
206 p.Pix[i+4] = uint8(c1.B >> 8)
207 p.Pix[i+5] = uint8(c1.B)
208 p.Pix[i+6] = uint8(c1.A >> 8)
209 p.Pix[i+7] = uint8(c1.A)
212 func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
213 if !(Point{x, y}.In(p.Rect)) {
214 return
216 i := p.PixOffset(x, y)
217 p.Pix[i+0] = uint8(c.R >> 8)
218 p.Pix[i+1] = uint8(c.R)
219 p.Pix[i+2] = uint8(c.G >> 8)
220 p.Pix[i+3] = uint8(c.G)
221 p.Pix[i+4] = uint8(c.B >> 8)
222 p.Pix[i+5] = uint8(c.B)
223 p.Pix[i+6] = uint8(c.A >> 8)
224 p.Pix[i+7] = uint8(c.A)
227 // SubImage returns an image representing the portion of the image p visible
228 // through r. The returned value shares pixels with the original image.
229 func (p *RGBA64) SubImage(r Rectangle) Image {
230 r = r.Intersect(p.Rect)
231 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
232 // either r1 or r2 if the intersection is empty. Without explicitly checking for
233 // this, the Pix[i:] expression below can panic.
234 if r.Empty() {
235 return &RGBA64{}
237 i := p.PixOffset(r.Min.X, r.Min.Y)
238 return &RGBA64{
239 Pix: p.Pix[i:],
240 Stride: p.Stride,
241 Rect: r,
245 // Opaque scans the entire image and reports whether it is fully opaque.
246 func (p *RGBA64) Opaque() bool {
247 if p.Rect.Empty() {
248 return true
250 i0, i1 := 6, p.Rect.Dx()*8
251 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
252 for i := i0; i < i1; i += 8 {
253 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
254 return false
257 i0 += p.Stride
258 i1 += p.Stride
260 return true
263 // NewRGBA64 returns a new RGBA64 image with the given bounds.
264 func NewRGBA64(r Rectangle) *RGBA64 {
265 w, h := r.Dx(), r.Dy()
266 pix := make([]uint8, 8*w*h)
267 return &RGBA64{pix, 8 * w, r}
270 // NRGBA is an in-memory image whose At method returns color.NRGBA values.
271 type NRGBA struct {
272 // Pix holds the image's pixels, in R, G, B, A order. The pixel at
273 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
274 Pix []uint8
275 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
276 Stride int
277 // Rect is the image's bounds.
278 Rect Rectangle
281 func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
283 func (p *NRGBA) Bounds() Rectangle { return p.Rect }
285 func (p *NRGBA) At(x, y int) color.Color {
286 return p.NRGBAAt(x, y)
289 func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
290 if !(Point{x, y}.In(p.Rect)) {
291 return color.NRGBA{}
293 i := p.PixOffset(x, y)
294 return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
297 // PixOffset returns the index of the first element of Pix that corresponds to
298 // the pixel at (x, y).
299 func (p *NRGBA) PixOffset(x, y int) int {
300 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
303 func (p *NRGBA) Set(x, y int, c color.Color) {
304 if !(Point{x, y}.In(p.Rect)) {
305 return
307 i := p.PixOffset(x, y)
308 c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
309 p.Pix[i+0] = c1.R
310 p.Pix[i+1] = c1.G
311 p.Pix[i+2] = c1.B
312 p.Pix[i+3] = c1.A
315 func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
316 if !(Point{x, y}.In(p.Rect)) {
317 return
319 i := p.PixOffset(x, y)
320 p.Pix[i+0] = c.R
321 p.Pix[i+1] = c.G
322 p.Pix[i+2] = c.B
323 p.Pix[i+3] = c.A
326 // SubImage returns an image representing the portion of the image p visible
327 // through r. The returned value shares pixels with the original image.
328 func (p *NRGBA) SubImage(r Rectangle) Image {
329 r = r.Intersect(p.Rect)
330 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
331 // either r1 or r2 if the intersection is empty. Without explicitly checking for
332 // this, the Pix[i:] expression below can panic.
333 if r.Empty() {
334 return &NRGBA{}
336 i := p.PixOffset(r.Min.X, r.Min.Y)
337 return &NRGBA{
338 Pix: p.Pix[i:],
339 Stride: p.Stride,
340 Rect: r,
344 // Opaque scans the entire image and reports whether it is fully opaque.
345 func (p *NRGBA) Opaque() bool {
346 if p.Rect.Empty() {
347 return true
349 i0, i1 := 3, p.Rect.Dx()*4
350 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
351 for i := i0; i < i1; i += 4 {
352 if p.Pix[i] != 0xff {
353 return false
356 i0 += p.Stride
357 i1 += p.Stride
359 return true
362 // NewNRGBA returns a new NRGBA image with the given bounds.
363 func NewNRGBA(r Rectangle) *NRGBA {
364 w, h := r.Dx(), r.Dy()
365 pix := make([]uint8, 4*w*h)
366 return &NRGBA{pix, 4 * w, r}
369 // NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
370 type NRGBA64 struct {
371 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
372 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
373 Pix []uint8
374 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
375 Stride int
376 // Rect is the image's bounds.
377 Rect Rectangle
380 func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
382 func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
384 func (p *NRGBA64) At(x, y int) color.Color {
385 return p.NRGBA64At(x, y)
388 func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
389 if !(Point{x, y}.In(p.Rect)) {
390 return color.NRGBA64{}
392 i := p.PixOffset(x, y)
393 return color.NRGBA64{
394 uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
395 uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
396 uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
397 uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
401 // PixOffset returns the index of the first element of Pix that corresponds to
402 // the pixel at (x, y).
403 func (p *NRGBA64) PixOffset(x, y int) int {
404 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
407 func (p *NRGBA64) Set(x, y int, c color.Color) {
408 if !(Point{x, y}.In(p.Rect)) {
409 return
411 i := p.PixOffset(x, y)
412 c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
413 p.Pix[i+0] = uint8(c1.R >> 8)
414 p.Pix[i+1] = uint8(c1.R)
415 p.Pix[i+2] = uint8(c1.G >> 8)
416 p.Pix[i+3] = uint8(c1.G)
417 p.Pix[i+4] = uint8(c1.B >> 8)
418 p.Pix[i+5] = uint8(c1.B)
419 p.Pix[i+6] = uint8(c1.A >> 8)
420 p.Pix[i+7] = uint8(c1.A)
423 func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
424 if !(Point{x, y}.In(p.Rect)) {
425 return
427 i := p.PixOffset(x, y)
428 p.Pix[i+0] = uint8(c.R >> 8)
429 p.Pix[i+1] = uint8(c.R)
430 p.Pix[i+2] = uint8(c.G >> 8)
431 p.Pix[i+3] = uint8(c.G)
432 p.Pix[i+4] = uint8(c.B >> 8)
433 p.Pix[i+5] = uint8(c.B)
434 p.Pix[i+6] = uint8(c.A >> 8)
435 p.Pix[i+7] = uint8(c.A)
438 // SubImage returns an image representing the portion of the image p visible
439 // through r. The returned value shares pixels with the original image.
440 func (p *NRGBA64) SubImage(r Rectangle) Image {
441 r = r.Intersect(p.Rect)
442 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
443 // either r1 or r2 if the intersection is empty. Without explicitly checking for
444 // this, the Pix[i:] expression below can panic.
445 if r.Empty() {
446 return &NRGBA64{}
448 i := p.PixOffset(r.Min.X, r.Min.Y)
449 return &NRGBA64{
450 Pix: p.Pix[i:],
451 Stride: p.Stride,
452 Rect: r,
456 // Opaque scans the entire image and reports whether it is fully opaque.
457 func (p *NRGBA64) Opaque() bool {
458 if p.Rect.Empty() {
459 return true
461 i0, i1 := 6, p.Rect.Dx()*8
462 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
463 for i := i0; i < i1; i += 8 {
464 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
465 return false
468 i0 += p.Stride
469 i1 += p.Stride
471 return true
474 // NewNRGBA64 returns a new NRGBA64 image with the given bounds.
475 func NewNRGBA64(r Rectangle) *NRGBA64 {
476 w, h := r.Dx(), r.Dy()
477 pix := make([]uint8, 8*w*h)
478 return &NRGBA64{pix, 8 * w, r}
481 // Alpha is an in-memory image whose At method returns color.Alpha values.
482 type Alpha struct {
483 // Pix holds the image's pixels, as alpha values. The pixel at
484 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
485 Pix []uint8
486 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
487 Stride int
488 // Rect is the image's bounds.
489 Rect Rectangle
492 func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
494 func (p *Alpha) Bounds() Rectangle { return p.Rect }
496 func (p *Alpha) At(x, y int) color.Color {
497 return p.AlphaAt(x, y)
500 func (p *Alpha) AlphaAt(x, y int) color.Alpha {
501 if !(Point{x, y}.In(p.Rect)) {
502 return color.Alpha{}
504 i := p.PixOffset(x, y)
505 return color.Alpha{p.Pix[i]}
508 // PixOffset returns the index of the first element of Pix that corresponds to
509 // the pixel at (x, y).
510 func (p *Alpha) PixOffset(x, y int) int {
511 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
514 func (p *Alpha) Set(x, y int, c color.Color) {
515 if !(Point{x, y}.In(p.Rect)) {
516 return
518 i := p.PixOffset(x, y)
519 p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
522 func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
523 if !(Point{x, y}.In(p.Rect)) {
524 return
526 i := p.PixOffset(x, y)
527 p.Pix[i] = c.A
530 // SubImage returns an image representing the portion of the image p visible
531 // through r. The returned value shares pixels with the original image.
532 func (p *Alpha) SubImage(r Rectangle) Image {
533 r = r.Intersect(p.Rect)
534 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
535 // either r1 or r2 if the intersection is empty. Without explicitly checking for
536 // this, the Pix[i:] expression below can panic.
537 if r.Empty() {
538 return &Alpha{}
540 i := p.PixOffset(r.Min.X, r.Min.Y)
541 return &Alpha{
542 Pix: p.Pix[i:],
543 Stride: p.Stride,
544 Rect: r,
548 // Opaque scans the entire image and reports whether it is fully opaque.
549 func (p *Alpha) Opaque() bool {
550 if p.Rect.Empty() {
551 return true
553 i0, i1 := 0, p.Rect.Dx()
554 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
555 for i := i0; i < i1; i++ {
556 if p.Pix[i] != 0xff {
557 return false
560 i0 += p.Stride
561 i1 += p.Stride
563 return true
566 // NewAlpha returns a new Alpha image with the given bounds.
567 func NewAlpha(r Rectangle) *Alpha {
568 w, h := r.Dx(), r.Dy()
569 pix := make([]uint8, 1*w*h)
570 return &Alpha{pix, 1 * w, r}
573 // Alpha16 is an in-memory image whose At method returns color.Alpha16 values.
574 type Alpha16 struct {
575 // Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
576 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
577 Pix []uint8
578 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
579 Stride int
580 // Rect is the image's bounds.
581 Rect Rectangle
584 func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
586 func (p *Alpha16) Bounds() Rectangle { return p.Rect }
588 func (p *Alpha16) At(x, y int) color.Color {
589 return p.Alpha16At(x, y)
592 func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
593 if !(Point{x, y}.In(p.Rect)) {
594 return color.Alpha16{}
596 i := p.PixOffset(x, y)
597 return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
600 // PixOffset returns the index of the first element of Pix that corresponds to
601 // the pixel at (x, y).
602 func (p *Alpha16) PixOffset(x, y int) int {
603 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
606 func (p *Alpha16) Set(x, y int, c color.Color) {
607 if !(Point{x, y}.In(p.Rect)) {
608 return
610 i := p.PixOffset(x, y)
611 c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
612 p.Pix[i+0] = uint8(c1.A >> 8)
613 p.Pix[i+1] = uint8(c1.A)
616 func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
617 if !(Point{x, y}.In(p.Rect)) {
618 return
620 i := p.PixOffset(x, y)
621 p.Pix[i+0] = uint8(c.A >> 8)
622 p.Pix[i+1] = uint8(c.A)
625 // SubImage returns an image representing the portion of the image p visible
626 // through r. The returned value shares pixels with the original image.
627 func (p *Alpha16) SubImage(r Rectangle) Image {
628 r = r.Intersect(p.Rect)
629 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
630 // either r1 or r2 if the intersection is empty. Without explicitly checking for
631 // this, the Pix[i:] expression below can panic.
632 if r.Empty() {
633 return &Alpha16{}
635 i := p.PixOffset(r.Min.X, r.Min.Y)
636 return &Alpha16{
637 Pix: p.Pix[i:],
638 Stride: p.Stride,
639 Rect: r,
643 // Opaque scans the entire image and reports whether it is fully opaque.
644 func (p *Alpha16) Opaque() bool {
645 if p.Rect.Empty() {
646 return true
648 i0, i1 := 0, p.Rect.Dx()*2
649 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
650 for i := i0; i < i1; i += 2 {
651 if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
652 return false
655 i0 += p.Stride
656 i1 += p.Stride
658 return true
661 // NewAlpha16 returns a new Alpha16 image with the given bounds.
662 func NewAlpha16(r Rectangle) *Alpha16 {
663 w, h := r.Dx(), r.Dy()
664 pix := make([]uint8, 2*w*h)
665 return &Alpha16{pix, 2 * w, r}
668 // Gray is an in-memory image whose At method returns color.Gray values.
669 type Gray struct {
670 // Pix holds the image's pixels, as gray values. The pixel at
671 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
672 Pix []uint8
673 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
674 Stride int
675 // Rect is the image's bounds.
676 Rect Rectangle
679 func (p *Gray) ColorModel() color.Model { return color.GrayModel }
681 func (p *Gray) Bounds() Rectangle { return p.Rect }
683 func (p *Gray) At(x, y int) color.Color {
684 return p.GrayAt(x, y)
687 func (p *Gray) GrayAt(x, y int) color.Gray {
688 if !(Point{x, y}.In(p.Rect)) {
689 return color.Gray{}
691 i := p.PixOffset(x, y)
692 return color.Gray{p.Pix[i]}
695 // PixOffset returns the index of the first element of Pix that corresponds to
696 // the pixel at (x, y).
697 func (p *Gray) PixOffset(x, y int) int {
698 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
701 func (p *Gray) Set(x, y int, c color.Color) {
702 if !(Point{x, y}.In(p.Rect)) {
703 return
705 i := p.PixOffset(x, y)
706 p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
709 func (p *Gray) SetGray(x, y int, c color.Gray) {
710 if !(Point{x, y}.In(p.Rect)) {
711 return
713 i := p.PixOffset(x, y)
714 p.Pix[i] = c.Y
717 // SubImage returns an image representing the portion of the image p visible
718 // through r. The returned value shares pixels with the original image.
719 func (p *Gray) SubImage(r Rectangle) Image {
720 r = r.Intersect(p.Rect)
721 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
722 // either r1 or r2 if the intersection is empty. Without explicitly checking for
723 // this, the Pix[i:] expression below can panic.
724 if r.Empty() {
725 return &Gray{}
727 i := p.PixOffset(r.Min.X, r.Min.Y)
728 return &Gray{
729 Pix: p.Pix[i:],
730 Stride: p.Stride,
731 Rect: r,
735 // Opaque scans the entire image and reports whether it is fully opaque.
736 func (p *Gray) Opaque() bool {
737 return true
740 // NewGray returns a new Gray image with the given bounds.
741 func NewGray(r Rectangle) *Gray {
742 w, h := r.Dx(), r.Dy()
743 pix := make([]uint8, 1*w*h)
744 return &Gray{pix, 1 * w, r}
747 // Gray16 is an in-memory image whose At method returns color.Gray16 values.
748 type Gray16 struct {
749 // Pix holds the image's pixels, as gray values in big-endian format. The pixel at
750 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
751 Pix []uint8
752 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
753 Stride int
754 // Rect is the image's bounds.
755 Rect Rectangle
758 func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
760 func (p *Gray16) Bounds() Rectangle { return p.Rect }
762 func (p *Gray16) At(x, y int) color.Color {
763 return p.Gray16At(x, y)
766 func (p *Gray16) Gray16At(x, y int) color.Gray16 {
767 if !(Point{x, y}.In(p.Rect)) {
768 return color.Gray16{}
770 i := p.PixOffset(x, y)
771 return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
774 // PixOffset returns the index of the first element of Pix that corresponds to
775 // the pixel at (x, y).
776 func (p *Gray16) PixOffset(x, y int) int {
777 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
780 func (p *Gray16) Set(x, y int, c color.Color) {
781 if !(Point{x, y}.In(p.Rect)) {
782 return
784 i := p.PixOffset(x, y)
785 c1 := color.Gray16Model.Convert(c).(color.Gray16)
786 p.Pix[i+0] = uint8(c1.Y >> 8)
787 p.Pix[i+1] = uint8(c1.Y)
790 func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
791 if !(Point{x, y}.In(p.Rect)) {
792 return
794 i := p.PixOffset(x, y)
795 p.Pix[i+0] = uint8(c.Y >> 8)
796 p.Pix[i+1] = uint8(c.Y)
799 // SubImage returns an image representing the portion of the image p visible
800 // through r. The returned value shares pixels with the original image.
801 func (p *Gray16) SubImage(r Rectangle) Image {
802 r = r.Intersect(p.Rect)
803 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
804 // either r1 or r2 if the intersection is empty. Without explicitly checking for
805 // this, the Pix[i:] expression below can panic.
806 if r.Empty() {
807 return &Gray16{}
809 i := p.PixOffset(r.Min.X, r.Min.Y)
810 return &Gray16{
811 Pix: p.Pix[i:],
812 Stride: p.Stride,
813 Rect: r,
817 // Opaque scans the entire image and reports whether it is fully opaque.
818 func (p *Gray16) Opaque() bool {
819 return true
822 // NewGray16 returns a new Gray16 image with the given bounds.
823 func NewGray16(r Rectangle) *Gray16 {
824 w, h := r.Dx(), r.Dy()
825 pix := make([]uint8, 2*w*h)
826 return &Gray16{pix, 2 * w, r}
829 // CMYK is an in-memory image whose At method returns color.CMYK values.
830 type CMYK struct {
831 // Pix holds the image's pixels, in C, M, Y, K order. The pixel at
832 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
833 Pix []uint8
834 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
835 Stride int
836 // Rect is the image's bounds.
837 Rect Rectangle
840 func (p *CMYK) ColorModel() color.Model { return color.CMYKModel }
842 func (p *CMYK) Bounds() Rectangle { return p.Rect }
844 func (p *CMYK) At(x, y int) color.Color {
845 return p.CMYKAt(x, y)
848 func (p *CMYK) CMYKAt(x, y int) color.CMYK {
849 if !(Point{x, y}.In(p.Rect)) {
850 return color.CMYK{}
852 i := p.PixOffset(x, y)
853 return color.CMYK{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
856 // PixOffset returns the index of the first element of Pix that corresponds to
857 // the pixel at (x, y).
858 func (p *CMYK) PixOffset(x, y int) int {
859 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
862 func (p *CMYK) Set(x, y int, c color.Color) {
863 if !(Point{x, y}.In(p.Rect)) {
864 return
866 i := p.PixOffset(x, y)
867 c1 := color.CMYKModel.Convert(c).(color.CMYK)
868 p.Pix[i+0] = c1.C
869 p.Pix[i+1] = c1.M
870 p.Pix[i+2] = c1.Y
871 p.Pix[i+3] = c1.K
874 func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
875 if !(Point{x, y}.In(p.Rect)) {
876 return
878 i := p.PixOffset(x, y)
879 p.Pix[i+0] = c.C
880 p.Pix[i+1] = c.M
881 p.Pix[i+2] = c.Y
882 p.Pix[i+3] = c.K
885 // SubImage returns an image representing the portion of the image p visible
886 // through r. The returned value shares pixels with the original image.
887 func (p *CMYK) SubImage(r Rectangle) Image {
888 r = r.Intersect(p.Rect)
889 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
890 // either r1 or r2 if the intersection is empty. Without explicitly checking for
891 // this, the Pix[i:] expression below can panic.
892 if r.Empty() {
893 return &CMYK{}
895 i := p.PixOffset(r.Min.X, r.Min.Y)
896 return &CMYK{
897 Pix: p.Pix[i:],
898 Stride: p.Stride,
899 Rect: r,
903 // Opaque scans the entire image and reports whether it is fully opaque.
904 func (p *CMYK) Opaque() bool {
905 return true
908 // NewCMYK returns a new CMYK image with the given bounds.
909 func NewCMYK(r Rectangle) *CMYK {
910 w, h := r.Dx(), r.Dy()
911 buf := make([]uint8, 4*w*h)
912 return &CMYK{buf, 4 * w, r}
915 // Paletted is an in-memory image of uint8 indices into a given palette.
916 type Paletted struct {
917 // Pix holds the image's pixels, as palette indices. The pixel at
918 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
919 Pix []uint8
920 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
921 Stride int
922 // Rect is the image's bounds.
923 Rect Rectangle
924 // Palette is the image's palette.
925 Palette color.Palette
928 func (p *Paletted) ColorModel() color.Model { return p.Palette }
930 func (p *Paletted) Bounds() Rectangle { return p.Rect }
932 func (p *Paletted) At(x, y int) color.Color {
933 if len(p.Palette) == 0 {
934 return nil
936 if !(Point{x, y}.In(p.Rect)) {
937 return p.Palette[0]
939 i := p.PixOffset(x, y)
940 return p.Palette[p.Pix[i]]
943 // PixOffset returns the index of the first element of Pix that corresponds to
944 // the pixel at (x, y).
945 func (p *Paletted) PixOffset(x, y int) int {
946 return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
949 func (p *Paletted) Set(x, y int, c color.Color) {
950 if !(Point{x, y}.In(p.Rect)) {
951 return
953 i := p.PixOffset(x, y)
954 p.Pix[i] = uint8(p.Palette.Index(c))
957 func (p *Paletted) ColorIndexAt(x, y int) uint8 {
958 if !(Point{x, y}.In(p.Rect)) {
959 return 0
961 i := p.PixOffset(x, y)
962 return p.Pix[i]
965 func (p *Paletted) SetColorIndex(x, y int, index uint8) {
966 if !(Point{x, y}.In(p.Rect)) {
967 return
969 i := p.PixOffset(x, y)
970 p.Pix[i] = index
973 // SubImage returns an image representing the portion of the image p visible
974 // through r. The returned value shares pixels with the original image.
975 func (p *Paletted) SubImage(r Rectangle) Image {
976 r = r.Intersect(p.Rect)
977 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
978 // either r1 or r2 if the intersection is empty. Without explicitly checking for
979 // this, the Pix[i:] expression below can panic.
980 if r.Empty() {
981 return &Paletted{
982 Palette: p.Palette,
985 i := p.PixOffset(r.Min.X, r.Min.Y)
986 return &Paletted{
987 Pix: p.Pix[i:],
988 Stride: p.Stride,
989 Rect: p.Rect.Intersect(r),
990 Palette: p.Palette,
994 // Opaque scans the entire image and reports whether it is fully opaque.
995 func (p *Paletted) Opaque() bool {
996 var present [256]bool
997 i0, i1 := 0, p.Rect.Dx()
998 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
999 for _, c := range p.Pix[i0:i1] {
1000 present[c] = true
1002 i0 += p.Stride
1003 i1 += p.Stride
1005 for i, c := range p.Palette {
1006 if !present[i] {
1007 continue
1009 _, _, _, a := c.RGBA()
1010 if a != 0xffff {
1011 return false
1014 return true
1017 // NewPaletted returns a new Paletted image with the given width, height and
1018 // palette.
1019 func NewPaletted(r Rectangle, p color.Palette) *Paletted {
1020 w, h := r.Dx(), r.Dy()
1021 pix := make([]uint8, 1*w*h)
1022 return &Paletted{pix, 1 * w, r, p}