in cpp/spectrum/plugins/avif/AvifDecompressor.cpp [89:145]
void AvifDecompressor::_ensureEntireImageIsRead() {
if (_entireImageHasBeenRead) {
return;
}
_entireImageHasBeenRead = true;
_parseContainer();
SPECTRUM_ERROR_CSTR_IF_NOT(
AVIF_RESULT_OK == avifDecoderNextImage(_decoder) && _decoder->image,
codecs::error::DecompressorFailure,
"failed avifDecoderNextImage");
_sourceData.clear();
const auto image = _decoder->image;
avifRGBImage rgb;
avifRGBImageSetDefaults(&rgb, image);
rgb.depth = 8;
rgb.format = AVIF_RGB_FORMAT_RGB;
avifRGBImageAllocatePixels(&rgb);
SCOPE_EXIT {
avifRGBImageFreePixels(&rgb);
};
SPECTRUM_ERROR_CSTR_IF_NOT(
AVIF_RESULT_OK == avifImageYUVToRGB(image, &rgb),
codecs::error::DecompressorFailure,
"failed avifImageYUVToRGB");
_entireImage.reserve(image->height);
for (auto row = 0; row < image->height; ++row) {
auto scanline = std::make_unique<image::Scanline>(
image::pixel::specifications::RGB, image->width);
SPECTRUM_ERROR_FORMAT_IF_NOT(
scanline->sizeBytes() == rgb.rowBytes,
codecs::error::DecompressorFailure,
"scanline size (%d) does not match decoded row bytes (%d)",
scanline->sizeBytes(),
rgb.rowBytes);
std::memcpy(
scanline->data(), rgb.pixels + row * rgb.rowBytes, rgb.rowBytes);
_entireImage.push_back(std::move(scanline));
}
_imageSpecification = image::Specification{
.size = image::Size{image->width, image->height},
.format = image::formats::Avif,
.pixelSpecification = image::pixel::specifications::RGB};
// We are done with the decoder, free it now to save memory
avifDecoderDestroy(_decoder);
_decoder = nullptr;
}