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  }