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// https://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 color.Palette p,
50// then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
51// color model is not a color.Palette, then ColorIndexAt's behavior is
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	return p.RGBAAt(x, y)
76}
77
78func (p *RGBA) RGBAAt(x, y int) color.RGBA {
79	if !(Point{x, y}.In(p.Rect)) {
80		return color.RGBA{}
81	}
82	i := p.PixOffset(x, y)
83	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
84	return color.RGBA{s[0], s[1], s[2], s[3]}
85}
86
87// PixOffset returns the index of the first element of Pix that corresponds to
88// the pixel at (x, y).
89func (p *RGBA) PixOffset(x, y int) int {
90	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
91}
92
93func (p *RGBA) Set(x, y int, c color.Color) {
94	if !(Point{x, y}.In(p.Rect)) {
95		return
96	}
97	i := p.PixOffset(x, y)
98	c1 := color.RGBAModel.Convert(c).(color.RGBA)
99	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
100	s[0] = c1.R
101	s[1] = c1.G
102	s[2] = c1.B
103	s[3] = c1.A
104}
105
106func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
107	if !(Point{x, y}.In(p.Rect)) {
108		return
109	}
110	i := p.PixOffset(x, y)
111	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
112	s[0] = c.R
113	s[1] = c.G
114	s[2] = c.B
115	s[3] = c.A
116}
117
118// SubImage returns an image representing the portion of the image p visible
119// through r. The returned value shares pixels with the original image.
120func (p *RGBA) SubImage(r Rectangle) Image {
121	r = r.Intersect(p.Rect)
122	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
123	// either r1 or r2 if the intersection is empty. Without explicitly checking for
124	// this, the Pix[i:] expression below can panic.
125	if r.Empty() {
126		return &RGBA{}
127	}
128	i := p.PixOffset(r.Min.X, r.Min.Y)
129	return &RGBA{
130		Pix:    p.Pix[i:],
131		Stride: p.Stride,
132		Rect:   r,
133	}
134}
135
136// Opaque scans the entire image and reports whether it is fully opaque.
137func (p *RGBA) Opaque() bool {
138	if p.Rect.Empty() {
139		return true
140	}
141	i0, i1 := 3, p.Rect.Dx()*4
142	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
143		for i := i0; i < i1; i += 4 {
144			if p.Pix[i] != 0xff {
145				return false
146			}
147		}
148		i0 += p.Stride
149		i1 += p.Stride
150	}
151	return true
152}
153
154// NewRGBA returns a new RGBA image with the given bounds.
155func NewRGBA(r Rectangle) *RGBA {
156	w, h := r.Dx(), r.Dy()
157	buf := make([]uint8, 4*w*h)
158	return &RGBA{buf, 4 * w, r}
159}
160
161// RGBA64 is an in-memory image whose At method returns color.RGBA64 values.
162type RGBA64 struct {
163	// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
164	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
165	Pix []uint8
166	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
167	Stride int
168	// Rect is the image's bounds.
169	Rect Rectangle
170}
171
172func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
173
174func (p *RGBA64) Bounds() Rectangle { return p.Rect }
175
176func (p *RGBA64) At(x, y int) color.Color {
177	return p.RGBA64At(x, y)
178}
179
180func (p *RGBA64) RGBA64At(x, y int) color.RGBA64 {
181	if !(Point{x, y}.In(p.Rect)) {
182		return color.RGBA64{}
183	}
184	i := p.PixOffset(x, y)
185	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
186	return color.RGBA64{
187		uint16(s[0])<<8 | uint16(s[1]),
188		uint16(s[2])<<8 | uint16(s[3]),
189		uint16(s[4])<<8 | uint16(s[5]),
190		uint16(s[6])<<8 | uint16(s[7]),
191	}
192}
193
194// PixOffset returns the index of the first element of Pix that corresponds to
195// the pixel at (x, y).
196func (p *RGBA64) PixOffset(x, y int) int {
197	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
198}
199
200func (p *RGBA64) Set(x, y int, c color.Color) {
201	if !(Point{x, y}.In(p.Rect)) {
202		return
203	}
204	i := p.PixOffset(x, y)
205	c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
206	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
207	s[0] = uint8(c1.R >> 8)
208	s[1] = uint8(c1.R)
209	s[2] = uint8(c1.G >> 8)
210	s[3] = uint8(c1.G)
211	s[4] = uint8(c1.B >> 8)
212	s[5] = uint8(c1.B)
213	s[6] = uint8(c1.A >> 8)
214	s[7] = uint8(c1.A)
215}
216
217func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
218	if !(Point{x, y}.In(p.Rect)) {
219		return
220	}
221	i := p.PixOffset(x, y)
222	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
223	s[0] = uint8(c.R >> 8)
224	s[1] = uint8(c.R)
225	s[2] = uint8(c.G >> 8)
226	s[3] = uint8(c.G)
227	s[4] = uint8(c.B >> 8)
228	s[5] = uint8(c.B)
229	s[6] = uint8(c.A >> 8)
230	s[7] = uint8(c.A)
231}
232
233// SubImage returns an image representing the portion of the image p visible
234// through r. The returned value shares pixels with the original image.
235func (p *RGBA64) SubImage(r Rectangle) Image {
236	r = r.Intersect(p.Rect)
237	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
238	// either r1 or r2 if the intersection is empty. Without explicitly checking for
239	// this, the Pix[i:] expression below can panic.
240	if r.Empty() {
241		return &RGBA64{}
242	}
243	i := p.PixOffset(r.Min.X, r.Min.Y)
244	return &RGBA64{
245		Pix:    p.Pix[i:],
246		Stride: p.Stride,
247		Rect:   r,
248	}
249}
250
251// Opaque scans the entire image and reports whether it is fully opaque.
252func (p *RGBA64) Opaque() bool {
253	if p.Rect.Empty() {
254		return true
255	}
256	i0, i1 := 6, p.Rect.Dx()*8
257	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
258		for i := i0; i < i1; i += 8 {
259			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
260				return false
261			}
262		}
263		i0 += p.Stride
264		i1 += p.Stride
265	}
266	return true
267}
268
269// NewRGBA64 returns a new RGBA64 image with the given bounds.
270func NewRGBA64(r Rectangle) *RGBA64 {
271	w, h := r.Dx(), r.Dy()
272	pix := make([]uint8, 8*w*h)
273	return &RGBA64{pix, 8 * w, r}
274}
275
276// NRGBA is an in-memory image whose At method returns color.NRGBA values.
277type NRGBA struct {
278	// Pix holds the image's pixels, in R, G, B, A order. The pixel at
279	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
280	Pix []uint8
281	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
282	Stride int
283	// Rect is the image's bounds.
284	Rect Rectangle
285}
286
287func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
288
289func (p *NRGBA) Bounds() Rectangle { return p.Rect }
290
291func (p *NRGBA) At(x, y int) color.Color {
292	return p.NRGBAAt(x, y)
293}
294
295func (p *NRGBA) NRGBAAt(x, y int) color.NRGBA {
296	if !(Point{x, y}.In(p.Rect)) {
297		return color.NRGBA{}
298	}
299	i := p.PixOffset(x, y)
300	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
301	return color.NRGBA{s[0], s[1], s[2], s[3]}
302}
303
304// PixOffset returns the index of the first element of Pix that corresponds to
305// the pixel at (x, y).
306func (p *NRGBA) PixOffset(x, y int) int {
307	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
308}
309
310func (p *NRGBA) Set(x, y int, c color.Color) {
311	if !(Point{x, y}.In(p.Rect)) {
312		return
313	}
314	i := p.PixOffset(x, y)
315	c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
316	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
317	s[0] = c1.R
318	s[1] = c1.G
319	s[2] = c1.B
320	s[3] = c1.A
321}
322
323func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
324	if !(Point{x, y}.In(p.Rect)) {
325		return
326	}
327	i := p.PixOffset(x, y)
328	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
329	s[0] = c.R
330	s[1] = c.G
331	s[2] = c.B
332	s[3] = c.A
333}
334
335// SubImage returns an image representing the portion of the image p visible
336// through r. The returned value shares pixels with the original image.
337func (p *NRGBA) SubImage(r Rectangle) Image {
338	r = r.Intersect(p.Rect)
339	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
340	// either r1 or r2 if the intersection is empty. Without explicitly checking for
341	// this, the Pix[i:] expression below can panic.
342	if r.Empty() {
343		return &NRGBA{}
344	}
345	i := p.PixOffset(r.Min.X, r.Min.Y)
346	return &NRGBA{
347		Pix:    p.Pix[i:],
348		Stride: p.Stride,
349		Rect:   r,
350	}
351}
352
353// Opaque scans the entire image and reports whether it is fully opaque.
354func (p *NRGBA) Opaque() bool {
355	if p.Rect.Empty() {
356		return true
357	}
358	i0, i1 := 3, p.Rect.Dx()*4
359	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
360		for i := i0; i < i1; i += 4 {
361			if p.Pix[i] != 0xff {
362				return false
363			}
364		}
365		i0 += p.Stride
366		i1 += p.Stride
367	}
368	return true
369}
370
371// NewNRGBA returns a new NRGBA image with the given bounds.
372func NewNRGBA(r Rectangle) *NRGBA {
373	w, h := r.Dx(), r.Dy()
374	pix := make([]uint8, 4*w*h)
375	return &NRGBA{pix, 4 * w, r}
376}
377
378// NRGBA64 is an in-memory image whose At method returns color.NRGBA64 values.
379type NRGBA64 struct {
380	// Pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
381	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*8].
382	Pix []uint8
383	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
384	Stride int
385	// Rect is the image's bounds.
386	Rect Rectangle
387}
388
389func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
390
391func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
392
393func (p *NRGBA64) At(x, y int) color.Color {
394	return p.NRGBA64At(x, y)
395}
396
397func (p *NRGBA64) NRGBA64At(x, y int) color.NRGBA64 {
398	if !(Point{x, y}.In(p.Rect)) {
399		return color.NRGBA64{}
400	}
401	i := p.PixOffset(x, y)
402	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
403	return color.NRGBA64{
404		uint16(s[0])<<8 | uint16(s[1]),
405		uint16(s[2])<<8 | uint16(s[3]),
406		uint16(s[4])<<8 | uint16(s[5]),
407		uint16(s[6])<<8 | uint16(s[7]),
408	}
409}
410
411// PixOffset returns the index of the first element of Pix that corresponds to
412// the pixel at (x, y).
413func (p *NRGBA64) PixOffset(x, y int) int {
414	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
415}
416
417func (p *NRGBA64) Set(x, y int, c color.Color) {
418	if !(Point{x, y}.In(p.Rect)) {
419		return
420	}
421	i := p.PixOffset(x, y)
422	c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
423	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
424	s[0] = uint8(c1.R >> 8)
425	s[1] = uint8(c1.R)
426	s[2] = uint8(c1.G >> 8)
427	s[3] = uint8(c1.G)
428	s[4] = uint8(c1.B >> 8)
429	s[5] = uint8(c1.B)
430	s[6] = uint8(c1.A >> 8)
431	s[7] = uint8(c1.A)
432}
433
434func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
435	if !(Point{x, y}.In(p.Rect)) {
436		return
437	}
438	i := p.PixOffset(x, y)
439	s := p.Pix[i : i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
440	s[0] = uint8(c.R >> 8)
441	s[1] = uint8(c.R)
442	s[2] = uint8(c.G >> 8)
443	s[3] = uint8(c.G)
444	s[4] = uint8(c.B >> 8)
445	s[5] = uint8(c.B)
446	s[6] = uint8(c.A >> 8)
447	s[7] = uint8(c.A)
448}
449
450// SubImage returns an image representing the portion of the image p visible
451// through r. The returned value shares pixels with the original image.
452func (p *NRGBA64) SubImage(r Rectangle) Image {
453	r = r.Intersect(p.Rect)
454	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
455	// either r1 or r2 if the intersection is empty. Without explicitly checking for
456	// this, the Pix[i:] expression below can panic.
457	if r.Empty() {
458		return &NRGBA64{}
459	}
460	i := p.PixOffset(r.Min.X, r.Min.Y)
461	return &NRGBA64{
462		Pix:    p.Pix[i:],
463		Stride: p.Stride,
464		Rect:   r,
465	}
466}
467
468// Opaque scans the entire image and reports whether it is fully opaque.
469func (p *NRGBA64) Opaque() bool {
470	if p.Rect.Empty() {
471		return true
472	}
473	i0, i1 := 6, p.Rect.Dx()*8
474	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
475		for i := i0; i < i1; i += 8 {
476			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
477				return false
478			}
479		}
480		i0 += p.Stride
481		i1 += p.Stride
482	}
483	return true
484}
485
486// NewNRGBA64 returns a new NRGBA64 image with the given bounds.
487func NewNRGBA64(r Rectangle) *NRGBA64 {
488	w, h := r.Dx(), r.Dy()
489	pix := make([]uint8, 8*w*h)
490	return &NRGBA64{pix, 8 * w, r}
491}
492
493// Alpha is an in-memory image whose At method returns color.Alpha values.
494type Alpha struct {
495	// Pix holds the image's pixels, as alpha values. The pixel at
496	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
497	Pix []uint8
498	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
499	Stride int
500	// Rect is the image's bounds.
501	Rect Rectangle
502}
503
504func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
505
506func (p *Alpha) Bounds() Rectangle { return p.Rect }
507
508func (p *Alpha) At(x, y int) color.Color {
509	return p.AlphaAt(x, y)
510}
511
512func (p *Alpha) AlphaAt(x, y int) color.Alpha {
513	if !(Point{x, y}.In(p.Rect)) {
514		return color.Alpha{}
515	}
516	i := p.PixOffset(x, y)
517	return color.Alpha{p.Pix[i]}
518}
519
520// PixOffset returns the index of the first element of Pix that corresponds to
521// the pixel at (x, y).
522func (p *Alpha) PixOffset(x, y int) int {
523	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
524}
525
526func (p *Alpha) Set(x, y int, c color.Color) {
527	if !(Point{x, y}.In(p.Rect)) {
528		return
529	}
530	i := p.PixOffset(x, y)
531	p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
532}
533
534func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
535	if !(Point{x, y}.In(p.Rect)) {
536		return
537	}
538	i := p.PixOffset(x, y)
539	p.Pix[i] = c.A
540}
541
542// SubImage returns an image representing the portion of the image p visible
543// through r. The returned value shares pixels with the original image.
544func (p *Alpha) SubImage(r Rectangle) Image {
545	r = r.Intersect(p.Rect)
546	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
547	// either r1 or r2 if the intersection is empty. Without explicitly checking for
548	// this, the Pix[i:] expression below can panic.
549	if r.Empty() {
550		return &Alpha{}
551	}
552	i := p.PixOffset(r.Min.X, r.Min.Y)
553	return &Alpha{
554		Pix:    p.Pix[i:],
555		Stride: p.Stride,
556		Rect:   r,
557	}
558}
559
560// Opaque scans the entire image and reports whether it is fully opaque.
561func (p *Alpha) Opaque() bool {
562	if p.Rect.Empty() {
563		return true
564	}
565	i0, i1 := 0, p.Rect.Dx()
566	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
567		for i := i0; i < i1; i++ {
568			if p.Pix[i] != 0xff {
569				return false
570			}
571		}
572		i0 += p.Stride
573		i1 += p.Stride
574	}
575	return true
576}
577
578// NewAlpha returns a new Alpha image with the given bounds.
579func NewAlpha(r Rectangle) *Alpha {
580	w, h := r.Dx(), r.Dy()
581	pix := make([]uint8, 1*w*h)
582	return &Alpha{pix, 1 * w, r}
583}
584
585// Alpha16 is an in-memory image whose At method returns color.Alpha16 values.
586type Alpha16 struct {
587	// Pix holds the image's pixels, as alpha values in big-endian format. The pixel at
588	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
589	Pix []uint8
590	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
591	Stride int
592	// Rect is the image's bounds.
593	Rect Rectangle
594}
595
596func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
597
598func (p *Alpha16) Bounds() Rectangle { return p.Rect }
599
600func (p *Alpha16) At(x, y int) color.Color {
601	return p.Alpha16At(x, y)
602}
603
604func (p *Alpha16) Alpha16At(x, y int) color.Alpha16 {
605	if !(Point{x, y}.In(p.Rect)) {
606		return color.Alpha16{}
607	}
608	i := p.PixOffset(x, y)
609	return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
610}
611
612// PixOffset returns the index of the first element of Pix that corresponds to
613// the pixel at (x, y).
614func (p *Alpha16) PixOffset(x, y int) int {
615	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
616}
617
618func (p *Alpha16) Set(x, y int, c color.Color) {
619	if !(Point{x, y}.In(p.Rect)) {
620		return
621	}
622	i := p.PixOffset(x, y)
623	c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
624	p.Pix[i+0] = uint8(c1.A >> 8)
625	p.Pix[i+1] = uint8(c1.A)
626}
627
628func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
629	if !(Point{x, y}.In(p.Rect)) {
630		return
631	}
632	i := p.PixOffset(x, y)
633	p.Pix[i+0] = uint8(c.A >> 8)
634	p.Pix[i+1] = uint8(c.A)
635}
636
637// SubImage returns an image representing the portion of the image p visible
638// through r. The returned value shares pixels with the original image.
639func (p *Alpha16) SubImage(r Rectangle) Image {
640	r = r.Intersect(p.Rect)
641	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
642	// either r1 or r2 if the intersection is empty. Without explicitly checking for
643	// this, the Pix[i:] expression below can panic.
644	if r.Empty() {
645		return &Alpha16{}
646	}
647	i := p.PixOffset(r.Min.X, r.Min.Y)
648	return &Alpha16{
649		Pix:    p.Pix[i:],
650		Stride: p.Stride,
651		Rect:   r,
652	}
653}
654
655// Opaque scans the entire image and reports whether it is fully opaque.
656func (p *Alpha16) Opaque() bool {
657	if p.Rect.Empty() {
658		return true
659	}
660	i0, i1 := 0, p.Rect.Dx()*2
661	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
662		for i := i0; i < i1; i += 2 {
663			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
664				return false
665			}
666		}
667		i0 += p.Stride
668		i1 += p.Stride
669	}
670	return true
671}
672
673// NewAlpha16 returns a new Alpha16 image with the given bounds.
674func NewAlpha16(r Rectangle) *Alpha16 {
675	w, h := r.Dx(), r.Dy()
676	pix := make([]uint8, 2*w*h)
677	return &Alpha16{pix, 2 * w, r}
678}
679
680// Gray is an in-memory image whose At method returns color.Gray values.
681type Gray struct {
682	// Pix holds the image's pixels, as gray values. The pixel at
683	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
684	Pix []uint8
685	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
686	Stride int
687	// Rect is the image's bounds.
688	Rect Rectangle
689}
690
691func (p *Gray) ColorModel() color.Model { return color.GrayModel }
692
693func (p *Gray) Bounds() Rectangle { return p.Rect }
694
695func (p *Gray) At(x, y int) color.Color {
696	return p.GrayAt(x, y)
697}
698
699func (p *Gray) GrayAt(x, y int) color.Gray {
700	if !(Point{x, y}.In(p.Rect)) {
701		return color.Gray{}
702	}
703	i := p.PixOffset(x, y)
704	return color.Gray{p.Pix[i]}
705}
706
707// PixOffset returns the index of the first element of Pix that corresponds to
708// the pixel at (x, y).
709func (p *Gray) PixOffset(x, y int) int {
710	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
711}
712
713func (p *Gray) Set(x, y int, c color.Color) {
714	if !(Point{x, y}.In(p.Rect)) {
715		return
716	}
717	i := p.PixOffset(x, y)
718	p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
719}
720
721func (p *Gray) SetGray(x, y int, c color.Gray) {
722	if !(Point{x, y}.In(p.Rect)) {
723		return
724	}
725	i := p.PixOffset(x, y)
726	p.Pix[i] = c.Y
727}
728
729// SubImage returns an image representing the portion of the image p visible
730// through r. The returned value shares pixels with the original image.
731func (p *Gray) SubImage(r Rectangle) Image {
732	r = r.Intersect(p.Rect)
733	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
734	// either r1 or r2 if the intersection is empty. Without explicitly checking for
735	// this, the Pix[i:] expression below can panic.
736	if r.Empty() {
737		return &Gray{}
738	}
739	i := p.PixOffset(r.Min.X, r.Min.Y)
740	return &Gray{
741		Pix:    p.Pix[i:],
742		Stride: p.Stride,
743		Rect:   r,
744	}
745}
746
747// Opaque scans the entire image and reports whether it is fully opaque.
748func (p *Gray) Opaque() bool {
749	return true
750}
751
752// NewGray returns a new Gray image with the given bounds.
753func NewGray(r Rectangle) *Gray {
754	w, h := r.Dx(), r.Dy()
755	pix := make([]uint8, 1*w*h)
756	return &Gray{pix, 1 * w, r}
757}
758
759// Gray16 is an in-memory image whose At method returns color.Gray16 values.
760type Gray16 struct {
761	// Pix holds the image's pixels, as gray values in big-endian format. The pixel at
762	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
763	Pix []uint8
764	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
765	Stride int
766	// Rect is the image's bounds.
767	Rect Rectangle
768}
769
770func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
771
772func (p *Gray16) Bounds() Rectangle { return p.Rect }
773
774func (p *Gray16) At(x, y int) color.Color {
775	return p.Gray16At(x, y)
776}
777
778func (p *Gray16) Gray16At(x, y int) color.Gray16 {
779	if !(Point{x, y}.In(p.Rect)) {
780		return color.Gray16{}
781	}
782	i := p.PixOffset(x, y)
783	return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
784}
785
786// PixOffset returns the index of the first element of Pix that corresponds to
787// the pixel at (x, y).
788func (p *Gray16) PixOffset(x, y int) int {
789	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
790}
791
792func (p *Gray16) Set(x, y int, c color.Color) {
793	if !(Point{x, y}.In(p.Rect)) {
794		return
795	}
796	i := p.PixOffset(x, y)
797	c1 := color.Gray16Model.Convert(c).(color.Gray16)
798	p.Pix[i+0] = uint8(c1.Y >> 8)
799	p.Pix[i+1] = uint8(c1.Y)
800}
801
802func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
803	if !(Point{x, y}.In(p.Rect)) {
804		return
805	}
806	i := p.PixOffset(x, y)
807	p.Pix[i+0] = uint8(c.Y >> 8)
808	p.Pix[i+1] = uint8(c.Y)
809}
810
811// SubImage returns an image representing the portion of the image p visible
812// through r. The returned value shares pixels with the original image.
813func (p *Gray16) SubImage(r Rectangle) Image {
814	r = r.Intersect(p.Rect)
815	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
816	// either r1 or r2 if the intersection is empty. Without explicitly checking for
817	// this, the Pix[i:] expression below can panic.
818	if r.Empty() {
819		return &Gray16{}
820	}
821	i := p.PixOffset(r.Min.X, r.Min.Y)
822	return &Gray16{
823		Pix:    p.Pix[i:],
824		Stride: p.Stride,
825		Rect:   r,
826	}
827}
828
829// Opaque scans the entire image and reports whether it is fully opaque.
830func (p *Gray16) Opaque() bool {
831	return true
832}
833
834// NewGray16 returns a new Gray16 image with the given bounds.
835func NewGray16(r Rectangle) *Gray16 {
836	w, h := r.Dx(), r.Dy()
837	pix := make([]uint8, 2*w*h)
838	return &Gray16{pix, 2 * w, r}
839}
840
841// CMYK is an in-memory image whose At method returns color.CMYK values.
842type CMYK struct {
843	// Pix holds the image's pixels, in C, M, Y, K order. The pixel at
844	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
845	Pix []uint8
846	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
847	Stride int
848	// Rect is the image's bounds.
849	Rect Rectangle
850}
851
852func (p *CMYK) ColorModel() color.Model { return color.CMYKModel }
853
854func (p *CMYK) Bounds() Rectangle { return p.Rect }
855
856func (p *CMYK) At(x, y int) color.Color {
857	return p.CMYKAt(x, y)
858}
859
860func (p *CMYK) CMYKAt(x, y int) color.CMYK {
861	if !(Point{x, y}.In(p.Rect)) {
862		return color.CMYK{}
863	}
864	i := p.PixOffset(x, y)
865	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
866	return color.CMYK{s[0], s[1], s[2], s[3]}
867}
868
869// PixOffset returns the index of the first element of Pix that corresponds to
870// the pixel at (x, y).
871func (p *CMYK) PixOffset(x, y int) int {
872	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
873}
874
875func (p *CMYK) Set(x, y int, c color.Color) {
876	if !(Point{x, y}.In(p.Rect)) {
877		return
878	}
879	i := p.PixOffset(x, y)
880	c1 := color.CMYKModel.Convert(c).(color.CMYK)
881	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
882	s[0] = c1.C
883	s[1] = c1.M
884	s[2] = c1.Y
885	s[3] = c1.K
886}
887
888func (p *CMYK) SetCMYK(x, y int, c color.CMYK) {
889	if !(Point{x, y}.In(p.Rect)) {
890		return
891	}
892	i := p.PixOffset(x, y)
893	s := p.Pix[i : i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
894	s[0] = c.C
895	s[1] = c.M
896	s[2] = c.Y
897	s[3] = c.K
898}
899
900// SubImage returns an image representing the portion of the image p visible
901// through r. The returned value shares pixels with the original image.
902func (p *CMYK) SubImage(r Rectangle) Image {
903	r = r.Intersect(p.Rect)
904	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
905	// either r1 or r2 if the intersection is empty. Without explicitly checking for
906	// this, the Pix[i:] expression below can panic.
907	if r.Empty() {
908		return &CMYK{}
909	}
910	i := p.PixOffset(r.Min.X, r.Min.Y)
911	return &CMYK{
912		Pix:    p.Pix[i:],
913		Stride: p.Stride,
914		Rect:   r,
915	}
916}
917
918// Opaque scans the entire image and reports whether it is fully opaque.
919func (p *CMYK) Opaque() bool {
920	return true
921}
922
923// NewCMYK returns a new CMYK image with the given bounds.
924func NewCMYK(r Rectangle) *CMYK {
925	w, h := r.Dx(), r.Dy()
926	buf := make([]uint8, 4*w*h)
927	return &CMYK{buf, 4 * w, r}
928}
929
930// Paletted is an in-memory image of uint8 indices into a given palette.
931type Paletted struct {
932	// Pix holds the image's pixels, as palette indices. The pixel at
933	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*1].
934	Pix []uint8
935	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
936	Stride int
937	// Rect is the image's bounds.
938	Rect Rectangle
939	// Palette is the image's palette.
940	Palette color.Palette
941}
942
943func (p *Paletted) ColorModel() color.Model { return p.Palette }
944
945func (p *Paletted) Bounds() Rectangle { return p.Rect }
946
947func (p *Paletted) At(x, y int) color.Color {
948	if len(p.Palette) == 0 {
949		return nil
950	}
951	if !(Point{x, y}.In(p.Rect)) {
952		return p.Palette[0]
953	}
954	i := p.PixOffset(x, y)
955	return p.Palette[p.Pix[i]]
956}
957
958// PixOffset returns the index of the first element of Pix that corresponds to
959// the pixel at (x, y).
960func (p *Paletted) PixOffset(x, y int) int {
961	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
962}
963
964func (p *Paletted) Set(x, y int, c color.Color) {
965	if !(Point{x, y}.In(p.Rect)) {
966		return
967	}
968	i := p.PixOffset(x, y)
969	p.Pix[i] = uint8(p.Palette.Index(c))
970}
971
972func (p *Paletted) ColorIndexAt(x, y int) uint8 {
973	if !(Point{x, y}.In(p.Rect)) {
974		return 0
975	}
976	i := p.PixOffset(x, y)
977	return p.Pix[i]
978}
979
980func (p *Paletted) SetColorIndex(x, y int, index uint8) {
981	if !(Point{x, y}.In(p.Rect)) {
982		return
983	}
984	i := p.PixOffset(x, y)
985	p.Pix[i] = index
986}
987
988// SubImage returns an image representing the portion of the image p visible
989// through r. The returned value shares pixels with the original image.
990func (p *Paletted) SubImage(r Rectangle) Image {
991	r = r.Intersect(p.Rect)
992	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
993	// either r1 or r2 if the intersection is empty. Without explicitly checking for
994	// this, the Pix[i:] expression below can panic.
995	if r.Empty() {
996		return &Paletted{
997			Palette: p.Palette,
998		}
999	}
1000	i := p.PixOffset(r.Min.X, r.Min.Y)
1001	return &Paletted{
1002		Pix:     p.Pix[i:],
1003		Stride:  p.Stride,
1004		Rect:    p.Rect.Intersect(r),
1005		Palette: p.Palette,
1006	}
1007}
1008
1009// Opaque scans the entire image and reports whether it is fully opaque.
1010func (p *Paletted) Opaque() bool {
1011	var present [256]bool
1012	i0, i1 := 0, p.Rect.Dx()
1013	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
1014		for _, c := range p.Pix[i0:i1] {
1015			present[c] = true
1016		}
1017		i0 += p.Stride
1018		i1 += p.Stride
1019	}
1020	for i, c := range p.Palette {
1021		if !present[i] {
1022			continue
1023		}
1024		_, _, _, a := c.RGBA()
1025		if a != 0xffff {
1026			return false
1027		}
1028	}
1029	return true
1030}
1031
1032// NewPaletted returns a new Paletted image with the given width, height and
1033// palette.
1034func NewPaletted(r Rectangle, p color.Palette) *Paletted {
1035	w, h := r.Dx(), r.Dy()
1036	pix := make([]uint8, 1*w*h)
1037	return &Paletted{pix, 1 * w, r, p}
1038}
1039