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!
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
Contact:

using libwebp with wxImage

Postby 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/blob/master/src/Util/Array.h array template (GPLV3) ...
see https://github.com/kytulendu/Gw2Browser/blob/master/src/Readers/ImageReader.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;

}

Return to “The Code Dump”

Who is online

Users browsing this forum: No registered users and 2 guests