22b955cca5
Reviewed-on: https://go-review.googlesource.com/25150 From-SVN: r238662
269 lines
7.5 KiB
Go
269 lines
7.5 KiB
Go
// generated by "go run gen.go". DO NOT EDIT.
|
|
|
|
package imageutil
|
|
|
|
import (
|
|
"image"
|
|
)
|
|
|
|
// DrawYCbCr draws the YCbCr source image on the RGBA destination image with
|
|
// r.Min in dst aligned with sp in src. It reports whether the draw was
|
|
// successful. If it returns false, no dst pixels were changed.
|
|
//
|
|
// This function assumes that r is entirely within dst's bounds and the
|
|
// translation of r from dst coordinate space to src coordinate space is
|
|
// entirely within src's bounds.
|
|
func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
|
|
// This function exists in the image/internal/imageutil package because it
|
|
// is needed by both the image/draw and image/jpeg packages, but it doesn't
|
|
// seem right for one of those two to depend on the other.
|
|
//
|
|
// Another option is to have this code be exported in the image package,
|
|
// but we'd need to make sure we're totally happy with the API (for the
|
|
// rest of Go 1 compatibility), and decide if we want to have a more
|
|
// general purpose DrawToRGBA method for other image types. One possibility
|
|
// is:
|
|
//
|
|
// func (src *YCbCr) CopyToRGBA(dst *RGBA, dr, sr Rectangle) (effectiveDr, effectiveSr Rectangle)
|
|
//
|
|
// in the spirit of the built-in copy function for 1-dimensional slices,
|
|
// that also allowed a CopyFromRGBA method if needed.
|
|
|
|
x0 := (r.Min.X - dst.Rect.Min.X) * 4
|
|
x1 := (r.Max.X - dst.Rect.Min.X) * 4
|
|
y0 := r.Min.Y - dst.Rect.Min.Y
|
|
y1 := r.Max.Y - dst.Rect.Min.Y
|
|
switch src.SubsampleRatio {
|
|
|
|
case image.YCbCrSubsampleRatio444:
|
|
for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
|
|
dpix := dst.Pix[y*dst.Stride:]
|
|
yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
|
|
|
|
ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
|
|
for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
|
|
|
|
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
|
|
yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
|
|
cb1 := int32(src.Cb[ci]) - 128
|
|
cr1 := int32(src.Cr[ci]) - 128
|
|
|
|
// The bit twiddling below is equivalent to
|
|
//
|
|
// r := (yy1 + 91881*cr1) >> 16
|
|
// if r < 0 {
|
|
// r = 0
|
|
// } else if r > 0xff {
|
|
// r = ^int32(0)
|
|
// }
|
|
//
|
|
// but uses fewer branches and is faster.
|
|
// Note that the uint8 type conversion in the return
|
|
// statement will convert ^int32(0) to 0xff.
|
|
// The code below to compute g and b uses a similar pattern.
|
|
r := yy1 + 91881*cr1
|
|
if uint32(r)&0xff000000 == 0 {
|
|
r >>= 16
|
|
} else {
|
|
r = ^(r >> 31)
|
|
}
|
|
|
|
g := yy1 - 22554*cb1 - 46802*cr1
|
|
if uint32(g)&0xff000000 == 0 {
|
|
g >>= 16
|
|
} else {
|
|
g = ^(g >> 31)
|
|
}
|
|
|
|
b := yy1 + 116130*cb1
|
|
if uint32(b)&0xff000000 == 0 {
|
|
b >>= 16
|
|
} else {
|
|
b = ^(b >> 31)
|
|
}
|
|
|
|
// use a temp slice to hint to the compiler that a single bounds check suffices
|
|
rgba := dpix[x : x+4 : len(dpix)]
|
|
rgba[0] = uint8(r)
|
|
rgba[1] = uint8(g)
|
|
rgba[2] = uint8(b)
|
|
rgba[3] = 255
|
|
}
|
|
}
|
|
|
|
case image.YCbCrSubsampleRatio422:
|
|
for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
|
|
dpix := dst.Pix[y*dst.Stride:]
|
|
yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
|
|
|
|
ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2
|
|
for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
|
|
ci := ciBase + sx/2
|
|
|
|
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
|
|
yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
|
|
cb1 := int32(src.Cb[ci]) - 128
|
|
cr1 := int32(src.Cr[ci]) - 128
|
|
|
|
// The bit twiddling below is equivalent to
|
|
//
|
|
// r := (yy1 + 91881*cr1) >> 16
|
|
// if r < 0 {
|
|
// r = 0
|
|
// } else if r > 0xff {
|
|
// r = ^int32(0)
|
|
// }
|
|
//
|
|
// but uses fewer branches and is faster.
|
|
// Note that the uint8 type conversion in the return
|
|
// statement will convert ^int32(0) to 0xff.
|
|
// The code below to compute g and b uses a similar pattern.
|
|
r := yy1 + 91881*cr1
|
|
if uint32(r)&0xff000000 == 0 {
|
|
r >>= 16
|
|
} else {
|
|
r = ^(r >> 31)
|
|
}
|
|
|
|
g := yy1 - 22554*cb1 - 46802*cr1
|
|
if uint32(g)&0xff000000 == 0 {
|
|
g >>= 16
|
|
} else {
|
|
g = ^(g >> 31)
|
|
}
|
|
|
|
b := yy1 + 116130*cb1
|
|
if uint32(b)&0xff000000 == 0 {
|
|
b >>= 16
|
|
} else {
|
|
b = ^(b >> 31)
|
|
}
|
|
|
|
// use a temp slice to hint to the compiler that a single bounds check suffices
|
|
rgba := dpix[x : x+4 : len(dpix)]
|
|
rgba[0] = uint8(r)
|
|
rgba[1] = uint8(g)
|
|
rgba[2] = uint8(b)
|
|
rgba[3] = 255
|
|
}
|
|
}
|
|
|
|
case image.YCbCrSubsampleRatio420:
|
|
for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
|
|
dpix := dst.Pix[y*dst.Stride:]
|
|
yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
|
|
|
|
ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2
|
|
for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
|
|
ci := ciBase + sx/2
|
|
|
|
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
|
|
yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
|
|
cb1 := int32(src.Cb[ci]) - 128
|
|
cr1 := int32(src.Cr[ci]) - 128
|
|
|
|
// The bit twiddling below is equivalent to
|
|
//
|
|
// r := (yy1 + 91881*cr1) >> 16
|
|
// if r < 0 {
|
|
// r = 0
|
|
// } else if r > 0xff {
|
|
// r = ^int32(0)
|
|
// }
|
|
//
|
|
// but uses fewer branches and is faster.
|
|
// Note that the uint8 type conversion in the return
|
|
// statement will convert ^int32(0) to 0xff.
|
|
// The code below to compute g and b uses a similar pattern.
|
|
r := yy1 + 91881*cr1
|
|
if uint32(r)&0xff000000 == 0 {
|
|
r >>= 16
|
|
} else {
|
|
r = ^(r >> 31)
|
|
}
|
|
|
|
g := yy1 - 22554*cb1 - 46802*cr1
|
|
if uint32(g)&0xff000000 == 0 {
|
|
g >>= 16
|
|
} else {
|
|
g = ^(g >> 31)
|
|
}
|
|
|
|
b := yy1 + 116130*cb1
|
|
if uint32(b)&0xff000000 == 0 {
|
|
b >>= 16
|
|
} else {
|
|
b = ^(b >> 31)
|
|
}
|
|
|
|
// use a temp slice to hint to the compiler that a single bounds check suffices
|
|
rgba := dpix[x : x+4 : len(dpix)]
|
|
rgba[0] = uint8(r)
|
|
rgba[1] = uint8(g)
|
|
rgba[2] = uint8(b)
|
|
rgba[3] = 255
|
|
}
|
|
}
|
|
|
|
case image.YCbCrSubsampleRatio440:
|
|
for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
|
|
dpix := dst.Pix[y*dst.Stride:]
|
|
yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
|
|
|
|
ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X)
|
|
for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
|
|
|
|
// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
|
|
yy1 := int32(src.Y[yi]) * 0x010100 // Convert 0x12 to 0x121200.
|
|
cb1 := int32(src.Cb[ci]) - 128
|
|
cr1 := int32(src.Cr[ci]) - 128
|
|
|
|
// The bit twiddling below is equivalent to
|
|
//
|
|
// r := (yy1 + 91881*cr1) >> 16
|
|
// if r < 0 {
|
|
// r = 0
|
|
// } else if r > 0xff {
|
|
// r = ^int32(0)
|
|
// }
|
|
//
|
|
// but uses fewer branches and is faster.
|
|
// Note that the uint8 type conversion in the return
|
|
// statement will convert ^int32(0) to 0xff.
|
|
// The code below to compute g and b uses a similar pattern.
|
|
r := yy1 + 91881*cr1
|
|
if uint32(r)&0xff000000 == 0 {
|
|
r >>= 16
|
|
} else {
|
|
r = ^(r >> 31)
|
|
}
|
|
|
|
g := yy1 - 22554*cb1 - 46802*cr1
|
|
if uint32(g)&0xff000000 == 0 {
|
|
g >>= 16
|
|
} else {
|
|
g = ^(g >> 31)
|
|
}
|
|
|
|
b := yy1 + 116130*cb1
|
|
if uint32(b)&0xff000000 == 0 {
|
|
b >>= 16
|
|
} else {
|
|
b = ^(b >> 31)
|
|
}
|
|
|
|
// use a temp slice to hint to the compiler that a single bounds check suffices
|
|
rgba := dpix[x : x+4 : len(dpix)]
|
|
rgba[0] = uint8(r)
|
|
rgba[1] = uint8(g)
|
|
rgba[2] = uint8(b)
|
|
rgba[3] = 255
|
|
}
|
|
}
|
|
|
|
default:
|
|
return false
|
|
}
|
|
return true
|
|
}
|