bool WebpInput::open (const std::string &name, ImageSpec &spec) { m_filename = name; m_file = Filesystem::fopen(m_filename, "rb"); if (!m_file) { error ("Could not open file \"%s\"", m_filename.c_str()); return false; } fseek (m_file, 0, SEEK_END); m_image_size = ftell(m_file); fseek (m_file, 0, SEEK_SET); std::vector<uint8_t> encoded_image; encoded_image.resize(m_image_size, 0); size_t numRead = fread(&encoded_image[0], sizeof(uint8_t), encoded_image.size(), m_file); if (numRead != encoded_image.size()) { error ("Read failure for \"%s\" (expected %d bytes, read %d)", m_filename, encoded_image.size(), numRead); close (); return false; } int width = 0, height = 0; if(!WebPGetInfo(&encoded_image[0], encoded_image.size(), &width, &height)) { error ("%s is not a WebP image file", m_filename.c_str()); close(); return false; } const int CHANNEL_NUM = 4; m_scanline_size = width * CHANNEL_NUM; m_spec = ImageSpec(width, height, CHANNEL_NUM, TypeDesc::UINT8); spec = m_spec; if (!(m_decoded_image = WebPDecodeRGBA(&encoded_image[0], encoded_image.size(), &m_spec.width, &m_spec.height))) { error ("Couldn't decode %s", m_filename.c_str()); close(); return false; } return true; }
void LoadWEBP(const char *filename, unsigned char **pic, int *width, int *height, byte alphaByte) { byte *out; int len; int stride; int size; union { byte *b; void *v; } fbuffer; /* read compressed data */ len = ri.FS_ReadFile((char *)filename, &fbuffer.v); if(!fbuffer.b || len < 0) { return; } /* validate data and query image size */ if( !WebPGetInfo( fbuffer.b, len, width, height ) ) return; stride = *width * sizeof( color4ub_t ); size = *height * stride; out = ri.Z_Malloc( size ); if( !WebPDecodeRGBAInto( fbuffer.b, len, out, size, stride ) ) { ri.Free( out ); return; } ri.FS_FreeFile(fbuffer.v); *pic = out; }
SWIGEXPORT jint JNICALL Java_com_google_webp_libwebpJNI_WebPGetInfo(JNIEnv *jenv, jclass jcls, jbyteArray jarg1, jint jarg2, jintArray jarg3, jintArray jarg4) { jint jresult = 0 ; uint8_t *arg1 = (uint8_t *) 0 ; uint32_t arg2 ; int *arg3 = (int *) 0 ; int *arg4 = (int *) 0 ; jbyte *jarr1 ; int temp3 ; int temp4 ; int result; (void)jenv; (void)jcls; if (!SWIG_JavaArrayInSchar(jenv, &jarr1, &arg1, jarg1)) return 0; arg2 = (uint32_t)jarg2; { if (!jarg3) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); return 0; } if ((*jenv)->GetArrayLength(jenv, jarg3) == 0) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); return 0; } arg3 = &temp3; } { if (!jarg4) { SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null"); return 0; } if ((*jenv)->GetArrayLength(jenv, jarg4) == 0) { SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element"); return 0; } arg4 = &temp4; } { if (arg2 < 0) { { SWIG_JavaException(jenv, SWIG_ValueError, "Expected a non-negative value."); return 0; }; } } result = (int)WebPGetInfo((uint8_t const *)arg1,arg2,arg3,arg4); jresult = (jint)result; SWIG_JavaArrayArgoutSchar(jenv, jarr1, arg1, jarg1); { jint jvalue = (jint)temp3; (*jenv)->SetIntArrayRegion(jenv, jarg3, 0, 1, &jvalue); } { jint jvalue = (jint)temp4; (*jenv)->SetIntArrayRegion(jenv, jarg4, 0, 1, &jvalue); } free(arg1); return jresult; }
int webp_get_info(const uint8_t* data, size_t data_size, int* width, int* height) { if (WebPGetInfo(data, data_size, width, height) == 1) { return 0; } else { return 1; } }
static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, size_t data_size, int* const width, int* const height, WebPDecBuffer* const keep_info) { WebPDecParams params; WebPDecBuffer output; WebPInitDecBuffer(&output); WebPResetDecParams(¶ms); params.output = &output; output.colorspace = mode; // Retrieve (and report back) the required dimensions from bitstream. if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { return NULL; } if (width != NULL) *width = output.width; if (height != NULL) *height = output.height; // Decode if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { return NULL; } if (keep_info != NULL) { // keep track of the side-info WebPCopyDecBuffer(&output, keep_info); } // return decoded samples (don't clear 'output'!) return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; }
static uint8_t* Decode(WEBP_CSP_MODE mode, const uint8_t* const data, size_t data_size, int* const width, int* const height, WebPDecBuffer* const keep_info) { WebPDecParams params; WebPDecBuffer output; WebPInitDecBuffer(&output); WebPResetDecParams(¶ms); params.output = &output; output.colorspace = mode; if (!WebPGetInfo(data, data_size, &output.width, &output.height)) { return NULL; } if (width != NULL) *width = output.width; if (height != NULL) *height = output.height; if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { return NULL; } if (keep_info != NULL) { WebPCopyDecBuffer(&output, keep_info); } return WebPIsRGBMode(mode) ? output.u.RGBA.rgba : output.u.YUVA.y; }
int vips__iswebp_buffer( const void *buf, size_t len ) { if( len >= MINIMAL_HEADER && WebPGetInfo( buf, MINIMAL_HEADER, NULL, NULL ) ) return( 1 ); return( 0 ); }
char load(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity, char immediate_load) { uint8_t *data; size_t size; int w,h; int has_alpha; #if (WEBP_DECODER_ABI_VERSION >= 0x200) WebPBitstreamFeatures features; #endif char ret = 0; if(im->data) return 0; if(!(data = read_file(im->real_file, &size, progress))) return 0; #if (WEBP_DECODER_ABI_VERSION >= 0x200) if(WebPGetFeatures(data, size, &features) != VP8_STATUS_OK) goto EXIT; w = features.width; h = features.height; has_alpha = features.has_alpha; #else /* compatibility with versions <= 0.1.3 */ if (!WebPGetInfo(data, size, &w, &h)) goto EXIT; has_alpha = 0; #endif if(!im->loader && !im->data) { im->w = w; im->h = h; if(!IMAGE_DIMENSIONS_OK(w, h)) goto EXIT; if(!has_alpha) UNSET_FLAGS(im->flags, F_HAS_ALPHA); else SET_FLAGS(im->flags, F_HAS_ALPHA); im->format = strdup("webp"); } if((!im->data && im->loader) || immediate_load || progress) im->data = (DATA32*)WebPDecodeBGRA(data, size, &w, &h); if(progress) progress(im, 100, 0, 0, 0, 0); ret = 1; EXIT: free(data); return ret; }
//{ Draw void image_load(img_t *img,BYTE *data,int sz) { BYTE *bits,*p1,*p2; BITMAPINFO bmi; int ret; int i; img->hasalpha=img->sx=img->sy=0; #ifdef CONSOLE_MODE return; #else ret=WebPGetInfo((PBYTE)data,sz,&img->sx,&img->sy); if(!ret) { log_err("ERROR in image_load(): failed WebPGetInfo\n"); return; } img->big=WebPDecodeBGRA((PBYTE)data,sz,&img->sx,&img->sy); if(!img->big) { log_err("ERROR in image_load(): failed WebPDecodeBGRA\n"); return; } #endif ZeroMemory(&bmi,sizeof(BITMAPINFO)); bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth=img->sx; bmi.bmiHeader.biHeight=-img->sy; bmi.bmiHeader.biPlanes=1; bmi.bmiHeader.biBitCount=32; bmi.bmiHeader.biCompression=BI_RGB; bmi.bmiHeader.biSizeImage=img->sx*img->sy*4; img->dc=CreateCompatibleDC(0); img->bitmap=CreateDIBSection(img->dc,&bmi,DIB_RGB_COLORS,(void *)&bits,0,0); SelectObject(img->dc,img->bitmap); p1=bits;p2=img->big; for(i=0;i<img->sx*img->sy;i++) { BYTE B,G,R,A; B=*p2++; G=*p2++; R=*p2++; A=*p2++; double dA=A/255.; if(A!=255)img->hasalpha=1; *p1++=(BYTE)(B*dA); *p1++=(BYTE)(G*dA); *p1++=(BYTE)(R*dA); *p1++=A; } //log_con("%dx%d:%d,%d\n",img->sx,img->sy,img->hasalpha,img->index); }
void webp_reader<T>::init() { int width, height; if (!WebPGetInfo(buffer_->data(), buffer_->size(), &width, &height)) { throw image_reader_exception("WEBP reader: WebPGetInfo failed"); } width_ = width; height_ = height; }
int vips__iswebp( const char *filename ) { unsigned char header[MINIMAL_HEADER]; if( vips__get_bytes( filename, header, MINIMAL_HEADER ) && WebPGetInfo( header, MINIMAL_HEADER, NULL, NULL ) ) return( 1 ); return( 0 ); }
bool WebPDecoder::readHeader() { if (m_buf.empty()) { FILE * wfile = NULL; wfile = fopen(m_filename.c_str(), "rb"); if(wfile == NULL) { return false; } fseek(wfile, 0, SEEK_END); size_t wfile_size = ftell(wfile); fseek(wfile, 0, SEEK_SET); if(wfile_size > (size_t)INT_MAX) { fclose(wfile); return false; } data.create(1, (int)wfile_size, CV_8U); size_t data_size = fread(data.data, 1, wfile_size, wfile); if(wfile) { fclose(wfile); } if( data_size < wfile_size ) { return false; } } else { data = m_buf; } if(WebPGetInfo(data.data, data.total(), &m_width, &m_height) == 1) { m_type = CV_8UC3; return true; } return false; }
bool WEBPImageDecoder::decode(bool onlySize) { // Minimum number of bytes needed to ensure one can parse size information. static const size_t sizeOfHeader = 30; // Number of bytes per pixel. static const int bytesPerPixel = 3; if (failed()) return false; const size_t dataSize = m_data->buffer().size(); const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->buffer().data()); int width, height; if (dataSize < sizeOfHeader) return true; if (!WebPGetInfo(dataBytes, dataSize, &width, &height)) return setFailed(); if (!ImageDecoder::isSizeAvailable() && !setSize(width, height)) return setFailed(); if (onlySize) return true; // FIXME: Add support for progressive decoding. if (!isAllDataReceived()) return true; ASSERT(!m_frameBufferCache.isEmpty()); RGBA32Buffer& buffer = m_frameBufferCache[0]; if (buffer.status() == RGBA32Buffer::FrameEmpty) { ASSERT(width == size().width()); ASSERT(height == size().height()); if (!buffer.setSize(width, height)) return setFailed(); } const int stride = width * bytesPerPixel; Vector<uint8_t> rgb; rgb.resize(height * stride); if (!WebPDecodeBGRInto(dataBytes, dataSize, rgb.data(), rgb.size(), stride)) return setFailed(); // FIXME: remove this data copy. for (int y = 0; y < height; ++y) { const uint8_t* const src = &rgb[y * stride]; for (int x = 0; x < width; ++x) buffer.setRGBA(x, y, src[bytesPerPixel * x + 2], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 0], 0xff); } buffer.setStatus(RGBA32Buffer::FrameComplete); buffer.setHasAlpha(false); buffer.setRect(IntRect(IntPoint(), size())); return true; }
PremultipliedImage decodeWebP(const uint8_t* data, size_t size) { int width = 0, height = 0; if (WebPGetInfo(data, size, &width, &height) == 0) { throw std::runtime_error("failed to retrieve WebP basic header information"); } int stride = width * 4; size_t webpSize = stride * height; auto webp = std::make_unique<uint8_t[]>(webpSize); if (!WebPDecodeRGBAInto(data, size, webp.get(), webpSize, stride)) { throw std::runtime_error("failed to decode WebP data"); } UnassociatedImage image { size_t(width), size_t(height), std::move(webp) }; return util::premultiply(std::move(image)); }
std::auto_ptr<Image> WebPFormat::read(byte_source* src, ImageFactory* factory, const options_map& opts) { std::vector<byte> data = full_data(*src); int w, h; int ok = WebPGetInfo(&data[0], data.size(), &w, &h); if (!ok) { throw CannotReadError("imread.imread._webp: File does not validate as WebP"); } std::auto_ptr<Image> output(factory->create(8, h, w, 4)); const int stride = w*4; const uint8_t* p = WebPDecodeRGBAInto( &data[0], data.size(), output->rowp_as<byte>(0), h*stride, stride); if (p != output->rowp_as<uint8_t>(0)) { throw CannotReadError("imread.imread._webp: Error in decoding file"); } return output; }
cairo_surface_t* guacenc_webp_decoder(unsigned char* data, int length) { int width, height; /* Validate WebP and pull dimensions */ if (!WebPGetInfo((uint8_t*) data, length, &width, &height)) { guacenc_log(GUAC_LOG_WARNING, "Invalid WebP data"); return NULL; } /* Create blank Cairo surface */ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); /* Fill surface with opaque black */ cairo_t* cairo = cairo_create(surface); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cairo, 0.0, 0.0, 0.0, 1.0); cairo_paint(cairo); cairo_destroy(cairo); /* Finish any pending draws */ cairo_surface_flush(surface); /* Pull underlying buffer and its stride */ int stride = cairo_image_surface_get_stride(surface); unsigned char* image = cairo_image_surface_get_data(surface); /* Read WebP into surface */ uint8_t* result = WebPDecodeBGRAInto((uint8_t*) data, length, (uint8_t*) image, stride * height, stride); /* Verify WebP was successfully decoded */ if (result == NULL) { guacenc_log(GUAC_LOG_WARNING, "Invalid WebP data"); cairo_surface_destroy(surface); return NULL; } /* WebP was read successfully */ return surface; }
Bitmap *ImageFromData(const char *data, size_t len) { int w, h; if (!WebPGetInfo((const uint8_t *)data, len, &w, &h)) return nullptr; Bitmap bmp(w, h, PixelFormat32bppARGB); Rect bmpRect(0, 0, w, h); BitmapData bmpData; Status ok = bmp.LockBits(&bmpRect, ImageLockModeWrite, PixelFormat32bppARGB, &bmpData); if (ok != Ok) return nullptr; if (!WebPDecodeBGRAInto((const uint8_t *)data, len, (uint8_t *)bmpData.Scan0, bmpData.Stride * h, bmpData.Stride)) return nullptr; bmp.UnlockBits(&bmpData); // hack to avoid the use of ::new (because there won't be a corresponding ::delete) return bmp.Clone(0, 0, w, h, PixelFormat32bppARGB); }
static gboolean gdk_pixbuf__webp_image_load_increment (gpointer context, const guchar *buf, guint size, GError **error) { gint w, h, stride; WebPContext *data = (WebPContext *) context; g_return_val_if_fail(data != NULL, FALSE); if (!data->got_header) { gint rc; rc = WebPGetInfo (buf, size, &w, &h); if (rc == 0) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Cannot read WebP image header."); return FALSE; } stride = w * 3; /* TODO Update when alpha support released */ data->got_header = TRUE; if (data->size_func) { (* data->size_func) (&w, &h, data->user_data); } data->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, w, h); data->decbuf = g_try_malloc (h * stride); if (!data->decbuf) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, "Cannot allocate memory for decoded image data."); return FALSE; } data->idec = WebPINewRGB (MODE_RGB, data->decbuf, h * stride, stride); if (!data->idec) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Cannot create WebP decoder."); return FALSE; } if (data->prepare_func) { (* data->prepare_func) (data->pixbuf, NULL, data->user_data); } } /* Append size bytes to decoder's buffer */ const VP8StatusCode status = WebPIAppend (data->idec, buf, size); if (status != VP8_STATUS_SUSPENDED && status != VP8_STATUS_OK) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "WebP decoder failed with status code %d.", status); return FALSE; } /* Decode decoder's updated buffer */ guint8 *dec_output; dec_output = WebPIDecGetRGB (data->idec, &data->last_y, &w, &h, &stride); if (dec_output == NULL && status != VP8_STATUS_SUSPENDED) { g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Bad inputs to WebP decoder."); return FALSE; } /* Copy decoder output to pixbuf */ gint y, row; guchar *dptr; dptr = gdk_pixbuf_get_pixels (data->pixbuf); const guint8 offset = w % 4; /* decoded width will be divisible by 4 */ for (y = 0; y < data->last_y; ++y, dptr += offset) { row = y * stride; g_memmove (dptr + row, dec_output + row, stride); } if (data->update_func) { (* data->update_func) (data->pixbuf, 0, 0, w, data->last_y, data->user_data); } return TRUE; }
bool WEBPImageDecoder::decode(bool onlySize) { if (failed()) return false; const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data()); const size_t dataSize = m_data->size(); if (!ImageDecoder::isSizeAvailable()) { static const size_t imageHeaderSize = 30; if (dataSize < imageHeaderSize) return false; int width, height; #ifdef QCMS_WEBP_COLOR_CORRECTION WebPData inputData = { dataBytes, dataSize }; WebPDemuxState state; WebPDemuxer* demuxer = WebPDemuxPartial(&inputData, &state); if (!demuxer) return setFailed(); width = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_WIDTH); height = WebPDemuxGetI(demuxer, WEBP_FF_CANVAS_HEIGHT); m_formatFlags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS); m_hasAlpha = !!(m_formatFlags & ALPHA_FLAG); WebPDemuxDelete(demuxer); if (state <= WEBP_DEMUX_PARSING_HEADER) return false; #elif (WEBP_DECODER_ABI_VERSION >= 0x0163) WebPBitstreamFeatures features; if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK) return setFailed(); width = features.width; height = features.height; m_hasAlpha = features.has_alpha; #else // Earlier version won't be able to display WebP files with alpha. if (!WebPGetInfo(dataBytes, dataSize, &width, &height)) return setFailed(); m_hasAlpha = false; #endif if (!setSize(width, height)) return setFailed(); } ASSERT(ImageDecoder::isSizeAvailable()); if (onlySize) return true; ASSERT(!m_frameBufferCache.isEmpty()); ImageFrame& buffer = m_frameBufferCache[0]; ASSERT(buffer.status() != ImageFrame::FrameComplete); if (buffer.status() == ImageFrame::FrameEmpty) { if (!buffer.setSize(size().width(), size().height())) return setFailed(); buffer.setStatus(ImageFrame::FramePartial); buffer.setHasAlpha(m_hasAlpha); buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); } if (!m_decoder) { WEBP_CSP_MODE mode = outputMode(m_hasAlpha); if (!m_premultiplyAlpha) mode = outputMode(false); if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) mode = MODE_RGBA; // Decode to RGBA for input to libqcms. int rowStride = size().width() * sizeof(ImageFrame::PixelData); uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0)); int outputSize = size().height() * rowStride; m_decoder = WebPINewRGB(mode, output, outputSize, rowStride); if (!m_decoder) return setFailed(); } switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) { case VP8_STATUS_OK: if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) applyColorProfile(dataBytes, dataSize, buffer); buffer.setStatus(ImageFrame::FrameComplete); clear(); return true; case VP8_STATUS_SUSPENDED: if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) applyColorProfile(dataBytes, dataSize, buffer); return false; default: clear(); return setFailed(); } }
SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src) { Sint64 start; const char *error = NULL; SDL_Surface *volatile surface = NULL; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; Uint32 Amask; WebPBitstreamFeatures features; int raw_data_size; uint8_t *raw_data = NULL; int r; uint8_t *ret; if ( !src ) { /* The error message has been set in SDL_RWFromFile */ return NULL; } start = SDL_RWtell(src); if ( !IMG_Init(IMG_INIT_WEBP) ) { goto error; } raw_data_size = -1; if ( !webp_getinfo( src, &raw_data_size ) ) { error = "Invalid WEBP"; goto error; } // seek to start of file SDL_RWseek(src, 0, RW_SEEK_SET ); raw_data = (uint8_t*) SDL_malloc( raw_data_size ); if ( raw_data == NULL ) { error = "Failed to allocate enought buffer for WEBP"; goto error; } r = SDL_RWread(src, raw_data, 1, raw_data_size ); if ( r != raw_data_size ) { error = "Failed to read WEBP"; goto error; } #if 0 // extract size of picture, not interesting since we don't know about alpha channel int width = -1, height = -1; if ( !WebPGetInfo( raw_data, raw_data_size, &width, &height ) ) { printf("WebPGetInfo has failed\n" ); return NULL; } #endif if ( lib.webp_get_features_internal( raw_data, raw_data_size, &features, WEBP_DECODER_ABI_VERSION ) != VP8_STATUS_OK ) { error = "WebPGetFeatures has failed"; goto error; } /* Check if it's ok !*/ #if SDL_BYTEORDER == SDL_LIL_ENDIAN Rmask = 0x000000FF; Gmask = 0x0000FF00; Bmask = 0x00FF0000; Amask = (features.has_alpha) ? 0xFF000000 : 0; #else s = (features.has_alpha) ? 0 : 8; Rmask = 0xFF000000 >> s; Gmask = 0x00FF0000 >> s; Bmask = 0x0000FF00 >> s; Amask = 0x000000FF >> s; #endif surface = SDL_CreateRGBSurface(SDL_SWSURFACE, features.width, features.height, features.has_alpha?32:24, Rmask,Gmask,Bmask,Amask); if ( surface == NULL ) { error = "Failed to allocate SDL_Surface"; goto error; } if ( features.has_alpha ) { ret = lib.webp_decode_rgba_into( raw_data, raw_data_size, (uint8_t *)surface->pixels, surface->pitch * surface->h, surface->pitch ); } else { ret = lib.webp_decode_rgb_into( raw_data, raw_data_size, (uint8_t *)surface->pixels, surface->pitch * surface->h, surface->pitch ); } if ( !ret ) { error = "Failed to decode WEBP"; goto error; } return surface; error: if ( surface ) { SDL_FreeSurface( surface ); } if ( raw_data ) { SDL_free( raw_data ); } if ( error ) { IMG_SetError( error ); } SDL_RWseek(src, start, RW_SEEK_SET); return(NULL); }
bool WEBPImageDecoder::decode(bool onlySize) { if (failed()) return false; #if defined(__LB_SHELL__) // We dont want progressive decoding. if (!isAllDataReceived()) return false; #endif const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data()); const size_t dataSize = m_data->size(); if (!ImageDecoder::isSizeAvailable()) { static const size_t imageHeaderSize = 30; if (dataSize < imageHeaderSize) return false; int width, height; #if (WEBP_DECODER_ABI_VERSION >= 0x0163) WebPBitstreamFeatures features; if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK) return setFailed(); width = features.width; height = features.height; m_hasAlpha = features.has_alpha; #else // Earlier version won't be able to display WebP files with alpha. if (!WebPGetInfo(dataBytes, dataSize, &width, &height)) return setFailed(); m_hasAlpha = false; #endif if (!setSize(width, height)) return setFailed(); } ASSERT(ImageDecoder::isSizeAvailable()); if (onlySize) return true; ASSERT(!m_frameBufferCache.isEmpty()); ImageFrame& buffer = m_frameBufferCache[0]; ASSERT(buffer.status() != ImageFrame::FrameComplete); if (buffer.status() == ImageFrame::FrameEmpty) { if (!buffer.setSize(size().width(), size().height())) return setFailed(); buffer.setStatus(ImageFrame::FramePartial); buffer.setHasAlpha(m_hasAlpha); buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); } if (!m_decoder) { int rowStride = size().width() * sizeof(ImageFrame::PixelData); uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0)); int outputSize = size().height() * rowStride; m_decoder = WebPINewRGB(outputMode(m_hasAlpha), output, outputSize, rowStride); if (!m_decoder) return setFailed(); } switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) { case VP8_STATUS_OK: buffer.setStatus(ImageFrame::FrameComplete); WebPIDelete(m_decoder); m_decoder = 0; return true; case VP8_STATUS_SUSPENDED: return false; default: WebPIDelete(m_decoder); m_decoder = 0; return setFailed(); } }
bool WEBPImageDecoder::decode(bool onlySize) { // Minimum number of bytes needed to ensure one can parse size information. static const size_t sizeOfHeader = 30; // Number of bytes per pixel. static const int bytesPerPixel = 3; if (failed()) return false; const size_t dataSize = m_data->size(); if (dataSize < sizeOfHeader) return true; int width, height; const uint8_t* dataBytes = reinterpret_cast<const uint8_t*>(m_data->data()); if (!WebPGetInfo(dataBytes, dataSize, &width, &height)) return setFailed(); if (!ImageDecoder::isSizeAvailable() && !setSize(width, height)) return setFailed(); if (onlySize) return true; bool allDataReceived = isAllDataReceived(); int stride = width * bytesPerPixel; ASSERT(!m_frameBufferCache.isEmpty()); ImageFrame& buffer = m_frameBufferCache[0]; if (buffer.status() == ImageFrame::FrameEmpty) { ASSERT(width == size().width()); ASSERT(height == size().height()); if (!buffer.setSize(width, height)) return setFailed(); buffer.setStatus(allDataReceived ? ImageFrame::FrameComplete : ImageFrame::FramePartial); // FIXME: We currently hard code false below because libwebp doesn't support alpha yet. buffer.setHasAlpha(false); buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); m_rgbOutput.resize(height * stride); } int newLastVisibleRow = 0; // Last completed row. if (allDataReceived) { if (!WebPDecodeRGBInto(dataBytes, dataSize, m_rgbOutput.data(), m_rgbOutput.size(), stride)) return setFailed(); newLastVisibleRow = height; } else { if (!m_decoder) { m_decoder = WebPINewRGB(MODE_RGB, m_rgbOutput.data(), m_rgbOutput.size(), stride); if (!m_decoder) return setFailed(); } const VP8StatusCode status = WebPIUpdate(m_decoder, dataBytes, dataSize); if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) return setFailed(); if (!WebPIDecGetRGB(m_decoder, &newLastVisibleRow, 0, 0, 0)) return setFailed(); ASSERT(newLastVisibleRow >= 0); ASSERT(newLastVisibleRow <= height); } // FIXME: remove this data copy. for (int y = m_lastVisibleRow; y < newLastVisibleRow; ++y) { const uint8_t* const src = &m_rgbOutput[y * stride]; for (int x = 0; x < width; ++x) buffer.setRGBA(x, y, src[bytesPerPixel * x + 0], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 2], 0xff); } m_lastVisibleRow = newLastVisibleRow; if (m_lastVisibleRow == height) buffer.setStatus(ImageFrame::FrameComplete); return m_lastVisibleRow == height; }
static jobject WebPFactory_decodeBuffer (JNIEnv *jniEnv, const uint8_t *buffer, size_t length, jobject options) { // Validate image int bitmapWidth = 0; int bitmapHeight = 0; if (!WebPGetInfo(buffer, length, &bitmapWidth, &bitmapHeight)) { jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Invalid WebP format"); return NULL; } // Check if size is all what we were requested to do if(options && jniEnv->GetBooleanField(options, jrefs::android::graphics::BitmapFactory->Options.inJustDecodeBounds) == JNI_TRUE) { jniEnv->SetIntField(options, jrefs::android::graphics::BitmapFactory->Options.outWidth, bitmapWidth); jniEnv->SetIntField(options, jrefs::android::graphics::BitmapFactory->Options.outHeight, bitmapHeight); return NULL; } // Initialize decoder config and configure scaling if requested WebPDecoderConfig config; if (!WebPInitDecoderConfig(&config)) { jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Unable to init WebP decoder config"); return NULL; } if (options) { jint inSampleSize = jniEnv->GetIntField(options, jrefs::android::graphics::BitmapFactory->Options.inSampleSize); if (inSampleSize > 1) { config.options.use_scaling = 1; config.options.scaled_width = bitmapWidth /= inSampleSize; config.options.scaled_height = bitmapHeight /= inSampleSize; } } __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "Decoding into %dx%d bitmap", bitmapWidth, bitmapHeight); // Create bitmap jobject value__ARGB_8888 = jniEnv->GetStaticObjectField(jrefs::android::graphics::Bitmap->Config.jclassRef, jrefs::android::graphics::Bitmap->Config.ARGB_8888); jobject outputBitmap = jniEnv->CallStaticObjectMethod(jrefs::android::graphics::Bitmap->jclassRef, jrefs::android::graphics::Bitmap->createBitmap, (jint)bitmapWidth, (jint)bitmapHeight, value__ARGB_8888); if (!outputBitmap) { jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to allocate Bitmap"); return NULL; } // Get information about bitmap passed AndroidBitmapInfo bitmapInfo; if (AndroidBitmap_getInfo(jniEnv, outputBitmap, &bitmapInfo) != ANDROID_BITMAP_RESULT_SUCCESS) { jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to get Bitmap information"); return NULL; } // Lock pixels void *bitmapPixels = 0; if (AndroidBitmap_lockPixels(jniEnv, outputBitmap, &bitmapPixels) != ANDROID_BITMAP_RESULT_SUCCESS) { jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to lock Bitmap pixels"); return NULL; } // Decode to ARGB config.output.colorspace = MODE_RGBA; config.output.u.RGBA.rgba = (uint8_t*)bitmapPixels; config.output.u.RGBA.stride = bitmapInfo.stride; config.output.u.RGBA.size = bitmapInfo.height * bitmapInfo.stride; config.output.is_external_memory = 1; if (WebPDecode(buffer, length, &config) != VP8_STATUS_OK) { AndroidBitmap_unlockPixels(jniEnv, outputBitmap); jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to decode WebP pixel data"); return NULL; } // Unlock pixels if (AndroidBitmap_unlockPixels(jniEnv, outputBitmap) != ANDROID_BITMAP_RESULT_SUCCESS) { jniEnv->ThrowNew(jrefs::java::lang::RuntimeException->jclassRef, "Failed to unlock Bitmap pixels"); return NULL; } return outputBitmap; }
int ImageFormatWEBP::load(const char *name, int& width, int& height, int& format) { printf("ImageFormatWEBP::load\n"); // Open File FILE* file = fopen(name,"rb"); if (file == 0) { printf("ImageFormatWEBP::load(): can't open file '%s'\n",name); return 0; } // init width / height / format value to 0 width = 0; height = 0; format = 0; // size of file fseek(file,0,SEEK_END); const long data_size = ftell(file); fseek(file,0,SEEK_SET); unsigned char * img_data = new unsigned char[data_size]; fread(img_data,data_size,1,file); fclose(file); // Get header info int webpinfo = WebPGetInfo(img_data, data_size, &width, &height); if (webpinfo == 0) { printf("ImageFormatWEBP::load(): wrong header in \"%s\" file\n",name); delete img_data; return 0; } // Get betstream WebPBitstreamFeatures features; VP8StatusCode status = WebPGetFeatures(img_data, data_size, &features); if (status != VP8_STATUS_OK) { printf("ImageFormatWEBP::load(): bad bitstream in \"%s\" file, error:\"%d\"\n",name,status); delete img_data; return 0; } format = features.has_alpha ? 4 : 3; int data_decoded_size = width * height * format; // raw data image container unsigned char * img_data_decoded = new unsigned char[data_decoded_size]; memset(img_data_decoded,0x00,data_decoded_size); // decode image inside container (RGB and RGBA) if (format == 3 ) { if ( WebPDecodeRGBInto(img_data, data_size, img_data_decoded, data_decoded_size, width * format) == NULL ) { printf("ImageFormatWEBP::load(): can't decode RGB \"%s\" file\n",name); delete img_data; delete img_data_decoded; return 0; } } else { if ( WebPDecodeRGBAInto(img_data, data_size, img_data_decoded, data_decoded_size, width * format) == NULL ) { printf("ImageFormatWEBP::load(): can't decode RGBA \"%s\" file\n",name); delete img_data; delete img_data_decoded; return 0; } } // create temporary file for glue code javascript FILE* raw = fopen(kTempararyName,"wb"); if (raw) { fwrite(img_data_decoded,data_decoded_size ,1 , raw); fclose(raw); } delete img_data; delete img_data_decoded; return 1; }
// Store image bearing chunks to 'frame'. static ParseStatus StoreFrame(int frame_num, MemBuffer* const mem, Frame* const frame) { int alpha_chunks = 0; int image_chunks = 0; int done = (MemDataSize(mem) < CHUNK_HEADER_SIZE); ParseStatus status = PARSE_OK; if (done) return PARSE_NEED_MORE_DATA; do { const size_t chunk_start_offset = mem->start_; const uint32_t fourcc = GetLE32(mem); const uint32_t payload_size = GetLE32(mem); const uint32_t payload_size_padded = payload_size + (payload_size & 1); const size_t payload_available = (payload_size_padded > MemDataSize(mem)) ? MemDataSize(mem) : payload_size_padded; const size_t chunk_size = CHUNK_HEADER_SIZE + payload_available; if (payload_size > MAX_CHUNK_PAYLOAD) return PARSE_ERROR; if (SizeIsInvalid(mem, payload_size_padded)) return PARSE_ERROR; if (payload_size_padded > MemDataSize(mem)) status = PARSE_NEED_MORE_DATA; switch (fourcc) { case MKFOURCC('A', 'L', 'P', 'H'): if (alpha_chunks == 0) { ++alpha_chunks; frame->img_components_[1].offset_ = chunk_start_offset; frame->img_components_[1].size_ = chunk_size; frame->frame_num_ = frame_num; Skip(mem, payload_available); } else { goto Done; } break; case MKFOURCC('V', 'P', '8', ' '): case MKFOURCC('V', 'P', '8', 'L'): if (image_chunks == 0) { int width = 0, height = 0; ++image_chunks; frame->img_components_[0].offset_ = chunk_start_offset; frame->img_components_[0].size_ = chunk_size; // Extract the width and height from the bitstream, tolerating // failures when the data is incomplete. if (!WebPGetInfo(mem->buf_ + frame->img_components_[0].offset_, frame->img_components_[0].size_, &width, &height) && status != PARSE_NEED_MORE_DATA) { return PARSE_ERROR; } frame->width_ = width; frame->height_ = height; frame->frame_num_ = frame_num; frame->complete_ = (status == PARSE_OK); Skip(mem, payload_available); } else { goto Done; } break; Done: default: // Restore fourcc/size when moving up one level in parsing. Rewind(mem, CHUNK_HEADER_SIZE); done = 1; break; } if (mem->start_ == mem->riff_end_) { done = 1; } else if (MemDataSize(mem) < CHUNK_HEADER_SIZE) { status = PARSE_NEED_MORE_DATA; } } while (!done && status == PARSE_OK); return status; }
GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) || poOpenInfo->fpL == NULL ) return NULL; int nWidth, nHeight; if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes, &nWidth, &nHeight)) return NULL; int nBands = 3; #if WEBP_DECODER_ABI_VERSION >= 0x0002 WebPDecoderConfig config; if (!WebPInitDecoderConfig(&config)) return NULL; int bOK = WebPGetFeatures(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes, &config.input) == VP8_STATUS_OK; if (config.input.has_alpha) nBands = 4; WebPFreeDecBuffer(&config.output); if (!bOK) return NULL; #endif if( poOpenInfo->eAccess == GA_Update ) { CPLError( CE_Failure, CPLE_NotSupported, "The WEBP driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ WEBPDataset *poDS; poDS = new WEBPDataset(); poDS->nRasterXSize = nWidth; poDS->nRasterYSize = nHeight; poDS->fpImage = poOpenInfo->fpL; poOpenInfo->fpL = NULL; /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML( poOpenInfo->GetSiblingFiles() ); /* -------------------------------------------------------------------- */ /* Open overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() ); return poDS; }
static int WEBPDecode(WEBPDec* pSrc, Vbitmap *vbitmap, YmagineFormatOptions *options) { int contentSize; int origWidth = 0; int origHeight = 0; int quality; unsigned char header[WEBP_HEADER_SIZE + 32]; int headerlen; int toRead; unsigned char *input = NULL; int inputlen; int oformat; int opitch; unsigned char *odata; int rc; Vrect srcrect; Vrect destrect; WebPIDecoder* idec; if (options == NULL) { /* Options argument is mandatory */ return 0; } headerlen = YchannelRead(pSrc->channel, (char *) header, sizeof(header)); if (headerlen < WEBP_HEADER_SIZE) { return 0; } /* Check WEBP header */ contentSize = WebpCheckHeader((const char*) header, headerlen); if (contentSize <= 0) { return 0; } if (WebPGetInfo(header, headerlen, &origWidth, &origHeight) == 0) { ALOGD("invalid VP8 header"); return 0; } if (origWidth <= 0 || origHeight <= 0) { return 0; } if (YmagineFormatOptions_invokeCallback(options, YMAGINE_IMAGEFORMAT_WEBP, origWidth, origHeight) != YMAGINE_OK) { return 0; } if (YmaginePrepareTransform(vbitmap, options, origWidth, origHeight, &srcrect, &destrect) != YMAGINE_OK) { return 0; } #if YMAGINE_DEBUG_WEBP ALOGD("size: %dx%d req: %dx%d %s -> output: %dx%d", origWidth, origHeight, destrect.width, destrect.height, (options->scalemode == YMAGINE_SCALE_CROP) ? "crop" : (options->scalemode == YMAGINE_SCALE_FIT ? "fit" : "letterbox"), destrect.width, destrect.height); #endif if (vbitmap != NULL) { if (options->resizable) { destrect.x = 0; destrect.y = 0; if (VbitmapResize(vbitmap, destrect.width, destrect.height) != YMAGINE_OK) { return 0; } } if (VbitmapType(vbitmap) == VBITMAP_NONE) { /* Decode bounds only, return positive number (number of lines) on success */ return VbitmapHeight(vbitmap); } } pSrc->bitmap = vbitmap; inputlen = contentSize; toRead = inputlen - headerlen; rc = VbitmapLock(vbitmap); if (rc != YMAGINE_OK) { ALOGE("VbitmapLock() failed (code %d)", rc); rc = YMAGINE_ERROR; } else { odata = VbitmapBuffer(vbitmap); opitch = VbitmapPitch(vbitmap); oformat = VbitmapColormode(vbitmap); pSrc->inwidth = origWidth; pSrc->inheight = origHeight; pSrc->outwidth = destrect.width; pSrc->outheight = destrect.height; if (odata == NULL) { ALOGD("failed to get reference to pixel buffer"); rc = YMAGINE_ERROR; } else { WebPDecoderConfig config; int supported = 1; int webpcolorspace; switch(oformat) { case VBITMAP_COLOR_RGBA: webpcolorspace = MODE_RGBA; break; case VBITMAP_COLOR_RGB: webpcolorspace = MODE_RGB; break; case VBITMAP_COLOR_rgbA: webpcolorspace = MODE_rgbA; break; case VBITMAP_COLOR_ARGB: webpcolorspace = MODE_ARGB; break; case VBITMAP_COLOR_Argb: webpcolorspace = MODE_Argb; break; case VBITMAP_COLOR_GRAYSCALE: case VBITMAP_COLOR_YUV: case VBITMAP_COLOR_CMYK: case VBITMAP_COLOR_YCbCr: default: supported = 0; break; } if (!supported) { ALOGD("currently only support RGB, RGBA webp decoding"); rc = YMAGINE_ERROR; } else { pSrc->isdirect = 1; pSrc->outformat = oformat; pSrc->outbpp = VbitmapBpp(vbitmap); pSrc->outstride = opitch; pSrc->outbuffer = odata + destrect.x * pSrc->outbpp + destrect.y * pSrc->outstride; WebPInitDecoderConfig(&config); quality = YmagineFormatOptions_normalizeQuality(options); if (quality < 90) { config.options.no_fancy_upsampling = 1; } if (quality < 60) { config.options.bypass_filtering = 1; } config.options.use_threads = 1; if (srcrect.x != 0 || srcrect.y != 0 || srcrect.width != origWidth || srcrect.height != origHeight) { /* Crop on source */ config.options.use_cropping = 1; config.options.crop_left = srcrect.x; config.options.crop_top = srcrect.y; config.options.crop_width = srcrect.width; config.options.crop_height = srcrect.height; } if (pSrc->outwidth != pSrc->inwidth || pSrc->outheight != pSrc->inheight) { config.options.use_scaling = 1; config.options.scaled_width = pSrc->outwidth; config.options.scaled_height = pSrc->outheight; } rc = YMAGINE_ERROR; // Specify the desired output colorspace: config.output.colorspace = webpcolorspace; // Have config.output point to an external buffer: config.output.u.RGBA.rgba = (uint8_t*) pSrc->outbuffer; config.output.u.RGBA.stride = pSrc->outstride; config.output.u.RGBA.size = pSrc->outstride * pSrc->outheight; config.output.is_external_memory = 1; idec = WebPIDecode(NULL, 0, &config); if (idec != NULL) { VP8StatusCode status; status = WebPIAppend(idec, header, headerlen); if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) { int bytes_remaining = toRead; int bytes_read; int bytes_req; unsigned char rbuf[8192]; // See WebPIUpdate(idec, buffer, size_of_transmitted_buffer); bytes_req = sizeof(rbuf); while (bytes_remaining > 0) { if (bytes_req > bytes_remaining) { bytes_req = bytes_remaining; } bytes_read = YchannelRead(pSrc->channel, rbuf, bytes_req); if (bytes_read <= 0) { break; } status = WebPIAppend(idec, (uint8_t*) rbuf, bytes_read); if (status == VP8_STATUS_OK) { rc = YMAGINE_OK; break; } else if (status == VP8_STATUS_SUSPENDED) { if (bytes_remaining > 0) { bytes_remaining -= bytes_read; } } else { /* error */ break; } // The above call decodes the current available buffer. // Part of the image can now be refreshed by calling // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. } } } // the object doesn't own the image memory, so it can now be deleted. WebPIDelete(idec); WebPFreeDecBuffer(&config.output); } } VbitmapUnlock(vbitmap); } if (input) { Ymem_free((char*) input); } if (!pSrc->isdirect) { Ymem_free(pSrc->outbuffer); } if (rc == YMAGINE_OK) { return origHeight; } return 0; }
gboolean load_image(const gchar *filename, gint32 *image_ID, GError **error) { gboolean status = FALSE; gchar *indata = NULL; gsize indatalen; gint width; gint height; WebPMux *mux = NULL; WebPData wp_data; uint32_t flags; uint8_t *outdata = NULL; #ifdef GIMP_2_9 /* Initialize GEGL */ gegl_init(NULL, NULL); #endif do { /* Attempt to read the file contents from disk */ if (g_file_get_contents(filename, &indata, &indatalen, error) == FALSE) { break; } /* Validate WebP data, grabbing the width and height */ if (!WebPGetInfo(indata, indatalen, &width, &height)) { break; } /* Create a WebPMux from the contents of the file */ wp_data.bytes = (uint8_t*)indata; wp_data.size = indatalen; mux = WebPMuxCreate(&wp_data, 1); if (mux == NULL) { break; } /* Retrieve the features present */ if (WebPMuxGetFeatures(mux, &flags) != WEBP_MUX_OK) { break; } /* TODO: decode the image in "chunks" or "tiles" */ /* TODO: check if an alpha channel is present */ /* Create the new image and associated layer */ *image_ID = gimp_image_new(width, height, GIMP_RGB); #ifdef WEBP_0_5 if (flags & ANIMATION_FLAG) { int frames, i; /* Retrieve the number of frames */ WebPMuxNumChunks(mux, WEBP_CHUNK_ANMF, &frames); /* Loop over each of the frames */ for (i = 0; i < frames; ++i) { WebPMuxFrameInfo frame = {0}; /* Retrieve the data for the frame */ if (WebPMuxGetFrame(mux, i, &frame) != WEBP_MUX_OK) { goto error; } /* Decode the frame */ outdata = WebPDecodeRGBA(frame.bitstream.bytes, frame.bitstream.size, &width, &height); /* Free the compressed data */ WebPDataClear(&frame.bitstream); if (!outdata) { goto error; } /* Create a layer for the frame */ char name[255]; snprintf(name, 255, "Frame %d", (i + 1)); if (create_layer(*image_ID, outdata, 0, (gchar*)name, width, height, frame.x_offset, frame.y_offset) == FALSE) { goto error; } } /* If all is well, jump *over* the error label - otherwise leave the loop and begin cleaning things up */ goto success; error: break; success: ; } else { #endif /* Attempt to decode the data as a WebP image */ outdata = WebPDecodeRGBA(indata, indatalen, &width, &height); if (!outdata) { break; } /* Create a single layer */ status = create_layer(*image_ID, outdata, 0, "Background", width, height, 0, 0); #ifdef WEBP_0_5 } #ifdef GIMP_2_9 /* Load a color profile if one was provided */ if (flags & ICCP_FLAG) { WebPData icc_profile; GimpColorProfile *profile; /* Load the ICC profile from the file */ WebPMuxGetChunk(mux, "ICCP", &icc_profile); /* Have Gimp load the color profile */ profile = gimp_color_profile_new_from_icc_profile( icc_profile.bytes, icc_profile.size, NULL); if (profile) { gimp_image_set_color_profile(image_ID, profile); g_object_unref(profile); } } #endif #endif /* Set the filename for the image */ gimp_image_set_filename(*image_ID, filename); } while(0); /* Delete the mux object */ if (mux) { WebPMuxDelete(mux); } /* Free the data read from disk */ if (indata) { g_free(indata); } return status; }
GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) ) return NULL; int nWidth, nHeight; if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes, &nWidth, &nHeight)) return NULL; if( poOpenInfo->eAccess == GA_Update ) { CPLError( CE_Failure, CPLE_NotSupported, "The WEBP driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Open the file using the large file api. */ /* -------------------------------------------------------------------- */ VSILFILE* fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( fpImage == NULL ) return NULL; GByte* pabyUncompressed = (GByte*)VSIMalloc3(nWidth, nHeight, 3); if (pabyUncompressed == NULL) { VSIFCloseL(fpImage); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ WEBPDataset *poDS; poDS = new WEBPDataset(); poDS->nRasterXSize = nWidth; poDS->nRasterYSize = nHeight; poDS->fpImage = fpImage; poDS->pabyUncompressed = pabyUncompressed; /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < 3; iBand++ ) poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML( poOpenInfo->papszSiblingFiles ); /* -------------------------------------------------------------------- */ /* Open overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles ); return poDS; }
// Returns true if this is a valid WebP bitstream. static int IsWebP(const WebPData* const webp_data) { return (WebPGetInfo(webp_data->bytes, webp_data->size, NULL, NULL) != 0); }