From a3a193c01855fc15429d5376f4dad11796b2b7bd Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Tue, 24 Mar 2015 11:45:29 +1100 Subject: [PATCH] image/internal/imageutil: inline the color.YCbCrToRGB calls. The image/draw benchmark: benchmark old ns/op new ns/op delta BenchmarkYCbCr 1198605 978647 -18.35% Change-Id: Iacfc21e6f641ecb05adc00b3aec0048f1f43d265 Reviewed-on: https://go-review.googlesource.com/7952 Reviewed-by: Rob Pike --- src/image/internal/imageutil/gen.go | 32 +++++-- src/image/internal/imageutil/impl.go | 121 +++++++++++++++++++++++---- 2 files changed, 131 insertions(+), 22 deletions(-) diff --git a/src/image/internal/imageutil/gen.go b/src/image/internal/imageutil/gen.go index 59125dadbf..cde05ad088 100644 --- a/src/image/internal/imageutil/gen.go +++ b/src/image/internal/imageutil/gen.go @@ -47,7 +47,6 @@ package imageutil import ( "image" - "image/color" ) // DrawYCbCr draws the YCbCr source image on the RGBA destination image with @@ -94,10 +93,33 @@ const sratioCase = ` dpix := dst.Pix[y*dst.Stride:] yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X) %s - 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 + + // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. + yy1 := int(src.Y[yi])<<16 + 1<<15 + cb1 := int(src.Cb[ci]) - 128 + cr1 := int(src.Cr[ci]) - 128 + r := (yy1 + 91881*cr1) >> 16 + g := (yy1 - 22554*cb1 - 46802*cr1) >> 16 + b := (yy1 + 116130*cb1) >> 16 + if r < 0 { + r = 0 + } else if r > 255 { + r = 255 + } + if g < 0 { + g = 0 + } else if g > 255 { + g = 255 + } + if b < 0 { + b = 0 + } else if b > 255 { + b = 255 + } + + dpix[x+0] = uint8(r) + dpix[x+1] = uint8(g) + dpix[x+2] = uint8(b) dpix[x+3] = 255 } } diff --git a/src/image/internal/imageutil/impl.go b/src/image/internal/imageutil/impl.go index 5a156e40bc..d4bd3250fd 100644 --- a/src/image/internal/imageutil/impl.go +++ b/src/image/internal/imageutil/impl.go @@ -4,7 +4,6 @@ package imageutil import ( "image" - "image/color" ) // DrawYCbCr draws the YCbCr source image on the RGBA destination image with @@ -44,10 +43,32 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po 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 + // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. + yy1 := int(src.Y[yi])<<16 + 1<<15 + cb1 := int(src.Cb[ci]) - 128 + cr1 := int(src.Cr[ci]) - 128 + r := (yy1 + 91881*cr1) >> 16 + g := (yy1 - 22554*cb1 - 46802*cr1) >> 16 + b := (yy1 + 116130*cb1) >> 16 + if r < 0 { + r = 0 + } else if r > 255 { + r = 255 + } + if g < 0 { + g = 0 + } else if g > 255 { + g = 255 + } + if b < 0 { + b = 0 + } else if b > 255 { + b = 255 + } + + dpix[x+0] = uint8(r) + dpix[x+1] = uint8(g) + dpix[x+2] = uint8(b) dpix[x+3] = 255 } } @@ -61,10 +82,32 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 { ci := ciBase + sx/2 - 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 + // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. + yy1 := int(src.Y[yi])<<16 + 1<<15 + cb1 := int(src.Cb[ci]) - 128 + cr1 := int(src.Cr[ci]) - 128 + r := (yy1 + 91881*cr1) >> 16 + g := (yy1 - 22554*cb1 - 46802*cr1) >> 16 + b := (yy1 + 116130*cb1) >> 16 + if r < 0 { + r = 0 + } else if r > 255 { + r = 255 + } + if g < 0 { + g = 0 + } else if g > 255 { + g = 255 + } + if b < 0 { + b = 0 + } else if b > 255 { + b = 255 + } + + dpix[x+0] = uint8(r) + dpix[x+1] = uint8(g) + dpix[x+2] = uint8(b) dpix[x+3] = 255 } } @@ -78,10 +121,32 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 { ci := ciBase + sx/2 - 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 + // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. + yy1 := int(src.Y[yi])<<16 + 1<<15 + cb1 := int(src.Cb[ci]) - 128 + cr1 := int(src.Cr[ci]) - 128 + r := (yy1 + 91881*cr1) >> 16 + g := (yy1 - 22554*cb1 - 46802*cr1) >> 16 + b := (yy1 + 116130*cb1) >> 16 + if r < 0 { + r = 0 + } else if r > 255 { + r = 255 + } + if g < 0 { + g = 0 + } else if g > 255 { + g = 255 + } + if b < 0 { + b = 0 + } else if b > 255 { + b = 255 + } + + dpix[x+0] = uint8(r) + dpix[x+1] = uint8(g) + dpix[x+2] = uint8(b) dpix[x+3] = 255 } } @@ -94,10 +159,32 @@ func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Po 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 - dpix[x+1] = gg - dpix[x+2] = bb + // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. + yy1 := int(src.Y[yi])<<16 + 1<<15 + cb1 := int(src.Cb[ci]) - 128 + cr1 := int(src.Cr[ci]) - 128 + r := (yy1 + 91881*cr1) >> 16 + g := (yy1 - 22554*cb1 - 46802*cr1) >> 16 + b := (yy1 + 116130*cb1) >> 16 + if r < 0 { + r = 0 + } else if r > 255 { + r = 255 + } + if g < 0 { + g = 0 + } else if g > 255 { + g = 255 + } + if b < 0 { + b = 0 + } else if b > 255 { + b = 255 + } + + dpix[x+0] = uint8(r) + dpix[x+1] = uint8(g) + dpix[x+2] = uint8(b) dpix[x+3] = 255 } } -- 2.48.1