// DecodeRGBA decodes WebP image into RGBA image and returns it as an *image.RGBA. func DecodeRGBA(data []byte, options *DecoderOptions) (img *image.RGBA, err error) { config, err := initDecoderConfig(options) if err != nil { return nil, err } cDataPtr := (*C.uint8_t)(&data[0]) cDataSize := (C.size_t)(len(data)) // Retrive WebP features if status := C.WebPGetFeatures(cDataPtr, cDataSize, &config.input); status != C.VP8_STATUS_OK { return nil, fmt.Errorf("Could not get features from the data stream, return %s", statusString(status)) } // Allocate output image outWidth, outHeight := calcOutputSize(config) img = image.NewRGBA(image.Rect(0, 0, outWidth, outHeight)) // Set up output configurations config.output.colorspace = C.MODE_RGBA config.output.is_external_memory = 1 // Allocate WebPRGBABuffer and fill in the pointers to output image buf := (*C.WebPRGBABuffer)(unsafe.Pointer(&config.output.u[0])) buf.rgba = (*C.uint8_t)(&img.Pix[0]) buf.stride = C.int(img.Stride) buf.size = (C.size_t)(len(img.Pix)) // Decode if status := C.WebPDecode(cDataPtr, cDataSize, config); status != C.VP8_STATUS_OK { return nil, fmt.Errorf("Could not decode data stream, return %s", statusString(status)) } return }
// DecodeYUVA decodes WebP image into YUV image with alpha channel, and returns // it as *YUVAImage. func DecodeYUVA(data []byte, options *DecoderOptions) (img *YUVAImage, err error) { config, err := initDecoderConfig(options) if err != nil { return nil, err } cDataPtr := (*C.uint8_t)(&data[0]) cDataSize := (C.size_t)(len(data)) // Retrive WebP features from data stream if status := C.WebPGetFeatures(cDataPtr, cDataSize, &config.input); status != C.VP8_STATUS_OK { return nil, fmt.Errorf("Could not get features from the data stream, return %s", statusString(status)) } outWidth, outHeight := calcOutputSize(config) buf := (*C.WebPYUVABuffer)(unsafe.Pointer(&config.output.u[0])) // Set up output configurations colorSpace := YUV420 config.output.colorspace = C.MODE_YUV if config.input.has_alpha > 0 { colorSpace = YUV420A config.output.colorspace = C.MODE_YUVA } config.output.is_external_memory = 1 // Allocate image and fill into buffer img = NewYUVAImage(image.Rect(0, 0, outWidth, outHeight), colorSpace) buf.y = (*C.uint8_t)(&img.Y[0]) buf.u = (*C.uint8_t)(&img.Cb[0]) buf.v = (*C.uint8_t)(&img.Cr[0]) buf.a = nil buf.y_stride = C.int(img.YStride) buf.u_stride = C.int(img.CStride) buf.v_stride = C.int(img.CStride) buf.a_stride = 0 buf.y_size = C.size_t(len(img.Y)) buf.u_size = C.size_t(len(img.Cb)) buf.v_size = C.size_t(len(img.Cr)) buf.a_size = 0 if config.input.has_alpha > 0 { buf.a = (*C.uint8_t)(&img.A[0]) buf.a_stride = C.int(img.AStride) buf.a_size = C.size_t(len(img.A)) } if status := C.WebPDecode(cDataPtr, cDataSize, config); status != C.VP8_STATUS_OK { return nil, fmt.Errorf("Could not decode data stream, return %s", statusString(status)) } return }
// GetFeatures returns features as BitstreamFeatures retrived from data stream. func GetFeatures(data []byte) (f *BitstreamFeatures, err error) { var cf C.WebPBitstreamFeatures status := C.WebPGetFeatures((*C.uint8_t)(&data[0]), (C.size_t)(len(data)), &cf) if status != C.VP8_STATUS_OK { return nil, fmt.Errorf("WebPGetFeatures returns unexpected status: %s", statusString(status)) } f = &BitstreamFeatures{ Width: int(cf.width), // TODO: use Rectangle instaed? Height: int(cf.height), HasAlpha: cf.has_alpha > 0, HasAnimation: cf.has_animation > 0, Format: int(cf.format), } return }