in imagecore/formats/internal/webp.cpp [333:429]
bool ImageWriterWebP::writeImage(Image* sourceImage)
{
if( !Image::colorModelIsRGBA(sourceImage->getColorModel()) && !Image::colorModelIsYUV(sourceImage->getColorModel()) ) {
return false;
}
if( !WebPValidateConfig(&m_Config) ) {
return false;
}
WebPPicture pic;
if( !WebPPictureInit(&pic) ) {
return false;
}
pic.width = sourceImage->getWidth();
pic.height = sourceImage->getHeight();
bool success = false;
if( Image::colorModelIsRGBA(sourceImage->getColorModel()) ) {
ImageRGBA* image = sourceImage->asRGBA();
unsigned int pitch = image->getPitch();
uint32_t* imageRGBA = (uint32_t*)image->getBytes();
uint32_t* swapBufferARGB = (uint32_t*)malloc(image->getImageSize());
if( swapBufferARGB != NULL ) {
// Swap RGBA -> BGRA.
for( unsigned int y = 0; y < pic.height; y++ ) {
for( unsigned int x = 0; x < pic.width; x++ ) {
unsigned int offset = (y * pitch / 4) + x;
uint32_t rgba = imageRGBA[offset];
#if __BYTE_ORDER == __LITTLE_ENDIAN
uint32_t argb = ((rgba & 0xFF) << 16) | ((rgba >> 16) & 0xFF) | (rgba & 0xFF00FF00);
#else
uint32_t argb = (((rgba >> 24) & 0xFF) << 8) | (((rgba >> 8) & 0xFF) << 24) | (rgba & 0x00FF00FF);
#endif
swapBufferARGB[offset] = argb;
}
}
if( WebPPictureAlloc(&pic) ) {
pic.writer = &webpWrite;
pic.custom_ptr = m_OutputStorage;
pic.use_argb = 1;
pic.argb = (uint32_t*)swapBufferARGB;
pic.argb_stride = image->getPitch() / image->getComponentSize();
success = WebPEncode(&m_Config, &pic);
WebPPictureFree(&pic);
}
free(swapBufferARGB);
}
} else if( Image::colorModelIsYUV(sourceImage->getColorModel()) ) {
ImageYUV* yuvImage = sourceImage->asYUV();
ImageYUV* image = yuvImage;
ImageYUV* tempImage = NULL;
if( yuvImage->getRange() == kYUVRange_Full ) {
tempImage = ImageYUV::create(yuvImage->getWidth(), yuvImage->getHeight(), yuvImage->getPadding(), 16);
if( tempImage == NULL ) {
return 0;
}
START_CLOCK(remap);
yuvImage->compressRange(tempImage);
END_CLOCK(remap);
image = tempImage;
}
if( (image->getHeight() & 1) == 1 ) {
ImagePlane8* uPlane = image->getPlaneU();
ImagePlane8* vPlane = image->getPlaneV();
// The WebP codec seems to read into the UV padding region, make sure it's filled out correctly.
uPlane->copyRect(uPlane, 0, uPlane->getHeight() - 2, 0, uPlane->getHeight() - 1, uPlane->getWidth(), 1);
vPlane->copyRect(vPlane, 0, vPlane->getHeight() - 2, 0, vPlane->getHeight() - 1, vPlane->getWidth(), 1);
}
if( WebPPictureAlloc(&pic) ) {
pic.writer = &webpWrite;
pic.custom_ptr = m_OutputStorage;
pic.use_argb = 0;
pic.y = (uint8_t*)image->getPlaneY()->getBytes();
pic.u = (uint8_t*)image->getPlaneU()->getBytes();
pic.v = (uint8_t*)image->getPlaneV()->getBytes();
pic.y_stride = image->getPlaneY()->getPitch();
pic.uv_stride = image->getPlaneU()->getPitch();
success = WebPEncode(&m_Config, &pic);
WebPPictureFree(&pic);
}
delete tempImage;
}
return success;
}