From: Nigel Tao Date: Thu, 18 Oct 2012 23:55:41 +0000 (+1100) Subject: image/draw: fast-path for 4:4:0 chroma subsampled sources. X-Git-Tag: go1.1rc2~2103 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5abf4bdc2775e4514f9cf8e2bf842f685eba2fd8;p=gostls13.git image/draw: fast-path for 4:4:0 chroma subsampled sources. R=r CC=golang-dev https://golang.org/cl/6699049 --- diff --git a/src/pkg/image/draw/draw.go b/src/pkg/image/draw/draw.go index bef325c0c9..56d30dd6f8 100644 --- a/src/pkg/image/draw/draw.go +++ b/src/pkg/image/draw/draw.go @@ -81,8 +81,9 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas drawNRGBAOver(dst0, r, src0, sp) return case *image.YCbCr: - drawYCbCr(dst0, r, src0, sp) - return + if drawYCbCr(dst0, r, src0, sp) { + return + } } } else if mask0, ok := mask.(*image.Alpha); ok { switch src0 := src.(type) { @@ -104,8 +105,9 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas drawNRGBASrc(dst0, r, src0, sp) return case *image.YCbCr: - drawYCbCr(dst0, r, src0, sp) - return + if drawYCbCr(dst0, r, src0, sp) { + 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 // (i.e. fully opaque) then the op is effectively always Src. 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 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 { + 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: for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { 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 } } - default: - // Default to 4:4:4 subsampling. + 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-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 { rr, gg, bb := color.YCbCrToRGB(src.Y[yi], src.Cb[ci], src.Cr[ci]) 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 } } + default: + return false } + return true } func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) { diff --git a/src/pkg/image/jpeg/reader_test.go b/src/pkg/image/jpeg/reader_test.go index c3c33a2bc5..f7fbd9a8a5 100644 --- a/src/pkg/image/jpeg/reader_test.go +++ b/src/pkg/image/jpeg/reader_test.go @@ -21,6 +21,7 @@ func TestDecodeProgressive(t *testing.T) { "../testdata/video-001", "../testdata/video-001.q50.420", "../testdata/video-001.q50.422", + "../testdata/video-001.q50.440", "../testdata/video-001.q50.444", "../testdata/video-005.gray.q50", } diff --git a/src/pkg/image/testdata/video-001.q50.440.jpeg b/src/pkg/image/testdata/video-001.q50.440.jpeg new file mode 100644 index 0000000000..32eeeaef6f Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.440.jpeg differ diff --git a/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg b/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg new file mode 100644 index 0000000000..e641a3bbbc Binary files /dev/null and b/src/pkg/image/testdata/video-001.q50.440.progressive.jpeg differ