github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/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]) * 0x10100 // Convert 0x12 to 0x121200. 99 cb1 := int32(src.Cb[ci]) - 128 100 cr1 := int32(src.Cr[ci]) - 128 101 r := (yy1 + 91881*cr1) >> 16 102 g := (yy1 - 22554*cb1 - 46802*cr1) >> 16 103 b := (yy1 + 116130*cb1) >> 16 104 if r < 0 { 105 r = 0 106 } else if r > 255 { 107 r = 255 108 } 109 if g < 0 { 110 g = 0 111 } else if g > 255 { 112 g = 255 113 } 114 if b < 0 { 115 b = 0 116 } else if b > 255 { 117 b = 255 118 } 119 120 dpix[x+0] = uint8(r) 121 dpix[x+1] = uint8(g) 122 dpix[x+2] = uint8(b) 123 dpix[x+3] = 255 124 } 125 } 126 ` 127 128 var subsampleRatios = []string{ 129 "444", 130 "422", 131 "420", 132 "440", 133 } 134 135 var sratioLines = map[string]string{ 136 "444": ` 137 ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X) 138 for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 { 139 `, 140 "422": ` 141 ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2 142 for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 { 143 ci := ciBase + sx/2 144 `, 145 "420": ` 146 ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2 147 for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 { 148 ci := ciBase + sx/2 149 `, 150 "440": ` 151 ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X) 152 for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 { 153 `, 154 }