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