// Copyright 2025 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "testing/image_diff/image_diff_png.h"

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "core/fxcrt/check_op.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/numerics/checked_math.h"
#include "core/fxcrt/span.h"
#include "core/fxcrt/span_util.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkColorType.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkStream.h"

#ifdef PDF_ENABLE_RUST_PNG
#include "third_party/skia/include/codec/SkPngRustDecoder.h"
#include "third_party/skia/include/encode/SkPngRustEncoder.h"
#else
#include "third_party/skia/include/codec/SkPngDecoder.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
#endif

namespace image_diff_png {

namespace {

std::vector<uint8_t> EncodePNG(pdfium::span<const uint8_t> input,
                               SkColorType color,
                               SkAlphaType alpha,
                               int width,
                               int height,
                               size_t row_byte_width) {
  SkImageInfo info =
      SkImageInfo::Make(width, height, color, alpha, SkColorSpace::MakeSRGB());
  CHECK_NE(info.minRowBytes(), 0);  // 0 means conversion problems.
  CHECK_LE(info.minRowBytes(), row_byte_width);
  CHECK_NE(info.computeMinByteSize(), 0);  // 0 means conversion problems.
  CHECK_LE(info.computeMinByteSize(), input.size());
  SkPixmap pixmap(info, input.data(), row_byte_width);

  SkDynamicMemoryWStream output;
#ifdef PDF_ENABLE_RUST_PNG
  bool success = SkPngRustEncoder::Encode(&output, pixmap, {});
#else
  bool success = SkPngEncoder::Encode(&output, pixmap, {});
#endif
  if (!success) {
    return {};
  }
  return output.detachAsVector();
}

}  // namespace

std::vector<uint8_t> DecodePNG(pdfium::span<const uint8_t> input,
                               bool reverse_byte_order,
                               int* width,
                               int* height) {
  CHECK(width);
  CHECK(height);

  auto stream = std::make_unique<SkMemoryStream>(input.data(), input.size(),
                                                 /*copyData=*/false);
#ifdef PDF_ENABLE_RUST_PNG
  std::unique_ptr<SkCodec> codec =
      SkPngRustDecoder::Decode(std::move(stream), nullptr);
#else
  std::unique_ptr<SkCodec> codec =
      SkPngDecoder::Decode(std::move(stream), nullptr);
#endif
  if (!codec) {
    return {};
  }

  SkColorType format =
      reverse_byte_order ? kBGRA_8888_SkColorType : kRGBA_8888_SkColorType;
  SkImageInfo info = codec->getInfo();
  info = info.makeColorType(format);
  info = info.makeColorSpace(SkColorSpace::MakeSRGB());

  std::vector<uint8_t> output;
  output.resize(info.computeMinByteSize());

  SkCodec::Result result =
      codec->getPixels(info, output.data(), info.minRowBytes());
  if (result != SkCodec::kSuccess) {
    return {};
  }

  *width = info.width();
  *height = info.height();
  return output;
}

std::vector<uint8_t> EncodeBGRPNG(pdfium::span<const uint8_t> bgr_input,
                                  int width,
                                  int height,
                                  int row_byte_width) {
  // Check inputs.  Expected values are manually calculated (instead of using
  // `SkImageInfo`'s `computeMinByteSize` and/or `minRowBytes`), because
  // `SkColorType` doesn't cover a format with 3 bytes per pixel (bpp) - e.g.
  // `kRGB_565_SkColorType` is 2 bpp and `kRGB_888x_SkColorType` is 4 bpp.
  size_t row_byte_width_as_size_t =
      pdfium::checked_cast<size_t>(row_byte_width);
  FX_SAFE_SIZE_T expected_minimum_row_byte_width = 3;
  expected_minimum_row_byte_width *= width;
  CHECK_LE(expected_minimum_row_byte_width.ValueOrDie(),
           row_byte_width_as_size_t);

  FX_SAFE_SIZE_T expected_minimum_input_size = row_byte_width_as_size_t;
  expected_minimum_input_size *= height;
  CHECK_LE(expected_minimum_input_size.ValueOrDie(), bgr_input.size());

  // Convert `bgr_input` into `intermediate_bgra_buf` (because Skia doesn't
  // allow encoding BGR pixels - see the comment at the top of the function
  // that talks about limitations of `SkColorType`).
  SkImageInfo intermediate_bgra_info =
      SkImageInfo::Make(width, height, kBGRA_8888_SkColorType,
                        kOpaque_SkAlphaType, SkColorSpace::MakeSRGB());
  size_t intermediate_bgra_row_byte_width =
      intermediate_bgra_info.minRowBytes();
  CHECK_NE(0,
           intermediate_bgra_row_byte_width);  // 0 means conversion problems.
  std::vector<uint8_t> intermediate_bgra_buf;
  intermediate_bgra_buf.resize(intermediate_bgra_info.computeMinByteSize());
  CHECK_NE(0, intermediate_bgra_buf.size());  // 0 means conversion problems.
  {
    pdfium::span<const uint8_t> src = bgr_input;
    pdfium::span<uint8_t> dst = intermediate_bgra_buf;
    size_t height_as_size_t = pdfium::checked_cast<size_t>(height);
    size_t width_as_size_t = pdfium::checked_cast<size_t>(width);
    for (size_t y = 0; y < height_as_size_t; y++) {
      for (size_t x = 0; x < width_as_size_t; x++) {
        // If `computeMinByteSize` didn't report an error (`0`), then integer
        // overflow won't happen in the `x * N` expressions below.
        pdfium::span<uint8_t> dst_pixel = dst.subspan(x * 4u).first(4u);
        pdfium::span<const uint8_t> src_pixel = src.subspan(x * 3u).first(3u);

        fxcrt::spancpy(dst_pixel.first(3u), src_pixel);  // Copy BGR channels.
        dst_pixel[3] = 0xFF;  // Set alpha channel to "opaque".
      }
      src = src.subspan(row_byte_width_as_size_t);
      dst = dst.subspan(intermediate_bgra_row_byte_width);
    }
  }

  return EncodePNG(intermediate_bgra_buf, kBGRA_8888_SkColorType,
                   kOpaque_SkAlphaType, width, height,
                   intermediate_bgra_row_byte_width);
}

std::vector<uint8_t> EncodeRGBAPNG(pdfium::span<const uint8_t> input,
                                   int width,
                                   int height,
                                   int row_byte_width) {
  return EncodePNG(input, kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, width,
                   height, pdfium::checked_cast<size_t>(row_byte_width));
}

std::vector<uint8_t> EncodeBGRAPNG(pdfium::span<const uint8_t> input,
                                   int width,
                                   int height,
                                   int row_byte_width,
                                   bool discard_transparency) {
  return EncodePNG(
      input, kBGRA_8888_SkColorType,
      discard_transparency ? kOpaque_SkAlphaType : kUnpremul_SkAlphaType, width,
      height, pdfium::checked_cast<size_t>(row_byte_width));
}

std::vector<uint8_t> EncodeGrayPNG(pdfium::span<const uint8_t> input,
                                   int width,
                                   int height,
                                   int row_byte_width) {
  return EncodePNG(input, kGray_8_SkColorType, kOpaque_SkAlphaType, width,
                   height, pdfium::checked_cast<size_t>(row_byte_width));
}

}  // namespace image_diff_png
