void LibWebpDecompressor::_ensureImageIsRead()

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;
}