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 // http://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 PalettedColorModel 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 PalettedColorModel, 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
{
75 if !(Point
{x
, y
}.In(p
.Rect
)) {
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]}
82 // PixOffset returns the index of the first element of Pix that corresponds to
83 // the pixel at (x, y).
84 func (p
*RGBA
) PixOffset(x
, y
int) int {
85 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*4
88 func (p
*RGBA
) Set(x
, y
int, c color
.Color
) {
89 if !(Point
{x
, y
}.In(p
.Rect
)) {
92 i
:= p
.PixOffset(x
, y
)
93 c1
:= color
.RGBAModel
.Convert(c
).(color
.RGBA
)
100 func (p
*RGBA
) SetRGBA(x
, y
int, c color
.RGBA
) {
101 if !(Point
{x
, y
}.In(p
.Rect
)) {
104 i
:= p
.PixOffset(x
, y
)
111 // SubImage returns an image representing the portion of the image p visible
112 // through r. The returned value shares pixels with the original image.
113 func (p
*RGBA
) SubImage(r Rectangle
) Image
{
114 r
= r
.Intersect(p
.Rect
)
115 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
116 // either r1 or r2 if the intersection is empty. Without explicitly checking for
117 // this, the Pix[i:] expression below can panic.
121 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
129 // Opaque scans the entire image and reports whether it is fully opaque.
130 func (p
*RGBA
) Opaque() bool {
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 {
147 // NewRGBA returns a new RGBA with the given bounds.
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
}
154 // RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
156 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
157 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
159 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
161 // Rect is the image's bounds.
165 func (p
*RGBA64
) ColorModel() color
.Model
{ return color
.RGBA64Model
}
167 func (p
*RGBA64
) Bounds() Rectangle
{ return p
.Rect
}
169 func (p
*RGBA64
) At(x
, y
int) color
.Color
{
170 if !(Point
{x
, y
}.In(p
.Rect
)) {
171 return color
.RGBA64
{}
173 i
:= p
.PixOffset(x
, y
)
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]),
182 // PixOffset returns the index of the first element of Pix that corresponds to
183 // the pixel at (x, y).
184 func (p
*RGBA64
) PixOffset(x
, y
int) int {
185 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*8
188 func (p
*RGBA64
) Set(x
, y
int, c color
.Color
) {
189 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
204 func (p
*RGBA64
) SetRGBA64(x
, y
int, c color
.RGBA64
) {
205 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
219 // SubImage returns an image representing the portion of the image p visible
220 // through r. The returned value shares pixels with the original image.
221 func (p
*RGBA64
) SubImage(r Rectangle
) Image
{
222 r
= r
.Intersect(p
.Rect
)
223 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
224 // either r1 or r2 if the intersection is empty. Without explicitly checking for
225 // this, the Pix[i:] expression below can panic.
229 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
237 // Opaque scans the entire image and reports whether it is fully opaque.
238 func (p
*RGBA64
) Opaque() bool {
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 {
255 // NewRGBA64 returns a new RGBA64 with the given bounds.
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
}
262 // NRGBA is an in-memory image whose At method returns color.NRGBA values.
264 // Pix holds the image's pixels, in R, G, B, A order. The pixel at
265 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
267 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
269 // Rect is the image's bounds.
273 func (p
*NRGBA
) ColorModel() color
.Model
{ return color
.NRGBAModel
}
275 func (p
*NRGBA
) Bounds() Rectangle
{ return p
.Rect
}
277 func (p
*NRGBA
) At(x
, y
int) color
.Color
{
278 if !(Point
{x
, y
}.In(p
.Rect
)) {
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]}
285 // PixOffset returns the index of the first element of Pix that corresponds to
286 // the pixel at (x, y).
287 func (p
*NRGBA
) PixOffset(x
, y
int) int {
288 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*4
291 func (p
*NRGBA
) Set(x
, y
int, c color
.Color
) {
292 if !(Point
{x
, y
}.In(p
.Rect
)) {
295 i
:= p
.PixOffset(x
, y
)
296 c1
:= color
.NRGBAModel
.Convert(c
).(color
.NRGBA
)
303 func (p
*NRGBA
) SetNRGBA(x
, y
int, c color
.NRGBA
) {
304 if !(Point
{x
, y
}.In(p
.Rect
)) {
307 i
:= p
.PixOffset(x
, y
)
314 // SubImage returns an image representing the portion of the image p visible
315 // through r. The returned value shares pixels with the original image.
316 func (p
*NRGBA
) SubImage(r Rectangle
) Image
{
317 r
= r
.Intersect(p
.Rect
)
318 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
319 // either r1 or r2 if the intersection is empty. Without explicitly checking for
320 // this, the Pix[i:] expression below can panic.
324 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
332 // Opaque scans the entire image and reports whether it is fully opaque.
333 func (p
*NRGBA
) Opaque() bool {
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 {
350 // NewNRGBA returns a new NRGBA with the given bounds.
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
}
357 // NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
358 type NRGBA64
struct {
359 // Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
360 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
362 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
364 // Rect is the image's bounds.
368 func (p
*NRGBA64
) ColorModel() color
.Model
{ return color
.NRGBA64Model
}
370 func (p
*NRGBA64
) Bounds() Rectangle
{ return p
.Rect
}
372 func (p
*NRGBA64
) At(x
, y
int) color
.Color
{
373 if !(Point
{x
, y
}.In(p
.Rect
)) {
374 return color
.NRGBA64
{}
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]),
385 // PixOffset returns the index of the first element of Pix that corresponds to
386 // the pixel at (x, y).
387 func (p
*NRGBA64
) PixOffset(x
, y
int) int {
388 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*8
391 func (p
*NRGBA64
) Set(x
, y
int, c color
.Color
) {
392 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
407 func (p
*NRGBA64
) SetNRGBA64(x
, y
int, c color
.NRGBA64
) {
408 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
422 // SubImage returns an image representing the portion of the image p visible
423 // through r. The returned value shares pixels with the original image.
424 func (p
*NRGBA64
) SubImage(r Rectangle
) Image
{
425 r
= r
.Intersect(p
.Rect
)
426 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
427 // either r1 or r2 if the intersection is empty. Without explicitly checking for
428 // this, the Pix[i:] expression below can panic.
432 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
440 // Opaque scans the entire image and reports whether it is fully opaque.
441 func (p
*NRGBA64
) Opaque() bool {
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 {
458 // NewNRGBA64 returns a new NRGBA64 with the given bounds.
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
}
465 // Alpha is an in-memory image whose At method returns color.Alpha values.
467 // Pix holds the image's pixels, as alpha values. The pixel at
468 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
470 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
472 // Rect is the image's bounds.
476 func (p
*Alpha
) ColorModel() color
.Model
{ return color
.AlphaModel
}
478 func (p
*Alpha
) Bounds() Rectangle
{ return p
.Rect
}
480 func (p
*Alpha
) At(x
, y
int) color
.Color
{
481 if !(Point
{x
, y
}.In(p
.Rect
)) {
484 i
:= p
.PixOffset(x
, y
)
485 return color
.Alpha
{p
.Pix
[i
]}
488 // PixOffset returns the index of the first element of Pix that corresponds to
489 // the pixel at (x, y).
490 func (p
*Alpha
) PixOffset(x
, y
int) int {
491 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*1
494 func (p
*Alpha
) Set(x
, y
int, c color
.Color
) {
495 if !(Point
{x
, y
}.In(p
.Rect
)) {
498 i
:= p
.PixOffset(x
, y
)
499 p
.Pix
[i
] = color
.AlphaModel
.Convert(c
).(color
.Alpha
).A
502 func (p
*Alpha
) SetAlpha(x
, y
int, c color
.Alpha
) {
503 if !(Point
{x
, y
}.In(p
.Rect
)) {
506 i
:= p
.PixOffset(x
, y
)
510 // SubImage returns an image representing the portion of the image p visible
511 // through r. The returned value shares pixels with the original image.
512 func (p
*Alpha
) SubImage(r Rectangle
) Image
{
513 r
= r
.Intersect(p
.Rect
)
514 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
515 // either r1 or r2 if the intersection is empty. Without explicitly checking for
516 // this, the Pix[i:] expression below can panic.
520 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
528 // Opaque scans the entire image and reports whether it is fully opaque.
529 func (p
*Alpha
) Opaque() bool {
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 {
546 // NewAlpha returns a new Alpha with the given bounds.
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
}
553 // Alpha16 is an in-memory image whose At method returns color.Alpha64 values.
554 type Alpha16
struct {
555 // Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
556 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
558 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
560 // Rect is the image's bounds.
564 func (p
*Alpha16
) ColorModel() color
.Model
{ return color
.Alpha16Model
}
566 func (p
*Alpha16
) Bounds() Rectangle
{ return p
.Rect
}
568 func (p
*Alpha16
) At(x
, y
int) color
.Color
{
569 if !(Point
{x
, y
}.In(p
.Rect
)) {
570 return color
.Alpha16
{}
572 i
:= p
.PixOffset(x
, y
)
573 return color
.Alpha16
{uint16(p
.Pix
[i
+0])<<8 |
uint16(p
.Pix
[i
+1])}
576 // PixOffset returns the index of the first element of Pix that corresponds to
577 // the pixel at (x, y).
578 func (p
*Alpha16
) PixOffset(x
, y
int) int {
579 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*2
582 func (p
*Alpha16
) Set(x
, y
int, c color
.Color
) {
583 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
592 func (p
*Alpha16
) SetAlpha16(x
, y
int, c color
.Alpha16
) {
593 if !(Point
{x
, y
}.In(p
.Rect
)) {
596 i
:= p
.PixOffset(x
, y
)
597 p
.Pix
[i
+0] = uint8(c
.A
>> 8)
598 p
.Pix
[i
+1] = uint8(c
.A
)
601 // SubImage returns an image representing the portion of the image p visible
602 // through r. The returned value shares pixels with the original image.
603 func (p
*Alpha16
) SubImage(r Rectangle
) Image
{
604 r
= r
.Intersect(p
.Rect
)
605 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
606 // either r1 or r2 if the intersection is empty. Without explicitly checking for
607 // this, the Pix[i:] expression below can panic.
611 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
619 // Opaque scans the entire image and reports whether it is fully opaque.
620 func (p
*Alpha16
) Opaque() bool {
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 {
637 // NewAlpha16 returns a new Alpha16 with the given bounds.
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
}
644 // Gray is an in-memory image whose At method returns color.Gray values.
646 // Pix holds the image's pixels, as gray values. The pixel at
647 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
649 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
651 // Rect is the image's bounds.
655 func (p
*Gray
) ColorModel() color
.Model
{ return color
.GrayModel
}
657 func (p
*Gray
) Bounds() Rectangle
{ return p
.Rect
}
659 func (p
*Gray
) At(x
, y
int) color
.Color
{
660 if !(Point
{x
, y
}.In(p
.Rect
)) {
663 i
:= p
.PixOffset(x
, y
)
664 return color
.Gray
{p
.Pix
[i
]}
667 // PixOffset returns the index of the first element of Pix that corresponds to
668 // the pixel at (x, y).
669 func (p
*Gray
) PixOffset(x
, y
int) int {
670 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*1
673 func (p
*Gray
) Set(x
, y
int, c color
.Color
) {
674 if !(Point
{x
, y
}.In(p
.Rect
)) {
677 i
:= p
.PixOffset(x
, y
)
678 p
.Pix
[i
] = color
.GrayModel
.Convert(c
).(color
.Gray
).Y
681 func (p
*Gray
) SetGray(x
, y
int, c color
.Gray
) {
682 if !(Point
{x
, y
}.In(p
.Rect
)) {
685 i
:= p
.PixOffset(x
, y
)
689 // SubImage returns an image representing the portion of the image p visible
690 // through r. The returned value shares pixels with the original image.
691 func (p
*Gray
) SubImage(r Rectangle
) Image
{
692 r
= r
.Intersect(p
.Rect
)
693 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
694 // either r1 or r2 if the intersection is empty. Without explicitly checking for
695 // this, the Pix[i:] expression below can panic.
699 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
707 // Opaque scans the entire image and reports whether it is fully opaque.
708 func (p
*Gray
) Opaque() bool {
712 // NewGray returns a new Gray with the given bounds.
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
}
719 // Gray16 is an in-memory image whose At method returns color.Gray16 values.
721 // Pix holds the image's pixels, as gray values in big-endian format. The pixel at
722 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
724 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
726 // Rect is the image's bounds.
730 func (p
*Gray16
) ColorModel() color
.Model
{ return color
.Gray16Model
}
732 func (p
*Gray16
) Bounds() Rectangle
{ return p
.Rect
}
734 func (p
*Gray16
) At(x
, y
int) color
.Color
{
735 if !(Point
{x
, y
}.In(p
.Rect
)) {
736 return color
.Gray16
{}
738 i
:= p
.PixOffset(x
, y
)
739 return color
.Gray16
{uint16(p
.Pix
[i
+0])<<8 |
uint16(p
.Pix
[i
+1])}
742 // PixOffset returns the index of the first element of Pix that corresponds to
743 // the pixel at (x, y).
744 func (p
*Gray16
) PixOffset(x
, y
int) int {
745 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*2
748 func (p
*Gray16
) Set(x
, y
int, c color
.Color
) {
749 if !(Point
{x
, y
}.In(p
.Rect
)) {
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
)
758 func (p
*Gray16
) SetGray16(x
, y
int, c color
.Gray16
) {
759 if !(Point
{x
, y
}.In(p
.Rect
)) {
762 i
:= p
.PixOffset(x
, y
)
763 p
.Pix
[i
+0] = uint8(c
.Y
>> 8)
764 p
.Pix
[i
+1] = uint8(c
.Y
)
767 // SubImage returns an image representing the portion of the image p visible
768 // through r. The returned value shares pixels with the original image.
769 func (p
*Gray16
) SubImage(r Rectangle
) Image
{
770 r
= r
.Intersect(p
.Rect
)
771 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
772 // either r1 or r2 if the intersection is empty. Without explicitly checking for
773 // this, the Pix[i:] expression below can panic.
777 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
785 // Opaque scans the entire image and reports whether it is fully opaque.
786 func (p
*Gray16
) Opaque() bool {
790 // NewGray16 returns a new Gray16 with the given bounds.
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
}
797 // Paletted is an in-memory image of uint8 indices into a given palette.
798 type Paletted
struct {
799 // Pix holds the image's pixels, as palette indices. The pixel at
800 // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
802 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
804 // Rect is the image's bounds.
806 // Palette is the image's palette.
807 Palette color
.Palette
810 func (p
*Paletted
) ColorModel() color
.Model
{ return p
.Palette
}
812 func (p
*Paletted
) Bounds() Rectangle
{ return p
.Rect
}
814 func (p
*Paletted
) At(x
, y
int) color
.Color
{
815 if len(p
.Palette
) == 0 {
818 if !(Point
{x
, y
}.In(p
.Rect
)) {
821 i
:= p
.PixOffset(x
, y
)
822 return p
.Palette
[p
.Pix
[i
]]
825 // PixOffset returns the index of the first element of Pix that corresponds to
826 // the pixel at (x, y).
827 func (p
*Paletted
) PixOffset(x
, y
int) int {
828 return (y
-p
.Rect
.Min
.Y
)*p
.Stride
+ (x
-p
.Rect
.Min
.X
)*1
831 func (p
*Paletted
) Set(x
, y
int, c color
.Color
) {
832 if !(Point
{x
, y
}.In(p
.Rect
)) {
835 i
:= p
.PixOffset(x
, y
)
836 p
.Pix
[i
] = uint8(p
.Palette
.Index(c
))
839 func (p
*Paletted
) ColorIndexAt(x
, y
int) uint8 {
840 if !(Point
{x
, y
}.In(p
.Rect
)) {
843 i
:= p
.PixOffset(x
, y
)
847 func (p
*Paletted
) SetColorIndex(x
, y
int, index
uint8) {
848 if !(Point
{x
, y
}.In(p
.Rect
)) {
851 i
:= p
.PixOffset(x
, y
)
855 // SubImage returns an image representing the portion of the image p visible
856 // through r. The returned value shares pixels with the original image.
857 func (p
*Paletted
) SubImage(r Rectangle
) Image
{
858 r
= r
.Intersect(p
.Rect
)
859 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
860 // either r1 or r2 if the intersection is empty. Without explicitly checking for
861 // this, the Pix[i:] expression below can panic.
867 i
:= p
.PixOffset(r
.Min
.X
, r
.Min
.Y
)
871 Rect
: p
.Rect
.Intersect(r
),
876 // Opaque scans the entire image and reports whether it is fully opaque.
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
] {
887 for i
, c
:= range p
.Palette
{
891 _
, _
, _
, a
:= c
.RGBA()
899 // NewPaletted returns a new Paletted with the given width, height and palette.
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
}