1
0
mirror of https://github.com/golang/go synced 2024-11-26 09:18:07 -07:00

image/draw: fast-path for 4:4:0 chroma subsampled sources.

R=r
CC=golang-dev
https://golang.org/cl/6699049
This commit is contained in:
Nigel Tao 2012-10-19 10:55:41 +11:00
parent 1e6d9f49da
commit 5abf4bdc27
4 changed files with 26 additions and 8 deletions

View File

@ -81,9 +81,10 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
drawNRGBAOver(dst0, r, src0, sp) drawNRGBAOver(dst0, r, src0, sp)
return return
case *image.YCbCr: case *image.YCbCr:
drawYCbCr(dst0, r, src0, sp) if drawYCbCr(dst0, r, src0, sp) {
return return
} }
}
} else if mask0, ok := mask.(*image.Alpha); ok { } else if mask0, ok := mask.(*image.Alpha); ok {
switch src0 := src.(type) { switch src0 := src.(type) {
case *image.Uniform: case *image.Uniform:
@ -104,11 +105,12 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
drawNRGBASrc(dst0, r, src0, sp) drawNRGBASrc(dst0, r, src0, sp)
return return
case *image.YCbCr: case *image.YCbCr:
drawYCbCr(dst0, r, src0, sp) if drawYCbCr(dst0, r, src0, sp) {
return return
} }
} }
} }
}
drawRGBA(dst0, r, src, sp, mask, mp, op) drawRGBA(dst0, r, src, sp, mask, mp, op)
return return
} }
@ -345,7 +347,7 @@ func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image
} }
} }
func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) { func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
// An image.YCbCr is always fully opaque, and so if the mask is implicitly nil // An image.YCbCr is always fully opaque, and so if the mask is implicitly nil
// (i.e. fully opaque) then the op is effectively always Src. // (i.e. fully opaque) then the op is effectively always Src.
x0 := (r.Min.X - dst.Rect.Min.X) * 4 x0 := (r.Min.X - dst.Rect.Min.X) * 4
@ -353,6 +355,19 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
y0 := r.Min.Y - dst.Rect.Min.Y y0 := r.Min.Y - dst.Rect.Min.Y
y1 := r.Max.Y - dst.Rect.Min.Y y1 := r.Max.Y - dst.Rect.Min.Y
switch src.SubsampleRatio { 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 {
rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
dpix[x+0] = rr
dpix[x+1] = gg
dpix[x+2] = bb
dpix[x+3] = 255
}
}
case image.YCbCrSubsampleRatio422: case image.YCbCrSubsampleRatio422:
for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
dpix := dst.Pix[y*dst.Stride:] dpix := dst.Pix[y*dst.Stride:]
@ -381,12 +396,11 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
dpix[x+3] = 255 dpix[x+3] = 255
} }
} }
default: case image.YCbCrSubsampleRatio440:
// Default to 4:4:4 subsampling.
for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
dpix := dst.Pix[y*dst.Stride:] dpix := dst.Pix[y*dst.Stride:]
yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X) 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) 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 { for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci]) rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci])
dpix[x+0] = rr dpix[x+0] = rr
@ -395,7 +409,10 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po
dpix[x+3] = 255 dpix[x+3] = 255
} }
} }
default:
return false
} }
return true
} }
func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) { func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {

View File

@ -21,6 +21,7 @@ func TestDecodeProgressive(t *testing.T) {
"../testdata/video-001", "../testdata/video-001",
"../testdata/video-001.q50.420", "../testdata/video-001.q50.420",
"../testdata/video-001.q50.422", "../testdata/video-001.q50.422",
"../testdata/video-001.q50.440",
"../testdata/video-001.q50.444", "../testdata/video-001.q50.444",
"../testdata/video-005.gray.q50", "../testdata/video-005.gray.q50",
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB