github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/image/internal/imageutil/gen.go (about) 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 = `// 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 }