func decodeGray(dinfo *C.struct_jpeg_decompress_struct) (dest *image.Gray, err error) { // output dawnsampled raw data before starting decompress dinfo.raw_data_out = C.TRUE C.jpeg_start_decompress(dinfo) compInfo := (*[1]C.jpeg_component_info)(unsafe.Pointer(dinfo.comp_info)) dest = NewGrayAligned(image.Rect(0, 0, int(compInfo[0].downsampled_width), int(compInfo[0].downsampled_height))) iMCURows := int(C.DCT_v_scaled_size(dinfo, C.int(0)) * compInfo[0].v_samp_factor) C.decode_gray(dinfo, C.JSAMPROW(unsafe.Pointer(&dest.Pix[0])), C.int(dest.Stride), C.int(iMCURows)) C.jpeg_finish_decompress(dinfo) return }
func decodeYCbCr(dinfo *C.struct_jpeg_decompress_struct) (dest *image.YCbCr, err error) { // output dawnsampled raw data before starting decompress dinfo.raw_data_out = C.TRUE C.jpeg_start_decompress(dinfo) compInfo := (*[3]C.jpeg_component_info)(unsafe.Pointer(dinfo.comp_info)) dwY := compInfo[Y].downsampled_width dhY := compInfo[Y].downsampled_height dwC := compInfo[Cb].downsampled_width dhC := compInfo[Cb].downsampled_height //fmt.Printf("%d %d %d %d\n", dwY, dhY, dwC, dhC) if dwC != compInfo[Cr].downsampled_width || dhC != compInfo[Cr].downsampled_height { return nil, errors.New("Unsupported color subsampling (Cb and Cr differ)") } // Since the decisions about which DCT size and subsampling mode // to use, if any, are complex, instead just check the calculated // output plane sizes and infer the subsampling mode from that. var subsampleRatio image.YCbCrSubsampleRatio colorVDiv := 1 switch { case dwY == dwC && dhY == dhC: subsampleRatio = image.YCbCrSubsampleRatio444 case dwY == dwC && (dhY+1)/2 == dhC: subsampleRatio = image.YCbCrSubsampleRatio440 colorVDiv = 2 case (dwY+1)/2 == dwC && dhY == dhC: subsampleRatio = image.YCbCrSubsampleRatio422 case (dwY+1)/2 == dwC && (dhY+1)/2 == dhC: subsampleRatio = image.YCbCrSubsampleRatio420 colorVDiv = 2 default: return nil, errors.New("Unsupported color subsampling") } // Allocate distination iamge dest = NewYCbCrAligned(image.Rect(0, 0, int(dinfo.output_width), int(dinfo.output_height)), subsampleRatio) var iMCURows int for i := 0; i < int(dinfo.num_components); i++ { compRows := int(C.DCT_v_scaled_size(dinfo, C.int(i)) * compInfo[i].v_samp_factor) if compRows > iMCURows { iMCURows = compRows } } //fmt.Printf("iMCU_rows: %d (div: %d)\n", iMCURows, colorVDiv) C.decode_ycbcr(dinfo, C.JSAMPROW(unsafe.Pointer(&dest.Y[0])), C.JSAMPROW(unsafe.Pointer(&dest.Cb[0])), C.JSAMPROW(unsafe.Pointer(&dest.Cr[0])), C.int(dest.YStride), C.int(dest.CStride), C.int(colorVDiv), C.int(iMCURows), ) C.jpeg_finish_decompress(dinfo) return }