...

Source file src/image/internal/imageutil/gen.go

     1	// Copyright 2015 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build ignore
     6	
     7	package main
     8	
     9	import (
    10		"bytes"
    11		"flag"
    12		"fmt"
    13		"go/format"
    14		"io/ioutil"
    15		"log"
    16		"os"
    17	)
    18	
    19	var debug = flag.Bool("debug", false, "")
    20	
    21	func main() {
    22		flag.Parse()
    23	
    24		w := new(bytes.Buffer)
    25		w.WriteString(pre)
    26		for _, sratio := range subsampleRatios {
    27			fmt.Fprintf(w, sratioCase, sratio, sratioLines[sratio])
    28		}
    29		w.WriteString(post)
    30	
    31		if *debug {
    32			os.Stdout.Write(w.Bytes())
    33			return
    34		}
    35		out, err := format.Source(w.Bytes())
    36		if err != nil {
    37			log.Fatal(err)
    38		}
    39		if err := ioutil.WriteFile("impl.go", out, 0660); err != nil {
    40			log.Fatal(err)
    41		}
    42	}
    43	
    44	const pre = `// Code generated by go run gen.go; DO NOT EDIT.
    45	
    46	package imageutil
    47	
    48	import (
    49		"image"
    50	)
    51	
    52	// DrawYCbCr draws the YCbCr source image on the RGBA destination image with
    53	// r.Min in dst aligned with sp in src. It reports whether the draw was
    54	// successful. If it returns false, no dst pixels were changed.
    55	//
    56	// This function assumes that r is entirely within dst's bounds and the
    57	// translation of r from dst coordinate space to src coordinate space is
    58	// entirely within src's bounds.
    59	func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) {
    60		// This function exists in the image/internal/imageutil package because it
    61		// is needed by both the image/draw and image/jpeg packages, but it doesn't
    62		// seem right for one of those two to depend on the other.
    63		//
    64		// Another option is to have this code be exported in the image package,
    65		// but we'd need to make sure we're totally happy with the API (for the
    66		// rest of Go 1 compatibility), and decide if we want to have a more
    67		// general purpose DrawToRGBA method for other image types. One possibility
    68		// is:
    69		//
    70		// func (src *YCbCr) CopyToRGBA(dst *RGBA, dr, sr Rectangle) (effectiveDr, effectiveSr Rectangle)
    71		//
    72		// in the spirit of the built-in copy function for 1-dimensional slices,
    73		// that also allowed a CopyFromRGBA method if needed.
    74	
    75		x0 := (r.Min.X - dst.Rect.Min.X) * 4
    76		x1 := (r.Max.X - dst.Rect.Min.X) * 4
    77		y0 := r.Min.Y - dst.Rect.Min.Y
    78		y1 := r.Max.Y - dst.Rect.Min.Y
    79		switch src.SubsampleRatio {
    80	`
    81	
    82	const post = `
    83		default:
    84			return false
    85		}
    86		return true
    87	}
    88	`
    89	
    90	const sratioCase = `
    91		case image.YCbCrSubsampleRatio%s:
    92			for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
    93				dpix := dst.Pix[y*dst.Stride:]
    94				yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X)
    95				%s
    96	
    97					// This is an inline version of image/color/ycbcr.go's func YCbCrToRGB.
    98					yy1 := int32(src.Y[yi]) * 0x10101
    99					cb1 := int32(src.Cb[ci]) - 128
   100					cr1 := int32(src.Cr[ci]) - 128
   101	
   102					// The bit twiddling below is equivalent to
   103					//
   104					// r := (yy1 + 91881*cr1) >> 16
   105					// if r < 0 {
   106					//     r = 0
   107					// } else if r > 0xff {
   108					//     r = ^int32(0)
   109					// }
   110					//
   111					// but uses fewer branches and is faster.
   112					// Note that the uint8 type conversion in the return
   113					// statement will convert ^int32(0) to 0xff.
   114					// The code below to compute g and b uses a similar pattern.
   115					r := yy1 + 91881*cr1
   116					if uint32(r)&0xff000000 == 0 {
   117						r >>= 16
   118					} else {
   119						r = ^(r >> 31)
   120					}
   121	
   122					g := yy1 - 22554*cb1 - 46802*cr1
   123					if uint32(g)&0xff000000 == 0 {
   124						g >>= 16
   125					} else {
   126						g = ^(g >> 31)
   127					}
   128	
   129					b := yy1 + 116130*cb1
   130					if uint32(b)&0xff000000 == 0 {
   131						b >>= 16
   132					} else {
   133						b = ^(b >> 31)
   134					}
   135	
   136	
   137					// use a temp slice to hint to the compiler that a single bounds check suffices
   138					rgba := dpix[x : x+4 : len(dpix)]
   139					rgba[0] = uint8(r)
   140					rgba[1] = uint8(g)
   141					rgba[2] = uint8(b)
   142					rgba[3] = 255
   143				}
   144			}
   145	`
   146	
   147	var subsampleRatios = []string{
   148		"444",
   149		"422",
   150		"420",
   151		"440",
   152	}
   153	
   154	var sratioLines = map[string]string{
   155		"444": `
   156			ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X)
   157			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
   158		`,
   159		"422": `
   160			ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2
   161			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
   162				ci := ciBase + sx/2
   163		`,
   164		"420": `
   165			ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2
   166			for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 {
   167				ci := ciBase + sx/2
   168		`,
   169		"440": `
   170			ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X)
   171			for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 {
   172		`,
   173	}
   174	

View as plain text