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.
4
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.
19//
20// See "The Go image package" for more details:
21// http://golang.org/doc/articles/image_package.html
22package image
23
24import (
25	"image/color"
26)
27
28// Config holds an image's color model and dimensions.
29type Config struct {
30	ColorModel    color.Model
31	Width, Height int
32}
33
34// Image is a finite rectangular grid of color.Color values taken from a color
35// model.
36type 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
46}
47
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
52// undefined.
53type PalettedImage interface {
54	// ColorIndexAt returns the palette index of the pixel at (x, y).
55	ColorIndexAt(x, y int) uint8
56	Image
57}
58
59// RGBA is an in-memory image whose At method returns color.RGBA values.
60type RGBA struct {
61	// Pix holds the image's pixels, in R, G, B, A order. The pixel at
62	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
63	Pix []uint8
64	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
65	Stride int
66	// Rect is the image's bounds.
67	Rect Rectangle
68}
69
70func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
71
72func (p *RGBA) Bounds() Rectangle { return p.Rect }
73
74func (p *RGBA) At(x, y int) color.Color {
75	if !(Point{x, y}.In(p.Rect)) {
76		return color.RGBA{}
77	}
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]}
80}
81
82// PixOffset returns the index of the first element of Pix that corresponds to
83// the pixel at (x, y).
84func (p *RGBA) PixOffset(x, y int) int {
85	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
86}
87
88func (p *RGBA) Set(x, y int, c color.Color) {
89	if !(Point{x, y}.In(p.Rect)) {
90		return
91	}
92	i := p.PixOffset(x, y)
93	c1 := color.RGBAModel.Convert(c).(color.RGBA)
94	p.Pix[i+0] = c1.R
95	p.Pix[i+1] = c1.G
96	p.Pix[i+2] = c1.B
97	p.Pix[i+3] = c1.A
98}
99
100func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
101	if !(Point{x, y}.In(p.Rect)) {
102		return
103	}
104	i := p.PixOffset(x, y)
105	p.Pix[i+0] = c.R
106	p.Pix[i+1] = c.G
107	p.Pix[i+2] = c.B
108	p.Pix[i+3] = c.A
109}
110
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.
113func (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.
118	if r.Empty() {
119		return &RGBA{}
120	}
121	i := p.PixOffset(r.Min.X, r.Min.Y)
122	return &RGBA{
123		Pix:    p.Pix[i:],
124		Stride: p.Stride,
125		Rect:   r,
126	}
127}
128
129// Opaque scans the entire image and reports whether it is fully opaque.
130func (p *RGBA) Opaque() bool {
131	if p.Rect.Empty() {
132		return true
133	}
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 {
138				return false
139			}
140		}
141		i0 += p.Stride
142		i1 += p.Stride
143	}
144	return true
145}
146
147// NewRGBA returns a new RGBA with the given bounds.
148func 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}
152}
153
154// RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
155type RGBA64 struct {
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].
158	Pix []uint8
159	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
160	Stride int
161	// Rect is the image's bounds.
162	Rect Rectangle
163}
164
165func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
166
167func (p *RGBA64) Bounds() Rectangle { return p.Rect }
168
169func (p *RGBA64) At(x, y int) color.Color {
170	if !(Point{x, y}.In(p.Rect)) {
171		return color.RGBA64{}
172	}
173	i := p.PixOffset(x, y)
174	return color.RGBA64{
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]),
179	}
180}
181
182// PixOffset returns the index of the first element of Pix that corresponds to
183// the pixel at (x, y).
184func (p *RGBA64) PixOffset(x, y int) int {
185	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
186}
187
188func (p *RGBA64) Set(x, y int, c color.Color) {
189	if !(Point{x, y}.In(p.Rect)) {
190		return
191	}
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)
202}
203
204func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
205	if !(Point{x, y}.In(p.Rect)) {
206		return
207	}
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)
217}
218
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.
221func (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.
226	if r.Empty() {
227		return &RGBA64{}
228	}
229	i := p.PixOffset(r.Min.X, r.Min.Y)
230	return &RGBA64{
231		Pix:    p.Pix[i:],
232		Stride: p.Stride,
233		Rect:   r,
234	}
235}
236
237// Opaque scans the entire image and reports whether it is fully opaque.
238func (p *RGBA64) Opaque() bool {
239	if p.Rect.Empty() {
240		return true
241	}
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 {
246				return false
247			}
248		}
249		i0 += p.Stride
250		i1 += p.Stride
251	}
252	return true
253}
254
255// NewRGBA64 returns a new RGBA64 with the given bounds.
256func 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}
260}
261
262// NRGBA is an in-memory image whose At method returns color.NRGBA values.
263type NRGBA struct {
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].
266	Pix []uint8
267	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
268	Stride int
269	// Rect is the image's bounds.
270	Rect Rectangle
271}
272
273func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
274
275func (p *NRGBA) Bounds() Rectangle { return p.Rect }
276
277func (p *NRGBA) At(x, y int) color.Color {
278	if !(Point{x, y}.In(p.Rect)) {
279		return color.NRGBA{}
280	}
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]}
283}
284
285// PixOffset returns the index of the first element of Pix that corresponds to
286// the pixel at (x, y).
287func (p *NRGBA) PixOffset(x, y int) int {
288	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
289}
290
291func (p *NRGBA) Set(x, y int, c color.Color) {
292	if !(Point{x, y}.In(p.Rect)) {
293		return
294	}
295	i := p.PixOffset(x, y)
296	c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
297	p.Pix[i+0] = c1.R
298	p.Pix[i+1] = c1.G
299	p.Pix[i+2] = c1.B
300	p.Pix[i+3] = c1.A
301}
302
303func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
304	if !(Point{x, y}.In(p.Rect)) {
305		return
306	}
307	i := p.PixOffset(x, y)
308	p.Pix[i+0] = c.R
309	p.Pix[i+1] = c.G
310	p.Pix[i+2] = c.B
311	p.Pix[i+3] = c.A
312}
313
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.
316func (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.
321	if r.Empty() {
322		return &NRGBA{}
323	}
324	i := p.PixOffset(r.Min.X, r.Min.Y)
325	return &NRGBA{
326		Pix:    p.Pix[i:],
327		Stride: p.Stride,
328		Rect:   r,
329	}
330}
331
332// Opaque scans the entire image and reports whether it is fully opaque.
333func (p *NRGBA) Opaque() bool {
334	if p.Rect.Empty() {
335		return true
336	}
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 {
341				return false
342			}
343		}
344		i0 += p.Stride
345		i1 += p.Stride
346	}
347	return true
348}
349
350// NewNRGBA returns a new NRGBA with the given bounds.
351func 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}
355}
356
357// NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
358type 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].
361	Pix []uint8
362	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
363	Stride int
364	// Rect is the image's bounds.
365	Rect Rectangle
366}
367
368func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
369
370func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
371
372func (p *NRGBA64) At(x, y int) color.Color {
373	if !(Point{x, y}.In(p.Rect)) {
374		return color.NRGBA64{}
375	}
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]),
382	}
383}
384
385// PixOffset returns the index of the first element of Pix that corresponds to
386// the pixel at (x, y).
387func (p *NRGBA64) PixOffset(x, y int) int {
388	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
389}
390
391func (p *NRGBA64) Set(x, y int, c color.Color) {
392	if !(Point{x, y}.In(p.Rect)) {
393		return
394	}
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)
405}
406
407func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
408	if !(Point{x, y}.In(p.Rect)) {
409		return
410	}
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)
420}
421
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.
424func (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.
429	if r.Empty() {
430		return &NRGBA64{}
431	}
432	i := p.PixOffset(r.Min.X, r.Min.Y)
433	return &NRGBA64{
434		Pix:    p.Pix[i:],
435		Stride: p.Stride,
436		Rect:   r,
437	}
438}
439
440// Opaque scans the entire image and reports whether it is fully opaque.
441func (p *NRGBA64) Opaque() bool {
442	if p.Rect.Empty() {
443		return true
444	}
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 {
449				return false
450			}
451		}
452		i0 += p.Stride
453		i1 += p.Stride
454	}
455	return true
456}
457
458// NewNRGBA64 returns a new NRGBA64 with the given bounds.
459func 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}
463}
464
465// Alpha is an in-memory image whose At method returns color.Alpha values.
466type Alpha struct {
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].
469	Pix []uint8
470	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
471	Stride int
472	// Rect is the image's bounds.
473	Rect Rectangle
474}
475
476func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
477
478func (p *Alpha) Bounds() Rectangle { return p.Rect }
479
480func (p *Alpha) At(x, y int) color.Color {
481	if !(Point{x, y}.In(p.Rect)) {
482		return color.Alpha{}
483	}
484	i := p.PixOffset(x, y)
485	return color.Alpha{p.Pix[i]}
486}
487
488// PixOffset returns the index of the first element of Pix that corresponds to
489// the pixel at (x, y).
490func (p *Alpha) PixOffset(x, y int) int {
491	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
492}
493
494func (p *Alpha) Set(x, y int, c color.Color) {
495	if !(Point{x, y}.In(p.Rect)) {
496		return
497	}
498	i := p.PixOffset(x, y)
499	p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
500}
501
502func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
503	if !(Point{x, y}.In(p.Rect)) {
504		return
505	}
506	i := p.PixOffset(x, y)
507	p.Pix[i] = c.A
508}
509
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.
512func (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.
517	if r.Empty() {
518		return &Alpha{}
519	}
520	i := p.PixOffset(r.Min.X, r.Min.Y)
521	return &Alpha{
522		Pix:    p.Pix[i:],
523		Stride: p.Stride,
524		Rect:   r,
525	}
526}
527
528// Opaque scans the entire image and reports whether it is fully opaque.
529func (p *Alpha) Opaque() bool {
530	if p.Rect.Empty() {
531		return true
532	}
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 {
537				return false
538			}
539		}
540		i0 += p.Stride
541		i1 += p.Stride
542	}
543	return true
544}
545
546// NewAlpha returns a new Alpha with the given bounds.
547func 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}
551}
552
553// Alpha16 is an in-memory image whose At method returns color.Alpha64 values.
554type 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].
557	Pix []uint8
558	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
559	Stride int
560	// Rect is the image's bounds.
561	Rect Rectangle
562}
563
564func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
565
566func (p *Alpha16) Bounds() Rectangle { return p.Rect }
567
568func (p *Alpha16) At(x, y int) color.Color {
569	if !(Point{x, y}.In(p.Rect)) {
570		return color.Alpha16{}
571	}
572	i := p.PixOffset(x, y)
573	return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
574}
575
576// PixOffset returns the index of the first element of Pix that corresponds to
577// the pixel at (x, y).
578func (p *Alpha16) PixOffset(x, y int) int {
579	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
580}
581
582func (p *Alpha16) Set(x, y int, c color.Color) {
583	if !(Point{x, y}.In(p.Rect)) {
584		return
585	}
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)
590}
591
592func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
593	if !(Point{x, y}.In(p.Rect)) {
594		return
595	}
596	i := p.PixOffset(x, y)
597	p.Pix[i+0] = uint8(c.A >> 8)
598	p.Pix[i+1] = uint8(c.A)
599}
600
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.
603func (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.
608	if r.Empty() {
609		return &Alpha16{}
610	}
611	i := p.PixOffset(r.Min.X, r.Min.Y)
612	return &Alpha16{
613		Pix:    p.Pix[i:],
614		Stride: p.Stride,
615		Rect:   r,
616	}
617}
618
619// Opaque scans the entire image and reports whether it is fully opaque.
620func (p *Alpha16) Opaque() bool {
621	if p.Rect.Empty() {
622		return true
623	}
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 {
628				return false
629			}
630		}
631		i0 += p.Stride
632		i1 += p.Stride
633	}
634	return true
635}
636
637// NewAlpha16 returns a new Alpha16 with the given bounds.
638func 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}
642}
643
644// Gray is an in-memory image whose At method returns color.Gray values.
645type Gray struct {
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].
648	Pix []uint8
649	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
650	Stride int
651	// Rect is the image's bounds.
652	Rect Rectangle
653}
654
655func (p *Gray) ColorModel() color.Model { return color.GrayModel }
656
657func (p *Gray) Bounds() Rectangle { return p.Rect }
658
659func (p *Gray) At(x, y int) color.Color {
660	if !(Point{x, y}.In(p.Rect)) {
661		return color.Gray{}
662	}
663	i := p.PixOffset(x, y)
664	return color.Gray{p.Pix[i]}
665}
666
667// PixOffset returns the index of the first element of Pix that corresponds to
668// the pixel at (x, y).
669func (p *Gray) PixOffset(x, y int) int {
670	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
671}
672
673func (p *Gray) Set(x, y int, c color.Color) {
674	if !(Point{x, y}.In(p.Rect)) {
675		return
676	}
677	i := p.PixOffset(x, y)
678	p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
679}
680
681func (p *Gray) SetGray(x, y int, c color.Gray) {
682	if !(Point{x, y}.In(p.Rect)) {
683		return
684	}
685	i := p.PixOffset(x, y)
686	p.Pix[i] = c.Y
687}
688
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.
691func (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.
696	if r.Empty() {
697		return &Gray{}
698	}
699	i := p.PixOffset(r.Min.X, r.Min.Y)
700	return &Gray{
701		Pix:    p.Pix[i:],
702		Stride: p.Stride,
703		Rect:   r,
704	}
705}
706
707// Opaque scans the entire image and reports whether it is fully opaque.
708func (p *Gray) Opaque() bool {
709	return true
710}
711
712// NewGray returns a new Gray with the given bounds.
713func 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}
717}
718
719// Gray16 is an in-memory image whose At method returns color.Gray16 values.
720type Gray16 struct {
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].
723	Pix []uint8
724	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
725	Stride int
726	// Rect is the image's bounds.
727	Rect Rectangle
728}
729
730func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
731
732func (p *Gray16) Bounds() Rectangle { return p.Rect }
733
734func (p *Gray16) At(x, y int) color.Color {
735	if !(Point{x, y}.In(p.Rect)) {
736		return color.Gray16{}
737	}
738	i := p.PixOffset(x, y)
739	return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
740}
741
742// PixOffset returns the index of the first element of Pix that corresponds to
743// the pixel at (x, y).
744func (p *Gray16) PixOffset(x, y int) int {
745	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
746}
747
748func (p *Gray16) Set(x, y int, c color.Color) {
749	if !(Point{x, y}.In(p.Rect)) {
750		return
751	}
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)
756}
757
758func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
759	if !(Point{x, y}.In(p.Rect)) {
760		return
761	}
762	i := p.PixOffset(x, y)
763	p.Pix[i+0] = uint8(c.Y >> 8)
764	p.Pix[i+1] = uint8(c.Y)
765}
766
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.
769func (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.
774	if r.Empty() {
775		return &Gray16{}
776	}
777	i := p.PixOffset(r.Min.X, r.Min.Y)
778	return &Gray16{
779		Pix:    p.Pix[i:],
780		Stride: p.Stride,
781		Rect:   r,
782	}
783}
784
785// Opaque scans the entire image and reports whether it is fully opaque.
786func (p *Gray16) Opaque() bool {
787	return true
788}
789
790// NewGray16 returns a new Gray16 with the given bounds.
791func 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}
795}
796
797// Paletted is an in-memory image of uint8 indices into a given palette.
798type 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].
801	Pix []uint8
802	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
803	Stride int
804	// Rect is the image's bounds.
805	Rect Rectangle
806	// Palette is the image's palette.
807	Palette color.Palette
808}
809
810func (p *Paletted) ColorModel() color.Model { return p.Palette }
811
812func (p *Paletted) Bounds() Rectangle { return p.Rect }
813
814func (p *Paletted) At(x, y int) color.Color {
815	if len(p.Palette) == 0 {
816		return nil
817	}
818	if !(Point{x, y}.In(p.Rect)) {
819		return p.Palette[0]
820	}
821	i := p.PixOffset(x, y)
822	return p.Palette[p.Pix[i]]
823}
824
825// PixOffset returns the index of the first element of Pix that corresponds to
826// the pixel at (x, y).
827func (p *Paletted) PixOffset(x, y int) int {
828	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
829}
830
831func (p *Paletted) Set(x, y int, c color.Color) {
832	if !(Point{x, y}.In(p.Rect)) {
833		return
834	}
835	i := p.PixOffset(x, y)
836	p.Pix[i] = uint8(p.Palette.Index(c))
837}
838
839func (p *Paletted) ColorIndexAt(x, y int) uint8 {
840	if !(Point{x, y}.In(p.Rect)) {
841		return 0
842	}
843	i := p.PixOffset(x, y)
844	return p.Pix[i]
845}
846
847func (p *Paletted) SetColorIndex(x, y int, index uint8) {
848	if !(Point{x, y}.In(p.Rect)) {
849		return
850	}
851	i := p.PixOffset(x, y)
852	p.Pix[i] = index
853}
854
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.
857func (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.
862	if r.Empty() {
863		return &Paletted{
864			Palette: p.Palette,
865		}
866	}
867	i := p.PixOffset(r.Min.X, r.Min.Y)
868	return &Paletted{
869		Pix:     p.Pix[i:],
870		Stride:  p.Stride,
871		Rect:    p.Rect.Intersect(r),
872		Palette: p.Palette,
873	}
874}
875
876// Opaque scans the entire image and reports whether it is fully opaque.
877func (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] {
882			present[c] = true
883		}
884		i0 += p.Stride
885		i1 += p.Stride
886	}
887	for i, c := range p.Palette {
888		if !present[i] {
889			continue
890		}
891		_, _, _, a := c.RGBA()
892		if a != 0xffff {
893			return false
894		}
895	}
896	return true
897}
898
899// NewPaletted returns a new Paletted with the given width, height and palette.
900func 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}
904}
905