| 1 | // tBaseImage.h  |
| 2 | //  |
| 3 | // Abstract base class for all tImageTYPE classes that load and save to a specific format.  |
| 4 | //  |
| 5 | // Copyright (c) 2022, 2024 Tristan Grimmer.  |
| 6 | // Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby  |
| 7 | // granted, provided that the above copyright notice and this permission notice appear in all copies.  |
| 8 | //  |
| 9 | // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL  |
| 10 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,  |
| 11 | // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN  |
| 12 | // AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR  |
| 13 | // PERFORMANCE OF THIS SOFTWARE.  |
| 14 |   |
| 15 | #pragma once  |
| 16 | #include <Foundation/tString.h>  |
| 17 | #include <Math/tColour.h>  |
| 18 | #include <Image/tPixelFormat.h>  |
| 19 | #include "Image/tFrame.h"  |
| 20 | namespace tImage  |
| 21 | {  |
| 22 | class tPicture;  |
| 23 | class tLayer;  |
| 24 |   |
| 25 |   |
| 26 | // These are hany for all image types that may contain cubemaps.  |
| 27 | enum tFaceIndex : uint32  |
| 28 | {  |
| 29 | tFaceIndex_Default,  |
| 30 | tFaceIndex_PosX = tFaceIndex_Default,  |
| 31 | tFaceIndex_NegX,  |
| 32 | tFaceIndex_PosY,  |
| 33 | tFaceIndex_NegY,  |
| 34 | tFaceIndex_PosZ,  |
| 35 | tFaceIndex_NegZ,  |
| 36 | tFaceIndex_NumFaces  |
| 37 | };  |
| 38 |   |
| 39 | // Faces are always specified using a left-handed coord system even when using the OpenGL functions.  |
| 40 | enum tFaceFlag : uint32  |
| 41 | {  |
| 42 | tFaceFlag_PosX = 1 << tFaceIndex_PosX,  |
| 43 | tFaceFlag_NegX = 1 << tFaceIndex_NegX,  |
| 44 | tFaceFlag_PosY = 1 << tFaceIndex_PosY,  |
| 45 | tFaceFlag_NegY = 1 << tFaceIndex_NegY,  |
| 46 | tFaceFlag_PosZ = 1 << tFaceIndex_PosZ,  |
| 47 | tFaceFlag_NegZ = 1 << tFaceIndex_NegZ,  |
| 48 | tFaceFlag_All = 0xFFFFFFFF  |
| 49 | };  |
| 50 |   |
| 51 |   |
| 52 | // Abstract base class for all tImage types. At a minumum all tImageEXTs need to be able to be set from a single tFrame  |
| 53 | // and return a single tFrame.  |
| 54 | class tBaseImage  |
| 55 | {  |
| 56 | public:  |
| 57 | virtual ~tBaseImage() { }  |
| 58 |   |
| 59 | // This one sets from a supplied pixel array. If steal is true it takes ownership of the pixels pointer. Otherwise  |
| 60 | // it just copies the data out.  |
| 61 | virtual bool Set(tPixel4b* pixels, int width, int height, bool steal = false) = 0;  |
| 62 |   |
| 63 | // For multi-frame image types (say an animated webp), the first frame is chosen. The 'steal' bool tells the object  |
| 64 | // whether it is allowed to take ownership of the supplied frame, or whether it must copy the data out of it.  |
| 65 | // Returns true on success. Image will be invalid if false returned. If steal true, entire frame object is stolen.  |
| 66 | virtual bool Set(tFrame*, bool steal = true) = 0;  |
| 67 |   |
| 68 | // Similar to above but sets from a tPicture. If steal is true, it takes the pixels from the picture and leaves it  |
| 69 | // in an invalid state.  |
| 70 | virtual bool Set(tPicture& picture, bool steal = true) = 0;  |
| 71 |   |
| 72 | // For some formats (eg. .astc, .dds, .ktx) the internal representation may not be R8G8B8A8 unless a decode was  |
| 73 | // performed (which is optional). In these cases a new frame will be generated if the decode was performed, and  |
| 74 | // nullptr otherwise.  |
| 75 | //  |
| 76 | // Stealing a frame (the default) may or may-not invalidate an image. For multiframe image types, if there is more  |
| 77 | // than one frame, stealing just takes one away. Only if it was the last one, will it invalidate the object. In all  |
| 78 | // cases if steal is false, you are guaranteed the tImage is not modified. A new frame is created for you if  |
| 79 | // possible (again it won't force a decode for, say, ktx2 files).  |
| 80 | virtual tFrame* GetFrame(bool steal = true) = 0;  |
| 81 |   |
| 82 | // After this call no memory will be consumed by the object and it will be invalid. The base version here can be  |
| 83 | // used just to clear the members in the base class.  |
| 84 | virtual void Clear() { PixelFormatSrc = tPixelFormat::Unspecified; PixelFormat = tPixelFormat::Unspecified; ColourProfileSrc = tColourProfile::Unspecified; ColourProfile = tColourProfile::Unspecified; }  |
| 85 |   |
| 86 | virtual bool IsValid() const = 0;  |
| 87 |   |
| 88 | // Returns the original (source) pixel format of the image. The source may be a file, or a buffer in memory, or some  |
| 89 | // other object like a picture. This format is only modified if you reload or set an image from new data. Saving to  |
| 90 | // a file does not modify this.  |
| 91 | virtual tPixelFormat GetPixelFormatSrc() const { return PixelFormatSrc; }  |
| 92 |   |
| 93 | // Returns the current in-memory pixel format of this image object. Load paramters often modify it from the source  |
| 94 | // pixel format. For example, if you load a DDS and decide to decode, this format will return the decoded format,  |
| 95 | // often R8G8B8A8. If you decide not to decode, it will match the source format. Another example is loading a  |
| 96 | // RLE-compressed TGA, it also gets uncompressed to R8G8B8A8. Some tImage classes like tImagePNG support decodeing  |
| 97 | // to R16G16B16A16, and in the future some might support R32G32B32A32f for the decompressed/generic HDR format.  |
| 98 | virtual tPixelFormat GetPixelFormat() const { return PixelFormat; }  |
| 99 |   |
| 100 | // Returns the original (source) colour profile of the image. See comment for GetPixelFormatSrc. It is worth noting  |
| 101 | // that many image types do not store colour-space information at all, in which case the ColourProfile members will  |
| 102 | // remain unspecified.  |
| 103 | virtual tColourProfile GetColourProfileSrc() const { return ColourProfileSrc; }  |
| 104 |   |
| 105 | // Returns the current colour profile of the pixels in this image object. Load paramters often modify it from the  |
| 106 | // source profile. For example loading a linear-colour-space HDR file will likely decode it into sRGB for display  |
| 107 | // purposes (if you asked it to do so with load parameters).  |
| 108 | virtual tColourProfile GetColourProfile() const { return ColourProfile; }  |
| 109 |   |
| 110 | virtual tAlphaMode GetAlphaMode() const { return tAlphaMode::Unspecified; }  |
| 111 | virtual tChannelType GetChannelType() const { return tChannelType::Unspecified; }  |
| 112 |   |
| 113 | // Not all derived classes need to support these next four functions.  |
| 114 | virtual bool IsMipmapped() const { return false; }  |
| 115 | virtual bool IsCubemap() const { return false; }  |
| 116 |   |
| 117 | // Gets the layers but you're not allowed to delete them, they're not yours. Make sure the list you supply doesn't  |
| 118 | // delete them when it's destructed. Returns the number of items appended to the list.  |
| 119 | virtual int GetLayers(tList<tLayer>&) const { return 0; }  |
| 120 | virtual int GetCubemapLayers(tList<tLayer> layers[tFaceIndex_NumFaces], uint32 faceFlags = tFaceFlag_All) const { return 0; }  |
| 121 |   |
| 122 | protected:  |
| 123 | // Pretty sure all tImageXXX classes will find these useful.  |
| 124 | tPixelFormat PixelFormatSrc = tPixelFormat::Unspecified;  |
| 125 | tPixelFormat PixelFormat = tPixelFormat::Unspecified;  |
| 126 | tColourProfile ColourProfileSrc = tColourProfile::Unspecified;  |
| 127 | tColourProfile ColourProfile = tColourProfile::Unspecified;  |
| 128 | };  |
| 129 |   |
| 130 |   |
| 131 | }  |
| 132 | |