#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_PIXELS_BITMAP_H #define NUCLEX_PIXELS_BITMAP_H #include "Nuclex/Pixels/Config.h" #include "Nuclex/Pixels/BitmapMemory.h" namespace Nuclex { namespace Pixels { // ------------------------------------------------------------------------------------------- // /// Raster-based image of variable size and color depth /// /// /// This bitmap implementation attempts to be a very thin wrapper around a block /// of raw memory. The layout and pixel format of the memory area is completely /// described by the bitmap, making it the ideal basic building block for storing /// and passing raster images. /// /// /// Bitmaps can be created on their own (in which case they will maintain their /// own memory) or they can be set up to use an externally provided memory buffer /// (whose the lifetime must be managed separately). /// /// /// Another option is to create bitmaps as views into other bitmaps. In this case /// ownership of the memory block will be shared (memory stays allocated until /// the last bitmap referencing it is destroyed). A manually triggered copy-on-write /// system allows a bitmaps to make itself autonomous, allocating its own memory /// block and storing a unique copy of all pixels it was referencing. /// /// class NUCLEX_PIXELS_TYPE Bitmap { /// Creates a bitmap that accesses an existing memory area /// /// Description of the existing memory area that will be accessed /// /// A bitmap that accesses pixels in the provided existing memory area /// /// Ownership of the memory area is not transferred to the bitmap. Destroying /// the bitmap will thus not free the existing memory. If you want an autonomous /// bitmap that is initialized from an existing memory buffer, immediately /// call the method on it. /// public: NUCLEX_PIXELS_API static Bitmap InExistingMemory(const BitmapMemory &bitmapMemory); /// Initializes a new bitmap /// Width of the bitmap in pixels /// Height of the bitmap in pixels /// Pixel format in which the pixels will be stored public: NUCLEX_PIXELS_API Bitmap( std::size_t width, std::size_t height, PixelFormat pixelFormat = PixelFormat::R8_G8_B8_A8_Unsigned ); /// Constructs an bitmap as a copy of an existing bitmap /// Bitmap that will be copied public: NUCLEX_PIXELS_API Bitmap(const Bitmap &other); /// Constructs an bitmap by taking over an existing bitmap /// Bitmap that will be taken over public: NUCLEX_PIXELS_API Bitmap(Bitmap &&other); /// Frees all resources owned by the bitmap instance public: NUCLEX_PIXELS_API virtual ~Bitmap(); /// Returns the width of the bitmap in pixels /// The width of the bitmap in pixels public: NUCLEX_PIXELS_API std::size_t GetWidth() const { return this->memory.Width; } /// Returns the height of the bitmap in pixels /// The height of the bitmap in pixels public: NUCLEX_PIXELS_API std::size_t GetHeight() const { return this->memory.Height; } /// Returns the pixel format in which the pixels are stored /// The pixel format used to store the bitmap's pixels public: NUCLEX_PIXELS_API PixelFormat GetPixelFormat() const { return this->memory.PixelFormat; } /// Accesses the bitmap's pixels /// A description of the bitmap's memory layout public: NUCLEX_PIXELS_API const BitmapMemory &Access() const { return this->memory; } /// /// If the bitmap is sharing memory with another bitmap, forces it to create /// its own copy of the image data /// /// /// /// When creating a bitmap as a view into another bitmap (think of it as /// bitmap-inside-a-bitmap), the view can be set to keep accessing the same /// memory buffer, thus changing pixels in the view also changes them in /// the bitmap the view was created in. /// /// /// This method will clone all pixels accessible by the bitmap so that /// it has its own standalone memory buffer. /// /// /// It can also be used on bitmaps accessing externally managed memory to /// clone the external memory and become independent of it. /// /// public: NUCLEX_PIXELS_API void Autonomize(); /// Creates a bitmap that accesses a region within this bitmap /// X coordinate of the region's left border /// Y coordinate of the region's top border /// Width of the region /// Height of the region /// A bitmap that accesses a region within this bitmap /// /// /// The region will still be using the memory of this bitmap, so changes /// to the sub-bitmap will change the parent. This can be useful for clipping /// and atlases. /// /// /// If the parent bitmap gets destroyed, the sub-bitmap will still hold onto /// the whole memory buffer. In this case, the /// method will return true. /// /// public: NUCLEX_PIXELS_API const Bitmap GetView( std::size_t x, std::size_t y, std::size_t width, std::size_t height ) const; /// Creates a bitmap that accesses a region within this bitmap /// X coordinate of the region's left border /// Y coordinate of the region's top border /// Width of the region /// Height of the region /// A bitmap that accesses a region within this bitmap /// /// /// The region will still be using the memory of this bitmap, so changes /// to the sub-bitmap will change the parent. This can be useful for clipping /// and atlases. /// /// /// If the parent bitmap gets destroyed, the sub-bitmap will still hold onto /// the whole memory buffer. In this case, the /// method will return true. /// /// public: NUCLEX_PIXELS_API Bitmap GetView( std::size_t x, std::size_t y, std::size_t width, std::size_t height ); #if 0 /// Returns the amount of memory used by the bitmap /// The number of bytes used to store the bitmap's pixels /// /// /// The number of bytes used by the bitmap to store its pixels. This number /// can be slightly higher than the actual memory required for a tight fit /// due to alignment and a header, or much higher if the bitmap is a region /// within a larger bitmap. /// /// public: NUCLEX_PIXELS_API std::size_t GetMemoryUsed() const; // CHECK: Does the IsWastingMemory() method serve any purpose? // // It is supposed to report when a bitmap is only accessing a small region inside // a larger bitmap (and no bitmap is referencing the larger region) // // * It will be unreliable if multiple Bitmap instances reference the smaller // region because it cannot look into the other Bitmap instance // * On the other hand, just leaving it up to calling Autonomize() will also // not be ideal because it would always unify a copy-on-write clone even if // the whole bitmap is being referenced. public: NUCLEX_PIXELS_API bool IsWastingMemory() const; #endif #if !defined(MOVED_THIS_TO_PIXELFORMATCONVERTER) /// Acts as if a bitmap had a different pixel format all along /// New pixel format under which the bitmap have /// /// This operation comes with the same caveats as the C++ reinterpret_cast keyword. /// The bitmap's current pixel format must have the same width and the target pixel /// format, so this method only allows you to fix issues like R-G-B / B-G-R mismapping, /// interpreting a loaded PNG as RGB-signed for normals maps even though it was loaded /// as RGB-unsigned and similar tweaks. /// public: NUCLEX_PIXELS_API void ReinterpretPixelFormat(PixelFormat newPixelFormat); #endif #if 0 /// Converts the bitmap to a different pixel format /// New pixel format the bitmap will be converted to /// /// This method performs the conversion on the current bitmap (rather than returning /// a converted copy of the bitmap). Since the Bitmap class is copy-on-write (i.e. /// cloning a bitmap will not copy its pixels until you try to modify it), this does /// not result in much overhead. /// public: NUCLEX_PIXELS_API void ConvertPixelFormat(PixelFormat newPixelFormat); /// Copies this bitmap into another bitmap /// Target bitmap this bitmap will be copied into /// X coordinate of the bitmap's left border in the target bitmap /// Y coordinate of the bitmap's lower border in the target bitmap /// /// This is a highly optimized blit operation if both bitmaps have identical pixel /// formats. Copying into a bitmap with a different pixel format is possible, too, /// but will be slower and, depending on the pixel formats involved, can remove or /// default-initialize some color channels. /// public: NUCLEX_PIXELS_API void CopyTo(Bitmap &target, std::size_t x, std::size_t y); #endif /// Copies another bitmap instance into this one /// Other bitmap instance that will be copied /// This bitmap instance public: NUCLEX_PIXELS_API Bitmap &operator =(const Bitmap &other); /// Takes over another bitmap instance /// Other bitmap instance that will be taken over /// This bitmap instance public: NUCLEX_PIXELS_API Bitmap &operator =(Bitmap &&other); /// Detachable memory buffer that allows for shared ownership private: struct SharedBuffer; /// Initializes a bitmap used the specified buffer and memory description /// Buffer that will be used by the new bitmap /// Description of the bitmap's memory layout private: Bitmap(SharedBuffer *buffer, const BitmapMemory &memory); /// Creates a new detachable buffer for a bitmap of the specified size /// Resolution for which a buffer will be created /// Pixel format usd by the bitmap private: static SharedBuffer *newSharedBuffer( const Size &resolution, PixelFormat pixelFormat ); /// Creates a new detachable buffer by copying an existing buffer /// Existing bitmap memory that will be copied /// A new detachable buffer with a copy of the existing buffer's contents private: static SharedBuffer *newSharedBuffer(const BitmapMemory &memory); /// Releases a shared buffer, freeing its memory if possible /// Buffer that will be released private: static void releaseSharedBuffer(SharedBuffer *buffer) throw(); /// Description of the memory allocated for the bitmaps and its layout private: BitmapMemory memory; /// Memory buffer holding or accessing the bitmap's pixels private: SharedBuffer *buffer; }; // ------------------------------------------------------------------------------------------- // }} // namespace Nuclex::Pixels #endif // NUCLEX_PIXELS_BITMAP_H