Avoid undefined behaviour in build_option_suggestions
[official-gcc.git] / libgo / go / image / image.go
blob930d9ac6c7bacdb9c98dfa2a7500e565cb42fd2e
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 // RGBA64Image is an Image whose pixels can be converted directly to a
49 // color.RGBA64.
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
56 Image
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
63 // undefined.
64 type PalettedImage interface {
65 // ColorIndexAt returns the palette index of the pixel at (x, y).
66 ColorIndexAt(x, y int) uint8
67 Image
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())
79 if totalLength < 0 {
80 panic("image: New" + imageTypeName + " Rectangle has huge or negative dimensions")
82 return totalLength
85 // RGBA is an in-memory image whose At method returns color.RGBA values.
86 type RGBA struct {
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].
89 Pix []uint8
90 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
91 Stride int
92 // Rect is the image's bounds.
93 Rect Rectangle
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
110 r := uint16(s[0])
111 g := uint16(s[1])
112 b := uint16(s[2])
113 a := uint16(s[3])
114 return color.RGBA64{
115 (r << 8) | r,
116 (g << 8) | g,
117 (b << 8) | b,
118 (a << 8) | a,
122 func (p *RGBA) RGBAAt(x, y int) color.RGBA {
123 if !(Point{x, y}.In(p.Rect)) {
124 return color.RGBA{}
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)) {
139 return
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
144 s[0] = c1.R
145 s[1] = c1.G
146 s[2] = c1.B
147 s[3] = c1.A
150 func (p *RGBA) SetRGBA64(x, y int, c color.RGBA64) {
151 if !(Point{x, y}.In(p.Rect)) {
152 return
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)) {
164 return
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
168 s[0] = c.R
169 s[1] = c.G
170 s[2] = c.B
171 s[3] = c.A
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.
181 if r.Empty() {
182 return &RGBA{}
184 i := p.PixOffset(r.Min.X, r.Min.Y)
185 return &RGBA{
186 Pix: p.Pix[i:],
187 Stride: p.Stride,
188 Rect: r,
192 // Opaque scans the entire image and reports whether it is fully opaque.
193 func (p *RGBA) Opaque() bool {
194 if p.Rect.Empty() {
195 return true
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 {
201 return false
204 i0 += p.Stride
205 i1 += p.Stride
207 return true
210 // NewRGBA returns a new RGBA image with the given bounds.
211 func NewRGBA(r Rectangle) *RGBA {
212 return &RGBA{
213 Pix: make([]uint8, pixelBufferLength(4, r, "RGBA")),
214 Stride: 4 * r.Dx(),
215 Rect: r,
219 // RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
220 type RGBA64 struct {
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].
223 Pix []uint8
224 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
225 Stride int
226 // Rect is the image's bounds.
227 Rect Rectangle
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
244 return color.RGBA64{
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)) {
260 return
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)
266 s[1] = uint8(c1.R)
267 s[2] = uint8(c1.G >> 8)
268 s[3] = uint8(c1.G)
269 s[4] = uint8(c1.B >> 8)
270 s[5] = uint8(c1.B)
271 s[6] = uint8(c1.A >> 8)
272 s[7] = uint8(c1.A)
275 func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
276 if !(Point{x, y}.In(p.Rect)) {
277 return
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)
282 s[1] = uint8(c.R)
283 s[2] = uint8(c.G >> 8)
284 s[3] = uint8(c.G)
285 s[4] = uint8(c.B >> 8)
286 s[5] = uint8(c.B)
287 s[6] = uint8(c.A >> 8)
288 s[7] = uint8(c.A)
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.
298 if r.Empty() {
299 return &RGBA64{}
301 i := p.PixOffset(r.Min.X, r.Min.Y)
302 return &RGBA64{
303 Pix: p.Pix[i:],
304 Stride: p.Stride,
305 Rect: r,
309 // Opaque scans the entire image and reports whether it is fully opaque.
310 func (p *RGBA64) Opaque() bool {
311 if p.Rect.Empty() {
312 return true
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 {
318 return false
321 i0 += p.Stride
322 i1 += p.Stride
324 return true
327 // NewRGBA64 returns a new RGBA64 image with the given bounds.
328 func NewRGBA64(r Rectangle) *RGBA64 {
329 return &RGBA64{
330 Pix: make([]uint8, pixelBufferLength(8, r, "RGBA64")),
331 Stride: 8 * r.Dx(),
332 Rect: r,
336 // NRGBA is an in-memory image whose At method returns color.NRGBA values.
337 type NRGBA struct {
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].
340 Pix []uint8
341 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
342 Stride int
343 // Rect is the image's bounds.
344 Rect Rectangle
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)) {
362 return color.NRGBA{}
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)) {
377 return
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
382 s[0] = c1.R
383 s[1] = c1.G
384 s[2] = c1.B
385 s[3] = c1.A
388 func (p *NRGBA) SetRGBA64(x, y int, c color.RGBA64) {
389 if !(Point{x, y}.In(p.Rect)) {
390 return
392 r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
393 if (a != 0) && (a != 0xffff) {
394 r = (r * 0xffff) / a
395 g = (g * 0xffff) / a
396 b = (b * 0xffff) / a
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
400 s[0] = uint8(r >> 8)
401 s[1] = uint8(g >> 8)
402 s[2] = uint8(b >> 8)
403 s[3] = uint8(a >> 8)
406 func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
407 if !(Point{x, y}.In(p.Rect)) {
408 return
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
412 s[0] = c.R
413 s[1] = c.G
414 s[2] = c.B
415 s[3] = c.A
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.
425 if r.Empty() {
426 return &NRGBA{}
428 i := p.PixOffset(r.Min.X, r.Min.Y)
429 return &NRGBA{
430 Pix: p.Pix[i:],
431 Stride: p.Stride,
432 Rect: r,
436 // Opaque scans the entire image and reports whether it is fully opaque.
437 func (p *NRGBA) Opaque() bool {
438 if p.Rect.Empty() {
439 return true
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 {
445 return false
448 i0 += p.Stride
449 i1 += p.Stride
451 return true
454 // NewNRGBA returns a new NRGBA image with the given bounds.
455 func NewNRGBA(r Rectangle) *NRGBA {
456 return &NRGBA{
457 Pix: make([]uint8, pixelBufferLength(4, r, "NRGBA")),
458 Stride: 4 * r.Dx(),
459 Rect: r,
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].
467 Pix []uint8
468 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
469 Stride int
470 // Rect is the image's bounds.
471 Rect Rectangle
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)) {
509 return
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)
515 s[1] = uint8(c1.R)
516 s[2] = uint8(c1.G >> 8)
517 s[3] = uint8(c1.G)
518 s[4] = uint8(c1.B >> 8)
519 s[5] = uint8(c1.B)
520 s[6] = uint8(c1.A >> 8)
521 s[7] = uint8(c1.A)
524 func (p *NRGBA64) SetRGBA64(x, y int, c color.RGBA64) {
525 if !(Point{x, y}.In(p.Rect)) {
526 return
528 r, g, b, a := uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
529 if (a != 0) && (a != 0xffff) {
530 r = (r * 0xffff) / a
531 g = (g * 0xffff) / a
532 b = (b * 0xffff) / a
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
536 s[0] = uint8(r >> 8)
537 s[1] = uint8(r)
538 s[2] = uint8(g >> 8)
539 s[3] = uint8(g)
540 s[4] = uint8(b >> 8)
541 s[5] = uint8(b)
542 s[6] = uint8(a >> 8)
543 s[7] = uint8(a)
546 func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
547 if !(Point{x, y}.In(p.Rect)) {
548 return
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)
553 s[1] = uint8(c.R)
554 s[2] = uint8(c.G >> 8)
555 s[3] = uint8(c.G)
556 s[4] = uint8(c.B >> 8)
557 s[5] = uint8(c.B)
558 s[6] = uint8(c.A >> 8)
559 s[7] = uint8(c.A)
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.
569 if r.Empty() {
570 return &NRGBA64{}
572 i := p.PixOffset(r.Min.X, r.Min.Y)
573 return &NRGBA64{
574 Pix: p.Pix[i:],
575 Stride: p.Stride,
576 Rect: r,
580 // Opaque scans the entire image and reports whether it is fully opaque.
581 func (p *NRGBA64) Opaque() bool {
582 if p.Rect.Empty() {
583 return true
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 {
589 return false
592 i0 += p.Stride
593 i1 += p.Stride
595 return true
598 // NewNRGBA64 returns a new NRGBA64 image with the given bounds.
599 func NewNRGBA64(r Rectangle) *NRGBA64 {
600 return &NRGBA64{
601 Pix: make([]uint8, pixelBufferLength(8, r, "NRGBA64")),
602 Stride: 8 * r.Dx(),
603 Rect: r,
607 // Alpha is an in-memory image whose At method returns color.Alpha values.
608 type Alpha struct {
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].
611 Pix []uint8
612 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
613 Stride int
614 // Rect is the image's bounds.
615 Rect Rectangle
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)
628 a |= a << 8
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)) {
634 return color.Alpha{}
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)) {
648 return
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)) {
656 return
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)) {
664 return
666 i := p.PixOffset(x, y)
667 p.Pix[i] = c.A
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.
677 if r.Empty() {
678 return &Alpha{}
680 i := p.PixOffset(r.Min.X, r.Min.Y)
681 return &Alpha{
682 Pix: p.Pix[i:],
683 Stride: p.Stride,
684 Rect: r,
688 // Opaque scans the entire image and reports whether it is fully opaque.
689 func (p *Alpha) Opaque() bool {
690 if p.Rect.Empty() {
691 return true
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 {
697 return false
700 i0 += p.Stride
701 i1 += p.Stride
703 return true
706 // NewAlpha returns a new Alpha image with the given bounds.
707 func NewAlpha(r Rectangle) *Alpha {
708 return &Alpha{
709 Pix: make([]uint8, pixelBufferLength(1, r, "Alpha")),
710 Stride: 1 * r.Dx(),
711 Rect: r,
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].
719 Pix []uint8
720 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
721 Stride int
722 // Rect is the image's bounds.
723 Rect Rectangle
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)) {
755 return
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)) {
765 return
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)) {
774 return
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.
788 if r.Empty() {
789 return &Alpha16{}
791 i := p.PixOffset(r.Min.X, r.Min.Y)
792 return &Alpha16{
793 Pix: p.Pix[i:],
794 Stride: p.Stride,
795 Rect: r,
799 // Opaque scans the entire image and reports whether it is fully opaque.
800 func (p *Alpha16) Opaque() bool {
801 if p.Rect.Empty() {
802 return true
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 {
808 return false
811 i0 += p.Stride
812 i1 += p.Stride
814 return true
817 // NewAlpha16 returns a new Alpha16 image with the given bounds.
818 func NewAlpha16(r Rectangle) *Alpha16 {
819 return &Alpha16{
820 Pix: make([]uint8, pixelBufferLength(2, r, "Alpha16")),
821 Stride: 2 * r.Dx(),
822 Rect: r,
826 // Gray is an in-memory image whose At method returns color.Gray values.
827 type Gray struct {
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].
830 Pix []uint8
831 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
832 Stride int
833 // Rect is the image's bounds.
834 Rect Rectangle
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)
847 gray |= gray << 8
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)) {
853 return color.Gray{}
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)) {
867 return
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)) {
875 return
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)) {
885 return
887 i := p.PixOffset(x, y)
888 p.Pix[i] = c.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.
898 if r.Empty() {
899 return &Gray{}
901 i := p.PixOffset(r.Min.X, r.Min.Y)
902 return &Gray{
903 Pix: p.Pix[i:],
904 Stride: p.Stride,
905 Rect: r,
909 // Opaque scans the entire image and reports whether it is fully opaque.
910 func (p *Gray) Opaque() bool {
911 return true
914 // NewGray returns a new Gray image with the given bounds.
915 func NewGray(r Rectangle) *Gray {
916 return &Gray{
917 Pix: make([]uint8, pixelBufferLength(1, r, "Gray")),
918 Stride: 1 * r.Dx(),
919 Rect: r,
923 // Gray16 is an in-memory image whose At method returns color.Gray16 values.
924 type Gray16 struct {
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].
927 Pix []uint8
928 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
929 Stride int
930 // Rect is the image's bounds.
931 Rect Rectangle
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)) {
963 return
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)) {
973 return
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)) {
984 return
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.
998 if r.Empty() {
999 return &Gray16{}
1001 i := p.PixOffset(r.Min.X, r.Min.Y)
1002 return &Gray16{
1003 Pix: p.Pix[i:],
1004 Stride: p.Stride,
1005 Rect: r,
1009 // Opaque scans the entire image and reports whether it is fully opaque.
1010 func (p *Gray16) Opaque() bool {
1011 return true
1014 // NewGray16 returns a new Gray16 image with the given bounds.
1015 func NewGray16(r Rectangle) *Gray16 {
1016 return &Gray16{
1017 Pix: make([]uint8, pixelBufferLength(2, r, "Gray16")),
1018 Stride: 2 * r.Dx(),
1019 Rect: r,
1023 // CMYK is an in-memory image whose At method returns color.CMYK values.
1024 type CMYK struct {
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].
1027 Pix []uint8
1028 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
1029 Stride int
1030 // Rect is the image's bounds.
1031 Rect Rectangle
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)) {
1049 return color.CMYK{}
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)) {
1064 return
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
1069 s[0] = c1.C
1070 s[1] = c1.M
1071 s[2] = c1.Y
1072 s[3] = c1.K
1075 func (p *CMYK) SetRGBA64(x, y int, c color.RGBA64) {
1076 if !(Point{x, y}.In(p.Rect)) {
1077 return
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
1082 s[0] = cc
1083 s[1] = mm
1084 s[2] = yy
1085 s[3] = kk
1088 func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
1089 if !(Point{x, y}.In(p.Rect)) {
1090 return
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
1094 s[0] = c.C
1095 s[1] = c.M
1096 s[2] = c.Y
1097 s[3] = c.K
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.
1107 if r.Empty() {
1108 return &CMYK{}
1110 i := p.PixOffset(r.Min.X, r.Min.Y)
1111 return &CMYK{
1112 Pix: p.Pix[i:],
1113 Stride: p.Stride,
1114 Rect: r,
1118 // Opaque scans the entire image and reports whether it is fully opaque.
1119 func (p *CMYK) Opaque() bool {
1120 return true
1123 // NewCMYK returns a new CMYK image with the given bounds.
1124 func NewCMYK(r Rectangle) *CMYK {
1125 return &CMYK{
1126 Pix: make([]uint8, pixelBufferLength(4, r, "CMYK")),
1127 Stride: 4 * r.Dx(),
1128 Rect: r,
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].
1136 Pix []uint8
1137 // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
1138 Stride int
1139 // Rect is the image's bounds.
1140 Rect Rectangle
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 {
1151 return nil
1153 if !(Point{x, y}.In(p.Rect)) {
1154 return p.Palette[0]
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)) {
1166 c = p.Palette[0]
1167 } else {
1168 i := p.PixOffset(x, y)
1169 c = p.Palette[p.Pix[i]]
1171 r, g, b, a := c.RGBA()
1172 return color.RGBA64{
1173 uint16(r),
1174 uint16(g),
1175 uint16(b),
1176 uint16(a),
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)) {
1188 return
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)) {
1196 return
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)) {
1204 return 0
1206 i := p.PixOffset(x, y)
1207 return p.Pix[i]
1210 func (p *Paletted) SetColorIndex(x, y int, index uint8) {
1211 if !(Point{x, y}.In(p.Rect)) {
1212 return
1214 i := p.PixOffset(x, y)
1215 p.Pix[i] = index
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.
1225 if r.Empty() {
1226 return &Paletted{
1227 Palette: p.Palette,
1230 i := p.PixOffset(r.Min.X, r.Min.Y)
1231 return &Paletted{
1232 Pix: p.Pix[i:],
1233 Stride: p.Stride,
1234 Rect: p.Rect.Intersect(r),
1235 Palette: p.Palette,
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] {
1245 present[c] = true
1247 i0 += p.Stride
1248 i1 += p.Stride
1250 for i, c := range p.Palette {
1251 if !present[i] {
1252 continue
1254 _, _, _, a := c.RGBA()
1255 if a != 0xffff {
1256 return false
1259 return true
1262 // NewPaletted returns a new Paletted image with the given width, height and
1263 // palette.
1264 func NewPaletted(r Rectangle, p color.Palette) *Paletted {
1265 return &Paletted{
1266 Pix: make([]uint8, pixelBufferLength(1, r, "Paletted")),
1267 Stride: 1 * r.Dx(),
1268 Rect: r,
1269 Palette: p,