// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #if COMPILE_WITH_TEXTURE_TOOL #include "Engine/Render2D/SpriteAtlas.h" #include "Engine/Graphics/Textures/Types.h" #include "Engine/Graphics/Textures/GPUTexture.h" #include "Engine/Core/ISerializable.h" class JsonWriter; /// /// Textures importing, processing and exporting utilities. /// API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API TextureTool { DECLARE_SCRIPTING_TYPE_MINIMAL(TextureTool); /// /// Texture import options. /// API_STRUCT(Attributes="HideInEditor") struct FLAXENGINE_API Options : public ISerializable { DECLARE_SCRIPTING_TYPE_MINIMAL(Options); // Texture format type. API_FIELD(Attributes="EditorOrder(0)") TextureFormatType Type = TextureFormatType::ColorRGB; // True if texture should be imported as a texture atlas (with sprites). API_FIELD(Attributes="EditorOrder(10)") bool IsAtlas = false; // True if disable dynamic texture streaming. API_FIELD(Attributes="EditorOrder(20)") bool NeverStream = false; // True if disable dynamic texture streaming. API_FIELD(Attributes="EditorOrder(30)") bool Compress = true; // True if texture channels have independent data (for compression methods). API_FIELD(Attributes="EditorOrder(40)") bool IndependentChannels = false; // True if use sRGB format for texture data. Recommended for color maps and diffuse color textures. API_FIELD(Attributes="EditorOrder(50), EditorDisplay(null, \"sRGB\")") bool sRGB = false; // True if generate mip maps chain for the texture. API_FIELD(Attributes="EditorOrder(60)") bool GenerateMipMaps = true; // True if flip Y coordinate of the texture. API_FIELD(Attributes="EditorOrder(70)") bool FlipY = false; // Texture size scale. Default is 1. API_FIELD(Attributes="EditorOrder(80), Limit(0.0001f, 1000.0f, 0.01f)") float Scale = 1.0f; // Maximum size of the texture (for both width and height). Higher resolution textures will be resized during importing process. API_FIELD(Attributes="HideInEditor") int32 MaxSize = 8192; // True if resize texture on import. Use SizeX/SizeY properties to define texture width and height. Texture scale property will be ignored. API_FIELD(Attributes="EditorOrder(100)") bool Resize = false; // The width of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored. API_FIELD(Attributes="HideInEditor") int32 SizeX = 1024; // The height of the imported texture. If Resize property is set to true then texture will be resized during the import to this value. Otherwise it will be ignored. API_FIELD(Attributes="HideInEditor") int32 SizeY = 1024; // Check to preserve alpha coverage in generated mips for alpha test reference. Scales mipmap alpha values to preserve alpha coverage based on an alpha test reference value. API_FIELD(Attributes="EditorOrder(200)") bool PreserveAlphaCoverage = false; // The reference value for the alpha coverage preserving. API_FIELD(Attributes="EditorOrder(210), VisibleIf(\"PreserveAlphaCoverage\")") float PreserveAlphaCoverageReference = 0.5f; // Texture group for streaming (negative if unused). See Streaming Settings. API_FIELD(Attributes="EditorOrder(300), CustomEditorAlias(\"FlaxEditor.CustomEditors.Dedicated.TextureGroupEditor\")") int32 TextureGroup = -1; // The sprites for the sprite sheet import mode. API_FIELD(Attributes="HideInEditor") Array Sprites; // Function used for fast importing textures used by internal parts of the engine Function InternalLoad; public: String ToString() const; // [ISerializable] void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; }; public: #if USE_EDITOR /// /// Checks whenever the given texture file contains alpha channel data with values different than solid fill of 1 (non fully opaque). /// /// The file path. /// True if has alpha channel, otherwise false. static bool HasAlpha(const StringView& path); #endif /// /// Imports the texture. /// /// The file path. /// The output data. /// True if fails, otherwise false. static bool ImportTexture(const StringView& path, TextureData& textureData); /// /// Imports the texture. /// /// The file path. /// The output data. /// The import options. /// The error message container. /// True if fails, otherwise false. static bool ImportTexture(const StringView& path, TextureData& textureData, Options options, String& errorMsg); /// /// Exports the texture. /// /// The output file path. /// The output data. /// True if fails, otherwise false. static bool ExportTexture(const StringView& path, const TextureData& textureData); /// /// Converts the specified source texture data into an another format. /// /// The destination data. /// The source data. /// The destination data format. Must be other than source data type. /// True if fails, otherwise false. static bool Convert(TextureData& dst, const TextureData& src, const PixelFormat dstFormat); /// /// Resizes the specified source texture data into an another dimensions. /// /// The destination data. /// The source data. /// The destination data width. /// The destination data height. /// True if fails, otherwise false. static bool Resize(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); public: typedef Color (*ReadPixel)(const void*); typedef void (*WritePixel)(const void*, const Color&); struct PixelFormatSampler { PixelFormat Format; int32 PixelSize; ReadPixel Sample; WritePixel Store; }; /// /// Determines whether this tool can sample the specified format to read texture samples and returns the sampler object. /// /// The format. /// The pointer to the sampler object or null if cannot sample the given format. static const PixelFormatSampler* GetSampler(PixelFormat format); /// /// Stores the color into the specified texture data (uses no interpolation). /// /// /// Use GetSampler for the texture sampler. /// /// The texture data sampler. /// The X texture coordinates (normalized to range 0-width). /// The Y texture coordinates (normalized to range 0-height). /// The data pointer for the texture slice (1D or 2D image). /// The row pitch (in bytes). The offset between each image rows. /// The color to store (linear). static void Store(const PixelFormatSampler* sampler, int32 x, int32 y, const void* data, int32 rowPitch, const Color& color); /// /// Samples the specified texture data (uses no interpolation). /// /// /// Use GetSampler for the texture sampler. /// /// The texture data sampler. /// The texture coordinates (normalized to range 0-1). /// The data pointer for the texture slice (1D or 2D image). /// The size of the input texture (in pixels). /// The row pitch (in bytes). The offset between each image rows. /// The sampled color (linear). static Color SamplePoint(const PixelFormatSampler* sampler, const Float2& uv, const void* data, const Int2& size, int32 rowPitch); /// /// Samples the specified texture data (uses no interpolation). /// /// /// Use GetSampler for the texture sampler. /// /// The texture data sampler. /// The X texture coordinates (normalized to range 0-width). /// The Y texture coordinates (normalized to range 0-height). /// The data pointer for the texture slice (1D or 2D image). /// The row pitch (in bytes). The offset between each image rows. /// The sampled color (linear). static Color SamplePoint(const PixelFormatSampler* sampler, int32 x, int32 y, const void* data, int32 rowPitch); /// /// Samples the specified texture data (uses linear interpolation). /// /// /// Use GetSampler for the texture sampler. /// /// The texture data sampler. /// The texture coordinates (normalized to range 0-1). /// The data pointer for the texture slice (1D or 2D image). /// The size of the input texture (in pixels). /// The row pitch (in bytes). The offset between each image rows. /// The sampled color (linear). static Color SampleLinear(const PixelFormatSampler* sampler, const Float2& uv, const void* data, const Int2& size, int32 rowPitch); private: enum class ImageType { DDS, TGA, PNG, BMP, GIF, TIFF, JPEG, HDR, RAW, Internal, }; static bool GetImageType(const StringView& path, ImageType& type); #if COMPILE_WITH_DIRECTXTEX static bool ExportTextureDirectXTex(ImageType type, const StringView& path, const TextureData& textureData); static bool ImportTextureDirectXTex(ImageType type, const StringView& path, TextureData& textureData, bool& hasAlpha); static bool ImportTextureDirectXTex(ImageType type, const StringView& path, TextureData& textureData, const Options& options, String& errorMsg, bool& hasAlpha); static bool ConvertDirectXTex(TextureData& dst, const TextureData& src, const PixelFormat dstFormat); static bool ResizeDirectXTex(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); #endif #if COMPILE_WITH_STB static bool ExportTextureStb(ImageType type, const StringView& path, const TextureData& textureData); static bool ImportTextureStb(ImageType type, const StringView& path, TextureData& textureData, bool& hasAlpha); static bool ImportTextureStb(ImageType type, const StringView& path, TextureData& textureData, const Options& options, String& errorMsg, bool& hasAlpha); static bool ConvertStb(TextureData& dst, const TextureData& src, const PixelFormat dstFormat); static bool ResizeStb(PixelFormat format, TextureMipData& dstMip, const TextureMipData& srcMip, int32 dstMipWidth, int32 dstMipHeight); static bool ResizeStb(TextureData& dst, const TextureData& src, int32 dstWidth, int32 dstHeight); #endif }; #endif