#pragma once
struct BitmapSaveOptions
{
BitmapSaveOptions()
{
Region = Rectangle2i(Vec2i::Origin, Vec2i::Origin);
ScratchSpace = NULL;
ScratchSpaceSize = 0;
SaveAlpha = false;
UseBGR = false;
}
Rectangle2i Region;
BYTE *ScratchSpace;
UINT ScratchSpaceSize;
bool SaveAlpha;
bool UseBGR;
};
class Bitmap
{
public:
Bitmap();
Bitmap(const Bitmap &B);
Bitmap(const Bitmap &B, UINT x, UINT y, UINT Width, UINT Height);
Bitmap(UINT Width, UINT Height);
~Bitmap();
void FreeMemory();
void Allocate(UINT Width, UINT Height);
Bitmap& operator = (const Bitmap &Bmp);
__forceinline RGBColor* operator [] (UINT Row) {return &_Data[Row * _Width];}
__forceinline const RGBColor* operator [] (UINT Row) const {return &_Data[Row * _Width];}
__forceinline UINT Width() const {return _Width;}
__forceinline UINT Height() const {return _Height;}
__forceinline Vec2i Dimensions() const {return Vec2i(_Width, _Height);}
__forceinline RGBColor SampleNearest(const Vec2f &Pos)
{
Vec2i SamplePos(Utility::Bound(Math::Round(Pos.x * (_Width - 1)), 0, int(_Width) - 1),
Utility::Bound(Math::Round(Pos.y * (_Height - 1)), 0, int(_Height) - 1));
return _Data[SamplePos.y * _Width + SamplePos.x];
}
void SaveBMP(const String &Filename) const; void SavePPM(const String &Filename) const; void SavePGM(const String &Filename, int Channel) const;
void SavePNG(const String &Filename) const; void SavePNG(const String &Filename, const BitmapSaveOptions &Options) const;
void SavePNGToMemory(Vector<BYTE> &Buffer) const; void SavePNGToMemory(Vector<BYTE> &Buffer, const BitmapSaveOptions &Options) const;
UINT SaveDelta(const Bitmap &Bmp, const String &Filename) const;
void LoadBMP(const String &Filename); void LoadPNG(const String &Filename); void LoadPNGFromMemory(const Vector<BYTE> &Buffer); void LoadSDL(const String &Filename); void LoadDelta(const Bitmap &Bmp, const String &Filename);
#ifdef USE_D3D9
void LoadFromSurface(LPDIRECT3DSURFACE9 Surface);
static void SaveSurfaceToPNG(LPDIRECT3DSURFACE9 Surface, const String &Filename, const BitmapSaveOptions &Options);
#endif
__forceinline void BltTo(Bitmap &B, const Vec2i &Target) const
{
BltTo(B, Target.x, Target.y);
}
void BltTo(Bitmap &B, int TargetX, int TargetY) const;
void BltToNoClipMemcpy(Bitmap &B, UINT TargetX, UINT TargetY) const;
void BltTo(Bitmap &B, int TargetX, int TargetY, int SourceX, int SourceY, int Width, int Height) const;
enum SamplingType
{
SamplingPoint,
SamplingLinear,
};
void StretchBltTo(Bitmap &B, const Rectangle2i &TargetRect, const Rectangle2i &SourceRect, SamplingType Sampling) const;
void StretchBltTo(Bitmap &B, int TargetX, int TargetY, int TargetWidth, int TargetHeight, int SourceX, int SourceY, int SourceWidth, int SourceHeight, SamplingType Sampling) const;
void LoadGrid(const Grid<float> &Values);
void LoadGrid(const Grid<float> &Values, float Min, float Max);
void FlipHorizontal();
void FlipVertical();
UINT Hash32() const;
UINT64 Hash64() const;
bool PerfectMatch(const Bitmap &Bmp) const;
bool Monochrome(RGBColor Color) const;
bool MonochromeIncludingAlpha(RGBColor Color) const;
UINT CountPixelsWithColor(RGBColor Color) const;
void ReplaceColor(RGBColor SourceColor, RGBColor NewColor);
void Clear(const RGBColor &Color); void Clear(); void LoadAlphaChannelAsGrayscale();
void FlipBlueAndRed();
RGBColor AverageColorOverRegion(const Rectangle2f &Region) const;
private:
#ifdef USE_PNG
static void __cdecl PNGReadFromBuffer(png_structp png_ptr, png_bytep data, png_size_t length);
static void __cdecl PNGWriteToBuffer(png_structp png_ptr, png_bytep data, png_size_t length);
static void __cdecl PNGFlushBuffer(png_structp png_ptr);
void PNGCompleteRead(png_structp PngRead, png_infop PngInfo, const String &Filename);
void PNGCompleteWrite(png_structp PngWrite, png_infop PngInfo, const BitmapSaveOptions &Options) const;
#endif
UINT _Width, _Height; RGBColor* _Data; };
namespace Utility
{
__forceinline bool PointInsideBitmap(const Bitmap &Bmp, int x, int y)
{
return (between(x, 0, int(Bmp.Width()) - 1) &&
between(y, 0, int(Bmp.Height()) - 1));
}
}