Example #1
0
// NewDrawableSize returns a new draw.Image with the same type as p and the given bounds.
// If p is not a draw.Image, another type is used.
func NewDrawableSize(p image.Image, r image.Rectangle) draw.Image {
	switch p := p.(type) {
	case *image.RGBA:
		return image.NewRGBA(r)
	case *image.RGBA64:
		return image.NewRGBA64(r)
	case *image.NRGBA:
		return image.NewNRGBA(r)
	case *image.NRGBA64:
		return image.NewNRGBA64(r)
	case *image.Alpha:
		return image.NewAlpha(r)
	case *image.Alpha16:
		return image.NewAlpha16(r)
	case *image.Gray:
		return image.NewGray(r)
	case *image.Gray16:
		return image.NewGray16(r)
	case *image.Paletted:
		pl := make(color.Palette, len(p.Palette))
		copy(pl, p.Palette)
		return image.NewPaletted(r, pl)
	case *image.CMYK:
		return image.NewCMYK(r)
	default:
		return image.NewRGBA(r)
	}
}
Example #2
0
func createRandomImage(maxPaletteSize int) image.Image {
	r := image.Rectangle{Min: image.Point{0, 0}, Max: image.Point{gen.Rand(32) + 1, gen.Rand(32) + 1}}
	var img Image
	switch gen.Rand(10) {
	case 0:
		img = image.NewAlpha(r)
	case 1:
		img = image.NewAlpha16(r)
	case 2:
		img = image.NewCMYK(r)
	case 3:
		img = image.NewGray(r)
	case 4:
		img = image.NewGray16(r)
	case 5:
		img = image.NewNRGBA(r)
	case 6:
		img = image.NewNRGBA64(r)
	case 7:
		img = image.NewPaletted(r, randPalette(maxPaletteSize))
	case 8:
		img = image.NewRGBA(r)
	case 9:
		img = image.NewRGBA64(r)
	default:
		panic("bad")
	}
	fill := gen.Rand(19)
	var palette []color.Color
	if fill == 17 {
		palette = randPalette(maxPaletteSize)
	}
	for y := 0; y < r.Max.Y; y++ {
		for x := 0; x < r.Max.X; x++ {
			switch {
			case fill <= 15:
				img.Set(x, y, color.RGBA64{
					^uint16(0) * uint16((fill>>0)&1),
					^uint16(0) * uint16((fill>>1)&1),
					^uint16(0) * uint16((fill>>2)&1),
					^uint16(0) * uint16((fill>>3)&1),
				})
			case fill == 16:
				img.Set(x, y, randColor())
			case fill == 17:
				img.Set(x, y, palette[gen.Rand(len(palette))])
			case fill == 18:
				if gen.Rand(3) != 0 {
					img.Set(x, y, color.RGBA64{})
				} else {
					img.Set(x, y, randColor())
				}
			default:
				panic("bad")
			}
		}
	}
	return img.(image.Image)
}
Example #3
0
func vgradMagenta() image.Image {
	m := image.NewCMYK(image.Rect(0, 0, 16, 16))
	for y := 0; y < 16; y++ {
		for x := 0; x < 16; x++ {
			m.Set(x, y, color.CMYK{0, uint8(y * 0x11), 0, 0x3f})
		}
	}
	return m
}
Example #4
0
// NewDrawableSize returns a new draw.Image with the same type as p and the given bounds.
// If p is not a draw.Image, another type is used.
func NewDrawableSize(p image.Image, r image.Rectangle) draw.Image {
	switch p.(type) {
	case *image.RGBA:
		return image.NewRGBA(r)
	case *image.RGBA64:
		return image.NewRGBA64(r)
	case *image.NRGBA:
		return image.NewNRGBA(r)
	case *image.NRGBA64:
		return image.NewNRGBA64(r)
	case *image.Alpha:
		return image.NewAlpha(r)
	case *image.Alpha16:
		return image.NewAlpha16(r)
	case *image.Gray:
		return image.NewGray(r)
	case *image.Gray16:
		return image.NewGray16(r)
	case *image.CMYK:
		return image.NewCMYK(r)
	default:
		return image.NewRGBA(r)
	}
}
Example #5
0
// applyBlack combines d.img3 and d.blackPix into a CMYK image. The formula
// used depends on whether the JPEG image is stored as CMYK or YCbCrK,
// indicated by the APP14 (Adobe) metadata.
//
// Adobe CMYK JPEG images are inverted, where 255 means no ink instead of full
// ink, so we apply "v = 255 - v" at various points. Note that a double
// inversion is a no-op, so inversions might be implicit in the code below.
func (d *decoder) applyBlack() (image.Image, error) {
	if !d.adobeTransformValid {
		return nil, UnsupportedError("unknown color model: 4-component JPEG doesn't have Adobe APP14 metadata")
	}

	// If the 4-component JPEG image isn't explicitly marked as "Unknown (RGB
	// or CMYK)" as per
	// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/JPEG.html#Adobe
	// we assume that it is YCbCrK. This matches libjpeg's jdapimin.c.
	if d.adobeTransform != adobeTransformUnknown {
		// Convert the YCbCr part of the YCbCrK to RGB, invert the RGB to get
		// CMY, and patch in the original K. The RGB to CMY inversion cancels
		// out the 'Adobe inversion' described in the applyBlack doc comment
		// above, so in practice, only the fourth channel (black) is inverted.
		bounds := d.img3.Bounds()
		img := image.NewRGBA(bounds)
		drawYCbCr(img, bounds, d.img3, bounds.Min)
		for iBase, y := 0, bounds.Min.Y; y < bounds.Max.Y; iBase, y = iBase+img.Stride, y+1 {
			for i, x := iBase+3, bounds.Min.X; x < bounds.Max.X; i, x = i+4, x+1 {
				img.Pix[i] = 255 - d.blackPix[(y-bounds.Min.Y)*d.blackStride+(x-bounds.Min.X)]
			}
		}
		return &image.CMYK{
			Pix:    img.Pix,
			Stride: img.Stride,
			Rect:   img.Rect,
		}, nil
	}

	// The first three channels (cyan, magenta, yellow) of the CMYK
	// were decoded into d.img3, but each channel was decoded into a separate
	// []byte slice, and some channels may be subsampled. We interleave the
	// separate channels into an image.CMYK's single []byte slice containing 4
	// contiguous bytes per pixel.
	bounds := d.img3.Bounds()
	img := image.NewCMYK(bounds)

	translations := [4]struct {
		src    []byte
		stride int
	}{
		{d.img3.Y, d.img3.YStride},
		{d.img3.Cb, d.img3.CStride},
		{d.img3.Cr, d.img3.CStride},
		{d.blackPix, d.blackStride},
	}
	for t, translation := range translations {
		subsample := d.comp[t].h != d.comp[0].h || d.comp[t].v != d.comp[0].v
		for iBase, y := 0, bounds.Min.Y; y < bounds.Max.Y; iBase, y = iBase+img.Stride, y+1 {
			sy := y - bounds.Min.Y
			if subsample {
				sy /= 2
			}
			for i, x := iBase+t, bounds.Min.X; x < bounds.Max.X; i, x = i+4, x+1 {
				sx := x - bounds.Min.X
				if subsample {
					sx /= 2
				}
				img.Pix[i] = 255 - translation.src[sy*translation.stride+sx]
			}
		}
	}
	return img, nil
}
func BenchmarkNewSetFuncCMYK(b *testing.B) {
	benchmarkNewSetFunc(b, image.NewCMYK(image.Rect(0, 0, 1, 1)))
}
Example #7
0
func TestNewDrawable(t *testing.T) {
	r := image.Rect(0, 0, 1, 1)
	for _, newImage := range []func(image.Rectangle) image.Image{
		func(r image.Rectangle) image.Image {
			return image.NewRGBA(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewRGBA64(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNRGBA(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNRGBA64(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewAlpha(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewAlpha16(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewGray(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewGray16(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewCMYK(r)
		},
		func(r image.Rectangle) image.Image {
			return image.NewPaletted(r, color.Palette{
				color.RGBA{0, 0, 0, 255},
				color.RGBA{255, 0, 0, 255},
				color.RGBA{0, 255, 0, 255},
				color.RGBA{0, 0, 255, 255},
				color.RGBA{255, 255, 255, 255},
			})
		},
		func(r image.Rectangle) image.Image {
			return image.NewYCbCr(r, image.YCbCrSubsampleRatio444)
		},
		func(r image.Rectangle) image.Image {
			return image.NewYCbCr(r, image.YCbCrSubsampleRatio422)
		},
		func(r image.Rectangle) image.Image {
			return image.NewYCbCr(r, image.YCbCrSubsampleRatio420)
		},
		func(r image.Rectangle) image.Image {
			return image.NewYCbCr(r, image.YCbCrSubsampleRatio440)
		},
		func(r image.Rectangle) image.Image {
			return image.NewYCbCr(r, image.YCbCrSubsampleRatio411)
		},
		func(r image.Rectangle) image.Image {
			return image.NewYCbCr(r, image.YCbCrSubsampleRatio410)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio444)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio422)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio420)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio440)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio411)
		},
		func(r image.Rectangle) image.Image {
			return image.NewNYCbCrA(r, image.YCbCrSubsampleRatio410)
		},
		func(r image.Rectangle) image.Image {
			return image.NewUniform(color.RGBA{})
		},
		func(r image.Rectangle) image.Image {
			return &testImageDefault{image.NewRGBA(r)}
		},
	} {
		p := newImage(r)
		t.Run(fmt.Sprintf("%T", p), func(t *testing.T) {
			NewDrawable(p)
		})
	}
}
Example #8
0
// bench benchmarks drawing src and mask images onto a dst image with the
// given op and the color models to create those images from.
// The created images' pixels are initialized to non-zero values.
func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
	b.StopTimer()

	var dst Image
	switch dcm {
	case color.RGBAModel:
		dst1 := image.NewRGBA(image.Rect(0, 0, dstw, dsth))
		for y := 0; y < dsth; y++ {
			for x := 0; x < dstw; x++ {
				dst1.SetRGBA(x, y, color.RGBA{
					uint8(5 * x % 0x100),
					uint8(7 * y % 0x100),
					uint8((7*x + 5*y) % 0x100),
					0xff,
				})
			}
		}
		dst = dst1
	case color.RGBA64Model:
		dst1 := image.NewRGBA64(image.Rect(0, 0, dstw, dsth))
		for y := 0; y < dsth; y++ {
			for x := 0; x < dstw; x++ {
				dst1.SetRGBA64(x, y, color.RGBA64{
					uint16(53 * x % 0x10000),
					uint16(59 * y % 0x10000),
					uint16((59*x + 53*y) % 0x10000),
					0xffff,
				})
			}
		}
		dst = dst1
	default:
		// The == operator isn't defined on a color.Palette (a slice), so we
		// use reflection.
		if reflect.DeepEqual(dcm, palette) {
			dst1 := image.NewPaletted(image.Rect(0, 0, dstw, dsth), palette)
			for y := 0; y < dsth; y++ {
				for x := 0; x < dstw; x++ {
					dst1.SetColorIndex(x, y, uint8(x^y)&1)
				}
			}
			dst = dst1
		} else {
			b.Fatal("unknown destination color model", dcm)
		}
	}

	var src image.Image
	switch scm {
	case nil:
		src = &image.Uniform{C: color.RGBA{0x11, 0x22, 0x33, 0x44}}
	case color.CMYKModel:
		src1 := image.NewCMYK(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetCMYK(x, y, color.CMYK{
					uint8(13 * x % 0x100),
					uint8(11 * y % 0x100),
					uint8((11*x + 13*y) % 0x100),
					uint8((31*x + 37*y) % 0x100),
				})
			}
		}
		src = src1
	case color.GrayModel:
		src1 := image.NewGray(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetGray(x, y, color.Gray{
					uint8((11*x + 13*y) % 0x100),
				})
			}
		}
		src = src1
	case color.RGBAModel:
		src1 := image.NewRGBA(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetRGBA(x, y, color.RGBA{
					uint8(13 * x % 0x80),
					uint8(11 * y % 0x80),
					uint8((11*x + 13*y) % 0x80),
					0x7f,
				})
			}
		}
		src = src1
	case color.RGBA64Model:
		src1 := image.NewRGBA64(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetRGBA64(x, y, color.RGBA64{
					uint16(103 * x % 0x8000),
					uint16(101 * y % 0x8000),
					uint16((101*x + 103*y) % 0x8000),
					0x7fff,
				})
			}
		}
		src = src1
	case color.NRGBAModel:
		src1 := image.NewNRGBA(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetNRGBA(x, y, color.NRGBA{
					uint8(13 * x % 0x100),
					uint8(11 * y % 0x100),
					uint8((11*x + 13*y) % 0x100),
					0x7f,
				})
			}
		}
		src = src1
	case color.YCbCrModel:
		yy := make([]uint8, srcw*srch)
		cb := make([]uint8, srcw*srch)
		cr := make([]uint8, srcw*srch)
		for i := range yy {
			yy[i] = uint8(3 * i % 0x100)
			cb[i] = uint8(5 * i % 0x100)
			cr[i] = uint8(7 * i % 0x100)
		}
		src = &image.YCbCr{
			Y:              yy,
			Cb:             cb,
			Cr:             cr,
			YStride:        srcw,
			CStride:        srcw,
			SubsampleRatio: image.YCbCrSubsampleRatio444,
			Rect:           image.Rect(0, 0, srcw, srch),
		}
	default:
		b.Fatal("unknown source color model", scm)
	}

	var mask image.Image
	switch mcm {
	case nil:
		// No-op.
	case color.AlphaModel:
		mask1 := image.NewAlpha(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				a := uint8((23*x + 29*y) % 0x100)
				// Glyph masks are typically mostly zero,
				// so we only set a quarter of mask1's pixels.
				if a >= 0xc0 {
					mask1.SetAlpha(x, y, color.Alpha{a})
				}
			}
		}
		mask = mask1
	default:
		b.Fatal("unknown mask color model", mcm)
	}

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		// Scatter the destination rectangle to draw into.
		x := 3 * i % (dstw - srcw)
		y := 7 * i % (dsth - srch)

		DrawMask(dst, dst.Bounds().Add(image.Pt(x, y)), src, image.ZP, mask, image.ZP, op)
	}
}
Example #9
0
		return image.NewNRGBA64(r)
	},
	func(r image.Rectangle) image.Image {
		return image.NewAlpha(r)
	},
	func(r image.Rectangle) image.Image {
		return image.NewAlpha16(r)
	},
	func(r image.Rectangle) image.Image {
		return image.NewGray(r)
	},
	func(r image.Rectangle) image.Image {
		return image.NewGray16(r)
	},
	func(r image.Rectangle) image.Image {
		return image.NewCMYK(r)
	},
	func(r image.Rectangle) image.Image {
		return image.NewPaletted(r, testPalette)
	},
	func(r image.Rectangle) image.Image {
		return image.NewYCbCr(r, image.YCbCrSubsampleRatio444)
	},
	func(r image.Rectangle) image.Image {
		return image.NewYCbCr(r, image.YCbCrSubsampleRatio422)
	},
	func(r image.Rectangle) image.Image {
		return image.NewYCbCr(r, image.YCbCrSubsampleRatio420)
	},
	func(r image.Rectangle) image.Image {
		return image.NewYCbCr(r, image.YCbCrSubsampleRatio440)