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 // RGBA64Image is an Image whose pixels can be converted directly to a
50 type RGBA64Image
interface {
51 // RGBA64At returns the RGBA64 color of the pixel at (x, y). It is
52 // equivalent to calling At(x, y).RGBA() and converting the resulting
53 // 32-bit return values to a color.RGBA64, but it can avoid allocations
54 // from converting concrete color types to the color.Color interface type.
55 RGBA64At(x
, y
int) color
.RGBA64
59 // PalettedImage is an image whose colors may come from a limited palette.
60 // If m is a PalettedImage and m.ColorModel() returns a color.Palette p,
61 // then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
62 // color model is not a color.Palette, then ColorIndexAt's behavior is
64 type PalettedImage
interface {
65 // ColorIndexAt returns the palette index of the pixel at (x, y).
66 ColorIndexAt(x
, y
int) uint8
70 // pixelBufferLength returns the length of the []uint8 typed Pix slice field
71 // for the NewXxx functions. Conceptually, this is just (bpp * width * height),
72 // but this function panics if at least one of those is negative or if the
73 // computation would overflow the int type.
75 // This panics instead of returning an error because of backwards
76 // compatibility. The NewXxx functions do not return an error.
77 func pixelBufferLength(bytesPerPixel
int, r Rectangle
, imageTypeName
string) int {
78 totalLength
:= mul3NonNeg(bytesPerPixel
, r
.Dx(), r
.Dy())
80 panic("image: New" + imageTypeName
+ " Rectangle has huge or negative dimensions")
85 // RGBA is an in-memory image whose At method returns color.RGBA values.
87 // Pix holds the image's pixels, in R, G, B, A order. The pixel at
88 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
90 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
92 // Rect is the image's bounds.
96 func (p
*RGBA
) ColorModel() color
.Model
{ return color
.RGBAModel
}
98 func (p
*RGBA
) Bounds() Rectangle
{ return p
.Rect
}
100 func (p
*RGBA
) At(x
, y
int) color
.Color
{
101 return p
.RGBAAt(x
, y
)
104 func (p
*RGBA
) RGBA64At(x
, y
int) color
.RGBA64
{
105 if !(Point
{x
, y
}.In(p
.Rect
)) {
106 return color
.RGBA64
{}
108 i
:= p
.PixOffset(x
, y
)
109 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
122 func (p
*RGBA
) RGBAAt(x
, y
int) color
.RGBA
{
123 if !(Point
{x
, y
}.In(p
.Rect
)) {
126 i
:= p
.PixOffset(x
, y
)
127 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
128 return color
.RGBA
{s
[0], s
[1], s
[2], s
[3]}
131 // PixOffset returns the index of the first element of Pix that corresponds to
132 // the pixel at (x, y).
133 func (p
*RGBA
) PixOffset(x
, y
int) int {
134 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*4
137 func (p
*RGBA
) Set(x
, y
int, c color
.Color
) {
138 if !(Point
{x
, y
}.In(p
.Rect
)) {
141 i
:= p
.PixOffset(x
, y
)
142 c1
:= color
.RGBAModel
.Convert(c
).(color
.RGBA
)
143 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
150 func (p
*RGBA
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
151 if !(Point
{x
, y
}.In(p
.Rect
)) {
154 i
:= p
.PixOffset(x
, y
)
155 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
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)
162 func (p
*RGBA
) SetRGBA(x
, y
int, c color
.RGBA
) {
163 if !(Point
{x
, y
}.In(p
.Rect
)) {
166 i
:= p
.PixOffset(x
, y
)
167 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
174 // SubImage returns an image representing the portion of the image p visible
175 // through r. The returned value shares pixels with the original image.
176 func (p
*RGBA
) SubImage(r Rectangle
) Image
{
177 r
= r
.Intersect(p
.Rect
)
178 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
179 // either r1 or r2 if the intersection is empty. Without explicitly checking for
180 // this, the Pix[i:] expression below can panic.
184 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
192 // Opaque scans the entire image and reports whether it is fully opaque.
193 func (p
*RGBA
) Opaque() bool {
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 {
210 // NewRGBA returns a new RGBA image with the given bounds.
211 func NewRGBA(r Rectangle
) *RGBA
{
213 Pix
: make([]uint8, pixelBufferLength(4, r
, "RGBA")),
219 // RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
221 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
222 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
224 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
226 // Rect is the image's bounds.
230 func (p
*RGBA64
) ColorModel() color
.Model
{ return color
.RGBA64Model
}
232 func (p
*RGBA64
) Bounds() Rectangle
{ return p
.Rect
}
234 func (p
*RGBA64
) At(x
, y
int) color
.Color
{
235 return p
.RGBA64At(x
, y
)
238 func (p
*RGBA64
) RGBA64At(x
, y
int) color
.RGBA64
{
239 if !(Point
{x
, y
}.In(p
.Rect
)) {
240 return color
.RGBA64
{}
242 i
:= p
.PixOffset(x
, y
)
243 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
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]),
252 // PixOffset returns the index of the first element of Pix that corresponds to
253 // the pixel at (x, y).
254 func (p
*RGBA64
) PixOffset(x
, y
int) int {
255 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*8
258 func (p
*RGBA64
) Set(x
, y
int, c color
.Color
) {
259 if !(Point
{x
, y
}.In(p
.Rect
)) {
262 i
:= p
.PixOffset(x
, y
)
263 c1
:= color
.RGBA64Model
.Convert(c
).(color
.RGBA64
)
264 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
265 s
[0] = uint8(c1
.R
>> 8)
267 s
[2] = uint8(c1
.G
>> 8)
269 s
[4] = uint8(c1
.B
>> 8)
271 s
[6] = uint8(c1
.A
>> 8)
275 func (p
*RGBA64
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
276 if !(Point
{x
, y
}.In(p
.Rect
)) {
279 i
:= p
.PixOffset(x
, y
)
280 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
281 s
[0] = uint8(c
.R
>> 8)
283 s
[2] = uint8(c
.G
>> 8)
285 s
[4] = uint8(c
.B
>> 8)
287 s
[6] = uint8(c
.A
>> 8)
291 // SubImage returns an image representing the portion of the image p visible
292 // through r. The returned value shares pixels with the original image.
293 func (p
*RGBA64
) SubImage(r Rectangle
) Image
{
294 r
= r
.Intersect(p
.Rect
)
295 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
296 // either r1 or r2 if the intersection is empty. Without explicitly checking for
297 // this, the Pix[i:] expression below can panic.
301 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
309 // Opaque scans the entire image and reports whether it is fully opaque.
310 func (p
*RGBA64
) Opaque() bool {
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 {
327 // NewRGBA64 returns a new RGBA64 image with the given bounds.
328 func NewRGBA64(r Rectangle
) *RGBA64
{
330 Pix
: make([]uint8, pixelBufferLength(8, r
, "RGBA64")),
336 // NRGBA is an in-memory image whose At method returns color.NRGBA values.
338 // Pix holds the image's pixels, in R, G, B, A order. The pixel at
339 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
341 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
343 // Rect is the image's bounds.
347 func (p
*NRGBA
) ColorModel() color
.Model
{ return color
.NRGBAModel
}
349 func (p
*NRGBA
) Bounds() Rectangle
{ return p
.Rect
}
351 func (p
*NRGBA
) At(x
, y
int) color
.Color
{
352 return p
.NRGBAAt(x
, y
)
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
)}
360 func (p
*NRGBA
) NRGBAAt(x
, y
int) color
.NRGBA
{
361 if !(Point
{x
, y
}.In(p
.Rect
)) {
364 i
:= p
.PixOffset(x
, y
)
365 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
366 return color
.NRGBA
{s
[0], s
[1], s
[2], s
[3]}
369 // PixOffset returns the index of the first element of Pix that corresponds to
370 // the pixel at (x, y).
371 func (p
*NRGBA
) PixOffset(x
, y
int) int {
372 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*4
375 func (p
*NRGBA
) Set(x
, y
int, c color
.Color
) {
376 if !(Point
{x
, y
}.In(p
.Rect
)) {
379 i
:= p
.PixOffset(x
, y
)
380 c1
:= color
.NRGBAModel
.Convert(c
).(color
.NRGBA
)
381 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
388 func (p
*NRGBA
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
389 if !(Point
{x
, y
}.In(p
.Rect
)) {
392 r
, g
, b
, a
:= uint32(c
.R
), uint32(c
.G
), uint32(c
.B
), uint32(c
.A
)
393 if (a
!= 0) && (a
!= 0xffff) {
398 i
:= p
.PixOffset(x
, y
)
399 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
406 func (p
*NRGBA
) SetNRGBA(x
, y
int, c color
.NRGBA
) {
407 if !(Point
{x
, y
}.In(p
.Rect
)) {
410 i
:= p
.PixOffset(x
, y
)
411 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
418 // SubImage returns an image representing the portion of the image p visible
419 // through r. The returned value shares pixels with the original image.
420 func (p
*NRGBA
) SubImage(r Rectangle
) Image
{
421 r
= r
.Intersect(p
.Rect
)
422 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
423 // either r1 or r2 if the intersection is empty. Without explicitly checking for
424 // this, the Pix[i:] expression below can panic.
428 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
436 // Opaque scans the entire image and reports whether it is fully opaque.
437 func (p
*NRGBA
) Opaque() bool {
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 {
454 // NewNRGBA returns a new NRGBA image with the given bounds.
455 func NewNRGBA(r Rectangle
) *NRGBA
{
457 Pix
: make([]uint8, pixelBufferLength(4, r
, "NRGBA")),
463 // NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
464 type NRGBA64
struct {
465 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
466 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
468 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
470 // Rect is the image's bounds.
474 func (p
*NRGBA64
) ColorModel() color
.Model
{ return color
.NRGBA64Model
}
476 func (p
*NRGBA64
) Bounds() Rectangle
{ return p
.Rect
}
478 func (p
*NRGBA64
) At(x
, y
int) color
.Color
{
479 return p
.NRGBA64At(x
, y
)
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
)}
487 func (p
*NRGBA64
) NRGBA64At(x
, y
int) color
.NRGBA64
{
488 if !(Point
{x
, y
}.In(p
.Rect
)) {
489 return color
.NRGBA64
{}
491 i
:= p
.PixOffset(x
, y
)
492 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
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]),
501 // PixOffset returns the index of the first element of Pix that corresponds to
502 // the pixel at (x, y).
503 func (p
*NRGBA64
) PixOffset(x
, y
int) int {
504 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*8
507 func (p
*NRGBA64
) Set(x
, y
int, c color
.Color
) {
508 if !(Point
{x
, y
}.In(p
.Rect
)) {
511 i
:= p
.PixOffset(x
, y
)
512 c1
:= color
.NRGBA64Model
.Convert(c
).(color
.NRGBA64
)
513 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
514 s
[0] = uint8(c1
.R
>> 8)
516 s
[2] = uint8(c1
.G
>> 8)
518 s
[4] = uint8(c1
.B
>> 8)
520 s
[6] = uint8(c1
.A
>> 8)
524 func (p
*NRGBA64
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
525 if !(Point
{x
, y
}.In(p
.Rect
)) {
528 r
, g
, b
, a
:= uint32(c
.R
), uint32(c
.G
), uint32(c
.B
), uint32(c
.A
)
529 if (a
!= 0) && (a
!= 0xffff) {
534 i
:= p
.PixOffset(x
, y
)
535 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
546 func (p
*NRGBA64
) SetNRGBA64(x
, y
int, c color
.NRGBA64
) {
547 if !(Point
{x
, y
}.In(p
.Rect
)) {
550 i
:= p
.PixOffset(x
, y
)
551 s
:= p
.Pix
[i
: i
+8 : i
+8] // Small cap improves performance, see https://golang.org/issue/27857
552 s
[0] = uint8(c
.R
>> 8)
554 s
[2] = uint8(c
.G
>> 8)
556 s
[4] = uint8(c
.B
>> 8)
558 s
[6] = uint8(c
.A
>> 8)
562 // SubImage returns an image representing the portion of the image p visible
563 // through r. The returned value shares pixels with the original image.
564 func (p
*NRGBA64
) SubImage(r Rectangle
) Image
{
565 r
= r
.Intersect(p
.Rect
)
566 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
567 // either r1 or r2 if the intersection is empty. Without explicitly checking for
568 // this, the Pix[i:] expression below can panic.
572 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
580 // Opaque scans the entire image and reports whether it is fully opaque.
581 func (p
*NRGBA64
) Opaque() bool {
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 {
598 // NewNRGBA64 returns a new NRGBA64 image with the given bounds.
599 func NewNRGBA64(r Rectangle
) *NRGBA64
{
601 Pix
: make([]uint8, pixelBufferLength(8, r
, "NRGBA64")),
607 // Alpha is an in-memory image whose At method returns color.Alpha values.
609 // Pix holds the image's pixels, as alpha values. The pixel at
610 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
612 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
614 // Rect is the image's bounds.
618 func (p
*Alpha
) ColorModel() color
.Model
{ return color
.AlphaModel
}
620 func (p
*Alpha
) Bounds() Rectangle
{ return p
.Rect
}
622 func (p
*Alpha
) At(x
, y
int) color
.Color
{
623 return p
.AlphaAt(x
, y
)
626 func (p
*Alpha
) RGBA64At(x
, y
int) color
.RGBA64
{
627 a
:= uint16(p
.AlphaAt(x
, y
).A
)
629 return color
.RGBA64
{a
, a
, a
, a
}
632 func (p
*Alpha
) AlphaAt(x
, y
int) color
.Alpha
{
633 if !(Point
{x
, y
}.In(p
.Rect
)) {
636 i
:= p
.PixOffset(x
, y
)
637 return color
.Alpha
{p
.Pix
[i
]}
640 // PixOffset returns the index of the first element of Pix that corresponds to
641 // the pixel at (x, y).
642 func (p
*Alpha
) PixOffset(x
, y
int) int {
643 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*1
646 func (p
*Alpha
) Set(x
, y
int, c color
.Color
) {
647 if !(Point
{x
, y
}.In(p
.Rect
)) {
650 i
:= p
.PixOffset(x
, y
)
651 p
.Pix
[i
] = color
.AlphaModel
.Convert(c
).(color
.Alpha
).A
654 func (p
*Alpha
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
655 if !(Point
{x
, y
}.In(p
.Rect
)) {
658 i
:= p
.PixOffset(x
, y
)
659 p
.Pix
[i
] = uint8(c
.A
>> 8)
662 func (p
*Alpha
) SetAlpha(x
, y
int, c color
.Alpha
) {
663 if !(Point
{x
, y
}.In(p
.Rect
)) {
666 i
:= p
.PixOffset(x
, y
)
670 // SubImage returns an image representing the portion of the image p visible
671 // through r. The returned value shares pixels with the original image.
672 func (p
*Alpha
) SubImage(r Rectangle
) Image
{
673 r
= r
.Intersect(p
.Rect
)
674 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
675 // either r1 or r2 if the intersection is empty. Without explicitly checking for
676 // this, the Pix[i:] expression below can panic.
680 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
688 // Opaque scans the entire image and reports whether it is fully opaque.
689 func (p
*Alpha
) Opaque() bool {
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 {
706 // NewAlpha returns a new Alpha image with the given bounds.
707 func NewAlpha(r Rectangle
) *Alpha
{
709 Pix
: make([]uint8, pixelBufferLength(1, r
, "Alpha")),
715 // Alpha16 is an in-memory image whose At method returns color.Alpha16 values.
716 type Alpha16
struct {
717 // Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
718 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
720 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
722 // Rect is the image's bounds.
726 func (p
*Alpha16
) ColorModel() color
.Model
{ return color
.Alpha16Model
}
728 func (p
*Alpha16
) Bounds() Rectangle
{ return p
.Rect
}
730 func (p
*Alpha16
) At(x
, y
int) color
.Color
{
731 return p
.Alpha16At(x
, y
)
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
}
739 func (p
*Alpha16
) Alpha16At(x
, y
int) color
.Alpha16
{
740 if !(Point
{x
, y
}.In(p
.Rect
)) {
741 return color
.Alpha16
{}
743 i
:= p
.PixOffset(x
, y
)
744 return color
.Alpha16
{uint16(p
.Pix
[i
+0])<<8 |
uint16(p
.Pix
[i
+1])}
747 // PixOffset returns the index of the first element of Pix that corresponds to
748 // the pixel at (x, y).
749 func (p
*Alpha16
) PixOffset(x
, y
int) int {
750 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*2
753 func (p
*Alpha16
) Set(x
, y
int, c color
.Color
) {
754 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
763 func (p
*Alpha16
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
764 if !(Point
{x
, y
}.In(p
.Rect
)) {
767 i
:= p
.PixOffset(x
, y
)
768 p
.Pix
[i
+0] = uint8(c
.A
>> 8)
769 p
.Pix
[i
+1] = uint8(c
.A
)
772 func (p
*Alpha16
) SetAlpha16(x
, y
int, c color
.Alpha16
) {
773 if !(Point
{x
, y
}.In(p
.Rect
)) {
776 i
:= p
.PixOffset(x
, y
)
777 p
.Pix
[i
+0] = uint8(c
.A
>> 8)
778 p
.Pix
[i
+1] = uint8(c
.A
)
781 // SubImage returns an image representing the portion of the image p visible
782 // through r. The returned value shares pixels with the original image.
783 func (p
*Alpha16
) SubImage(r Rectangle
) Image
{
784 r
= r
.Intersect(p
.Rect
)
785 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
786 // either r1 or r2 if the intersection is empty. Without explicitly checking for
787 // this, the Pix[i:] expression below can panic.
791 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
799 // Opaque scans the entire image and reports whether it is fully opaque.
800 func (p
*Alpha16
) Opaque() bool {
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 {
817 // NewAlpha16 returns a new Alpha16 image with the given bounds.
818 func NewAlpha16(r Rectangle
) *Alpha16
{
820 Pix
: make([]uint8, pixelBufferLength(2, r
, "Alpha16")),
826 // Gray is an in-memory image whose At method returns color.Gray values.
828 // Pix holds the image's pixels, as gray values. The pixel at
829 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
831 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
833 // Rect is the image's bounds.
837 func (p
*Gray
) ColorModel() color
.Model
{ return color
.GrayModel
}
839 func (p
*Gray
) Bounds() Rectangle
{ return p
.Rect
}
841 func (p
*Gray
) At(x
, y
int) color
.Color
{
842 return p
.GrayAt(x
, y
)
845 func (p
*Gray
) RGBA64At(x
, y
int) color
.RGBA64
{
846 gray
:= uint16(p
.GrayAt(x
, y
).Y
)
848 return color
.RGBA64
{gray
, gray
, gray
, 0xffff}
851 func (p
*Gray
) GrayAt(x
, y
int) color
.Gray
{
852 if !(Point
{x
, y
}.In(p
.Rect
)) {
855 i
:= p
.PixOffset(x
, y
)
856 return color
.Gray
{p
.Pix
[i
]}
859 // PixOffset returns the index of the first element of Pix that corresponds to
860 // the pixel at (x, y).
861 func (p
*Gray
) PixOffset(x
, y
int) int {
862 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*1
865 func (p
*Gray
) Set(x
, y
int, c color
.Color
) {
866 if !(Point
{x
, y
}.In(p
.Rect
)) {
869 i
:= p
.PixOffset(x
, y
)
870 p
.Pix
[i
] = color
.GrayModel
.Convert(c
).(color
.Gray
).Y
873 func (p
*Gray
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
874 if !(Point
{x
, y
}.In(p
.Rect
)) {
877 // This formula is the same as in color.grayModel.
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
)
883 func (p
*Gray
) SetGray(x
, y
int, c color
.Gray
) {
884 if !(Point
{x
, y
}.In(p
.Rect
)) {
887 i
:= p
.PixOffset(x
, y
)
891 // SubImage returns an image representing the portion of the image p visible
892 // through r. The returned value shares pixels with the original image.
893 func (p
*Gray
) SubImage(r Rectangle
) Image
{
894 r
= r
.Intersect(p
.Rect
)
895 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
896 // either r1 or r2 if the intersection is empty. Without explicitly checking for
897 // this, the Pix[i:] expression below can panic.
901 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
909 // Opaque scans the entire image and reports whether it is fully opaque.
910 func (p
*Gray
) Opaque() bool {
914 // NewGray returns a new Gray image with the given bounds.
915 func NewGray(r Rectangle
) *Gray
{
917 Pix
: make([]uint8, pixelBufferLength(1, r
, "Gray")),
923 // Gray16 is an in-memory image whose At method returns color.Gray16 values.
925 // Pix holds the image's pixels, as gray values in big-endian format. The pixel at
926 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
928 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
930 // Rect is the image's bounds.
934 func (p
*Gray16
) ColorModel() color
.Model
{ return color
.Gray16Model
}
936 func (p
*Gray16
) Bounds() Rectangle
{ return p
.Rect
}
938 func (p
*Gray16
) At(x
, y
int) color
.Color
{
939 return p
.Gray16At(x
, y
)
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}
947 func (p
*Gray16
) Gray16At(x
, y
int) color
.Gray16
{
948 if !(Point
{x
, y
}.In(p
.Rect
)) {
949 return color
.Gray16
{}
951 i
:= p
.PixOffset(x
, y
)
952 return color
.Gray16
{uint16(p
.Pix
[i
+0])<<8 |
uint16(p
.Pix
[i
+1])}
955 // PixOffset returns the index of the first element of Pix that corresponds to
956 // the pixel at (x, y).
957 func (p
*Gray16
) PixOffset(x
, y
int) int {
958 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*2
961 func (p
*Gray16
) Set(x
, y
int, c color
.Color
) {
962 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
971 func (p
*Gray16
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
972 if !(Point
{x
, y
}.In(p
.Rect
)) {
975 // This formula is the same as in color.gray16Model.
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
)
982 func (p
*Gray16
) SetGray16(x
, y
int, c color
.Gray16
) {
983 if !(Point
{x
, y
}.In(p
.Rect
)) {
986 i
:= p
.PixOffset(x
, y
)
987 p
.Pix
[i
+0] = uint8(c
.Y
>> 8)
988 p
.Pix
[i
+1] = uint8(c
.Y
)
991 // SubImage returns an image representing the portion of the image p visible
992 // through r. The returned value shares pixels with the original image.
993 func (p
*Gray16
) SubImage(r Rectangle
) Image
{
994 r
= r
.Intersect(p
.Rect
)
995 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
996 // either r1 or r2 if the intersection is empty. Without explicitly checking for
997 // this, the Pix[i:] expression below can panic.
1001 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
1009 // Opaque scans the entire image and reports whether it is fully opaque.
1010 func (p
*Gray16
) Opaque() bool {
1014 // NewGray16 returns a new Gray16 image with the given bounds.
1015 func NewGray16(r Rectangle
) *Gray16
{
1017 Pix
: make([]uint8, pixelBufferLength(2, r
, "Gray16")),
1023 // CMYK is an in-memory image whose At method returns color.CMYK values.
1025 // Pix holds the image's pixels, in C, M, Y, K order. The pixel at
1026 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
1028 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
1030 // Rect is the image's bounds.
1034 func (p
*CMYK
) ColorModel() color
.Model
{ return color
.CMYKModel
}
1036 func (p
*CMYK
) Bounds() Rectangle
{ return p
.Rect
}
1038 func (p
*CMYK
) At(x
, y
int) color
.Color
{
1039 return p
.CMYKAt(x
, y
)
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
)}
1047 func (p
*CMYK
) CMYKAt(x
, y
int) color
.CMYK
{
1048 if !(Point
{x
, y
}.In(p
.Rect
)) {
1051 i
:= p
.PixOffset(x
, y
)
1052 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
1053 return color
.CMYK
{s
[0], s
[1], s
[2], s
[3]}
1056 // PixOffset returns the index of the first element of Pix that corresponds to
1057 // the pixel at (x, y).
1058 func (p
*CMYK
) PixOffset(x
, y
int) int {
1059 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*4
1062 func (p
*CMYK
) Set(x
, y
int, c color
.Color
) {
1063 if !(Point
{x
, y
}.In(p
.Rect
)) {
1066 i
:= p
.PixOffset(x
, y
)
1067 c1
:= color
.CMYKModel
.Convert(c
).(color
.CMYK
)
1068 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
1075 func (p
*CMYK
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
1076 if !(Point
{x
, y
}.In(p
.Rect
)) {
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] // Small cap improves performance, see https://golang.org/issue/27857
1088 func (p
*CMYK
) SetCMYK(x
, y
int, c color
.CMYK
) {
1089 if !(Point
{x
, y
}.In(p
.Rect
)) {
1092 i
:= p
.PixOffset(x
, y
)
1093 s
:= p
.Pix
[i
: i
+4 : i
+4] // Small cap improves performance, see https://golang.org/issue/27857
1100 // SubImage returns an image representing the portion of the image p visible
1101 // through r. The returned value shares pixels with the original image.
1102 func (p
*CMYK
) SubImage(r Rectangle
) Image
{
1103 r
= r
.Intersect(p
.Rect
)
1104 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
1105 // either r1 or r2 if the intersection is empty. Without explicitly checking for
1106 // this, the Pix[i:] expression below can panic.
1110 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
1118 // Opaque scans the entire image and reports whether it is fully opaque.
1119 func (p
*CMYK
) Opaque() bool {
1123 // NewCMYK returns a new CMYK image with the given bounds.
1124 func NewCMYK(r Rectangle
) *CMYK
{
1126 Pix
: make([]uint8, pixelBufferLength(4, r
, "CMYK")),
1132 // Paletted is an in-memory image of uint8 indices into a given palette.
1133 type Paletted
struct {
1134 // Pix holds the image's pixels, as palette indices. The pixel at
1135 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
1137 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
1139 // Rect is the image's bounds.
1141 // Palette is the image's palette.
1142 Palette color
.Palette
1145 func (p
*Paletted
) ColorModel() color
.Model
{ return p
.Palette
}
1147 func (p
*Paletted
) Bounds() Rectangle
{ return p
.Rect
}
1149 func (p
*Paletted
) At(x
, y
int) color
.Color
{
1150 if len(p
.Palette
) == 0 {
1153 if !(Point
{x
, y
}.In(p
.Rect
)) {
1156 i
:= p
.PixOffset(x
, y
)
1157 return p
.Palette
[p
.Pix
[i
]]
1160 func (p
*Paletted
) RGBA64At(x
, y
int) color
.RGBA64
{
1161 if len(p
.Palette
) == 0 {
1162 return color
.RGBA64
{}
1164 c
:= color
.Color(nil)
1165 if !(Point
{x
, y
}.In(p
.Rect
)) {
1168 i
:= p
.PixOffset(x
, y
)
1169 c
= p
.Palette
[p
.Pix
[i
]]
1171 r
, g
, b
, a
:= c
.RGBA()
1172 return color
.RGBA64
{
1180 // PixOffset returns the index of the first element of Pix that corresponds to
1181 // the pixel at (x, y).
1182 func (p
*Paletted
) PixOffset(x
, y
int) int {
1183 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*1
1186 func (p
*Paletted
) Set(x
, y
int, c color
.Color
) {
1187 if !(Point
{x
, y
}.In(p
.Rect
)) {
1190 i
:= p
.PixOffset(x
, y
)
1191 p
.Pix
[i
] = uint8(p
.Palette
.Index(c
))
1194 func (p
*Paletted
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
1195 if !(Point
{x
, y
}.In(p
.Rect
)) {
1198 i
:= p
.PixOffset(x
, y
)
1199 p
.Pix
[i
] = uint8(p
.Palette
.Index(c
))
1202 func (p
*Paletted
) ColorIndexAt(x
, y
int) uint8 {
1203 if !(Point
{x
, y
}.In(p
.Rect
)) {
1206 i
:= p
.PixOffset(x
, y
)
1210 func (p
*Paletted
) SetColorIndex(x
, y
int, index
uint8) {
1211 if !(Point
{x
, y
}.In(p
.Rect
)) {
1214 i
:= p
.PixOffset(x
, y
)
1218 // SubImage returns an image representing the portion of the image p visible
1219 // through r. The returned value shares pixels with the original image.
1220 func (p
*Paletted
) SubImage(r Rectangle
) Image
{
1221 r
= r
.Intersect(p
.Rect
)
1222 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
1223 // either r1 or r2 if the intersection is empty. Without explicitly checking for
1224 // this, the Pix[i:] expression below can panic.
1230 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
1234 Rect
: p
.Rect
.Intersect(r
),
1239 // Opaque scans the entire image and reports whether it is fully opaque.
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
] {
1250 for i
, c
:= range p
.Palette
{
1254 _
, _
, _
, a
:= c
.RGBA()
1262 // NewPaletted returns a new Paletted image with the given width, height and
1264 func NewPaletted(r Rectangle
, p color
.Palette
) *Paletted
{
1266 Pix
: make([]uint8, pixelBufferLength(1, r
, "Paletted")),