#pragma once #include #include "zstring.h" #include "tarray.h" #include "textures.h" #include "bitmap.h" #include "memarena.h" class FImageSource; using PrecacheInfo = TMap>; // Doom patch format header struct patch_t { int16_t width; // bounding box size int16_t height; int16_t leftoffset; // pixels to the left of origin int16_t topoffset; // pixels below the origin uint32_t columnofs[1]; // only [width] used }; struct PalettedPixels { friend class FImageSource; TArrayView Pixels; private: TArray PixelStore; bool ownsPixels() const { return Pixels.Data() == PixelStore.Data(); } }; // This represents a naked image. It has no high level logic attached to it. // All it can do is provide raw image data to its users. class FImageSource { friend class FBrightmapTexture; protected: static FMemArena ImageArena; static TArrayImageForLump; static int NextID; int SourceLump; int Width = 0, Height = 0; int LeftOffset = 0, TopOffset = 0; // Offsets stored in the image. bool bUseGamePalette = false; // true if this is an image without its own color set. int ImageID = -1; // Internal image creation functions. All external access should go through the cache interface, // so that all code can benefit from future improvements to that. virtual TArray CreatePalettedPixels(int conversion); virtual int CopyPixels(FBitmap *bmp, int conversion); // This will always ignore 'luminance'. int CopyTranslatedPixels(FBitmap *bmp, const PalEntry *remap); public: void CopySize(FImageSource &other) { Width = other.Width; Height = other.Height; LeftOffset = other.LeftOffset; TopOffset = other.TopOffset; SourceLump = other.SourceLump; } // Images are statically allocated and freed in bulk. None of the subclasses may hold any destructible data. void *operator new(size_t block) { return ImageArena.Alloc(block); } void operator delete(void *block) {} bool bMasked = true; // Image (might) have holes (Assume true unless proven otherwise!) int8_t bTranslucent = -1; // Image has pixels with a non-0/1 value. (-1 means the user needs to do a real check) int GetId() const { return ImageID; } // 'noremap0' will only be looked at by FPatchTexture and forwarded by FMultipatchTexture. // Either returns a reference to the cache, or a newly created item. The return of this has to be considered transient. If you need to store the result, use GetPalettedPixels PalettedPixels GetCachedPalettedPixels(int conversion); // tries to get a buffer from the cache. If not available, create a new one. If further references are pending, create a copy. TArray GetPalettedPixels(int conversion); // Unlile for paletted images there is no variant here that returns a persistent bitmap, because all users have to process the returned image into another format. FBitmap GetCachedBitmap(const PalEntry *remap, int conversion, int *trans = nullptr); static void ClearImages() { ImageArena.FreeAll(); ImageForLump.Clear(); NextID = 0; } static FImageSource * GetImage(int lumpnum, bool checkflat); // Conversion option enum EType { normal = 0, luminance = 1, noremap0 = 2 }; FImageSource(int sourcelump = -1) : SourceLump(sourcelump) { ImageID = ++NextID; } virtual ~FImageSource() {} int GetWidth() const { return Width; } int GetHeight() const { return Height; } std::pair GetSize() const { return std::make_pair(Width, Height); } std::pair GetOffsets() const { return std::make_pair(LeftOffset, TopOffset); } void SetOffsets(int x, int y) { LeftOffset = x; TopOffset = y; } int LumpNum() const { return SourceLump; } bool UseGamePalette() const { return bUseGamePalette; } virtual void CollectForPrecache(PrecacheInfo &info, bool requiretruecolor); static void BeginPrecaching(); static void EndPrecaching(); static void RegisterForPrecache(FImageSource *img, bool requiretruecolor); }; //========================================================================== // // A texture defined in a Build TILESxxx.ART file // //========================================================================== struct FRemapTable; class FBuildTexture : public FImageSource { public: FBuildTexture(const FString& pathprefix, int tilenum, const uint8_t* pixels, FRemapTable* translation, int width, int height, int left, int top); TArray CreatePalettedPixels(int conversion) override; int CopyPixels(FBitmap* bmp, int conversion) override; protected: const uint8_t* RawPixels; FRemapTable* Translation; }; //========================================================================== // // a TGA texture // //========================================================================== class FImageTexture : public FTexture { FImageSource *mImage; public: FImageTexture (FImageSource *image, const char *name = nullptr); ~FImageTexture() { if (mImage) delete mImage; } void Create8BitPixels(uint8_t* buffer) override; FImageSource *GetImage() const override { return mImage; } FBitmap GetBgraBitmap(const PalEntry *p, int *trans) override; }; FTexture* CreateImageTexture(FImageSource* img, const char *name = nullptr) noexcept;