#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