tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/image/internal/imageutil/impl.go (about) 1 // Code generated by go run gen.go; DO NOT EDIT. 2 3 package imageutil 4 5 import ( 6 "image" 7 ) 8 9 // DrawYCbCr draws the YCbCr source image on the RGBA destination image with 10 // r.Min in dst aligned with sp in src. It reports whether the draw was 11 // successful. If it returns false, no dst pixels were changed. 12 // 13 // This function assumes that r is entirely within dst's bounds and the 14 // translation of r from dst coordinate space to src coordinate space is 15 // entirely within src's bounds. 16 func DrawYCbCr(dst *image.RGBA, r image.Rectangle, src *image.YCbCr, sp image.Point) (ok bool) { 17 // This function exists in the image/internal/imageutil package because it 18 // is needed by both the image/draw and image/jpeg packages, but it doesn't 19 // seem right for one of those two to depend on the other. 20 // 21 // Another option is to have this code be exported in the image package, 22 // but we'd need to make sure we're totally happy with the API (for the 23 // rest of Go 1 compatibility), and decide if we want to have a more 24 // general purpose DrawToRGBA method for other image types. One possibility 25 // is: 26 // 27 // func (src *YCbCr) CopyToRGBA(dst *RGBA, dr, sr Rectangle) (effectiveDr, effectiveSr Rectangle) 28 // 29 // in the spirit of the built-in copy function for 1-dimensional slices, 30 // that also allowed a CopyFromRGBA method if needed. 31 32 x0 := (r.Min.X - dst.Rect.Min.X) * 4 33 x1 := (r.Max.X - dst.Rect.Min.X) * 4 34 y0 := r.Min.Y - dst.Rect.Min.Y 35 y1 := r.Max.Y - dst.Rect.Min.Y 36 switch src.SubsampleRatio { 37 38 case image.YCbCrSubsampleRatio444: 39 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { 40 dpix := dst.Pix[y*dst.Stride:] 41 yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X) 42 43 ci := (sy-src.Rect.Min.Y)*src.CStride + (sp.X - src.Rect.Min.X) 44 for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 { 45 46 // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. 47 yy1 := int32(src.Y[yi]) * 0x10101 48 cb1 := int32(src.Cb[ci]) - 128 49 cr1 := int32(src.Cr[ci]) - 128 50 51 // The bit twiddling below is equivalent to 52 // 53 // r := (yy1 + 91881*cr1) >> 16 54 // if r < 0 { 55 // r = 0 56 // } else if r > 0xff { 57 // r = ^int32(0) 58 // } 59 // 60 // but uses fewer branches and is faster. 61 // Note that the uint8 type conversion in the return 62 // statement will convert ^int32(0) to 0xff. 63 // The code below to compute g and b uses a similar pattern. 64 r := yy1 + 91881*cr1 65 if uint32(r)&0xff000000 == 0 { 66 r >>= 16 67 } else { 68 r = ^(r >> 31) 69 } 70 71 g := yy1 - 22554*cb1 - 46802*cr1 72 if uint32(g)&0xff000000 == 0 { 73 g >>= 16 74 } else { 75 g = ^(g >> 31) 76 } 77 78 b := yy1 + 116130*cb1 79 if uint32(b)&0xff000000 == 0 { 80 b >>= 16 81 } else { 82 b = ^(b >> 31) 83 } 84 85 // use a temp slice to hint to the compiler that a single bounds check suffices 86 rgba := dpix[x : x+4 : len(dpix)] 87 rgba[0] = uint8(r) 88 rgba[1] = uint8(g) 89 rgba[2] = uint8(b) 90 rgba[3] = 255 91 } 92 } 93 94 case image.YCbCrSubsampleRatio422: 95 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { 96 dpix := dst.Pix[y*dst.Stride:] 97 yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X) 98 99 ciBase := (sy-src.Rect.Min.Y)*src.CStride - src.Rect.Min.X/2 100 for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 { 101 ci := ciBase + sx/2 102 103 // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. 104 yy1 := int32(src.Y[yi]) * 0x10101 105 cb1 := int32(src.Cb[ci]) - 128 106 cr1 := int32(src.Cr[ci]) - 128 107 108 // The bit twiddling below is equivalent to 109 // 110 // r := (yy1 + 91881*cr1) >> 16 111 // if r < 0 { 112 // r = 0 113 // } else if r > 0xff { 114 // r = ^int32(0) 115 // } 116 // 117 // but uses fewer branches and is faster. 118 // Note that the uint8 type conversion in the return 119 // statement will convert ^int32(0) to 0xff. 120 // The code below to compute g and b uses a similar pattern. 121 r := yy1 + 91881*cr1 122 if uint32(r)&0xff000000 == 0 { 123 r >>= 16 124 } else { 125 r = ^(r >> 31) 126 } 127 128 g := yy1 - 22554*cb1 - 46802*cr1 129 if uint32(g)&0xff000000 == 0 { 130 g >>= 16 131 } else { 132 g = ^(g >> 31) 133 } 134 135 b := yy1 + 116130*cb1 136 if uint32(b)&0xff000000 == 0 { 137 b >>= 16 138 } else { 139 b = ^(b >> 31) 140 } 141 142 // use a temp slice to hint to the compiler that a single bounds check suffices 143 rgba := dpix[x : x+4 : len(dpix)] 144 rgba[0] = uint8(r) 145 rgba[1] = uint8(g) 146 rgba[2] = uint8(b) 147 rgba[3] = 255 148 } 149 } 150 151 case image.YCbCrSubsampleRatio420: 152 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { 153 dpix := dst.Pix[y*dst.Stride:] 154 yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X) 155 156 ciBase := (sy/2-src.Rect.Min.Y/2)*src.CStride - src.Rect.Min.X/2 157 for x, sx := x0, sp.X; x != x1; x, sx, yi = x+4, sx+1, yi+1 { 158 ci := ciBase + sx/2 159 160 // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. 161 yy1 := int32(src.Y[yi]) * 0x10101 162 cb1 := int32(src.Cb[ci]) - 128 163 cr1 := int32(src.Cr[ci]) - 128 164 165 // The bit twiddling below is equivalent to 166 // 167 // r := (yy1 + 91881*cr1) >> 16 168 // if r < 0 { 169 // r = 0 170 // } else if r > 0xff { 171 // r = ^int32(0) 172 // } 173 // 174 // but uses fewer branches and is faster. 175 // Note that the uint8 type conversion in the return 176 // statement will convert ^int32(0) to 0xff. 177 // The code below to compute g and b uses a similar pattern. 178 r := yy1 + 91881*cr1 179 if uint32(r)&0xff000000 == 0 { 180 r >>= 16 181 } else { 182 r = ^(r >> 31) 183 } 184 185 g := yy1 - 22554*cb1 - 46802*cr1 186 if uint32(g)&0xff000000 == 0 { 187 g >>= 16 188 } else { 189 g = ^(g >> 31) 190 } 191 192 b := yy1 + 116130*cb1 193 if uint32(b)&0xff000000 == 0 { 194 b >>= 16 195 } else { 196 b = ^(b >> 31) 197 } 198 199 // use a temp slice to hint to the compiler that a single bounds check suffices 200 rgba := dpix[x : x+4 : len(dpix)] 201 rgba[0] = uint8(r) 202 rgba[1] = uint8(g) 203 rgba[2] = uint8(b) 204 rgba[3] = 255 205 } 206 } 207 208 case image.YCbCrSubsampleRatio440: 209 for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 { 210 dpix := dst.Pix[y*dst.Stride:] 211 yi := (sy-src.Rect.Min.Y)*src.YStride + (sp.X - src.Rect.Min.X) 212 213 ci := (sy/2-src.Rect.Min.Y/2)*src.CStride + (sp.X - src.Rect.Min.X) 214 for x := x0; x != x1; x, yi, ci = x+4, yi+1, ci+1 { 215 216 // This is an inline version of image/color/ycbcr.go's func YCbCrToRGB. 217 yy1 := int32(src.Y[yi]) * 0x10101 218 cb1 := int32(src.Cb[ci]) - 128 219 cr1 := int32(src.Cr[ci]) - 128 220 221 // The bit twiddling below is equivalent to 222 // 223 // r := (yy1 + 91881*cr1) >> 16 224 // if r < 0 { 225 // r = 0 226 // } else if r > 0xff { 227 // r = ^int32(0) 228 // } 229 // 230 // but uses fewer branches and is faster. 231 // Note that the uint8 type conversion in the return 232 // statement will convert ^int32(0) to 0xff. 233 // The code below to compute g and b uses a similar pattern. 234 r := yy1 + 91881*cr1 235 if uint32(r)&0xff000000 == 0 { 236 r >>= 16 237 } else { 238 r = ^(r >> 31) 239 } 240 241 g := yy1 - 22554*cb1 - 46802*cr1 242 if uint32(g)&0xff000000 == 0 { 243 g >>= 16 244 } else { 245 g = ^(g >> 31) 246 } 247 248 b := yy1 + 116130*cb1 249 if uint32(b)&0xff000000 == 0 { 250 b >>= 16 251 } else { 252 b = ^(b >> 31) 253 } 254 255 // use a temp slice to hint to the compiler that a single bounds check suffices 256 rgba := dpix[x : x+4 : len(dpix)] 257 rgba[0] = uint8(r) 258 rgba[1] = uint8(g) 259 rgba[2] = uint8(b) 260 rgba[3] = 255 261 } 262 } 263 264 default: 265 return false 266 } 267 return true 268 }