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; }
uint8_t* WebPDecodeYUVInto(const uint8_t* data, size_t data_size, uint8_t* luma, size_t luma_size, int luma_stride, uint8_t* u, size_t u_size, int u_stride, uint8_t* v, size_t v_size, int v_stride) { WebPDecParams params; WebPDecBuffer output; if (luma == NULL) return NULL; WebPInitDecBuffer(&output); WebPResetDecParams(¶ms); params.output = &output; output.colorspace = MODE_YUV; output.u.YUVA.y = luma; output.u.YUVA.y_stride = luma_stride; output.u.YUVA.y_size = luma_size; output.u.YUVA.u = u; output.u.YUVA.u_stride = u_stride; output.u.YUVA.u_size = u_size; output.u.YUVA.v = v; output.u.YUVA.v_stride = v_stride; output.u.YUVA.v_size = v_size; output.is_external_memory = 1; if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { return NULL; } return luma; }
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; }
/* * Setup state for decoding a strip. */ static int TWebPPreDecode(TIFF* tif, uint16 s) { static const char module[] = "TWebPPreDecode"; uint32 segment_width, segment_height; WebPState* sp = DecoderState(tif); TIFFDirectory* td = &tif->tif_dir; (void) s; assert(sp != NULL); if (isTiled(tif)) { segment_width = td->td_tilewidth; segment_height = td->td_tilelength; } else { segment_width = td->td_imagewidth; segment_height = td->td_imagelength - tif->tif_row; if (segment_height > td->td_rowsperstrip) segment_height = td->td_rowsperstrip; } if( (sp->state & LSTATE_INIT_DECODE) == 0 ) tif->tif_setupdecode(tif); if (sp->psDecoder != NULL) { WebPIDelete(sp->psDecoder); WebPFreeDecBuffer(&sp->sDecBuffer); sp->psDecoder = NULL; } sp->last_y = 0; WebPInitDecBuffer(&sp->sDecBuffer); sp->sDecBuffer.is_external_memory = 0; sp->sDecBuffer.width = segment_width; sp->sDecBuffer.height = segment_height; sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples; sp->sDecBuffer.u.RGBA.size = segment_width * sp->nSamples * segment_height; if (sp->nSamples > 3) { sp->sDecBuffer.colorspace = MODE_RGBA; } else { sp->sDecBuffer.colorspace = MODE_RGB; } sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer); if (sp->psDecoder == NULL) { TIFFErrorExt(tif->tif_clientdata, module, "Unable to allocate WebP decoder."); return 0; } return 1; }
int WebPInitDecoderConfigInternal(WebPDecoderConfig* config, int version) { if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_DECODER_ABI_VERSION)) { return 0; // version mismatch } if (config == NULL) { return 0; } memset(config, 0, sizeof(*config)); DefaultFeatures(&config->input); WebPInitDecBuffer(&config->output); return 1; }
void nsWEBPDecoder::InitInternal() { if (!WebPInitDecBuffer(&mDecBuf)) { PostDecoderError(NS_ERROR_FAILURE); return; } mLastLine = 0; mDecBuf.colorspace = MODE_rgbA; mDecoder = WebPINewDecoder(&mDecBuf); if (!mDecoder) { PostDecoderError(NS_ERROR_FAILURE); } }
VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size, WebPDecoderConfig* config) { WebPDecParams params; VP8StatusCode status; if (config == NULL) { return VP8_STATUS_INVALID_PARAM; } status = GetFeatures(data, data_size, &config->input); if (status != VP8_STATUS_OK) { if (status == VP8_STATUS_NOT_ENOUGH_DATA) { return VP8_STATUS_BITSTREAM_ERROR; // Not-enough-data treated as error. } return status; } WebPResetDecParams(¶ms); params.options = &config->options; params.output = &config->output; if (WebPAvoidSlowMemory(params.output, &config->input)) { // decoding to slow memory: use a temporary in-mem buffer to decode into. WebPDecBuffer in_mem_buffer; WebPInitDecBuffer(&in_mem_buffer); in_mem_buffer.colorspace = config->output.colorspace; in_mem_buffer.width = config->input.width; in_mem_buffer.height = config->input.height; params.output = &in_mem_buffer; status = DecodeInto(data, data_size, ¶ms); if (status == VP8_STATUS_OK) { // do the slow-copy status = WebPCopyDecBufferPixels(&in_mem_buffer, &config->output); } WebPFreeDecBuffer(&in_mem_buffer); } else { status = DecodeInto(data, data_size, ¶ms); } return status; }
// Helpers static uint8_t* DecodeIntoRGBABuffer(WEBP_CSP_MODE colorspace, const uint8_t* const data, size_t data_size, uint8_t* const rgba, int stride, size_t size) { WebPDecParams params; WebPDecBuffer buf; if (rgba == NULL) { return NULL; } WebPInitDecBuffer(&buf); WebPResetDecParams(¶ms); params.output = &buf; buf.colorspace = colorspace; buf.u.RGBA.rgba = rgba; buf.u.RGBA.stride = stride; buf.u.RGBA.size = size; buf.is_external_memory = 1; if (DecodeInto(data, data_size, ¶ms) != VP8_STATUS_OK) { return NULL; } return rgba; }
bool WEBPImageDecoder::decode(const uint8_t* dataBytes, size_t dataSize, bool onlySize, size_t frameIndex) { if (failed()) return false; if (!ImageDecoder::isSizeAvailable()) { static const size_t imageHeaderSize = 30; if (dataSize < imageHeaderSize) return false; int width, height; WebPBitstreamFeatures features; if (WebPGetFeatures(dataBytes, dataSize, &features) != VP8_STATUS_OK) return setFailed(); width = features.width; height = features.height; m_formatFlags = features.has_alpha ? ALPHA_FLAG : 0; if (!setSize(width, height)) return setFailed(); } ASSERT(ImageDecoder::isSizeAvailable()); if (onlySize) return true; ASSERT(m_frameBufferCache.size() > frameIndex); ImageFrame& buffer = m_frameBufferCache[frameIndex]; ASSERT(buffer.status() != ImageFrame::FrameComplete); if (buffer.status() == ImageFrame::FrameEmpty) { if (!buffer.setSize(size().width(), size().height())) return setFailed(); buffer.setStatus(ImageFrame::FramePartial); // The buffer is transparent outside the decoded area while the image is loading. // The correct value of 'hasAlpha' for the frame will be set when it is fully decoded. buffer.setHasAlpha(true); buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); } const IntRect& frameRect = buffer.originalFrameRect(); if (!m_decoder) { WEBP_CSP_MODE mode = outputMode(m_formatFlags & ALPHA_FLAG); if (!m_premultiplyAlpha) mode = outputMode(false); #if USE(QCMSLIB) if ((m_formatFlags & ICCP_FLAG) && !ignoresGammaAndColorProfile()) mode = MODE_RGBA; // Decode to RGBA for input to libqcms. #endif WebPInitDecBuffer(&m_decoderBuffer); m_decoderBuffer.colorspace = mode; m_decoderBuffer.u.RGBA.stride = size().width() * sizeof(ImageFrame::PixelData); m_decoderBuffer.u.RGBA.size = m_decoderBuffer.u.RGBA.stride * frameRect.height(); m_decoderBuffer.is_external_memory = 1; m_decoder = WebPINewDecoder(&m_decoderBuffer); if (!m_decoder) return setFailed(); } m_decoderBuffer.u.RGBA.rgba = reinterpret_cast<uint8_t*>(buffer.getAddr(frameRect.x(), frameRect.y())); switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) { case VP8_STATUS_OK: applyPostProcessing(frameIndex); buffer.setHasAlpha((m_formatFlags & ALPHA_FLAG) || m_frameBackgroundHasAlpha); buffer.setStatus(ImageFrame::FrameComplete); clearDecoder(); return true; case VP8_STATUS_SUSPENDED: if (!isAllDataReceived() && !frameIsCompleteAtIndex(frameIndex)) { applyPostProcessing(frameIndex); return false; } // FALLTHROUGH default: clear(); return setFailed(); } }
bool WEBPImageDecoder::decodeSingleFrame(const uint8_t* dataBytes, size_t dataSize, size_t frameIndex) { if (failed()) return false; ASSERT(isDecodedSizeAvailable()); ASSERT(m_frameBufferCache.size() > frameIndex); ImageFrame& buffer = m_frameBufferCache[frameIndex]; ASSERT(buffer.getStatus() != ImageFrame::FrameComplete); if (buffer.getStatus() == ImageFrame::FrameEmpty) { if (!buffer.setSizeAndColorSpace(size().width(), size().height(), colorSpace())) return setFailed(); buffer.setStatus(ImageFrame::FramePartial); // The buffer is transparent outside the decoded area while the image is // loading. The correct alpha value for the frame will be set when it is // fully decoded. buffer.setHasAlpha(true); buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); } const IntRect& frameRect = buffer.originalFrameRect(); if (!m_decoder) { WEBP_CSP_MODE mode = outputMode(m_formatFlags & ALPHA_FLAG); if (!m_premultiplyAlpha) mode = outputMode(false); if (colorTransform()) { // Swizzling between RGBA and BGRA is zero cost in a color transform. // So when we have a color transform, we should decode to whatever is // easiest for libwebp, and then let the color transform swizzle if // necessary. // Lossy webp is encoded as YUV (so RGBA and BGRA are the same cost). // Lossless webp is encoded as BGRA. This means decoding to BGRA is // either faster or the same cost as RGBA. mode = MODE_BGRA; } WebPInitDecBuffer(&m_decoderBuffer); m_decoderBuffer.colorspace = mode; m_decoderBuffer.u.RGBA.stride = size().width() * sizeof(ImageFrame::PixelData); m_decoderBuffer.u.RGBA.size = m_decoderBuffer.u.RGBA.stride * frameRect.height(); m_decoderBuffer.is_external_memory = 1; m_decoder = WebPINewDecoder(&m_decoderBuffer); if (!m_decoder) return setFailed(); } m_decoderBuffer.u.RGBA.rgba = reinterpret_cast<uint8_t*>(buffer.getAddr(frameRect.x(), frameRect.y())); switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) { case VP8_STATUS_OK: applyPostProcessing(frameIndex); buffer.setHasAlpha((m_formatFlags & ALPHA_FLAG) || m_frameBackgroundHasAlpha); buffer.setStatus(ImageFrame::FrameComplete); clearDecoder(); return true; case VP8_STATUS_SUSPENDED: if (!isAllDataReceived() && !frameIsCompleteAtIndex(frameIndex)) { applyPostProcessing(frameIndex); return false; } // FALLTHROUGH default: clear(); return setFailed(); } }