using libwebp with wxImage

If you have a cool piece of software to share, but you are not hosting it officially yet, please dump it in here. If you have code snippets that are useful, please donate!
Post Reply
User avatar
khral
In need of some credit
In need of some credit
Posts: 1
Joined: Fri Mar 07, 2014 7:06 pm
Location: Black Citadel, Ascalon

using libwebp with wxImage

Post by khral » Fri Mar 07, 2014 8:02 pm

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;

}

Post Reply