/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_TEXTURES_IMAGE_CIMAGE_H #define CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_TEXTURES_IMAGE_CIMAGE_H #pragma once #include "IImage.h" #define SH_LITTLE_ENDIAN // The mask for extracting just R/G/B from an ulong or SRGBPixel #ifdef SH_BIG_ENDIAN # define RGB_MASK 0xffffff00 #else # define RGB_MASK 0x00ffffff #endif /** * An RGB pixel. */ struct SRGBPixel { uint8 blue, green, red, alpha; SRGBPixel() /* : red(0), green(0), blue(0), alpha(255) {} */ { *(unsigned int*)this = (unsigned int)~RGB_MASK; } SRGBPixel(int r, int g, int b) : red(r) , green(g) , blue(b) , alpha(255) {} //bool eq (const SRGBPixel& p) const { return ((*(unsigned int *)this) & RGB_MASK) == ((*(unsigned int *)&p) & RGB_MASK); } }; class CImageFile; namespace DDSSplitted { struct DDSDesc; } struct IImageFileStreamCallback { virtual void OnImageFileStreamComplete(CImageFile* pImFile) = 0; protected: virtual ~IImageFileStreamCallback() {} }; struct SImageFileStreamState { enum { MaxStreams = 64 }; struct Request { void* pOut; size_t nOffs; size_t nSize; }; void RaiseComplete(CImageFile* pFile) { if (m_pCallback) { m_pCallback->OnImageFileStreamComplete(pFile); m_pCallback = NULL; } } volatile int m_nPending; uint32 m_nFlags; IImageFileStreamCallback* m_pCallback; IReadStreamPtr m_pStreams[MaxStreams]; Request m_requests[MaxStreams]; }; class CImageFile : public IImageFile , public IStreamCallback { private: CImageFile(const CImageFile&); CImageFile& operator = (const CImageFile&); private: volatile int m_nRefCount; bool m_bIsImageMissing = false; protected: int m_Width; // Width of image. int m_Height; // Height of image. int m_Depth; // Depth of image. int m_Sides; // Depth of image. int m_ImgSize; int m_NumMips; int m_NumPersistentMips; int m_Flags; // e.g. FIM_GREYSCALE|FIM_ALPHA int m_nStartSeek; float m_fAvgBrightness; ColorF m_cMinColor; ColorF m_cMaxColor; union // The image data. { byte* m_pByteImage[6]; SRGBPixel* m_pPixImage[6]; }; EImFileError m_eError; // Last error code. string m_FileName; // file name ETEX_Format m_eFormat; ETEX_TileMode m_eTileMode; SImageFileStreamState* m_pStreamState; protected: CImageFile(const string& filename); void mfSet_error(const EImFileError error, const char* detail = NULL); void mfSet_dimensions(const int w, const int h); public: virtual ~CImageFile(); virtual int AddRef() { return CryInterlockedIncrement(&m_nRefCount); } virtual int Release() { int nRef = CryInterlockedDecrement(&m_nRefCount); if (nRef == 0) { delete this; } else if (nRef < 0) { assert(0); CryFatalError("Deleting Reference Counted Object Twice"); } return nRef; } const string& mfGet_filename() const { return m_FileName; } void mfChange_Filename(const string& newName) { // used when one texture (such as the 'missing texture') is masquerading as another one until reloaded. m_FileName = newName; } int mfGet_width() const { return m_Width; } int mfGet_height() const { return m_Height; } int mfGet_depth() const { return m_Depth; } int mfGet_NumSides() const { return m_Sides; } bool mfGet_IsImageMissing() const { return m_bIsImageMissing; } EImFileError mfGet_error() const { return m_eError; } byte* mfGet_image(const int nSide); void mfFree_image(const int nSide); bool mfIs_image(const int nSide) const { return m_pByteImage[nSide] != NULL; } int mfGet_StartSeek() const { return m_nStartSeek; } void mfSet_ImageSize(int Size) { m_ImgSize = Size; } int mfGet_ImageSize() const { return m_ImgSize; } ETEX_Format mfGetFormat() const { return m_eFormat; } ETEX_TileMode mfGetTileMode() const { return m_eTileMode; } void mfSet_numMips(const int num) { m_NumMips = num; } int mfGet_numMips() const { return m_NumMips; } void mfSet_numPersistentMips(const int num) { m_NumPersistentMips = num; } int mfGet_numPersistentMips() const { return m_NumPersistentMips; } void mfSet_avgBrightness(const float avgBrightness) { m_fAvgBrightness = avgBrightness; } float mfGet_avgBrightness() const { return m_fAvgBrightness; } void mfSet_minColor(const ColorF& minColor) { m_cMinColor = minColor; } const ColorF& mfGet_minColor() const { return m_cMinColor; } void mfSet_maxColor(const ColorF& maxColor) { m_cMaxColor = maxColor; } const ColorF& mfGet_maxColor() const { return m_cMaxColor; } void mfSet_Flags(const int Flags) { m_Flags |= Flags; } int mfGet_Flags() const { return m_Flags; } void mfAbortStreaming(); virtual DDSSplitted::DDSDesc mfGet_DDSDesc() const; public: /** * Load a image from memory by assigning the image byte data directly without copying. * * @param filename The image filename * @param data byte image data, caller owns this data and is responsible for cleanup. * @param width image width * @param height image height * @param format image format (eTF_R8G8B8A8, eTF_PVRTC4 etc.) * @param numMips number of mip maps * @param nFlags image flags (e.g. FIM_GREYSCALE|FIM_ALPHA) */ static _smart_ptr<CImageFile> mfLoad_mem(const string& filename, void* data, int width, int height, ETEX_Format format, int numMips, const uint32 nFlags); static _smart_ptr<CImageFile> mfLoad_file(const string& filename, const uint32 nFlags); static _smart_ptr<CImageFile> mfStream_File(const string& filename, const uint32 nFlags, IImageFileStreamCallback* pCallback); }; #endif // CRYINCLUDE_CRYENGINE_RENDERDLL_COMMON_TEXTURES_IMAGE_CIMAGE_H