예제 #1
0
// 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
}
예제 #2
0
// 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
}
예제 #3
0
// 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
}