| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104 |
- /*
- * 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 <AzTest/AzTest.h>
- #include <AzTest/Utils.h>
- #include <AzQtComponents/Utilities/QtPluginPaths.h>
- #include <AzCore/AzCore_Traits_Platform.h>
- #include <AzCore/Asset/AssetManager.h>
- #include <AzCore/Asset/AssetManagerComponent.h>
- #include <AzCore/Jobs/JobContext.h>
- #include <AzCore/Jobs/JobManager.h>
- #include <AzCore/Memory/Memory.h>
- #include <AzCore/Memory/PoolAllocator.h>
- #include <AzCore/Name/NameDictionary.h>
- #include <AzCore/RTTI/ReflectionManager.h>
- #include <AzCore/Serialization/DataPatch.h>
- #include <AzCore/Serialization/Json/JsonSystemComponent.h>
- #include <AzCore/Serialization/Json/RegistrationContext.h>
- #include <AzCore/Serialization/ObjectStream.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/Serialization/Utils.h>
- #include <AzCore/Settings/SettingsRegistryImpl.h>
- #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
- #include <AzFramework/IO/LocalFileIO.h>
- #include <Atom/ImageProcessing/ImageObject.h>
- #include <Atom/ImageProcessing/ImageProcessingDefines.h>
- #include <Processing/PixelFormatInfo.h>
- #include <Processing/ImageConvert.h>
- #include <Processing/ImageToProcess.h>
- #include <Processing/ImageAssetProducer.h>
- #include <Processing/ImageFlags.h>
- #include <ImageLoader/ImageLoaders.h>
- #include <Compressors/Compressor.h>
- #include <Converters/Cubemap.h>
- #include <BuilderSettings/BuilderSettingManager.h>
- #include <BuilderSettings/CubemapSettings.h>
- #include <BuilderSettings/PresetSettings.h>
- #include <Editor/EditorCommon.h>
- #include <Atom/RPI.Reflect/Asset/AssetHandler.h>
- #include <Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h>
- #include <Atom/RHI.Reflect/ReflectSystemComponent.h>
- #include <QFileInfo>
- #include <qdir.h>
- #include <QDirIterator>
- #include <QIODevice>
- #include <array>
- #include <utility>
- //Enable generate image files for result of some tests.
- //This is slow and only useful for debugging. This should be disabled for unit test
- //#define DEBUG_OUTPUT_IMAGES
- //There are some test functions in this test which are DISABLED. They were mainly for programming tests.
- //It's only recommended to enable them for programming test purpose.
- #include <AzCore/UnitTest/TestTypes.h>
- #include <ImageBuilderComponent.h>
- using namespace ImageProcessingAtom;
- namespace UnitTest
- {
- // Expose AZ::AssetManagerComponent::Reflect function for testing
- class MyAssetManagerComponent
- : public AZ::AssetManagerComponent
- {
- public:
- static void Reflect(ReflectContext* reflection)
- {
- AZ::AssetManagerComponent::Reflect(reflection);
- };
- };
- class ImageProcessingTest
- : public LeakDetectionFixture
- , public AZ::ComponentApplicationBus::Handler
- {
- public:
- //////////////////////////////////////////////////////////////////////////
- // ComponentApplicationMessages.
- AZ::ComponentApplication* GetApplication() override { return nullptr; }
- void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
- void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
- void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override { }
- void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override { }
- void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override { }
- void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override { }
- void SignalEntityActivated(AZ::Entity*) override { }
- void SignalEntityDeactivated(AZ::Entity*) override { }
- bool AddEntity(AZ::Entity*) override { return false; }
- bool RemoveEntity(AZ::Entity*) override { return false; }
- bool DeleteEntity(const AZ::EntityId&) override { return false; }
- Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
- AZ::SerializeContext* GetSerializeContext() override { return m_context.get(); }
- AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
- AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return m_jsonRegistrationContext.get(); }
- const char* GetEngineRoot() const override { return nullptr; }
- const char* GetExecutableFolder() const override { return nullptr; }
- void EnumerateEntities(const AZ::ComponentApplicationRequests::EntityCallback& /*callback*/) override {}
- void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
- //////////////////////////////////////////////////////////////////////////
- protected:
- AZStd::unique_ptr<AZ::SerializeContext> m_context;
- AZStd::unique_ptr<AZ::JsonRegistrationContext> m_jsonRegistrationContext;
- AZStd::unique_ptr<AZ::JsonSystemComponent> m_jsonSystemComponent;
- AZStd::vector<AZStd::unique_ptr<AZ::Data::AssetHandler>> m_assetHandlers;
- AZ::IO::Path m_gemFolder;
- AZ::IO::Path m_outputRootFolder;
- AZ::IO::Path m_outputFolder;
- AZStd::unique_ptr<AZ::JobManager> m_jobManager;
- AZStd::unique_ptr<AZ::JobContext> m_jobContext;
- void SetUp() override
- {
- // Adding this handler to allow utility functions access the serialize context
- ComponentApplicationBus::Handler::BusConnect();
- AZ::Interface<AZ::ComponentApplicationRequests>::Register(this);
- // AssetManager required to generate image assets
- AZ::Data::AssetManager::Descriptor desc;
- AZ::Data::AssetManager::Create(desc);
- AZ::NameDictionary::Create();
- m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler<AZ::RPI::ImageMipChainAssetHandler>());
- m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler<AZ::RPI::StreamingImageAssetHandler>());
- m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler<AZ::RPI::StreamingImagePoolAssetHandler>());
- BuilderSettingManager::CreateInstance();
- //prepare reflection
- m_context = AZStd::make_unique<AZ::SerializeContext>();
- AZ::Name::Reflect(m_context.get());
- BuilderPluginComponent::Reflect(m_context.get());
- AZ::DataPatch::Reflect(m_context.get());
- AZ::RHI::ReflectSystemComponent::Reflect(m_context.get());
- AZ::RPI::ImageMipChainAsset::Reflect(m_context.get());
- AZ::RPI::ImageAsset::Reflect(m_context.get());
- AZ::RPI::StreamingImageAsset::Reflect(m_context.get());
- MyAssetManagerComponent::Reflect(m_context.get());
- m_jsonRegistrationContext = AZStd::make_unique<AZ::JsonRegistrationContext>();
- m_jsonSystemComponent = AZStd::make_unique<AZ::JsonSystemComponent>();
- m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get());
- AZ::Name::Reflect(m_jsonRegistrationContext.get());
- BuilderPluginComponent::Reflect(m_jsonRegistrationContext.get());
- // Setup job context for job system
- JobManagerDesc jobManagerDesc;
- JobManagerThreadDesc threadDesc;
- #if AZ_TRAIT_SET_JOB_PROCESSOR_ID
- threadDesc.m_cpuId = 0; // Don't set processors IDs on windows
- #endif
- uint32_t numWorkerThreads = AZStd::thread::hardware_concurrency();
- for (unsigned int i = 0; i < numWorkerThreads; ++i)
- {
- jobManagerDesc.m_workerThreads.push_back(threadDesc);
- #if AZ_TRAIT_SET_JOB_PROCESSOR_ID
- threadDesc.m_cpuId++;
- #endif
- }
- m_jobManager = AZStd::make_unique<JobManager>(jobManagerDesc);
- m_jobContext = AZStd::make_unique<JobContext>(*m_jobManager);
- JobContext::SetGlobalContext(m_jobContext.get());
- // Startup default local FileIO (hits OSAllocator) if not already setup.
- if (AZ::IO::FileIOBase::GetInstance() == nullptr)
- {
- AZ::IO::FileIOBase::SetInstance(aznew AZ::IO::LocalFileIO());
- }
- //load qt plug-ins for some image file formats support
- AzQtComponents::PrepareQtPaths();
- using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
- AZ::SettingsRegistryImpl localRegistry;
- localRegistry.Set(AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder, AZ::Test::GetEngineRootPath());
- // Merge in the o3de manifest files gem root paths to the Settings Registry
- // and set the ImageProcessingAtom gem as an active gem which will add it to the active gem
- // section of the Settings Registry as well as add a @gemroot@ alias for it
- AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ManifestGemsPaths(localRegistry);
- AZ::Test::AddActiveGem("ImageProcessingAtom", localRegistry, AZ::IO::FileIOBase::GetInstance());
- // Validate the path to the ImageProcessingAtom Gem root is registered in the Settings Registry
- ASSERT_TRUE(localRegistry.Get(m_gemFolder.Native(), FixedValueString::format("%s/ImageProcessingAtom/Path",
- AZ::SettingsRegistryMergeUtils::ManifestGemsRootKey)));
- m_outputFolder = m_gemFolder/ "Code/Tests/TestAssets/temp/";
- m_defaultSettingFolder = m_gemFolder / "Assets/Config/";
- m_testFileFolder = m_gemFolder /"Code/Tests/TestAssets/";
- InitialImageFilenames();
- ImageProcessingAtomEditor::EditorHelper::InitPixelFormatString();
- }
- void TearDown() override
- {
- m_gemFolder = AZ::IO::Path{};
- m_outputFolder = AZ::IO::Path{};
- m_defaultSettingFolder = AZ::IO::Path{};
- m_testFileFolder = AZ::IO::Path{};
- m_imagFileNameMap = AZStd::map<ImageFeature, AZStd::string>();
- m_assetHandlers = AZStd::vector<AZStd::unique_ptr<AZ::Data::AssetHandler>>();
- delete AZ::IO::FileIOBase::GetInstance();
- AZ::IO::FileIOBase::SetInstance(nullptr);
- JobContext::SetGlobalContext(nullptr);
- m_jobContext = nullptr;
- m_jobManager = nullptr;
- m_jsonRegistrationContext->EnableRemoveReflection();
- m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get());
- BuilderPluginComponent::Reflect(m_jsonRegistrationContext.get());
- AZ::Name::Reflect(m_jsonRegistrationContext.get());
- m_jsonRegistrationContext->DisableRemoveReflection();
- m_jsonRegistrationContext.reset();
- m_jsonSystemComponent.reset();
- m_context.reset();
- BuilderSettingManager::DestroyInstance();
- CPixelFormats::DestroyInstance();
- AZ::NameDictionary::Destroy();
- AZ::Data::AssetManager::Destroy();
- AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(this);
- ComponentApplicationBus::Handler::BusDisconnect();
- }
- //enum names for Images with specific identification
- enum ImageFeature
- {
- Image_20X16_RGBA8_Png = 0,
- Image_32X32_16bit_F_Tif,
- Image_32X32_32bit_F_Tif,
- Image_32X32_checkerboard_png,
- Image_32X32_halfRedHalfTransparentGreen_png,
- Image_200X200_RGB8_Jpg,
- Image_512X288_RGB8_Tga,
- Image_1024X1024_RGB8_Tif,
- Image_UpperCase_Tga,
- Image_512x512_normal_tiff,
- Image_128x128_Transparent_Tga,
- Image_237x177_RGB_Jpg,
- Image_GreyScale_Png,
- Image_Alpha8_64x64_Mip7_Dds,
- Image_BGRA_64x64_Mip7_Dds,
- Image_Luminance8bpp_66x33_dds,
- Image_BGR_64x64_dds,
- Image_defaultprobe_cm_1536x256_64bits_tif,
- Image_workshop_iblskyboxcm_exr
- };
- //image file names for testing
- AZStd::map<ImageFeature, AZStd::string> m_imagFileNameMap;
- AZ::IO::Path m_defaultSettingFolder;
- AZ::IO::Path m_testFileFolder;
- //initialize image file names for testing
- void InitialImageFilenames()
- {
- m_imagFileNameMap[Image_20X16_RGBA8_Png] = (m_testFileFolder / "20x16_32bit.png").Native();
- m_imagFileNameMap[Image_32X32_16bit_F_Tif] = (m_testFileFolder / "32x32_16bit_f.tif").Native();
- m_imagFileNameMap[Image_32X32_32bit_F_Tif] = (m_testFileFolder / "32x32_32bit_f.tif").Native();
- m_imagFileNameMap[Image_32X32_checkerboard_png] = (m_testFileFolder / "32x32_checkerboard.png").Native();
- m_imagFileNameMap[Image_32X32_halfRedHalfTransparentGreen_png] = (m_testFileFolder / "32x32_halfRedHalfTransparentGreen.png").Native();
- m_imagFileNameMap[Image_200X200_RGB8_Jpg] = (m_testFileFolder / "200x200_24bit.jpg").Native();
- m_imagFileNameMap[Image_512X288_RGB8_Tga] = (m_testFileFolder / "512x288_24bit.tga").Native();
- m_imagFileNameMap[Image_1024X1024_RGB8_Tif] = (m_testFileFolder / "1024x1024_24bit.tif").Native();
- m_imagFileNameMap[Image_UpperCase_Tga] = (m_testFileFolder / "uppercase.TGA").Native();
- m_imagFileNameMap[Image_512x512_normal_tiff] = (m_testFileFolder / "512x512_normal.tiff").Native();
- m_imagFileNameMap[Image_128x128_Transparent_Tga] = (m_testFileFolder / "128x128_RGBA8.tga").Native();
- m_imagFileNameMap[Image_237x177_RGB_Jpg] = (m_testFileFolder / "237x177_RGB.jpg").Native();
- m_imagFileNameMap[Image_GreyScale_Png] = (m_testFileFolder / "greyscale.png").Native();
- m_imagFileNameMap[Image_Alpha8_64x64_Mip7_Dds] = (m_testFileFolder / "Alpha8_64x64_Mip7.dds").Native();
- m_imagFileNameMap[Image_BGRA_64x64_Mip7_Dds] = (m_testFileFolder / "BGRA_64x64_MIP7.dds").Native();
- m_imagFileNameMap[Image_Luminance8bpp_66x33_dds] = (m_testFileFolder / "Luminance8bpp_66x33.dds").Native();
- m_imagFileNameMap[Image_BGR_64x64_dds] = (m_testFileFolder / "RGBA_64x64.dds").Native();
- m_imagFileNameMap[Image_defaultprobe_cm_1536x256_64bits_tif] = (m_testFileFolder / "defaultProbe_cm.tif").Native();
- m_imagFileNameMap[Image_workshop_iblskyboxcm_exr] = (m_testFileFolder / "workshop_iblskyboxcm.exr").Native();
- }
- public:
- void SetOutputSubFolder(const char* subFolderName)
- {
- if (subFolderName)
- {
- m_outputFolder = m_outputRootFolder / subFolderName;
- }
- else
- {
- m_outputFolder = m_outputRootFolder;
- }
- }
- //helper function to save an image object to a file through QtImage
- void SaveImageToFile([[maybe_unused]] const IImageObjectPtr imageObject, [[maybe_unused]] const AZStd::string imageName, [[maybe_unused]] AZ::u32 maxMipCnt = 100)
- {
- #ifndef DEBUG_OUTPUT_IMAGES
- return;
- #else
- if (imageObject == nullptr)
- {
- return;
- }
- // create dir if it doesn't exist
- QDir dir;
- QDir outputDir(m_outputFolder.c_str());
- if (!outputDir.exists())
- {
- dir.mkpath(m_outputFolder.c_str());
- }
- //save origin file pixel format so we could use it to generate name later
- EPixelFormat originPixelFormat = imageObject->GetPixelFormat();
- //convert to RGBA8 before can be exported.
- ImageToProcess imageToProcess(imageObject);
- imageToProcess.ConvertFormat(ePixelFormat_R8G8B8A8);
- IImageObjectPtr finalImage = imageToProcess.Get();
- //for each mipmap
- for (uint32 mip = 0; mip < finalImage->GetMipCount() && mip < maxMipCnt; mip++)
- {
- uint8* imageBuf;
- uint32 pitch;
- finalImage->GetImagePointer(mip, imageBuf, pitch);
- uint32 width = finalImage->GetWidth(mip);
- uint32 height = finalImage->GetHeight(mip);
- uint32 originalSize = imageObject->GetMipBufSize(mip);
- //generate file name
- char filePath[2048];
- azsprintf(filePath, "%s%s_%s_mip%d_%dx%d_%d.png", m_outputFolder.data(), imageName.c_str()
- , CPixelFormats::GetInstance().GetPixelFormatInfo(originPixelFormat)->szName
- , mip, width, height, originalSize);
- QImage qimage(imageBuf, width, height, pitch, QImage::Format_RGBA8888);
- qimage.save(filePath);
- }
- #endif
- }
- static bool GetComparisonResult(IImageObjectPtr image1, IImageObjectPtr image2, QString& output)
- {
- bool isImageLoaded = true;
- bool isDifferent = false;
- if (image1 == nullptr)
- {
- isImageLoaded = false;
- output += ",Image 1 does not exist. ";
- }
- if (image2 == nullptr)
- {
- isImageLoaded = false;
- output += ",Image 2 does not exist. ";
- }
- if (!isImageLoaded)
- {
- return (!image1 && !image2) ? false : true;
- }
- // Mip
- int mip1 = image1->GetMipCount();
- int mip2 = image2->GetMipCount();
- int mipDiff = abs(mip1 - mip2);
- isDifferent |= mipDiff != 0;
- // Format
- EPixelFormat format1 = image1->GetPixelFormat();
- EPixelFormat format2 = image2->GetPixelFormat();
- isDifferent |= (format1 != format2);
- // Flag
- AZ::u32 flag1 = image1->GetImageFlags();
- AZ::u32 flag2 = image2->GetImageFlags();
- isDifferent |= (flag1 != flag2);
- // Size
- int memSize1 = image1->GetTextureMemory();
- int memSize2 = image2->GetTextureMemory();
- int memDiff = abs(memSize1 - memSize2);
- isDifferent |= memDiff != 0;
- // Error
- float error = GetErrorBetweenImages(image1, image2);
- static float EPSILON = 0.000001f;
- isDifferent |= abs(error) >= EPSILON;
- output += QString(",%1/%2,%3,%4/%5,%6/%7,").arg(QString::number(mip1, 'f', 1), QString::number(mip2, 'f', 1), QString::number(mipDiff),
- QString(ImageProcessingAtomEditor::EditorHelper::s_PixelFormatString[format1]),
- QString(ImageProcessingAtomEditor::EditorHelper::s_PixelFormatString[format2]),
- QString::number(flag1, 16), QString::number(flag2, 16));
- output += QString("%1/%2,%3,%4").arg(QString(ImageProcessingAtomEditor::EditorHelper::GetFileSizeString(memSize1).c_str()),
- QString(ImageProcessingAtomEditor::EditorHelper::GetFileSizeString(memSize2).c_str()),
- QString(ImageProcessingAtomEditor::EditorHelper::GetFileSizeString(memDiff).c_str()),
- QString::number(error, 'f', 8));
- return isDifferent;
- }
- };
- // test CPixelFormats related functions
- TEST_F(ImageProcessingTest, TestPixelFormats)
- {
- CPixelFormats& pixelFormats = CPixelFormats::GetInstance();
- //for all the non-compressed textures, if there minimum required texture size is 1x1
- for (uint32 i = 0; i < ePixelFormat_Count; i++)
- {
- EPixelFormat pixelFormat = (EPixelFormat)i;
- if (pixelFormats.IsPixelFormatUncompressed(pixelFormat))
- {
- //square, power of 2 sizes for uncompressed format which minimum required size is 1x1
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 128, 128) == 8);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 64, 64) == 7);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 4, 4) == 3);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 2, 2) == 2);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 1, 1) == 1);
- //non-square, power of 2 sizes for uncompressed format which minimum required size is 1x1
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 128, 64) == 8);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 128, 32) == 8);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 32, 2) == 6);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 2, 1) == 2);
- //Non power of 2 sizes for uncompressed format which minimum required size is 1x1
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 128, 64) == 8);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 128, 32) == 8);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 32, 2) == 6);
- ASSERT_TRUE(pixelFormats.ComputeMaxMipCount(pixelFormat, 2, 1) == 2);
- }
- }
- //check function IsImageSizeValid && EvaluateImageDataSize function
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 2, 1, false) == false);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 16, 16, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 16, 32, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 34, 34, false) == false);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 256, 256, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_ASTC_4x4, 2, 1, false) == false);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_ASTC_4x4, 16, 16, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_ASTC_4x4, 16, 32, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_ASTC_4x4, 34, 34, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_ASTC_4x4, 256, 256, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_A8, 2, 1, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_A8, 16, 16, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_A8, 16, 32, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_A8, 34, 34, false) == true);
- ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_A8, 256, 256, false) == true);
- }
- TEST_F(ImageProcessingTest, TestCubemapLayouts)
- {
- {
- IImageObjectPtr srcImage(LoadImageFromFile(m_imagFileNameMap[Image_defaultprobe_cm_1536x256_64bits_tif]));
- ImageToProcess imageToProcess(srcImage);
- imageToProcess.ConvertCubemapLayout(CubemapLayoutVertical);
- ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) * 6 == imageToProcess.Get()->GetHeight(0));
- SaveImageToFile(imageToProcess.Get(), "Vertical", 100);
- imageToProcess.ConvertCubemapLayout(CubemapLayoutHorizontalCross);
- ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) * 3 == imageToProcess.Get()->GetHeight(0) * 4);
- SaveImageToFile(imageToProcess.Get(), "HorizontalCross", 100);
- imageToProcess.ConvertCubemapLayout(CubemapLayoutVerticalCross);
- ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) * 4 == imageToProcess.Get()->GetHeight(0) * 3);
- SaveImageToFile(imageToProcess.Get(), "VerticalCross", 100);
- imageToProcess.ConvertCubemapLayout(CubemapLayoutHorizontal);
- ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) == imageToProcess.Get()->GetHeight(0) * 6);
- SaveImageToFile(imageToProcess.Get(), "VerticalHorizontal", 100);
- }
- }
- // test image file loading
- TEST_F(ImageProcessingTest, TestImageLoaders)
- {
- //file extension support for different loader
- ASSERT_TRUE(IsExtensionSupported("jpg") == true);
- ASSERT_TRUE(IsExtensionSupported("JPG") == true);
- ASSERT_TRUE(IsExtensionSupported(".JPG") == false);
- ASSERT_TRUE(IsExtensionSupported("tga") == true);
- ASSERT_TRUE(IsExtensionSupported("TGA") == true);
- ASSERT_TRUE(IsExtensionSupported("tif") == true);
- ASSERT_TRUE(IsExtensionSupported("tiff") == true);
- IImageObjectPtr img;
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_1024X1024_RGB8_Tif]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetWidth(0) == 1024);
- ASSERT_TRUE(img->GetHeight(0) == 1024);
- ASSERT_TRUE(img->GetMipCount() == 1);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R8G8B8X8);
- //load png
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_20X16_RGBA8_Png]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetWidth(0) == 20);
- ASSERT_TRUE(img->GetHeight(0) == 16);
- ASSERT_TRUE(img->GetMipCount() == 1);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R8G8B8A8);
- //load jpg
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_200X200_RGB8_Jpg]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetWidth(0) == 200);
- ASSERT_TRUE(img->GetHeight(0) == 200);
- ASSERT_TRUE(img->GetMipCount() == 1);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R8G8B8A8);
- //tga
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_512X288_RGB8_Tga]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetWidth(0) == 512);
- ASSERT_TRUE(img->GetHeight(0) == 288);
- ASSERT_TRUE(img->GetMipCount() == 1);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R8G8B8);
- // tga with transparency
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_128x128_Transparent_Tga]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R8G8B8A8);
- //image with upper case extension
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_UpperCase_Tga]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R8G8B8);
- //16bits float tif
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_32X32_16bit_F_Tif]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R16G16B16A16F);
- //32bits float tif
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_32X32_32bit_F_Tif]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_R32G32B32A32F);
- // DDS files
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_Alpha8_64x64_Mip7_Dds]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_A8);
- ASSERT_TRUE(img->GetMipCount() == 7);
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_BGRA_64x64_Mip7_Dds]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_B8G8R8A8);
- ASSERT_TRUE(img->GetMipCount() == 7);
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_Luminance8bpp_66x33_dds]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_A8);
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_BGR_64x64_dds]));
- ASSERT_TRUE(img != nullptr);
- ASSERT_TRUE(img->GetPixelFormat() == ePixelFormat_B8G8R8);
- // Exr file
- img = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[Image_workshop_iblskyboxcm_exr]));
- ASSERT_TRUE(img != nullptr);
- }
- TEST_F(ImageProcessingTest, PresetSettingCopyAssignmentOperatorOverload_WithDynamicallyAllocatedSettings_ReturnsTwoSeparateAllocations)
- {
- PresetSettings presetSetting;
- presetSetting.m_mipmapSetting = AZStd::unique_ptr<MipmapSettings>(new MipmapSettings());
- presetSetting.m_cubemapSetting = AZStd::unique_ptr<CubemapSettings>(new CubemapSettings());
- // Explicit invoke assignment operator by splitting the operation into two lines.
- PresetSettings otherPresetSetting;
- otherPresetSetting = presetSetting;
- EXPECT_NE(otherPresetSetting.m_cubemapSetting, presetSetting.m_cubemapSetting);
- EXPECT_NE(otherPresetSetting.m_mipmapSetting, presetSetting.m_mipmapSetting);
- }
- TEST_F(ImageProcessingTest, PresetSettingCopyConstructor_WithDynamicallyAllocatedSettings_ReturnsTwoSeparateAllocations)
- {
- PresetSettings presetSetting;
- presetSetting.m_mipmapSetting = AZStd::unique_ptr<MipmapSettings>(new MipmapSettings());
- presetSetting.m_cubemapSetting = AZStd::unique_ptr<CubemapSettings>(new CubemapSettings());
- PresetSettings otherPresetSetting(presetSetting);
- EXPECT_NE(otherPresetSetting.m_cubemapSetting, presetSetting.m_cubemapSetting);
- EXPECT_NE(otherPresetSetting.m_mipmapSetting, presetSetting.m_mipmapSetting);
- }
- TEST_F(ImageProcessingTest, PresetSettingEqualityOperatorOverload_WithIdenticalSettings_ReturnsEquivalent)
- {
- PresetSettings presetSetting;
- PresetSettings otherPresetSetting(presetSetting);
- EXPECT_TRUE(otherPresetSetting == presetSetting);
- }
- TEST_F(ImageProcessingTest, PresetSettingEqualityOperatorOverload_WithDifferingDynamicallyAllocatedSettings_ReturnsUnequivalent)
- {
- PresetSettings presetSetting;
- presetSetting.m_mipmapSetting = AZStd::unique_ptr<MipmapSettings>(new MipmapSettings());
- presetSetting.m_mipmapSetting->m_type = MipGenType::gaussian;
- PresetSettings otherPresetSetting(presetSetting);
- otherPresetSetting.m_mipmapSetting = AZStd::unique_ptr<MipmapSettings>(new MipmapSettings());
- otherPresetSetting.m_mipmapSetting->m_type = MipGenType::blackmanHarris;
- EXPECT_FALSE(otherPresetSetting == presetSetting);
- }
- //this test is to test image data won't be lost between uncompressed formats (for low to high precision or same precision)
- TEST_F(ImageProcessingTest, TestConvertFormatUncompressed)
- {
- //source image
- IImageObjectPtr srcImage(LoadImageFromFile(m_imagFileNameMap[Image_200X200_RGB8_Jpg]));
- ImageToProcess imageToProcess(srcImage);
- //image pointers to hold precessed images for comparison
- IImageObjectPtr dstImage1, dstImage2, dstImage3, dstImage4, dstImage5;
- //compare four channels pixel formats
- //we will convert to target format then convert back to RGBX8 so they can compare to easy other
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8A8);
- dstImage1 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R16G16B16A16);
- ASSERT_FALSE(srcImage->CompareImage(imageToProcess.Get())); //this is different than source image
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8A8);
- dstImage2 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R16G16B16A16F);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8A8);
- dstImage3 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R32G32B32A32F);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8A8);
- dstImage4 = imageToProcess.Get();
- ASSERT_TRUE(dstImage2->CompareImage(dstImage1));
- ASSERT_TRUE(dstImage3->CompareImage(dstImage1));
- ASSERT_TRUE(dstImage4->CompareImage(dstImage1));
- // three channels formats
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage1 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R9G9B9E5);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage2 = imageToProcess.Get();
- ASSERT_TRUE(dstImage2->CompareImage(dstImage1));
- //convert image to all one channel formats then convert them back to RGBX8 for comparison
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage1 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R16);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage2 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R16F);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage3 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R32F);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage4 = imageToProcess.Get();
- ASSERT_TRUE(dstImage2->CompareImage(dstImage1));
- ASSERT_TRUE(dstImage3->CompareImage(dstImage1));
- ASSERT_TRUE(dstImage4->CompareImage(dstImage1));
- //convert image to all two channels formats then convert them back to RGBX8 for comparison
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage1 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R16G16);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage2 = imageToProcess.Get();
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R16G16F);
- imageToProcess.ConvertFormatUncompressed(ePixelFormat_R8G8B8X8);
- dstImage3 = imageToProcess.Get();
- ASSERT_TRUE(dstImage2->CompareImage(dstImage1));
- ASSERT_TRUE(dstImage3->CompareImage(dstImage1));
- }
- TEST_F(ImageProcessingTest, TestConvertFormatCompressed)
- {
- IImageObjectPtr srcImage;
- //images to be tested
- static const int imageCount = 4;
- ImageFeature images[imageCount] = {
- Image_20X16_RGBA8_Png,
- Image_237x177_RGB_Jpg,
- Image_128x128_Transparent_Tga,
- Image_defaultprobe_cm_1536x256_64bits_tif};
- // collect all compressed pixel formats
- AZStd::vector<EPixelFormat> compressedFormats;
- for (uint32 i = 0; i < ePixelFormat_Count; i++)
- {
- EPixelFormat pixelFormat = (EPixelFormat)i;
- auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat);
- if (formatInfo->bCompressed)
- {
- // skip ASTC formats which are tested in TestConvertASTCCompressor
- if (!IsASTCFormat(pixelFormat))
- {
- compressedFormats.push_back(pixelFormat);
- }
- }
- }
- for (int imageIdx = 0; imageIdx < imageCount; imageIdx++)
- {
- //get image's name and it will be used for output file name
- QFileInfo fi(m_imagFileNameMap[images[imageIdx]].c_str());
- AZStd::string imageName = fi.baseName().toUtf8().constData();
- srcImage = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[images[imageIdx]]));
- ImageToProcess imageToProcess(srcImage);
- //test ConvertFormat functions against all the pixel formats
- for (EPixelFormat pixelFormat : compressedFormats)
- {
- //
- if (!CPixelFormats::GetInstance().IsImageSizeValid(pixelFormat, srcImage->GetWidth(0), srcImage->GetHeight(0), false))
- {
- continue;
- }
- #if defined(AZ_ENABLE_TRACING)
- auto formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormat);
- #endif
- ColorSpace sourceColorSpace = srcImage->HasImageFlags(EIF_SRGBRead) ? ColorSpace::sRGB : ColorSpace::linear;
- ICompressorPtr compressor = ICompressor::FindCompressor(pixelFormat, sourceColorSpace, true);
- if (!compressor)
- {
- AZ_Warning("test", false, "unsupported format: %s", formatInfo->szName);
- continue;
- }
- imageToProcess.Set(srcImage);
- imageToProcess.ConvertFormat(pixelFormat);
- ASSERT_TRUE(imageToProcess.Get());
- ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == pixelFormat);
- //convert back to an uncompressed format and expect it will be successful
- imageToProcess.ConvertFormat(srcImage->GetPixelFormat());
- ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == srcImage->GetPixelFormat());
- // Save the image to a file so we can check the visual result
- AZStd::string outputName = AZStd::string::format("%s_%s", imageName.c_str(), compressor->GetName());
- SaveImageToFile(imageToProcess.Get(), outputName, 1);
- }
- }
- }
-
- TEST_F(ImageProcessingTest, Test_ConvertAllAstc_Success)
- {
- // Compress/Decompress to all astc formats (LDR)
- auto imageIdx = Image_237x177_RGB_Jpg;
- IImageObjectPtr srcImage = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[imageIdx]));
- QFileInfo fi(m_imagFileNameMap[imageIdx].c_str());
- AZStd::string imageName = fi.baseName().toUtf8().constData();
- for (uint32 i = 0; i < ePixelFormat_Count; i++)
- {
- EPixelFormat pixelFormat = (EPixelFormat)i;
- if (IsASTCFormat(pixelFormat))
- {
- ImageToProcess imageToProcess(srcImage);
- imageToProcess.ConvertFormat(pixelFormat);
- ASSERT_TRUE(imageToProcess.Get());
- ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == pixelFormat);
- ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) == srcImage->GetWidth(0));
- ASSERT_TRUE(imageToProcess.Get()->GetHeight(0) == srcImage->GetHeight(0));
- // convert back to an uncompressed format and expect it will be successful
- imageToProcess.ConvertFormat(srcImage->GetPixelFormat());
- ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == srcImage->GetPixelFormat());
- // save the image to a file so we can check the visual result
- AZStd::string outputName = AZStd::string::format("ASTC_%s", imageName.c_str());
- SaveImageToFile(imageToProcess.Get(), outputName, 1);
- }
- }
- }
-
- TEST_F(ImageProcessingTest, Test_ConvertHdrToAstc_Success)
- {
- // Compress/Decompress HDR
- auto imageIdx = Image_defaultprobe_cm_1536x256_64bits_tif;
- IImageObjectPtr srcImage = IImageObjectPtr(LoadImageFromFile(m_imagFileNameMap[imageIdx]));
- EPixelFormat dstFormat = ePixelFormat_ASTC_4x4;
- ImageToProcess imageToProcess(srcImage);
- imageToProcess.ConvertFormat(ePixelFormat_ASTC_4x4);
-
- ASSERT_TRUE(imageToProcess.Get());
- ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == dstFormat);
- ASSERT_TRUE(imageToProcess.Get()->GetWidth(0) == srcImage->GetWidth(0));
- ASSERT_TRUE(imageToProcess.Get()->GetHeight(0) == srcImage->GetHeight(0));
-
- //convert back to an uncompressed format and expect it will be successful
- imageToProcess.ConvertFormat(srcImage->GetPixelFormat());
- ASSERT_TRUE(imageToProcess.Get()->GetPixelFormat() == srcImage->GetPixelFormat());
-
- //save the image to a file so we can check the visual result
- SaveImageToFile(imageToProcess.Get(), "ASTC_HDR", 1);
- }
-
- TEST_F(ImageProcessingTest, Test_AstcNormalPreset_Success)
- {
- // Normal.preset which uses ASTC as output format
- // This test compress a normal texture and its mipmaps
- auto outcome = BuilderSettingManager::Instance()->LoadConfigFromFolder(m_defaultSettingFolder.Native());
- ASSERT_TRUE(outcome.IsSuccess());
- AZStd::string inputFile;
- AZStd::vector<AssetBuilderSDK::JobProduct> outProducts;
- inputFile = m_imagFileNameMap[Image_512x512_normal_tiff];
- IImageObjectPtr srcImage = IImageObjectPtr(LoadImageFromFile(inputFile));
- ImageConvertProcess* process = CreateImageConvertProcess(inputFile, m_outputFolder.Native(), "ios", outProducts, m_context.get());
- const PresetSettings* preset = &process->GetInputDesc()->m_presetSetting;
- if (process != nullptr)
- {
- process->ProcessAll();
- //get process result
- ASSERT_TRUE(process->IsSucceed());
- auto outputImage = process->GetOutputImage();
- ASSERT_TRUE(outputImage->GetPixelFormat() == preset->m_pixelFormat);
- ASSERT_TRUE(outputImage->GetWidth(0) == srcImage->GetWidth(0));
- ASSERT_TRUE(outputImage->GetHeight(0) == srcImage->GetHeight(0));
-
- SaveImageToFile(outputImage, "ASTC_Normal", 10);
- delete process;
- }
- }
- TEST_F(ImageProcessingTest, DISABLED_TestImageFilter)
- {
- AZStd::string testImageFile = m_imagFileNameMap[Image_1024X1024_RGB8_Tif];
- IImageObjectPtr srcImage, dstImage;
- QFileInfo fi(testImageFile.c_str());
- AZStd::string imageName = fi.baseName().toUtf8().constData();
- //load source image and convert it to RGBA32F
- srcImage = IImageObjectPtr(LoadImageFromFile(testImageFile));
- ImageToProcess imageToProcess(srcImage);
- imageToProcess.ConvertFormat(ePixelFormat_R32G32B32A32F);
- srcImage = imageToProcess.Get();
- //create destination image with same size and mipmaps
- dstImage = IImageObjectPtr(
- IImageObject::CreateImage(srcImage->GetWidth(0), srcImage->GetHeight(0), 3,
- ePixelFormat_R32G32B32A32F));
- //for each filters
- const std::array<std::pair<MipGenType, AZStd::string>, 7> allFilters =
- {
- {
- {MipGenType::point, "point"},
- {MipGenType::box, "box" },
- { MipGenType::triangle, "triangle" },
- { MipGenType::quadratic, "Quadratic" },
- { MipGenType::blackmanHarris, "blackmanHarris" },
- { MipGenType::kaiserSinc, "kaiserSinc" }
- }
- };
- for (std::pair<MipGenType, AZStd::string> filter : allFilters)
- {
- for (uint mip = 0; mip < dstImage->GetMipCount(); mip++)
- {
- FilterImage(filter.first, MipGenEvalType::sum,
- 0, 0, imageToProcess.Get(), 0, dstImage, mip, nullptr, nullptr);
- }
- SaveImageToFile(dstImage, imageName + "_" + filter.second);
- }
- }
- TEST_F(ImageProcessingTest, TestAverageColor)
- {
- //load builder presets
- auto outcome = BuilderSettingManager::Instance()->LoadConfigFromFolder(m_defaultSettingFolder.Native());
- ASSERT_TRUE(outcome.IsSuccess());
- auto checkAverageColor = [&](ImageFeature figureKey, AZ::Color expectedAverage)
- {
- AZStd::vector<AssetBuilderSDK::JobProduct> outProducts;
- AZStd::string inputFile = m_imagFileNameMap[figureKey];
- ImageConvertProcess* process = CreateImageConvertProcess(inputFile, m_outputFolder.Native(), "pc", outProducts, m_context.get());
- if (process != nullptr)
- {
- process->ProcessAll();
- ASSERT_TRUE(process->IsSucceed());
- ASSERT_TRUE(process->GetOutputImage());
- ASSERT_TRUE(process->GetOutputImage()->GetAverageColor().IsClose(expectedAverage));
- delete process;
- }
- };
- checkAverageColor(Image_32X32_checkerboard_png, AZ::Color(0.5f, 0.5f, 0.5f, 1.0f));
- checkAverageColor(Image_32X32_halfRedHalfTransparentGreen_png, AZ::Color(1.0f, 0.0f, 0.0f, 0.5f));
- }
- TEST_F(ImageProcessingTest, TestColorSpaceConversion)
- {
- IImageObjectPtr srcImage(LoadImageFromFile(m_imagFileNameMap[Image_GreyScale_Png]));
- ImageToProcess imageToProcess(srcImage);
- imageToProcess.GammaToLinearRGBA32F(true);
- SaveImageToFile(imageToProcess.Get(), "GammaTolinear_DeGamma", 1);
- imageToProcess.LinearToGamma();
- SaveImageToFile(imageToProcess.Get(), "LinearToGamma_DeGamma", 1);
- }
- TEST_F(ImageProcessingTest, VerifyRestrictedPlatform)
- {
- auto outcome = BuilderSettingManager::Instance()->LoadConfigFromFolder(m_defaultSettingFolder.Native());
- ASSERT_TRUE(outcome.IsSuccess());
- PlatformNameList platforms = BuilderSettingManager::Instance()->GetPlatformList();
- #ifndef AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
- EXPECT_THAT(platforms, testing::UnorderedPointwise(testing::Eq(), {"pc", "linux", "mac", "ios", "android"}));
- #endif //AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
- }
- //test image conversion for builder
- TEST_F(ImageProcessingTest, TestBuilderImageConvertor)
- {
- //load builder presets
- auto outcome = BuilderSettingManager::Instance()->LoadConfigFromFolder(m_defaultSettingFolder.Native());
- ASSERT_TRUE(outcome.IsSuccess());
- AZStd::string inputFile;
- AZStd::vector<AssetBuilderSDK::JobProduct> outProducts;
- inputFile = m_imagFileNameMap[Image_128x128_Transparent_Tga];
- ImageConvertProcess* process = CreateImageConvertProcess(inputFile, m_outputFolder.Native(), "pc", outProducts, m_context.get());
- if (process != nullptr)
- {
- //the process can be stopped if the job is canceled or the worker is shutting down
- while (!process->IsFinished())
- {
- process->UpdateProcess();
- }
- //get process result
- ASSERT_TRUE(process->IsSucceed());
- SaveImageToFile(process->GetOutputImage(), "rgb", 10);
- process->GetAppendOutputProducts(outProducts);
- delete process;
- }
- }
- TEST_F(ImageProcessingTest, TestIblSkyboxPreset)
- {
- //load builder presets
- auto outcome = BuilderSettingManager::Instance()->LoadConfigFromFolder(m_defaultSettingFolder.Native());
- ASSERT_TRUE(outcome.IsSuccess());
- AZStd::string inputFile;
- AZStd::vector<AssetBuilderSDK::JobProduct> outProducts;
- inputFile = m_imagFileNameMap[Image_workshop_iblskyboxcm_exr];
- ImageConvertProcess* process = CreateImageConvertProcess(inputFile, m_outputFolder.Native(), "pc", outProducts, m_context.get());
- if (process != nullptr)
- {
- process->ProcessAll();
- //get process result
- ASSERT_TRUE(process->IsSucceed());
- auto specularImage = process->GetOutputIBLSpecularCubemap();
- auto diffuseImage = process->GetOutputIBLDiffuseCubemap();
- ASSERT_TRUE(process->GetOutputImage());
- ASSERT_TRUE(specularImage);
- ASSERT_TRUE(diffuseImage);
- // output converted result if save image is enabled
- SaveImageToFile(process->GetOutputImage(), "ibl_skybox", 10);
- SaveImageToFile(specularImage, "ibl_specular", 10);
- SaveImageToFile(diffuseImage, "ibl_diffuse", 10);
- delete process;
- }
- }
- TEST_F(ImageProcessingTest, TextureSettingReflect_SerializingModernDataInAndOut_WritesAndParsesFileAccurately)
- {
- AZStd::string filepath = "test.xml";
- // Fill-in structure with test data
- TextureSettings fakeTextureSettings;
- fakeTextureSettings.m_preset = "testPreset";
- fakeTextureSettings.m_sizeReduceLevel = 0;
- fakeTextureSettings.m_suppressEngineReduce = true;
- fakeTextureSettings.m_enableMipmap = false;
- fakeTextureSettings.m_maintainAlphaCoverage = true;
- fakeTextureSettings.m_mipAlphaAdjust = { 0xDEAD, 0xBADBEEF, 0xBADC0DE, 0xFEEFEE, 0xBADF00D, 0xC0FFEE };
- fakeTextureSettings.m_mipGenEval = MipGenEvalType::max;
- fakeTextureSettings.m_mipGenType = MipGenType::quadratic;
- // Write test data to file
- auto writeOutcome = TextureSettings::WriteTextureSetting(filepath, fakeTextureSettings, m_context.get());
- EXPECT_TRUE(writeOutcome.IsSuccess());
- // Parse test data to file
- TextureSettings parsedFakeTextureSettings;
- auto readOutcome = TextureSettings::LoadTextureSetting(filepath, parsedFakeTextureSettings, m_context.get());
- EXPECT_TRUE(readOutcome.IsSuccess());
- EXPECT_TRUE(parsedFakeTextureSettings.Equals(fakeTextureSettings, m_context.get()));
- // Delete temp data
- AZ::IO::FileIOBase::GetInstance()->Remove(filepath.c_str());
- }
- } // UnitTest
- AZ_UNIT_TEST_HOOK(DEFAULT_UNIT_TEST_ENV);
|