]> Cypherpunks repositories - gostls13.git/commitdiff
image/jpeg: remove the (temporary) dependency on image/draw.
authorNigel Tao <nigeltao@golang.org>
Mon, 16 Feb 2015 04:10:50 +0000 (15:10 +1100)
committerNigel Tao <nigeltao@golang.org>
Mon, 16 Feb 2015 04:37:15 +0000 (04:37 +0000)
Change-Id: Idd66f9c3c9eaa4ff1f950fb90e4800dc625dec08
Reviewed-on: https://go-review.googlesource.com/4916
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
src/image/draw/draw.go
src/image/jpeg/reader.go

index cffdcbc0d7cf4814a4e8b2aec9cc566500b32f5e..b1fc979a7dc8e7a7c548e8cd44b2adf9525c6c7b 100644 (file)
@@ -392,6 +392,8 @@ func drawNRGBASrc(dst *image.RGBA, r image.Rectangle, src *image.NRGBA, sp image
        }
 }
 
+// TODO(nigeltao): this function is copy/pasted to image/jpeg/reader.go. We
+// should un-copy/paste it.
 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.
index 72c3f064c0bc5a696a21221c23aeb1bd408b31c4..863f55bf2528571afe0fc77c62452b8c616ff063 100644 (file)
@@ -10,7 +10,6 @@ package jpeg
 import (
        "image"
        "image/color"
-       "image/draw"
        "io"
 )
 
@@ -587,10 +586,7 @@ func (d *decoder) applyBlack() (image.Image, error) {
                // above, so in practice, only the fourth channel (black) is inverted.
                bounds := d.img3.Bounds()
                img := image.NewRGBA(bounds)
-               // TODO(nigeltao): do the draw.Draw YCbCr -> RGB conversion directly,
-               // instead of having the image/jpeg package depend on the image/draw
-               // package.
-               draw.Draw(img, bounds, d.img3, bounds.Min, draw.Src)
+               drawYCbCr(img, bounds, d.img3, bounds.Min)
                for iBase, y := 0, bounds.Min.Y; y < bounds.Max.Y; iBase, y = iBase+img.Stride, y+1 {
                        for i, x := iBase+3, bounds.Min.X; x < bounds.Max.X; i, x = i+4, x+1 {
                                img.Pix[i] = 255 - d.blackPix[(y-bounds.Min.Y)*d.blackStride+(x-bounds.Min.X)]
@@ -639,6 +635,82 @@ func (d *decoder) applyBlack() (image.Image, error) {
        return img, nil
 }
 
+// drawYCbCr is the non-exported drawYCbCr function copy/pasted from the
+// image/draw package. It is copy/pasted because it doesn't seem right for the
+// image/jpeg package to depend on image/draw.
+//
+// TODO(nigeltao): remove the copy/paste, possibly by moving this to be an
+// exported method on *image.YCbCr. We'd need to make sure we're totally happy
+// with the API (for the rest of Go 1 compatibility) though, and if we want to
+// have a more general purpose DrawToRGBA method for other image types.
+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
+       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 {
+                               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:]
+                       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
+                               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.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
+                               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.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 {
+                               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
+                       }
+               }
+       default:
+               return false
+       }
+       return true
+}
+
 // Decode reads a JPEG image from r and returns it as an image.Image.
 func Decode(r io.Reader) (image.Image, error) {
        var d decoder