Exemplo n.º 1
0
// ycbcr returns the YCbCr values for the given colour, converting to them if
// necessary.
func ycbcr(colour color.Color) (y, cb, cr uint8) {
	switch spec := colour.(type) {
	case color.YCbCr:
		return spec.Y, spec.Cb, spec.Cr
	default:
		r, g, b, _ := colour.RGBA()
		return color.RGBToYCbCr(uint8(r), uint8(g), uint8(b))
	}
}
Exemplo n.º 2
0
func image2YCbCrs(src image.Image) (yCbCrs []color.YCbCr) {
	srcBounds := src.Bounds()
	for i := 0; i < srcBounds.Max.Y; i++ {
		for j := 0; j < srcBounds.Max.X; j++ {
			r, g, b, _ := src.At(j, i).RGBA()
			y, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
			yCbCrs = append(yCbCrs, color.YCbCr{y, cb, cr})
		}
	}
	return yCbCrs
}
Exemplo n.º 3
0
func ImageTransformByProfile(src_image image.Image, src_prof, dst_prof *Profile) (image.Image, error) {
	var dst_image image.Image
	rect := src_image.Bounds()
	width := rect.Dx()
	height := rect.Dy()
	colorModel := src_image.ColorModel()
	// 今のところ RGBA, YCbCr のみ対応
	if (colorModel != color.YCbCrModel) && (colorModel != color.RGBAModel) {
		return nil, fmt.Errorf("ImageTransformByProfile: Unsupported ColorModel(%d)", colorModel)
	}
	var src_rgba *image.RGBA
	var src_ycbcr *image.YCbCr
	if colorModel == color.YCbCrModel {
		// YCbCr の場合は RGB に変換する
		src_ycbcr = src_image.(*image.YCbCr)
		src_rgba = image.NewRGBA(rect)
		DrawYCbCr(src_rgba, rect, src_ycbcr, image.Pt(0, 0))
	} else {
		src_rgba = src_image.(*image.RGBA) // type assertions
	}
	transform := CreateTransform(src_prof, DATA_RGBA_8, dst_prof, DATA_RGBA_8)
	defer transform.DeleteTransform()
	if transform == nil {
		return nil, fmt.Errorf("ImageTransformByProfile: CreateTransform Failedl(%d)", colorModel)
	}
	dst_rgba := image.NewRGBA(rect)
	src_pix := src_rgba.Pix
	dst_pix := dst_rgba.Pix
	len_pix := len(src_pix)
	transform.DoTransform(src_pix, dst_pix, len_pix)
	// YCbCr の場合は RGB から戻す
	if colorModel == color.YCbCrModel {
		dst_ycbcr := image.NewYCbCr(rect, src_ycbcr.SubsampleRatio)
		var x int
		var y int
		for y = 0; y < height; y++ {
			for x = 0; x < width; x++ {
				r, g, b, _ := dst_rgba.At(x, y).RGBA()
				yy, cb, cr := color.RGBToYCbCr(uint8(r), uint8(g), uint8(b))
				yi := dst_ycbcr.YOffset(x, y)
				ci := dst_ycbcr.COffset(x, y)
				dst_ycbcr.Y[yi] = yy
				dst_ycbcr.Cb[ci] = cb
				dst_ycbcr.Cr[ci] = cr
			}
		}
		dst_image = image.Image(dst_ycbcr)
	} else {
		dst_image = image.Image(dst_rgba)
	}

	return dst_image, nil
}
Exemplo n.º 4
0
// toYCbCr converts the 8x8 region of m whose top-left corner is p to its
// YCbCr values.
func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
	b := m.Bounds()
	xmax := b.Max.X - 1
	ymax := b.Max.Y - 1
	for j := 0; j < 8; j++ {
		for i := 0; i < 8; i++ {
			r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
			yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
			yBlock[8*j+i] = int(yy)
			cbBlock[8*j+i] = int(cb)
			crBlock[8*j+i] = int(cr)
		}
	}
}
Exemplo n.º 5
0
func delta(c1, c2 color.NRGBA) float64 {

	if c1.A == 0 && c2.A == 0 {
		return 0.0
	}

	y1, cb1, cr1 := color.RGBToYCbCr(c1.R, c1.G, c1.B)
	y2, cb2, cr2 := color.RGBToYCbCr(c2.R, c2.G, c2.B)

	dy := (int(y1) - int(y2)) * 3
	dcb := int(cb1) - int(cb2)
	dcr := int(cr1) - int(cr2)
	da := int(c1.A) - int(c2.A)

	// if c2.A == 233 && c1.A == 255 {
	// 	fmt.Println(dy, dcb, dcr, da)
	// }

	// if c1.A == 255 && c2.A == 255 && c2.R > 0 {
	// 	fmt.Println(c1, c2, dy, dcb, dcr, da, float64(dy*dy+dcb*dcb+dcr*dcr+da*da)/32.0)
	// }

	return float64(dy*dy+dcb*dcb+dcr*dcr+da*da) / 32.0
}
Exemplo n.º 6
0
func FromImage(src image.Image) *image.YCbCr {
	r := src.Bounds()
	dst := image.NewYCbCr(src.Bounds(), image.YCbCrSubsampleRatio444)
	for x := r.Min.X; x < r.Max.X; x++ {
		for y := r.Min.Y; y < r.Max.Y; y++ {
			c := src.At(x, y)
			r, g, b, _ := c.RGBA()
			yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))

			i := dst.YOffset(x, y)
			dst.Y[i] = yy
			dst.Cb[i] = cb
			dst.Cr[i] = cr
		}
	}

	return dst
}
Exemplo n.º 7
0
func nYCbCrAModel(c color.Color) color.Color {
	switch c := c.(type) {
	case Color:
		return c
	case color.YCbCr:
		return Color{c, 0xff}
	}
	r, g, b, a := c.RGBA()

	// Convert from alpha-premultiplied to non-alpha-premultiplied.
	if a != 0 {
		r = (r * 0xffff) / a
		g = (g * 0xffff) / a
		b = (b * 0xffff) / a
	}

	y, u, v := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
	return Color{color.YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)}
}
Exemplo n.º 8
0
// rgbaToYCbCr is a specialized version of toYCbCr for image.RGBA images.
func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block) {
	b := m.Bounds()
	xmax := b.Max.X - 1
	ymax := b.Max.Y - 1
	for j := 0; j < 8; j++ {
		sj := p.Y + j
		if sj > ymax {
			sj = ymax
		}
		offset := (sj-b.Min.Y)*m.Stride - b.Min.X*4
		for i := 0; i < 8; i++ {
			sx := p.X + i
			if sx > xmax {
				sx = xmax
			}
			pix := m.Pix[offset+sx*4:]
			yy, cb, cr := color.RGBToYCbCr(pix[0], pix[1], pix[2])
			yBlock[8*j+i] = int(yy)
			cbBlock[8*j+i] = int(cb)
			crBlock[8*j+i] = int(cr)
		}
	}
}
Exemplo n.º 9
0
func fillTestImage(im image.Image) {
	b := im.Bounds()
	if !b.Eq(testIm.Bounds()) {
		panic("Requested target image dimensions not equal reference image.")
	}
	src := testIm
	if dst, ok := im.(*image.YCbCr); ok {
		b := testIm.Bounds()
		for y := b.Min.Y; y < b.Max.Y; y++ {
			for x := b.Min.X; x < b.Max.X; x++ {
				r, g, b, _ := src.At(x, y).RGBA()
				yp, cb, cr := color.RGBToYCbCr(uint8(r), uint8(g), uint8(b))

				dst.Y[dst.YOffset(x, y)] = yp
				off := dst.COffset(x, y)
				dst.Cb[off] = cb
				dst.Cr[off] = cr
			}
		}
		return
	}
	draw.Draw(im.(draw.Image), b, testIm, b.Min, draw.Src)
}
Exemplo n.º 10
0
func colorCheck(c color.Color) bool {
	r, g, b, _ := c.RGBA()
	_, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
	return (86 <= cb) && (cb <= 117) && (140 <= cr) && (cr <= 168)
}
Exemplo n.º 11
0
func NewImageMap(img image.Image) (*ImageMap, error) {
	var im *ImageMap
	switch m := img.(type) {
	case *image.YCbCr:
		im = &ImageMap{
			Pix:     m.Y,
			YStride: m.YStride,
			XStride: 1,
			Width:   img.Bounds().Dx(),
			Height:  img.Bounds().Dy(),
			Stddev:  1.0,
		}
		var verticalRes, horizontalRes int
		switch m.SubsampleRatio {
		case image.YCbCrSubsampleRatio420:
			verticalRes = 2
			horizontalRes = 2
		case image.YCbCrSubsampleRatio422:
			verticalRes = 1
			horizontalRes = 2
		case image.YCbCrSubsampleRatio440:
			verticalRes = 2
			horizontalRes = 1
		case image.YCbCrSubsampleRatio444:
			verticalRes = 1
			horizontalRes = 1
		default:
			return nil, errors.New("unsupported YCbCr subsample ratio")
		}
		im.setter = func(x, y int, c color.Color) {
			r, g, b, _ := c.RGBA()
			yc, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
			m.Y[y*m.YStride+x] = yc
			off := y/verticalRes*m.CStride + x/horizontalRes
			m.Cb[off] = cb
			m.Cr[off] = cr
		}
	case *image.RGBA:
		im = &ImageMap{
			Pix:     m.Pix[1:],
			YStride: m.Stride,
			XStride: 4,
			Width:   img.Bounds().Dx(),
			Height:  img.Bounds().Dy(),
			Stddev:  1.0,
			setter:  m.Set,
		}
	case *image.Gray:
		im = &ImageMap{
			Pix:     m.Pix,
			YStride: m.Stride,
			XStride: 1,
			Width:   img.Bounds().Dx(),
			Height:  img.Bounds().Dy(),
			Stddev:  1.0,
			setter:  m.Set,
		}
	default:
		return nil, errors.New("Unsupported image format")
	}

	m := -1.0
	s := 0.0
	count := 0
	for y := 0; y < im.Height; y++ {
		for x := 0; x < im.Width; x++ {
			count++
			v := float64(im.Pix[y*im.YStride+x*im.XStride])
			oldM := m
			if oldM == -1 {
				m = v
				s = 0
			} else {
				m = oldM + ((v - oldM) / float64(count))
				s += (v - oldM) * (v - m)
			}
		}
	}
	stddev := math.Sqrt(s / float64(count-1))
	im.Stddev = stddev

	return im, nil
}
Exemplo n.º 12
0
func TestGetPixel(t *testing.T) {
	var pg *pixelGetter

	// RGBA, NRGBA, RGBA64, NRGBA64

	palette := []color.Color{
		color.NRGBA{0, 0, 0, 0},
		color.NRGBA{255, 255, 255, 255},
		color.NRGBA{50, 100, 150, 255},
		color.NRGBA{150, 100, 50, 200},
	}

	images1 := []draw.Image{
		image.NewRGBA(image.Rect(-1, -2, 3, 4)),
		image.NewRGBA64(image.Rect(-1, -2, 3, 4)),
		image.NewNRGBA(image.Rect(-1, -2, 3, 4)),
		image.NewNRGBA64(image.Rect(-1, -2, 3, 4)),
		image.NewPaletted(image.Rect(-1, -2, 3, 4), palette),
	}

	colors1 := []struct {
		c  color.NRGBA
		px pixel
	}{
		{color.NRGBA{0, 0, 0, 0}, pixel{0, 0, 0, 0}},
		{color.NRGBA{255, 255, 255, 255}, pixel{1, 1, 1, 1}},
		{color.NRGBA{50, 100, 150, 255}, pixel{0.196, 0.392, 0.588, 1}},
		{color.NRGBA{150, 100, 50, 200}, pixel{0.588, 0.392, 0.196, 0.784}},
	}

	for _, img := range images1 {
		pg = newPixelGetter(img)
		for _, k := range colors1 {
			for _, x := range []int{-1, 0, 2} {
				for _, y := range []int{-2, 0, 3} {
					img.Set(x, y, k.c)
					px := pg.getPixel(x, y)
					if !comparePixels(k.px, px, 0.005) {
						t.Errorf("getPixel %T %v %dx%d %v %v", img, k.c, x, y, k.px, px)
					}
				}
			}
		}
	}

	// Uniform (Generic)

	for _, k := range colors1 {
		img := image.NewUniform(k.c)
		pg = newPixelGetter(img)
		for _, x := range []int{-1, 0, 2} {
			for _, y := range []int{-2, 0, 3} {
				px := pg.getPixel(x, y)
				if !comparePixels(k.px, px, 0.005) {
					t.Errorf("getPixel %T %v %dx%d %v %v", img, k.c, x, y, k.px, px)
				}
			}
		}
	}

	// YCbCr

	colors2 := []struct {
		c  color.NRGBA
		px pixel
	}{
		{color.NRGBA{0, 0, 0, 255}, pixel{0, 0, 0, 1}},
		{color.NRGBA{255, 255, 255, 255}, pixel{1, 1, 1, 1}},
		{color.NRGBA{50, 100, 150, 255}, pixel{0.196, 0.392, 0.588, 1}},
	}

	for _, k := range colors2 {
		img := image.NewYCbCr(image.Rect(-1, -2, 3, 4), image.YCbCrSubsampleRatio444)
		pg = newPixelGetter(img)
		for _, x := range []int{-1, 0, 2} {
			for _, y := range []int{-2, 0, 3} {
				iy := img.YOffset(x, y)
				ic := img.COffset(x, y)
				img.Y[iy], img.Cb[ic], img.Cr[ic] = color.RGBToYCbCr(k.c.R, k.c.G, k.c.B)
				px := pg.getPixel(x, y)
				if !comparePixels(k.px, px, 0.005) {
					t.Errorf("getPixel %T %v %dx%d %v %v", img, k.c, x, y, k.px, px)
				}
			}
		}
	}

	// Gray, Gray16

	images2 := []draw.Image{
		image.NewGray(image.Rect(-1, -2, 3, 4)),
		image.NewGray16(image.Rect(-1, -2, 3, 4)),
	}

	colors3 := []struct {
		c  color.NRGBA
		px pixel
	}{
		{color.NRGBA{0, 0, 0, 0}, pixel{0, 0, 0, 1}},
		{color.NRGBA{255, 255, 255, 255}, pixel{1, 1, 1, 1}},
		{color.NRGBA{50, 100, 150, 255}, pixel{0.356, 0.356, 0.356, 1}},
		{color.NRGBA{150, 100, 50, 200}, pixel{0.337, 0.337, 0.337, 1}},
	}

	for _, img := range images2 {
		pg = newPixelGetter(img)
		for _, k := range colors3 {
			for _, x := range []int{-1, 0, 2} {
				for _, y := range []int{-2, 0, 3} {
					img.Set(x, y, k.c)
					px := pg.getPixel(x, y)
					if !comparePixels(k.px, px, 0.005) {
						t.Errorf("getPixel %T %v %dx%d %v %v", img, k.c, x, y, k.px, px)
					}
				}
			}
		}
	}
}