chromium/ui/gfx/codec/png_codec_unittest.cc

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

#include "ui/gfx/codec/png_codec.h"

#include <stddef.h>
#include <stdint.h>

#include <cmath>
#include <iomanip>

#include "base/base_paths.h"
#include "base/check.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/ranges/algorithm.h"
#include "base/test/metrics/histogram_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/libpng/png.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColorPriv.h"
#include "third_party/skia/include/core/SkUnPreMultiply.h"
#include "third_party/zlib/zlib.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/skia_util.h"

namespace gfx {

namespace {

void MakeRGBImage(int w, int h, std::vector<unsigned char>* data) {}

// Set use_transparency to write data into the alpha channel, otherwise it will
// be filled with 0xff. With the alpha channel stripped, this should yield the
// same image as MakeRGBImage above, so the code below can make reference
// images for conversion testing.
void MakeRGBAImage(int w,
                   int h,
                   bool use_transparency,
                   std::vector<unsigned char>* data) {}

// Creates a palette-based image.
void MakePaletteImage(int w,
                      int h,
                      std::vector<unsigned char>* data,
                      std::vector<png_color>* palette,
                      std::vector<unsigned char>* trans_chunk = 0) {}

// Creates a grayscale image without an alpha channel.
void MakeGrayscaleImage(int w, int h, std::vector<unsigned char>* data) {}

// Creates a grayscale image with an alpha channel.
void MakeGrayscaleAlphaImage(int w, int h, std::vector<unsigned char>* data) {}

// User write function (to be passed to libpng by EncodeImage) which writes
// into a buffer instead of to a file.
void WriteImageData(png_structp png_ptr, png_bytep data, png_size_t length) {}

// User flush function; goes with WriteImageData, above.
void FlushImageData(png_structp /*png_ptr*/) {}

// Libpng user error function which allows us to print libpng errors using
// Chrome's logging facilities instead of stderr.
void LogLibPNGError(png_structp png_ptr, png_const_charp error_msg) {}

// Goes with LogLibPNGError, above.
void LogLibPNGWarning(png_structp png_ptr, png_const_charp warning_msg) {}

// Color types supported by EncodeImage. Required because neither libpng nor
// PNGCodec::Encode supports all of the required values.
enum ColorType {};

constexpr size_t PixelBytesForColorType(ColorType color_type) {}

std::tuple<uint8_t, uint8_t, uint8_t> Read3(const std::vector<uint8_t>& pixels,
                                            size_t base) {}

std::tuple<uint8_t, uint8_t, uint8_t, uint8_t> Read4(
    const std::vector<uint8_t>& pixels,
    size_t base) {}

struct ImageSpec {};

SkColor ImageSpec::ReadPixel(int x, int y) const {}

bool ImagesExactlyEqual(const ImageSpec& a, const ImageSpec& b) {}

bool ImageExactlyEqualsSkBitmap(const ImageSpec& a, const SkBitmap& b) {}

// PNG encoder used for testing. Required because PNGCodec::Encode doesn't do
// interlaced, palette-based, or grayscale images, but PNGCodec::Decode is
// actually asked to decode these types of images by Chrome.
bool EncodeImage(const std::vector<unsigned char>& input,
                 const int width,
                 const int height,
                 ColorType output_color_type,
                 std::vector<unsigned char>* output,
                 const int interlace_type = PNG_INTERLACE_NONE,
                 std::vector<png_color>* palette = 0,
                 std::vector<unsigned char>* palette_alpha = 0) {}

}  // namespace

// Returns true if each channel of the given two colors are "close." This is
// used for comparing colors where rounding errors may cause off-by-one.
bool ColorsClose(uint32_t a, uint32_t b) {}

// Returns true if the RGB components are "close."
bool NonAlphaColorsClose(uint32_t a, uint32_t b) {}

// Returns true if the BGRA 32-bit SkColor specified by |a| is equivalent to the
// 8-bit Gray color specified by |b|.
bool BGRAGrayEqualsA8Gray(uint32_t a, uint8_t b) {}

void MakeTestBGRASkBitmap(int w, int h, SkBitmap* bmp) {}

void MakeTestA8SkBitmap(int w, int h, SkBitmap* bmp) {}

TEST(PNGCodec, EncodeDecodeRGBA) {}

TEST(PNGCodec, EncodeDecodeBGRA) {}

TEST(PNGCodec, DecodePalette) {}

TEST(PNGCodec, DecodeInterlacedPalette) {}

TEST(PNGCodec, DecodeGrayscale) {}

TEST(PNGCodec, DecodeGrayscaleWithAlpha) {}

TEST(PNGCodec, DecodeInterlacedGrayscale) {}

TEST(PNGCodec, DecodeInterlacedGrayscaleWithAlpha) {}

TEST(PNGCodec, DecodeInterlacedRGBA) {}

TEST(PNGCodec, DecodeInterlacedBGR) {}

TEST(PNGCodec, DecodeInterlacedBGRA) {}

// Not encoding an interlaced PNG from SkBitmap because we don't do it
// anywhere, and the ability to do that requires more code changes.
TEST(PNGCodec, DecodeInterlacedRGBtoSkBitmap) {}

void DecodeInterlacedRGBAtoSkBitmap(bool use_transparency) {}

TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap_Opaque) {}

TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap_Transparent) {}

TEST(PNGCodec, EncoderSavesImagesWithAllOpaquePixelsAsOpaque) {}

// Test that corrupted data decompression causes failures.
TEST(PNGCodec, DecodeCorrupted) {}

// Test decoding three PNG images, identical except for different gAMA chunks
// (with gamma values of 1.0, 1.8 and 2.2). All images are 256 x 256 pixels and
// 8-bit grayscale. The left half of the image is a solid block of medium gray
// (128 out of 255). The right half of the image alternates between black (0
// out of 255) and white (255 out of 255) in a checkerboard pattern.
//
// For the first file (gamma 1.0, linear), if you squint, the 128/255 left half
// should look about as bright as the checkerboard right half. PNGCodec::Decode
// applies gamma correction (assuming a default display gamma of 2.2), so the
// top left pixel value should be corrected from 128 to 186.
//
// The second file (gamma 1.8)'s correction is not as strong: from 128 to 145.
//
// The third file (gamma 2.2) matches the default display gamma and so the 128
// nominal value is unchanged. If you squint, the 128/255 left half should look
// darker than the right half.
//
// The "as used by libpng" formula for calculating these expected 186, 145 or
// (unchanged) 128 values can be seen in the diff at
// https://crrev.com/c/5402327/13/ui/gfx/codec/png_codec_unittest.cc
// and the same formula is at
// https://www.w3.org/TR/2003/REC-PNG-20031110/#13Decoder-gamma-handling but
// note the spec's caveat: "Viewers capable of full colour management... will
// perform more sophisticated calculations than those described here."
//
// Being corrected to 186, 145 or 128 assumes that, like libpng, the PNG
// decoder honors the gAMA chunk in the checkerboard.gamma*.png files. Those
// files don't have an iCCP color profile chunk, but since the PNGCodec::Decode
// API fills in a bag of RGBA pixels (without an associated colorspace), the
// PNGCodec::Decode implementation nonetheless applies sRGB color correction
// (approximately exponential) instead of basic gamma correction (literally
// exponential). This produces slightly different numbers: 188, 146 or 129. The
// code review in https://crrev.com/c/5402327 gives a little more context.
//
// When viewing these images in a browser, make sure to apply the "img {
// image-rendering: pixelated }" CSS. Otherwise, browsers will often blur when
// up-scaling (e.g. on high DPI displays), trumping the "two halves should have
// roughly equal / different brightness" effect. You can view the images at
// https://nigeltao.github.io/blog/2022/gamma-aware-pixelated-images.html
TEST(PNGCodec, DecodeGamma) {}

TEST(PNGCodec, EncodeBGRASkBitmapStridePadded) {}

TEST(PNGCodec, EncodeBGRASkBitmap) {}

TEST(PNGCodec, EncodeA8SkBitmap) {}

TEST(PNGCodec, EncodeBGRASkBitmapDiscardTransparency) {}

TEST(PNGCodec, EncodeWithComment) {}

TEST(PNGCodec, EncodeDecodeWithVaryingCompressionLevels) {}

TEST(PNGCodec, DecodingTruncatedEXIFChunkIsSafe) {}

}  // namespace gfx