#include "CImageWriterBMP.h"
#ifdef _IRR_COMPILE_WITH_BMP_WRITER_
#include "CImageLoaderBMP.h"
#include "IWriteFile.h"
#include "CColorConverter.h"
#include "irrString.h"
namespace irr
{
namespace video
{
IImageWriter* createImageWriterBMP()
{
return new CImageWriterBMP;
}
CImageWriterBMP::CImageWriterBMP()
{
#ifdef _DEBUG
setDebugName("CImageWriterBMP");
#endif
}
bool CImageWriterBMP::isAWriteableFileExtension(const io::path& filename) const
{
return core::hasFileExtension ( filename, "bmp" );
}
bool CImageWriterBMP::writeImage(io::IWriteFile* file, IImage* image, u32 param) const
{
SBMPHeader imageHeader;
imageHeader.Id = 0x4d42;
imageHeader.Reserved = 0;
imageHeader.BitmapDataOffset = sizeof(imageHeader);
imageHeader.BitmapHeaderSize = 0x28;
imageHeader.Width = image->getDimension().Width;
imageHeader.Height = image->getDimension().Height;
imageHeader.Planes = 1;
imageHeader.BPP = 24;
imageHeader.Compression = 0;
imageHeader.PixelPerMeterX = 0;
imageHeader.PixelPerMeterY = 0;
imageHeader.Colors = 0;
imageHeader.ImportantColors = 0;
imageHeader.BitmapDataSize = imageHeader.Width * imageHeader.BPP / 8;
imageHeader.BitmapDataSize = (imageHeader.BitmapDataSize + 3) & ~3;
imageHeader.BitmapDataSize *= imageHeader.Height;
imageHeader.FileSize = imageHeader.BitmapDataOffset + imageHeader.BitmapDataSize;
void (*CColorConverter_convertFORMATtoFORMAT)(const void*, s32, void*) = 0;
switch(image->getColorFormat())
{
case ECF_R8G8B8:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_R8G8B8toR8G8B8;
break;
case ECF_A8R8G8B8:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_A8R8G8B8toB8G8R8;
break;
case ECF_A1R5G5B5:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_A1R5G5B5toR8G8B8;
break;
case ECF_R5G6B5:
CColorConverter_convertFORMATtoFORMAT
= CColorConverter::convert_R5G6B5toR8G8B8;
break;
}
if (!CColorConverter_convertFORMATtoFORMAT)
return false;
if (file->write(&imageHeader, sizeof(imageHeader)) != sizeof(imageHeader))
return false;
u8* scan_lines = (u8*)image->lock();
if (!scan_lines)
return false;
u32 pixel_size = image->getBytesPerPixel();
u32 row_stride = (pixel_size * imageHeader.Width);
s32 row_size = ((3 * imageHeader.Width) + 3) & ~3;
u8* row_pointer = new u8[row_size];
memset(row_pointer, 0, row_size);
s32 y;
for (y = imageHeader.Height - 1; 0 <= y; --y)
{
if (image->getColorFormat()==ECF_R8G8B8)
CColorConverter::convert24BitTo24Bit(&scan_lines[y * row_stride], row_pointer, imageHeader.Width, 1, 0, false, true);
else
CColorConverter_convertFORMATtoFORMAT(&scan_lines[y * row_stride], imageHeader.Width, row_pointer);
if (file->write(row_pointer, row_size) < row_size)
break;
}
delete [] row_pointer;
image->unlock();
return y < 0;
}
}
}
#endif