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.
7 // The fundamental interface is called Image. An Image contains colors, which
8 // are described in the image/color package.
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
28 // Config holds an image's color model and dimensions.
30 ColorModel color
.Model
34 // Image is a finite rectangular grid of color.Color values taken from a color
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).
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
53 type PalettedImage
interface {
54 // ColorIndexAt returns the palette index of the pixel at (x, y).
55 ColorIndexAt(x
, y
int) uint8
59 // RGBA is an in-memory image whose At method returns color.RGBA values.
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].
64 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
66 // Rect is the image's bounds.
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
{
78 func (p
*RGBA
) RGBAAt(x
, y
int) color
.RGBA
{
79 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)) {
96 i
:= p
.PixOffset(x
, y
)
97 c1
:= color
.RGBAModel
.Convert(c
).(color
.RGBA
)
104 func (p
*RGBA
) SetRGBA(x
, y
int, c color
.RGBA
) {
105 if !(Point
{x
, y
}.In(p
.Rect
)) {
108 i
:= p
.PixOffset(x
, y
)
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.
125 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
133 // Opaque scans the entire image and reports whether it is fully opaque.
134 func (p
*RGBA
) Opaque() bool {
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 {
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.
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].
163 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
165 // Rect is the image's bounds.
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
)
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
)) {
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
)) {
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.
237 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
245 // Opaque scans the entire image and reports whether it is fully opaque.
246 func (p
*RGBA64
) Opaque() bool {
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 {
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.
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].
275 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
277 // Rect is the image's bounds.
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
)) {
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
)) {
307 i
:= p
.PixOffset(x
, y
)
308 c1
:= color
.NRGBAModel
.Convert(c
).(color
.NRGBA
)
315 func (p
*NRGBA
) SetNRGBA(x
, y
int, c color
.NRGBA
) {
316 if !(Point
{x
, y
}.In(p
.Rect
)) {
319 i
:= p
.PixOffset(x
, y
)
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.
336 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
344 // Opaque scans the entire image and reports whether it is fully opaque.
345 func (p
*NRGBA
) Opaque() bool {
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 {
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].
374 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
376 // Rect is the image's bounds.
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
)) {
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
)) {
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.
448 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
456 // Opaque scans the entire image and reports whether it is fully opaque.
457 func (p
*NRGBA64
) Opaque() bool {
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 {
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.
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].
486 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
488 // Rect is the image's bounds.
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
)) {
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
)) {
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
)) {
526 i
:= p
.PixOffset(x
, y
)
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.
540 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
548 // Opaque scans the entire image and reports whether it is fully opaque.
549 func (p
*Alpha
) Opaque() bool {
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 {
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].
578 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
580 // Rect is the image's bounds.
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
)) {
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
)) {
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.
635 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
643 // Opaque scans the entire image and reports whether it is fully opaque.
644 func (p
*Alpha16
) Opaque() bool {
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 {
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.
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].
673 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
675 // Rect is the image's bounds.
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
)) {
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
)) {
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
)) {
713 i
:= p
.PixOffset(x
, 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.
727 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
735 // Opaque scans the entire image and reports whether it is fully opaque.
736 func (p
*Gray
) Opaque() bool {
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.
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].
752 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
754 // Rect is the image's bounds.
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
)) {
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
)) {
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.
809 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
817 // Opaque scans the entire image and reports whether it is fully opaque.
818 func (p
*Gray16
) Opaque() bool {
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.
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].
834 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
836 // Rect is the image's bounds.
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
)) {
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
)) {
866 i
:= p
.PixOffset(x
, y
)
867 c1
:= color
.CMYKModel
.Convert(c
).(color
.CMYK
)
874 func (p
*CMYK
) SetCMYK(x
, y
int, c color
.CMYK
) {
875 if !(Point
{x
, y
}.In(p
.Rect
)) {
878 i
:= p
.PixOffset(x
, y
)
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.
895 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
903 // Opaque scans the entire image and reports whether it is fully opaque.
904 func (p
*CMYK
) Opaque() bool {
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].
920 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
922 // Rect is the image's bounds.
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 {
936 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)) {
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
)) {
961 i
:= p
.PixOffset(x
, y
)
965 func (p
*Paletted
) SetColorIndex(x
, y
int, index
uint8) {
966 if !(Point
{x
, y
}.In(p
.Rect
)) {
969 i
:= p
.PixOffset(x
, y
)
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.
985 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
989 Rect
: p
.Rect
.Intersect(r
),
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
] {
1005 for i
, c
:= range p
.Palette
{
1009 _
, _
, _
, a
:= c
.RGBA()
1017 // NewPaletted returns a new Paletted image with the given width, height and
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
}