in cpp/spectrum/plugins/webp/LibWebpDecompressor.cpp [111:184]
void LibWebpDecompressor::_ensureImageIsRead() {
if (_isImageRead) {
return;
}
_ensureHeaderIsRead();
// init buffer
const auto pixelSpecification = outputImageSpecification().pixelSpecification;
const auto bytesPerPixel = pixelSpecification.bytesPerPixel;
const auto stride = _webpFeatures.width * bytesPerPixel;
_rawImage.resize(_webpFeatures.height * stride);
// init config
WebPDecoderConfig config;
const auto webpConfigInitSuccess = WebPInitDecoderConfig(&config);
SPECTRUM_ERROR_CSTR_IF_NOT(
webpConfigInitSuccess,
codecs::error::DecompressorFailure,
"webp_init_decoder_config_failed");
// init decoder
_webpDecoder = WebPINewDecoder(&config.output);
SPECTRUM_ERROR_CSTR_IF(
_webpDecoder == nullptr,
codecs::error::DecompressorFailure,
"webp_i_new_decoder_failed");
// collect rest of input
std::size_t bytesRead;
do {
std::array<char, core::DefaultBufferSize> chunk{};
bytesRead = _source.read(chunk.data(), core::DefaultBufferSize);
std::copy_n(chunk.begin(), bytesRead, std::back_inserter(_webpPayload));
} while (bytesRead > 0);
// read image information
const auto getFeaturesStatus = WebPGetFeatures(
reinterpret_cast<std::uint8_t*>(_webpPayload.data()),
_webpPayload.size(),
&config.input);
SPECTRUM_ERROR_CSTR_IF_NOT(
getFeaturesStatus == VP8_STATUS_OK,
codecs::error::DecompressorFailure,
"webp_get_features_failed");
// set options
config.options.no_fancy_upsampling = 1;
config.options.use_threads = 0;
config.output.colorspace = pixelSpecificationToCspMode(pixelSpecification);
config.output.is_external_memory = 1;
config.output.u.RGBA.rgba = _rawImage.data();
config.output.u.RGBA.size = _rawImage.size();
config.output.u.RGBA.stride = stride;
// decode image
const auto decodeStatus = WebPDecode(
reinterpret_cast<std::uint8_t*>(_webpPayload.data()),
_webpPayload.size(),
&config);
_webpPayload.clear(); // payload bytes are no longer needed
SPECTRUM_ERROR_CSTR_IF_NOT(
decodeStatus == VP8_STATUS_OK,
codecs::error::DecompressorFailure,
"webp_decode_failed");
_isImageRead = true;
}