bool ImageWriterWebP::writeImage()

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;
}