123
This commit is contained in:
258
RenderDll/Common/Textures/Image/BmpImage.cpp
Normal file
258
RenderDll/Common/Textures/Image/BmpImage.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
/*=============================================================================
|
||||
BmpImage.cpp : BMP image file format implementation.
|
||||
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
|
||||
|
||||
Revision history:
|
||||
* Created by Khonich Andrey
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "RenderPCH.h"
|
||||
#include "CImage.h"
|
||||
#include "BmpImage.h"
|
||||
|
||||
#include "SHEndian.h"
|
||||
|
||||
//===========================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Some platforms require strict-alignment, which means that values of
|
||||
// primitive types must be accessed at memory locations which are multiples
|
||||
// of the size of those types. For instance, a 'long' can only be accessed
|
||||
// at a memory location which is a multiple of four. Consequently, the
|
||||
// following endian-conversion functions first copy the raw data into a
|
||||
// variable of the proper data type using memcpy() prior to attempting to
|
||||
// access it as the given type.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static inline ushort us_endian (const byte* ptr)
|
||||
{
|
||||
short n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return convert_endian(n);
|
||||
}
|
||||
|
||||
static inline unsigned long ul_endian (const byte* ptr)
|
||||
{
|
||||
long n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return convert_endian(n);
|
||||
}
|
||||
|
||||
static inline long l_endian (const byte* ptr)
|
||||
{
|
||||
long n;
|
||||
memcpy(&n, ptr, sizeof(n));
|
||||
return convert_endian(n);
|
||||
}
|
||||
|
||||
#define BFTYPE(x) us_endian((x) + 0)
|
||||
#define BFSIZE(x) ul_endian((x) + 2)
|
||||
#define BFOFFBITS(x) ul_endian((x) + 10)
|
||||
#define BISIZE(x) ul_endian((x) + 14)
|
||||
#define BIWIDTH(x) l_endian ((x) + 18)
|
||||
#define BIHEIGHT(x) l_endian ((x) + 22)
|
||||
#define BITCOUNT(x) us_endian((x) + 28)
|
||||
#define BICOMP(x) ul_endian((x) + 30)
|
||||
#define IMAGESIZE(x) ul_endian((x) + 34)
|
||||
#define BICLRUSED(x) ul_endian((x) + 46)
|
||||
#define BICLRIMP(x) ul_endian((x) + 50)
|
||||
#define BIPALETTE(x) ((x) + 54)
|
||||
|
||||
// Type ID
|
||||
#define BM "BM" // Windows 3.1x, 95, NT, ...
|
||||
#define BA "BA" // OS/2 Bitmap Array
|
||||
#define CI "CI" // OS/2 Color Icon
|
||||
#define CP "CP" // OS/2 Color Pointer
|
||||
#define IC "IC" // OS/2 Icon
|
||||
#define PT "PT" // OS/2 Pointer
|
||||
|
||||
// Possible values for the header size
|
||||
#define WinHSize 0x28
|
||||
#define OS21xHSize 0x0C
|
||||
#define OS22xHSize 0xF0
|
||||
|
||||
// Possible values for the BPP setting
|
||||
#define Mono 1 // Monochrome bitmap
|
||||
#define _16Color 4 // 16 color bitmap
|
||||
#define _256Color 8 // 256 color bitmap
|
||||
#define HIGHCOLOR 16 // 16bit (high color) bitmap
|
||||
#define TRUECOLOR24 24 // 24bit (true color) bitmap
|
||||
#define TRUECOLOR32 32 // 32bit (true color) bitmap
|
||||
|
||||
// Compression Types
|
||||
#ifndef BI_RGB
|
||||
#define BI_RGB 0 // none
|
||||
#define BI_RLE8 1 // RLE 8-bit / pixel
|
||||
#define BI_RLE4 2 // RLE 4-bit / pixel
|
||||
#define BI_BITFIELDS 3 // Bitfields
|
||||
#endif
|
||||
|
||||
//===========================================================================
|
||||
|
||||
void CImageBmpFile::mfLoadWindowsBitmap (byte* iBuffer, long iSize)
|
||||
{
|
||||
mfSet_dimensions (BIWIDTH(iBuffer), BIHEIGHT(iBuffer));
|
||||
const int bmp_size = m_Width * m_Height;
|
||||
m_eFormat = eIF_Bmp;
|
||||
|
||||
byte *iPtr = iBuffer + BFOFFBITS(iBuffer);
|
||||
|
||||
// The last scanline in BMP corresponds to the top line in the image
|
||||
int buffer_y = m_Width * (m_Height - 1);
|
||||
bool blip = false;
|
||||
|
||||
if (BITCOUNT(iBuffer) == _256Color && BICLRUSED(iBuffer))
|
||||
{
|
||||
mfSet_ImageSize(m_Width * m_Height);
|
||||
byte *buffer = mfGet_image();
|
||||
m_pPal = new SRGBPixel [256];
|
||||
SRGBPixel *pwork = m_pPal;
|
||||
byte *inpal = BIPALETTE(iBuffer);
|
||||
mfSet_bps(8);
|
||||
|
||||
for (int color=0; color<256; color++, pwork++)
|
||||
{
|
||||
// Whacky BMP palette is in BGR order.
|
||||
pwork->blue = *inpal++;
|
||||
pwork->green = *inpal++;
|
||||
pwork->red = *inpal++;
|
||||
pwork->alpha = 255;
|
||||
inpal++; // Skip unused byte.
|
||||
}
|
||||
|
||||
if (BICOMP(iBuffer) == BI_RGB)
|
||||
{
|
||||
// Read the pixels from "top" to "bottom"
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
memcpy (buffer + buffer_y, iPtr, m_Width);
|
||||
iPtr += m_Width;
|
||||
buffer_y -= m_Width;
|
||||
} /* endwhile */
|
||||
}
|
||||
else
|
||||
if (BICOMP(iBuffer) == BI_RLE8)
|
||||
{
|
||||
// Decompress pixel data
|
||||
byte rl, rl1, i; // runlength
|
||||
byte clridx, clridx1; // colorindex
|
||||
int buffer_x = 0;
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
rl = rl1 = *iPtr++;
|
||||
clridx = clridx1 = *iPtr++;
|
||||
if (rl == 0)
|
||||
if (clridx == 0)
|
||||
{
|
||||
// new scanline
|
||||
if (!blip)
|
||||
{
|
||||
// if we didnt already jumped to the new line, do it now
|
||||
buffer_x = 0;
|
||||
buffer_y -= m_Width;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (clridx == 1)
|
||||
// end of bitmap
|
||||
break;
|
||||
else
|
||||
if (clridx == 2)
|
||||
{
|
||||
// next 2 bytes mean column- and scanline- offset
|
||||
buffer_x += *iPtr++;
|
||||
buffer_y -= (m_Width * (*iPtr++));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if (clridx > 2)
|
||||
rl1 = clridx;
|
||||
|
||||
for ( i = 0; i < rl1; i++ )
|
||||
{
|
||||
if (!rl)
|
||||
clridx1 = *iPtr++;
|
||||
buffer [buffer_y + buffer_x] = clridx1;
|
||||
|
||||
if (++buffer_x >= m_Width)
|
||||
{
|
||||
buffer_x = 0;
|
||||
buffer_y -= m_Width;
|
||||
blip = true;
|
||||
}
|
||||
else
|
||||
blip = false;
|
||||
}
|
||||
// pad in case rl == 0 and clridx in [3..255]
|
||||
if (rl == 0 && (clridx & 0x01))
|
||||
iPtr++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR24)
|
||||
{
|
||||
mfSet_ImageSize(m_Width * m_Height * 4);
|
||||
mfSet_bps (24);
|
||||
SRGBPixel *buffer = (SRGBPixel *)mfGet_image();
|
||||
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
SRGBPixel *d = buffer + buffer_y;
|
||||
for (int x = m_Width; x; x--)
|
||||
{
|
||||
d->blue = *iPtr++;
|
||||
d->green = *iPtr++;
|
||||
d->red = *iPtr++;
|
||||
d->alpha = 255;
|
||||
d++;
|
||||
} /* endfor */
|
||||
|
||||
buffer_y -= m_Width;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (!BICLRUSED(iBuffer) && BITCOUNT(iBuffer) == TRUECOLOR32)
|
||||
{
|
||||
mfSet_ImageSize(m_Width * m_Height * 4);
|
||||
mfSet_bps (32);
|
||||
SRGBPixel *buffer = (SRGBPixel *)mfGet_image();
|
||||
|
||||
while (iPtr < iBuffer + iSize && buffer_y >= 0)
|
||||
{
|
||||
SRGBPixel *d = buffer + buffer_y;
|
||||
for (int x = m_Width; x; x--)
|
||||
{
|
||||
d->blue = *iPtr++;
|
||||
d->green = *iPtr++;
|
||||
d->red = *iPtr++;
|
||||
d->alpha = *iPtr++;
|
||||
d++;
|
||||
} /* endfor */
|
||||
|
||||
buffer_y -= m_Width;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mfSet_error (eIFE_BadFormat, "Unknown BMP image format");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CImageBmpFile::CImageBmpFile (byte* ptr, long filesize) : CImageFile ()
|
||||
{
|
||||
if ((memcmp (ptr, BM, 2) == 0) && BISIZE(ptr) == WinHSize)
|
||||
mfLoadWindowsBitmap (ptr, filesize);
|
||||
else
|
||||
mfSet_error (eIFE_BadFormat, "Not a Windows BMP file");
|
||||
return;
|
||||
}
|
||||
|
||||
CImageBmpFile::~CImageBmpFile ()
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user