Added unit tests for PngFile.
Fixed a couple issue like palettized files would not load, and stripping alpha was not affecting the color type reported by libpng. Also cleaned up some error reporting. Added AzFramework to Atom/Utils tests to support PngFile testing. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
This commit is contained in:
@@ -44,6 +44,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
AZ::AzTest
|
||||
AZ::AzFramework
|
||||
Gem::Atom_Utils.Static
|
||||
)
|
||||
ly_add_googletest(
|
||||
|
||||
@@ -55,9 +55,10 @@ namespace AZ
|
||||
//! @param size the dimensions of the image (m_depth is not used, assumed to be 1)
|
||||
//! @param format indicates the pixel format represented by @data. Only a limited set of formats are supported, see implementation.
|
||||
//! @param data the buffer of image data. The size of the buffer must match the @size and @format parameters.
|
||||
//! @param errorHandler optional callback function describing any errors that are encountered
|
||||
//! @return the created PngFile or an invalid PngFile if there was an error.
|
||||
static PngFile Create(const RHI::Size& size, RHI::Format format, AZStd::array_view<uint8_t> data);
|
||||
static PngFile Create(const RHI::Size& size, RHI::Format format, AZStd::vector<uint8_t>&& data);
|
||||
static PngFile Create(const RHI::Size& size, RHI::Format format, AZStd::array_view<uint8_t> data, ErrorHandler errorHandler = {});
|
||||
static PngFile Create(const RHI::Size& size, RHI::Format format, AZStd::vector<uint8_t>&& data, ErrorHandler errorHandler = {});
|
||||
|
||||
PngFile() = default;
|
||||
AZ_DEFAULT_MOVE(PngFile)
|
||||
@@ -84,11 +85,9 @@ namespace AZ
|
||||
|
||||
static void DefaultErrorHandler(const char* message);
|
||||
|
||||
// See png_get_IHDR in http://www.libpng.org/pub/png/libpng-1.4.0-manual.pdf...
|
||||
uint32_t m_width = 0;
|
||||
uint32_t m_height = 0;
|
||||
int32_t m_bitDepth = 0;
|
||||
int32_t m_colorType = 0;
|
||||
|
||||
Format m_bufferFormat = Format::Unknown;
|
||||
AZStd::vector<uint8_t> m_buffer;
|
||||
|
||||
@@ -27,13 +27,18 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
PngFile PngFile::Create(const RHI::Size& size, RHI::Format format, AZStd::array_view<uint8_t> data)
|
||||
PngFile PngFile::Create(const RHI::Size& size, RHI::Format format, AZStd::array_view<uint8_t> data, ErrorHandler errorHandler)
|
||||
{
|
||||
return Create(size, format, AZStd::vector<uint8_t>{data.begin(), data.end()});
|
||||
return Create(size, format, AZStd::vector<uint8_t>{data.begin(), data.end()}, errorHandler);
|
||||
}
|
||||
|
||||
PngFile PngFile::Create(const RHI::Size& size, RHI::Format format, AZStd::vector<uint8_t>&& data)
|
||||
PngFile PngFile::Create(const RHI::Size& size, RHI::Format format, AZStd::vector<uint8_t>&& data, ErrorHandler errorHandler)
|
||||
{
|
||||
if (!errorHandler)
|
||||
{
|
||||
errorHandler = [](const char* message) { DefaultErrorHandler(message); };
|
||||
}
|
||||
|
||||
PngFile image;
|
||||
|
||||
if (RHI::Format::R8G8B8A8_UNORM == format)
|
||||
@@ -43,15 +48,18 @@ namespace AZ
|
||||
image.m_width = size.m_width;
|
||||
image.m_height = size.m_height;
|
||||
image.m_bitDepth = 8;
|
||||
image.m_colorType = PNG_COLOR_TYPE_RGB_ALPHA;
|
||||
image.m_bufferFormat = PngFile::Format::RGBA;
|
||||
image.m_buffer = data;
|
||||
image.m_buffer = AZStd::move(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Invalid arguments. Buffer size does not match the image dimensions.");
|
||||
errorHandler("Invalid arguments. Buffer size does not match the image dimensions.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorHandler(AZStd::string::format("Cannot create PngFile with unsupported format %s", AZ::RHI::ToString(format)).c_str());
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
@@ -68,7 +76,7 @@ namespace AZ
|
||||
FILE* fp = NULL;
|
||||
if (fopen_s(&fp, path, "rb") || !fp)
|
||||
{
|
||||
loadSettings.m_errorHandler("Failed to open file.");
|
||||
loadSettings.m_errorHandler("Cannot open file.");
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -77,7 +85,7 @@ namespace AZ
|
||||
if (fread(header, 1, HeaderSize, fp) != HeaderSize)
|
||||
{
|
||||
fclose(fp);
|
||||
loadSettings.m_errorHandler("Invalid header.");
|
||||
loadSettings.m_errorHandler("Invalid png header.");
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -85,7 +93,7 @@ namespace AZ
|
||||
if (!isPng)
|
||||
{
|
||||
fclose(fp);
|
||||
loadSettings.m_errorHandler("Invalid header.");
|
||||
loadSettings.m_errorHandler("Invalid png header.");
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -154,11 +162,13 @@ namespace AZ
|
||||
|
||||
PngFile pngFile;
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr, &pngFile.m_width, &pngFile.m_height, &pngFile.m_bitDepth, &pngFile.m_colorType, NULL, NULL, NULL);
|
||||
int colorType = 0;
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr, &pngFile.m_width, &pngFile.m_height, &pngFile.m_bitDepth, &colorType, NULL, NULL, NULL);
|
||||
|
||||
uint32_t bytesPerPixel = 0;
|
||||
|
||||
switch (pngFile.m_colorType)
|
||||
switch (colorType)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
pngFile.m_bufferFormat = PngFile::Format::RGB;
|
||||
@@ -168,6 +178,12 @@ namespace AZ
|
||||
pngFile.m_bufferFormat = PngFile::Format::RGBA;
|
||||
bytesPerPixel = 4;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_PALETTE:
|
||||
// Handles cases where the image uses 1, 2, or 4 bit samples.
|
||||
// Note bytesPerPixel is 3 because we use PNG_TRANSFORM_PACKING
|
||||
pngFile.m_bufferFormat = PngFile::Format::RGB;
|
||||
bytesPerPixel = 3;
|
||||
break;
|
||||
default:
|
||||
AZ_Assert(false, "The png transforms should have ensured a pixel format of RGB or RGBA, 8 bits per channel");
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
|
||||
@@ -207,7 +223,7 @@ namespace AZ
|
||||
FILE* fp = NULL;
|
||||
if (fopen_s(&fp, path, "wb") || !fp)
|
||||
{
|
||||
saveSettings.m_errorHandler("Failed to open file.");
|
||||
saveSettings.m_errorHandler("Cannot open file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -245,7 +261,23 @@ namespace AZ
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, m_width, m_height, m_bitDepth, m_colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
int colorType = 0;
|
||||
if (saveSettings.m_stripAlpha || m_bufferFormat == PngFile::Format::RGB)
|
||||
{
|
||||
colorType = PNG_COLOR_TYPE_RGB;
|
||||
}
|
||||
else
|
||||
{
|
||||
colorType = PNG_COLOR_TYPE_RGBA;
|
||||
}
|
||||
|
||||
int transforms = PNG_TRANSFORM_IDENTITY;
|
||||
if (saveSettings.m_stripAlpha && m_bufferFormat == PngFile::Format::RGBA)
|
||||
{
|
||||
transforms |= PNG_TRANSFORM_STRIP_FILLER_AFTER;
|
||||
}
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, m_width, m_height, m_bitDepth, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_set_compression_level(png_ptr, saveSettings.m_compressionLevel);
|
||||
|
||||
@@ -259,14 +291,8 @@ namespace AZ
|
||||
}
|
||||
|
||||
png_set_rows(png_ptr, info_ptr, rows.begin());
|
||||
|
||||
int transforms = PNG_TRANSFORM_IDENTITY;
|
||||
if (saveSettings.m_stripAlpha && m_bufferFormat == PngFile::Format::RGBA)
|
||||
{
|
||||
transforms |= PNG_TRANSFORM_STRIP_FILLER_AFTER;
|
||||
}
|
||||
|
||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
|
||||
png_write_png(png_ptr, info_ptr, transforms, NULL);
|
||||
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/Utils/PngFile.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/Math/Color.h>
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
using namespace AZ::Utils;
|
||||
|
||||
class PngFileTests
|
||||
: public AllocatorsFixture
|
||||
{
|
||||
protected:
|
||||
AZStd::string m_testImageFolder;
|
||||
AZStd::string m_tempPngFilePath;
|
||||
AZStd::vector<uint8_t> m_primaryColors3x1;
|
||||
AZStd::unique_ptr<AZ::IO::FileIOBase> m_localFileIO;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AllocatorsFixture::SetUp();
|
||||
|
||||
m_testImageFolder = AZ::Test::GetEngineRootPath() + "/Gems/Atom/Utils/Code/Tests/PngTestImages/";
|
||||
m_tempPngFilePath = m_testImageFolder + "temp.png";
|
||||
|
||||
m_localFileIO.reset(aznew AZ::IO::LocalFileIO());
|
||||
AZ::IO::FileIOBase::SetInstance(m_localFileIO.get());
|
||||
|
||||
AZ::IO::FileIOBase::GetInstance()->Remove(m_tempPngFilePath.c_str());
|
||||
|
||||
m_primaryColors3x1 = {
|
||||
255u, 0u, 0u, 255u,
|
||||
0u, 255u, 0u, 255u,
|
||||
0u, 0u, 255u, 255u
|
||||
};
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_testImageFolder = AZStd::string{};
|
||||
m_tempPngFilePath = AZStd::string{};
|
||||
m_primaryColors3x1 = AZStd::vector<uint8_t>{};
|
||||
|
||||
AZ::IO::FileIOBase::SetInstance(nullptr);
|
||||
m_localFileIO.reset();
|
||||
|
||||
AllocatorsFixture::TearDown();
|
||||
}
|
||||
|
||||
struct Color3 : public AZStd::array<uint8_t, 3>
|
||||
{
|
||||
using Base = AZStd::array<uint8_t, 3>;
|
||||
Color3(uint8_t r, uint8_t g, uint8_t b) : Base({r, g, b}) {}
|
||||
Color3(const uint8_t* raw) : Base({raw[0], raw[1], raw[2]}) {}
|
||||
};
|
||||
|
||||
struct Color4 : public AZStd::array<uint8_t, 4>
|
||||
{
|
||||
using Base = AZStd::array<uint8_t, 4>;
|
||||
Color4(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : Base({r, g, b, a}) {}
|
||||
Color4(const uint8_t* raw) : Base({raw[0], raw[1], raw[2], raw[3]}) {}
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(PngFileTests, LoadRgb)
|
||||
{
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "ColorChart_rgb.png").c_str());
|
||||
EXPECT_TRUE(image.IsValid());
|
||||
EXPECT_EQ(image.GetBufferFormat(), PngFile::Format::RGB);
|
||||
EXPECT_EQ(image.GetWidth(), 3);
|
||||
EXPECT_EQ(image.GetHeight(), 2);
|
||||
EXPECT_EQ(image.GetBuffer().size(), 18);
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 0), Color3(255u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 3), Color3(0u, 255u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 6), Color3(0u, 0u, 255u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 9), Color3(255u, 255u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 12), Color3(0u, 255u, 255u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 15), Color3(255u, 0u, 255u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, LoadRgba)
|
||||
{
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "ColorChart_rgba.png").c_str());
|
||||
EXPECT_TRUE(image.IsValid());
|
||||
EXPECT_EQ(image.GetBufferFormat(), PngFile::Format::RGBA);
|
||||
EXPECT_EQ(image.GetWidth(), 3);
|
||||
EXPECT_EQ(image.GetHeight(), 2);
|
||||
EXPECT_EQ(image.GetBuffer().size(), 24);
|
||||
EXPECT_EQ(Color4(image.GetBuffer().begin() + 0), Color4(255u, 0u, 0u, 200u));
|
||||
EXPECT_EQ(Color4(image.GetBuffer().begin() + 4), Color4(0u, 255u, 0u, 150u));
|
||||
EXPECT_EQ(Color4(image.GetBuffer().begin() + 8), Color4(0u, 0u, 255u, 100u));
|
||||
EXPECT_EQ(Color4(image.GetBuffer().begin() + 12), Color4(255u, 255u, 0u, 125u));
|
||||
EXPECT_EQ(Color4(image.GetBuffer().begin() + 16), Color4(0u, 255u, 255u, 175u));
|
||||
EXPECT_EQ(Color4(image.GetBuffer().begin() + 20), Color4(255u, 0u, 255u, 75u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, LoadRgbaStripAlpha)
|
||||
{
|
||||
PngFile::LoadSettings loadSettings;
|
||||
loadSettings.m_stripAlpha = true;
|
||||
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "ColorChart_rgba.png").c_str(), loadSettings);
|
||||
// Note these checks are identical to the LoadRgb test.
|
||||
EXPECT_TRUE(image.IsValid());
|
||||
EXPECT_EQ(image.GetBufferFormat(), PngFile::Format::RGB);
|
||||
EXPECT_EQ(image.GetWidth(), 3);
|
||||
EXPECT_EQ(image.GetHeight(), 2);
|
||||
EXPECT_EQ(image.GetBuffer().size(), 18);
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 0), Color3(255u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 3), Color3(0u, 255u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 6), Color3(0u, 0u, 255u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 9), Color3(255u, 255u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 12), Color3(0u, 255u, 255u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 15), Color3(255u, 0u, 255u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, LoadColorPaletteTwoBits)
|
||||
{
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "ColorPalette_2bit.png").c_str());
|
||||
EXPECT_TRUE(image.IsValid());
|
||||
EXPECT_EQ(image.GetBufferFormat(), PngFile::Format::RGB);
|
||||
EXPECT_EQ(image.GetWidth(), 1);
|
||||
EXPECT_EQ(image.GetHeight(), 3);
|
||||
EXPECT_EQ(image.GetBuffer().size(), 9);
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 0), Color3(255u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 3), Color3(0u, 255u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 6), Color3(0u, 0u, 255u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, LoadGrayscaleOneBit)
|
||||
{
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "GrayPalette_1bit.png").c_str());
|
||||
EXPECT_TRUE(image.IsValid());
|
||||
EXPECT_EQ(image.GetBufferFormat(), PngFile::Format::RGB);
|
||||
EXPECT_EQ(image.GetWidth(), 1);
|
||||
EXPECT_EQ(image.GetHeight(), 2);
|
||||
EXPECT_EQ(image.GetBuffer().size(), 6);
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 0), Color3(0u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 3), Color3(255u, 255u, 255u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, LoadRgba64Bits)
|
||||
{
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "Gradient_rgb_16bpc.png").c_str());
|
||||
EXPECT_TRUE(image.IsValid());
|
||||
EXPECT_EQ(image.GetBufferFormat(), PngFile::Format::RGB);
|
||||
EXPECT_EQ(image.GetWidth(), 5);
|
||||
EXPECT_EQ(image.GetHeight(), 1);
|
||||
EXPECT_EQ(image.GetBuffer().size(), 15);
|
||||
// The values in this file are 30.0f, 30.1f, 30.2f, 30.3f, 30.4f. But we use PNG_TRANSFORM_STRIP_16 to reduce them to 8 bits per channel for simplicity.
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 0), Color3(76u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 3), Color3(77u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 6), Color3(77u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 9), Color3(77u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(image.GetBuffer().begin() + 12), Color3(77u, 0u, 0u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, CreateCopy)
|
||||
{
|
||||
AZStd::vector<uint8_t> data = m_primaryColors3x1;
|
||||
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 1, 0}, AZ::RHI::Format::R8G8B8A8_UNORM, data);
|
||||
EXPECT_TRUE(savedImage.IsValid());
|
||||
EXPECT_EQ(savedImage.GetWidth(), 3);
|
||||
EXPECT_EQ(savedImage.GetHeight(), 1);
|
||||
EXPECT_EQ(savedImage.GetBuffer(), data);
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, CreateMove)
|
||||
{
|
||||
AZStd::vector<uint8_t> data = m_primaryColors3x1;
|
||||
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 1, 0}, AZ::RHI::Format::R8G8B8A8_UNORM, AZStd::move(data));
|
||||
EXPECT_TRUE(savedImage.IsValid());
|
||||
EXPECT_EQ(savedImage.GetWidth(), 3);
|
||||
EXPECT_EQ(savedImage.GetHeight(), 1);
|
||||
EXPECT_EQ(savedImage.GetBuffer(), m_primaryColors3x1);
|
||||
EXPECT_TRUE(data.empty()); // The data should have been moved
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, SaveRgba)
|
||||
{
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 1, 0}, AZ::RHI::Format::R8G8B8A8_UNORM, m_primaryColors3x1);
|
||||
bool result = savedImage.Save(m_tempPngFilePath.c_str());
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
PngFile loadedImage = PngFile::Load(m_tempPngFilePath.c_str());
|
||||
EXPECT_TRUE(loadedImage.IsValid());
|
||||
EXPECT_EQ(loadedImage.GetBufferFormat(), savedImage.GetBufferFormat());
|
||||
EXPECT_EQ(loadedImage.GetWidth(), savedImage.GetWidth());
|
||||
EXPECT_EQ(loadedImage.GetHeight(), savedImage.GetHeight());
|
||||
EXPECT_EQ(loadedImage.GetBuffer(), savedImage.GetBuffer());
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, SaveRgbaStripAlpha)
|
||||
{
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 1, 0}, AZ::RHI::Format::R8G8B8A8_UNORM, m_primaryColors3x1);
|
||||
|
||||
PngFile::SaveSettings saveSettings;
|
||||
saveSettings.m_stripAlpha = true;
|
||||
|
||||
bool result = savedImage.Save(m_tempPngFilePath.c_str(), saveSettings);
|
||||
EXPECT_TRUE(result);
|
||||
|
||||
// The alpha was stripped when saving. Now we load the data without stripping anything and should find
|
||||
// that there is no alpha channel.
|
||||
|
||||
PngFile loadedImage = PngFile::Load(m_tempPngFilePath.c_str());
|
||||
|
||||
// The dimensions are the same...
|
||||
EXPECT_TRUE(loadedImage.IsValid());
|
||||
EXPECT_EQ(loadedImage.GetWidth(), savedImage.GetWidth());
|
||||
EXPECT_EQ(loadedImage.GetHeight(), savedImage.GetHeight());
|
||||
|
||||
// ... but the format is different
|
||||
EXPECT_NE(loadedImage.GetBufferFormat(), savedImage.GetBufferFormat());
|
||||
EXPECT_EQ(loadedImage.GetBufferFormat(), PngFile::Format::RGB);
|
||||
|
||||
// ... and the loaded data is smaller
|
||||
EXPECT_NE(loadedImage.GetBuffer(), savedImage.GetBuffer());
|
||||
EXPECT_EQ(Color3(loadedImage.GetBuffer().begin() + 0), Color3(255u, 0u, 0u));
|
||||
EXPECT_EQ(Color3(loadedImage.GetBuffer().begin() + 3), Color3(0u, 255u, 0u));
|
||||
EXPECT_EQ(Color3(loadedImage.GetBuffer().begin() + 6), Color3(0u, 0u, 255u));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_CreateUnsupportedFormat)
|
||||
{
|
||||
AZStd::vector<uint8_t> data = m_primaryColors3x1;
|
||||
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 1, 0}, AZ::RHI::Format::R32_UINT, data,
|
||||
[&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; });
|
||||
|
||||
EXPECT_FALSE(savedImage.IsValid());
|
||||
EXPECT_TRUE(gotErrorMessage.find("unsupported format R32_UINT") != AZStd::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_CreateIncorrectBufferSize)
|
||||
{
|
||||
AZStd::vector<uint8_t> data = m_primaryColors3x1;
|
||||
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 2, 0}, AZ::RHI::Format::R8G8B8A8_UNORM, data,
|
||||
[&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; });
|
||||
|
||||
EXPECT_FALSE(savedImage.IsValid());
|
||||
EXPECT_TRUE(gotErrorMessage.find("does not match") != AZStd::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_LoadFileNotFound)
|
||||
{
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile::LoadSettings loadSettings;
|
||||
loadSettings.m_errorHandler = [&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; };
|
||||
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "DoesNotExist.png").c_str(), loadSettings);
|
||||
EXPECT_FALSE(image.IsValid());
|
||||
EXPECT_TRUE(gotErrorMessage.find("not open file") != AZStd::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_LoadEmptyFile)
|
||||
{
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile::LoadSettings loadSettings;
|
||||
loadSettings.m_errorHandler = [&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; };
|
||||
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "EmptyFile.png").c_str(), loadSettings);
|
||||
EXPECT_FALSE(image.IsValid());
|
||||
EXPECT_TRUE(gotErrorMessage.find("Invalid png header") != AZStd::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_LoadNotPngFile)
|
||||
{
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile::LoadSettings loadSettings;
|
||||
loadSettings.m_errorHandler = [&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; };
|
||||
|
||||
PngFile image = PngFile::Load((m_testImageFolder + "ColorChart_rgba.jpg").c_str(), loadSettings);
|
||||
EXPECT_FALSE(image.IsValid());
|
||||
EXPECT_TRUE(gotErrorMessage.find("Invalid png header") != AZStd::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_SaveInvalidPngFile)
|
||||
{
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile::SaveSettings saveSettings;
|
||||
saveSettings.m_errorHandler = [&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; };
|
||||
|
||||
PngFile savedImage;
|
||||
bool result = savedImage.Save(m_tempPngFilePath.c_str(), saveSettings);
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_TRUE(gotErrorMessage.find("PngFile is invalid") != AZStd::string::npos);
|
||||
EXPECT_FALSE(AZ::IO::FileIOBase::GetInstance()->Exists(m_tempPngFilePath.c_str()));
|
||||
}
|
||||
|
||||
TEST_F(PngFileTests, Error_SaveOverLockedFile)
|
||||
{
|
||||
AZStd::string gotErrorMessage;
|
||||
|
||||
PngFile::SaveSettings saveSettings;
|
||||
saveSettings.m_errorHandler = [&gotErrorMessage](const char* errorMessage) { gotErrorMessage = errorMessage; };
|
||||
|
||||
AZ::IO::FileIOStream tempFileStream;
|
||||
tempFileStream.Open(m_tempPngFilePath.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeCreatePath);
|
||||
|
||||
PngFile savedImage = PngFile::Create(AZ::RHI::Size{3, 1, 0}, AZ::RHI::Format::R8G8B8A8_UNORM, m_primaryColors3x1);
|
||||
bool result = savedImage.Save(m_tempPngFilePath.c_str(), saveSettings);
|
||||
EXPECT_FALSE(result);
|
||||
EXPECT_TRUE(gotErrorMessage.find("not open file") != AZStd::string::npos);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
temp.png
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:af0d0d079354495ff96aa266ecb4092d679e6c5a952e8b2d4ee743e538d54809
|
||||
size 126
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:01cad8dd75c9a26169e858960817424362c16cbf2a8df8bc55857f6172ce2526
|
||||
size 834
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6ddb5f70eaf72fe09add6cc7cdf7cbba2d327ab312bb9bde73d7f456f80b8d6e
|
||||
size 141
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b50e93bbbd320d69752df2c25b4118c0198226a0d230781a6ed93f89b7eea053
|
||||
size 142
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cb56e8bf15a4727bcebba579cb97a36e1f26e4a4870b2b4a38bdbd4b4bd076fd
|
||||
size 127
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:710fd5c80af49a42249a471ded6c9119be79d6748218073bb8297ffb4b4e62d1
|
||||
size 137
|
||||
@@ -8,5 +8,6 @@
|
||||
|
||||
set(FILES
|
||||
Tests/ImageComparisonTests.cpp
|
||||
Tests/PngFileTests.cpp
|
||||
Tests/StableDynamicArrayTests.cpp
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user