// Copyright 2022 Google LLC
// SPDX-License-Identifier: BSD-2-Clause

#include "aviftest_helpers.h"

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <limits>
#include <string>
#include <vector>

#include "avif/avif.h"
#include "avif/avif_cxx.h"
#include "avifpng.h"
#include "avifutil.h"

namespace avif {
namespace testutil {

//------------------------------------------------------------------------------
// CopyImageSamples is a copy of avifImageCopySamples

namespace {
void CopyImageSamples(avifImage* dstImage, const avifImage* srcImage,
                      avifPlanesFlags planes) {
  assert(srcImage->depth == dstImage->depth);
  if (planes & AVIF_PLANES_YUV) {
    assert(srcImage->yuvFormat == dstImage->yuvFormat);
    // Note that there may be a mismatch between srcImage->yuvRange and
    // dstImage->yuvRange because libavif allows for 'colr' and AV1 OBU video
    // range values to differ.
  }
  const size_t bytesPerPixel = avifImageUsesU16(srcImage) ? 2 : 1;

  const avifBool skipColor = !(planes & AVIF_PLANES_YUV);
  const avifBool skipAlpha = !(planes & AVIF_PLANES_A);
  for (int c = AVIF_CHAN_Y; c <= AVIF_CHAN_A; ++c) {
    const avifBool alpha = c == AVIF_CHAN_A;
    if ((skipColor && !alpha) || (skipAlpha && alpha)) {
      continue;
    }

    const uint32_t planeWidth = avifImagePlaneWidth(srcImage, c);
    const uint32_t planeHeight = avifImagePlaneHeight(srcImage, c);
    const uint8_t* srcRow = avifImagePlane(srcImage, c);
    uint8_t* dstRow = avifImagePlane(dstImage, c);
    const uint32_t srcRowBytes = avifImagePlaneRowBytes(srcImage, c);
    const uint32_t dstRowBytes = avifImagePlaneRowBytes(dstImage, c);
    assert(!srcRow == !dstRow);
    if (!srcRow) {
      continue;
    }
    assert(planeWidth == avifImagePlaneWidth(dstImage, c));
    assert(planeHeight == avifImagePlaneHeight(dstImage, c));

    const size_t planeWidthBytes = planeWidth * bytesPerPixel;
    for (uint32_t y = 0; y < planeHeight; ++y) {
      memcpy(dstRow, srcRow, planeWidthBytes);
      srcRow += srcRowBytes;
      dstRow += dstRowBytes;
    }
  }
}
}  // namespace

//------------------------------------------------------------------------------

AvifRgbImage::AvifRgbImage(const avifImage* yuv, int rgbDepth,
                           avifRGBFormat rgbFormat) {
  avifRGBImageSetDefaults(this, yuv);
  depth = rgbDepth;
  format = rgbFormat;
  if (avifRGBImageAllocatePixels(this) != AVIF_RESULT_OK) {
    std::abort();
  }
}

AvifRwData::AvifRwData(AvifRwData&& other) : avifRWData{other} {
  other.data = nullptr;
  other.size = 0;
}

//------------------------------------------------------------------------------

RgbChannelOffsets GetRgbChannelOffsets(avifRGBFormat format) {
  switch (format) {
    case AVIF_RGB_FORMAT_RGB:
      return {/*r=*/0, /*g=*/1, /*b=*/2, /*a=*/0};
    case AVIF_RGB_FORMAT_RGBA:
      return {/*r=*/0, /*g=*/1, /*b=*/2, /*a=*/3};
    case AVIF_RGB_FORMAT_ARGB:
      return {/*r=*/1, /*g=*/2, /*b=*/3, /*a=*/0};
    case AVIF_RGB_FORMAT_BGR:
      return {/*r=*/2, /*g=*/1, /*b=*/0, /*a=*/0};
    case AVIF_RGB_FORMAT_BGRA:
      return {/*r=*/2, /*g=*/1, /*b=*/0, /*a=*/3};
    case AVIF_RGB_FORMAT_ABGR:
      return {/*r=*/3, /*g=*/2, /*b=*/1, /*a=*/0};
    case AVIF_RGB_FORMAT_RGB_565:
    case AVIF_RGB_FORMAT_COUNT:
    default:
      return {/*r=*/0, /*g=*/0, /*b=*/0, /*a=*/0};
  }
}

//------------------------------------------------------------------------------

ImagePtr CreateImage(int width, int height, int depth,
                     avifPixelFormat yuv_format, avifPlanesFlags planes,
                     avifRange yuv_range) {
  ImagePtr image(avifImageCreate(width, height, depth, yuv_format));
  if (!image) {
    return nullptr;
  }
  image->yuvRange = yuv_range;
  if (avifImageAllocatePlanes(image.get(), planes) != AVIF_RESULT_OK) {
    return nullptr;
  }
  return image;
}

void FillImagePlain(avifImage* image, const uint32_t yuva[4]) {
  for (avifChannelIndex c :
       {AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A}) {
    const uint32_t plane_width = avifImagePlaneWidth(image, c);
    // 0 for A if no alpha and 0 for UV if 4:0:0.
    const uint32_t plane_height = avifImagePlaneHeight(image, c);
    uint8_t* row = avifImagePlane(image, c);
    const uint32_t row_bytes = avifImagePlaneRowBytes(image, c);
    for (uint32_t y = 0; y < plane_height; ++y) {
      if (avifImageUsesU16(image)) {
        std::fill(reinterpret_cast<uint16_t*>(row),
                  reinterpret_cast<uint16_t*>(row) + plane_width,
                  static_cast<uint16_t>(yuva[c]));
      } else {
        std::fill(row, row + plane_width, static_cast<uint8_t>(yuva[c]));
      }
      row += row_bytes;
    }
  }
}

void FillImageGradient(avifImage* image) {
  for (avifChannelIndex c :
       {AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A}) {
    const uint32_t limitedRangeMin =
        c == AVIF_CHAN_Y ? 16 << (image->depth - 8) : 0;
    const uint32_t limitedRangeMax = (c == AVIF_CHAN_Y ? 219 : 224)
                                     << (image->depth - 8);

    const uint32_t plane_width = avifImagePlaneWidth(image, c);
    // 0 for A if no alpha and 0 for UV if 4:0:0.
    const uint32_t plane_height = avifImagePlaneHeight(image, c);
    uint8_t* row = avifImagePlane(image, c);
    const uint32_t row_bytes = avifImagePlaneRowBytes(image, c);
    for (uint32_t y = 0; y < plane_height; ++y) {
      for (uint32_t x = 0; x < plane_width; ++x) {
        uint32_t value;
        if (image->yuvRange == AVIF_RANGE_FULL || c == AVIF_CHAN_A) {
          value = (x + y) * ((1u << image->depth) - 1u) /
                  std::max(1u, plane_width + plane_height - 2);
        } else {
          value = limitedRangeMin +
                  (x + y) * (limitedRangeMax - limitedRangeMin) /
                      std::max(1u, plane_width + plane_height - 2);
        }
        if (avifImageUsesU16(image)) {
          reinterpret_cast<uint16_t*>(row)[x] = static_cast<uint16_t>(value);
        } else {
          row[x] = static_cast<uint8_t>(value);
        }
      }
      row += row_bytes;
    }
  }
}

namespace {
template <typename PixelType>
void FillImageChannel(avifRGBImage* image, uint32_t channel_offset,
                      uint32_t value) {
  const uint32_t channel_count = avifRGBFormatChannelCount(image->format);
  assert(channel_offset < channel_count);
  for (uint32_t y = 0; y < image->height; ++y) {
    PixelType* pixel =
        reinterpret_cast<PixelType*>(image->pixels + image->rowBytes * y);
    for (uint32_t x = 0; x < image->width; ++x) {
      pixel[channel_offset] = static_cast<PixelType>(value);
      pixel += channel_count;
    }
  }
}
}  // namespace

void FillImageChannel(avifRGBImage* image, uint32_t channel_offset,
                      uint32_t value) {
  (image->depth <= 8)
      ? FillImageChannel<uint8_t>(image, channel_offset, value)
      : FillImageChannel<uint16_t>(image, channel_offset, value);
}

//------------------------------------------------------------------------------

bool AreByteSequencesEqual(const uint8_t data1[], size_t data1_length,
                           const uint8_t data2[], size_t data2_length) {
  if (data1_length != data2_length) return false;
  return data1_length == 0 || std::equal(data1, data1 + data1_length, data2);
}

bool AreByteSequencesEqual(const avifRWData& data1, const avifRWData& data2) {
  return AreByteSequencesEqual(data1.data, data1.size, data2.data, data2.size);
}

// Returns true if image1 and image2 are identical.
bool AreImagesEqual(const avifImage& image1, const avifImage& image2,
                    bool ignore_alpha) {
  if (image1.width != image2.width || image1.height != image2.height ||
      image1.depth != image2.depth || image1.yuvFormat != image2.yuvFormat ||
      image1.yuvRange != image2.yuvRange) {
    return false;
  }
  assert(image1.width * image1.height > 0);

  if (image1.clli.maxCLL != image2.clli.maxCLL ||
      image1.clli.maxPALL != image2.clli.maxPALL) {
    return false;
  }
  if (image1.transformFlags != image2.transformFlags ||
      ((image1.transformFlags & AVIF_TRANSFORM_PASP) &&
       std::memcmp(&image1.pasp, &image2.pasp, sizeof(image1.pasp))) ||
      ((image1.transformFlags & AVIF_TRANSFORM_CLAP) &&
       std::memcmp(&image1.clap, &image2.clap, sizeof(image1.clap))) ||
      ((image1.transformFlags & AVIF_TRANSFORM_IROT) &&
       std::memcmp(&image1.irot, &image2.irot, sizeof(image1.irot))) ||
      ((image1.transformFlags & AVIF_TRANSFORM_IMIR) &&
       std::memcmp(&image1.imir, &image2.imir, sizeof(image1.imir)))) {
    return false;
  }

  for (avifChannelIndex c :
       {AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A}) {
    if (ignore_alpha && c == AVIF_CHAN_A) continue;
    const uint8_t* row1 = avifImagePlane(&image1, c);
    const uint8_t* row2 = avifImagePlane(&image2, c);
    if (!row1 != !row2) {
      // Maybe one image contains an opaque alpha channel while the other has no
      // alpha channel, but they should still be considered equal.
      if (c == AVIF_CHAN_A && avifImageIsOpaque(&image1) &&
          avifImageIsOpaque(&image2)) {
        continue;
      }
      return false;
    }
    const uint32_t row_bytes1 = avifImagePlaneRowBytes(&image1, c);
    const uint32_t row_bytes2 = avifImagePlaneRowBytes(&image2, c);
    const uint32_t plane_width = avifImagePlaneWidth(&image1, c);
    // 0 for A if no alpha and 0 for UV if 4:0:0.
    const uint32_t plane_height = avifImagePlaneHeight(&image1, c);
    for (uint32_t y = 0; y < plane_height; ++y) {
      if (avifImageUsesU16(&image1)) {
        if (!std::equal(reinterpret_cast<const uint16_t*>(row1),
                        reinterpret_cast<const uint16_t*>(row1) + plane_width,
                        reinterpret_cast<const uint16_t*>(row2))) {
          return false;
        }
      } else {
        if (!std::equal(row1, row1 + plane_width, row2)) {
          return false;
        }
      }
      row1 += row_bytes1;
      row2 += row_bytes2;
    }
  }
  return AreByteSequencesEqual(image1.icc, image2.icc) &&
         AreByteSequencesEqual(image1.exif, image2.exif) &&
         AreByteSequencesEqual(image1.xmp, image2.xmp);
}

namespace {

template <typename Sample>
uint64_t SquaredDiffSum(const Sample* samples1, const Sample* samples2,
                        uint32_t num_samples) {
  uint64_t sum = 0;
  for (uint32_t i = 0; i < num_samples; ++i) {
    const int32_t diff = static_cast<int32_t>(samples1[i]) - samples2[i];
    sum += diff * diff;
  }
  return sum;
}

}  // namespace

double GetPsnr(const avifImage& image1, const avifImage& image2,
               bool ignore_alpha) {
  if (image1.width != image2.width || image1.height != image2.height ||
      image1.depth != image2.depth || image1.yuvFormat != image2.yuvFormat ||
      image1.yuvRange != image2.yuvRange) {
    return -1;
  }
  assert(image1.width * image1.height > 0);

  if (image1.colorPrimaries != image2.colorPrimaries ||
      image1.transferCharacteristics != image2.transferCharacteristics ||
      image1.matrixCoefficients != image2.matrixCoefficients ||
      image1.yuvRange != image2.yuvRange) {
    fprintf(stderr,
            "WARNING: computing PSNR of images with different CICP: %d/%d/%d%s "
            "vs %d/%d/%d%s\n",
            image1.colorPrimaries, image1.transferCharacteristics,
            image1.matrixCoefficients,
            (image1.yuvRange == AVIF_RANGE_FULL) ? "f" : "l",
            image2.colorPrimaries, image2.transferCharacteristics,
            image2.matrixCoefficients,
            (image2.yuvRange == AVIF_RANGE_FULL) ? "f" : "l");
  }

  uint64_t squared_diff_sum = 0;
  uint32_t num_samples = 0;
  const uint32_t max_sample_value = (1 << image1.depth) - 1;
  for (avifChannelIndex c :
       {AVIF_CHAN_Y, AVIF_CHAN_U, AVIF_CHAN_V, AVIF_CHAN_A}) {
    if (ignore_alpha && c == AVIF_CHAN_A) continue;

    const uint32_t plane_width = std::max(avifImagePlaneWidth(&image1, c),
                                          avifImagePlaneWidth(&image2, c));
    const uint32_t plane_height = std::max(avifImagePlaneHeight(&image1, c),
                                           avifImagePlaneHeight(&image2, c));
    if (plane_width == 0 || plane_height == 0) continue;

    const uint8_t* row1 = avifImagePlane(&image1, c);
    const uint8_t* row2 = avifImagePlane(&image2, c);
    if (!row1 != !row2 && c != AVIF_CHAN_A) {
      return -1;
    }
    uint32_t row_bytes1 = avifImagePlaneRowBytes(&image1, c);
    uint32_t row_bytes2 = avifImagePlaneRowBytes(&image2, c);

    // Consider missing alpha planes as samples set to the maximum value.
    std::vector<uint8_t> opaque_alpha_samples;
    if (!row1 != !row2) {
      opaque_alpha_samples.resize(std::max(row_bytes1, row_bytes2));
      if (avifImageUsesU16(&image1)) {
        uint16_t* opaque_alpha_samples_16b =
            reinterpret_cast<uint16_t*>(opaque_alpha_samples.data());
        std::fill(opaque_alpha_samples_16b,
                  opaque_alpha_samples_16b + plane_width,
                  static_cast<int16_t>(max_sample_value));
      } else {
        std::fill(opaque_alpha_samples.begin(), opaque_alpha_samples.end(),
                  uint8_t{255});
      }
      if (!row1) {
        row1 = opaque_alpha_samples.data();
        row_bytes1 = 0;
      } else {
        row2 = opaque_alpha_samples.data();
        row_bytes2 = 0;
      }
    }

    for (uint32_t y = 0; y < plane_height; ++y) {
      if (avifImageUsesU16(&image1)) {
        squared_diff_sum += SquaredDiffSum(
            reinterpret_cast<const uint16_t*>(row1),
            reinterpret_cast<const uint16_t*>(row2), plane_width);
      } else {
        squared_diff_sum += SquaredDiffSum(row1, row2, plane_width);
      }
      row1 += row_bytes1;
      row2 += row_bytes2;
      num_samples += plane_width;
    }
  }

  if (squared_diff_sum == 0) {
    return 99.0;
  }
  const double normalized_error =
      squared_diff_sum /
      (static_cast<double>(num_samples) * max_sample_value * max_sample_value);
  if (normalized_error <= std::numeric_limits<double>::epsilon()) {
    return 98.99;  // Very small distortion but not lossless.
  }
  return std::min(-10 * std::log10(normalized_error), 98.99);
}

bool AreImagesEqual(const avifRGBImage& image1, const avifRGBImage& image2) {
  if (image1.width != image2.width || image1.height != image2.height ||
      image1.depth != image2.depth || image1.format != image2.format ||
      image1.alphaPremultiplied != image2.alphaPremultiplied ||
      image1.isFloat != image2.isFloat) {
    return false;
  }
  const uint8_t* row1 = image1.pixels;
  const uint8_t* row2 = image2.pixels;
  const unsigned int row_width = image1.width * avifRGBImagePixelSize(&image1);
  for (unsigned int y = 0; y < image1.height; ++y) {
    if (!std::equal(row1, row1 + row_width, row2)) {
      return false;
    }
    row1 += image1.rowBytes;
    row2 += image2.rowBytes;
  }
  return true;
}

avifResult MergeGrid(int grid_cols, int grid_rows,
                     const std::vector<ImagePtr>& cells, avifImage* merged) {
  std::vector<const avifImage*> ptrs(cells.size());
  for (size_t i = 0; i < cells.size(); ++i) {
    ptrs[i] = cells[i].get();
  }
  return MergeGrid(grid_cols, grid_rows, ptrs, merged);
}

avifResult MergeGrid(int grid_cols, int grid_rows,
                     const std::vector<const avifImage*>& cells,
                     avifImage* merged) {
  const uint32_t tile_width = cells[0]->width;
  const uint32_t tile_height = cells[0]->height;
  const uint32_t grid_width =
      (grid_cols - 1) * tile_width + cells.back()->width;
  const uint32_t grid_height =
      (grid_rows - 1) * tile_height + cells.back()->height;

  ImagePtr view(avifImageCreateEmpty());
  AVIF_CHECKERR(view, AVIF_RESULT_OUT_OF_MEMORY);

  avifCropRect rect = {};
  for (int j = 0; j < grid_rows; ++j) {
    rect.x = 0;
    for (int i = 0; i < grid_cols; ++i) {
      const avifImage* image = cells[j * grid_cols + i];
      rect.width = image->width;
      rect.height = image->height;
      AVIF_CHECKRES(avifImageSetViewRect(view.get(), merged, &rect));
      CopyImageSamples(/*dstImage=*/view.get(), image, AVIF_PLANES_ALL);
      assert(!view->imageOwnsYUVPlanes);
      rect.x += rect.width;
    }
    rect.y += rect.height;
  }

  if ((rect.x != grid_width) || (rect.y != grid_height)) {
    return AVIF_RESULT_UNKNOWN_ERROR;
  }

  return AVIF_RESULT_OK;
}

//------------------------------------------------------------------------------

testutil::AvifRwData ReadFile(const std::string& file_path) {
  std::ifstream file(file_path, std::ios::binary | std::ios::ate);
  testutil::AvifRwData bytes;
  if (avifRWDataRealloc(&bytes, file.good() ? static_cast<size_t>(file.tellg())
                                            : 0) != AVIF_RESULT_OK) {
    return {};
  }
  file.seekg(0, std::ios::beg);
  file.read(reinterpret_cast<char*>(bytes.data),
            static_cast<std::streamsize>(bytes.size));
  return bytes;
}

//------------------------------------------------------------------------------

ImagePtr ReadImage(const char* folder_path, const char* file_name,
                   avifPixelFormat requested_format, int requested_depth,
                   avifChromaDownsampling chroma_downsampling,
                   avifBool ignore_icc, avifBool ignore_exif,
                   avifBool ignore_xmp, avifBool allow_changing_cicp,
                   avifBool ignore_gain_map) {
  ImagePtr image(avifImageCreateEmpty());
  if (!image ||
      avifReadImage((std::string(folder_path) + file_name).c_str(),
                    requested_format, requested_depth, chroma_downsampling,
                    ignore_icc, ignore_exif, ignore_xmp, allow_changing_cicp,
                    ignore_gain_map, AVIF_DEFAULT_IMAGE_SIZE_LIMIT, image.get(),
                    /*outDepth=*/nullptr, /*sourceTiming=*/nullptr,
                    /*frameIter=*/nullptr) == AVIF_APP_FILE_FORMAT_UNKNOWN) {
    return nullptr;
  }
  return image;
}

bool WriteImage(const avifImage* image, const char* file_path) {
  if (!image || !file_path) return false;
  const size_t str_len = std::strlen(file_path);
  if (str_len >= 4 && !std::strncmp(file_path + str_len - 4, ".png", 4)) {
    return avifPNGWrite(file_path, image, /*requestedDepth=*/0,
                        AVIF_CHROMA_UPSAMPLING_BEST_QUALITY,
                        /*compressionLevel=*/0);
  }
  // Other formats are not supported.
  return false;
}

AvifRwData Encode(const avifImage* image, int speed, int quality) {
  EncoderPtr encoder(avifEncoderCreate());
  if (!encoder) return {};
  encoder->speed = speed;
  encoder->quality = quality;
  encoder->qualityAlpha = quality;
#if defined(AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP)
  encoder->qualityGainMap = quality;
#endif
  testutil::AvifRwData bytes;
  if (avifEncoderWrite(encoder.get(), image, &bytes) != AVIF_RESULT_OK) {
    return {};
  }
  return bytes;
}

ImagePtr Decode(const uint8_t* bytes, size_t num_bytes) {
  ImagePtr decoded(avifImageCreateEmpty());
  DecoderPtr decoder(avifDecoderCreate());
  if (!decoded || !decoder ||
      (avifDecoderReadMemory(decoder.get(), decoded.get(), bytes, num_bytes) !=
       AVIF_RESULT_OK)) {
    return nullptr;
  }
  return decoded;
}

ImagePtr DecodeFile(const std::string& path) {
  ImagePtr decoded(avifImageCreateEmpty());
  DecoderPtr decoder(avifDecoderCreate());
  if (!decoded || !decoder ||
      (avifDecoderReadFile(decoder.get(), decoded.get(), path.c_str()) !=
       AVIF_RESULT_OK)) {
    return nullptr;
  }
  return decoded;
}

bool Av1EncoderAvailable() {
  const char* encoding_codec =
      avifCodecName(AVIF_CODEC_CHOICE_AUTO, AVIF_CODEC_FLAG_CAN_ENCODE);
  return encoding_codec != nullptr && std::string(encoding_codec) != "avm";
}

bool Av1DecoderAvailable() {
  const char* decoding_codec =
      avifCodecName(AVIF_CODEC_CHOICE_AUTO, AVIF_CODEC_FLAG_CAN_DECODE);
  return decoding_codec != nullptr && std::string(decoding_codec) != "avm";
}

//------------------------------------------------------------------------------

static avifResult avifIOLimitedReaderRead(avifIO* io, uint32_t readFlags,
                                          uint64_t offset, size_t size,
                                          avifROData* out) {
  auto reader = reinterpret_cast<AvifIOLimitedReader*>(io);

  if (offset > UINT64_MAX - size) {
    return AVIF_RESULT_IO_ERROR;
  }
  if (offset + size > reader->clamp) {
    return AVIF_RESULT_WAITING_ON_IO;
  }

  return reader->underlyingIO->read(reader->underlyingIO, readFlags, offset,
                                    size, out);
}

static void avifIOLimitedReaderDestroy(avifIO* io) {
  auto reader = reinterpret_cast<AvifIOLimitedReader*>(io);
  reader->underlyingIO->destroy(reader->underlyingIO);
  delete reader;
}

avifIO* AvifIOCreateLimitedReader(avifIO* underlyingIO, uint64_t clamp) {
  return reinterpret_cast<avifIO*>(
      new AvifIOLimitedReader{{
                                  avifIOLimitedReaderDestroy,
                                  avifIOLimitedReaderRead,
                                  nullptr,
                                  underlyingIO->sizeHint,
                                  underlyingIO->persistent,
                                  nullptr,
                              },
                              underlyingIO,
                              clamp});
}

//------------------------------------------------------------------------------

std::vector<ImagePtr> ImageToGrid(const avifImage* image, uint32_t grid_cols,
                                  uint32_t grid_rows) {
  if (image->width < grid_cols || image->height < grid_rows) return {};

  // Round up, to make sure all samples are used by exactly one cell.
  uint32_t cell_width = (image->width + grid_cols - 1) / grid_cols;
  uint32_t cell_height = (image->height + grid_rows - 1) / grid_rows;

  if ((grid_cols - 1) * cell_width >= image->width) {
    // Some cells are completely outside the image. Fallback to a grid entirely
    // contained within the image boundaries. Some samples will be discarded but
    // at least the test can go on.
    cell_width = image->width / grid_cols;
  }
  if ((grid_rows - 1) * cell_height >= image->height) {
    cell_height = image->height / grid_rows;
  }

  std::vector<ImagePtr> cells;
  for (uint32_t row = 0; row < grid_rows; ++row) {
    for (uint32_t col = 0; col < grid_cols; ++col) {
      avifCropRect rect{col * cell_width, row * cell_height, cell_width,
                        cell_height};
      assert(rect.x < image->width);
      assert(rect.y < image->height);
      // The right-most and bottom-most cells may be smaller than others.
      // The encoder will pad them.
      if (rect.x + rect.width > image->width) {
        rect.width = image->width - rect.x;
      }
      if (rect.y + rect.height > image->height) {
        rect.height = image->height - rect.y;
      }
      cells.emplace_back(avifImageCreateEmpty());
      if (avifImageSetViewRect(cells.back().get(), image, &rect) !=
          AVIF_RESULT_OK) {
        return {};
      }
    }
  }
  return cells;
}

std::vector<const avifImage*> UniquePtrToRawPtr(
    const std::vector<ImagePtr>& unique_ptrs) {
  std::vector<const avifImage*> rawPtrs;
  rawPtrs.reserve(unique_ptrs.size());
  for (const ImagePtr& unique_ptr : unique_ptrs) {
    rawPtrs.emplace_back(unique_ptr.get());
  }
  return rawPtrs;
}

//------------------------------------------------------------------------------

}  // namespace testutil
}  // namespace avif
