Page 1 of 1

using libwebp with wxImage

Posted: Fri Mar 07, 2014 8:02 pm
by khral
Rawr! Hello!

Here is a code snippet/example of how to decode WebP image and send the image to wxImage.
You also need libwebp, which can be found at https://code.google.com/p/webp/, to able to use this code.

Compile with compiler that support C++11.

Since I'm C++ and wxWidgets beginner my self, any comment of this code will be appreciated. :)

Hope this will give you some ideas of convert WebP image (may be any image format) to wxImage.

*Note* require this https://github.com/kytulendu/Gw2Browser ... il/Array.h array template (GPLV3) ...
see https://github.com/kytulendu/Gw2Browser ... Reader.cpp for example.

Edit: add missing thing.
Edit2: fix NULL to nullptr, remove license.
Edit3: cleanup
Edit4: fix memory leak?

Code: Select all

/*
WebP to wxImage code snippet
by Khral Steelforge

usage: [WebP]->readWebP( );
return wxImage.
*/

struct RGBA {
	unsigned int r;
	unsigned int g;
	unsigned int b;
	unsigned int a;
};

struct RGB {
	unsigned int r;
	unsigned int g;
	unsigned int b;
};

wxImage foo::readWebP( ) const {
	// Create image
	wxImage image;

	auto data = reinterpret_cast<const uint8_t*>( m_data.GetPointer( ) );
	size_t data_size = m_data.GetSize( );
	po_colors = nullptr;
	po_alphas = nullptr;

	WebPDecoderConfig config;
	WebPBitstreamFeatures* bitstream = &config.input;

	VP8StatusCode status = VP8_STATUS_OK;

	status = WebPGetFeatures( reinterpret_cast<const uint8_t*>( data ), data_size, bitstream );

	if ( status != VP8_STATUS_OK ) {
		wxMessageBox( wxString( "This file isn't WebP!" ), _( "" ), wxOK | wxICON_EXCLAMATION );
		return image;
	}

	if ( bitstream->has_animation ) {
		wxMessageBox( wxString( "Not support Animation WebP." ), _( "" ), wxOK | wxICON_INFORMATION );
		return image;
	}

	uint numPixels = bitstream->width * bitstream->height;

	// Why it need to convert RGB to BGR?
	auto decoded_data = reinterpret_cast<BGRA*>( WebPDecodeRGBA( data, data_size, nullptr, nullptr ) );

	if ( decoded_data == nullptr ) {
		wxMessageBox( wxString( "Invalid WebP format." ), _( "ERROR" ), wxOK | wxICON_ERROR );
		return image;
	}

	//auto colors = allocate<RGB>( numPixels );
	auto colors = static_cast<RGB*>( ::malloc( numPixels * sizeof( RGB ) ) );
	//auto alphas = allocate<uint8_t>( numPixels );
	auto alphas = static_cast<uint8_t*>( ::malloc( numPixels * sizeof( uint8_t ) ) );

#pragma omp parallel for   // comment this out if it give you compile error or you don't want to use OpenMP
	for ( int y = 0; y < static_cast<int>( bitstream->height ); y++ ) {
		uint32 curPixel = ( y * bitstream->width );

		for ( uint x = 0; x < static_cast<unsigned int>( bitstream->width ); x++ ) {
			::memcpy( &po_colors[curPixel].b, &decoded_data[curPixel].b, sizeof( po_colors[curPixel].b ) );
			::memcpy( &po_colors[curPixel].g, &decoded_data[curPixel].g, sizeof( po_colors[curPixel].g ) );
			::memcpy( &po_colors[curPixel].r, &decoded_data[curPixel].r, sizeof( po_colors[curPixel].r ) );

			if ( bitstream->has_alpha ) {
				::memcpy( &po_alphas[curPixel], &decoded_data[curPixel].a, sizeof( po_alphas[curPixel] ) );
			}
			curPixel++;
		}
	}

	freePointer( decoded_data );

	image = wxImage( bitstream->width, bitstream->height, reinterpret_cast<uint8_t*>( colors ), false );
	// Set alpha if the format has any
	if ( output_buffer->colorspace == bitstream->has_alpha ) {
		image.SetAlpha( alphas );
	}

	return image;

}