demos/cubetext: Post-SVN tidy
- Move source code from `trunk` into root directory.
This commit is contained in:
442
programs/demos/cubetext/bmp.cpp
Normal file
442
programs/demos/cubetext/bmp.cpp
Normal file
@@ -0,0 +1,442 @@
|
||||
//
|
||||
// bmp.cpp - source file / freeware
|
||||
//
|
||||
// David Henry - tfc_duke@hotmail.com
|
||||
//
|
||||
|
||||
|
||||
#include "bmp.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libc/stubs.h>
|
||||
|
||||
extern "C"{
|
||||
long filelength(int fhandle);
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// LoadFileBMP() - load a Windows/OS2 BITMAP image
|
||||
// [.bmp].
|
||||
//
|
||||
// parameters :
|
||||
// - filename [in] : image source file
|
||||
// - pixels [out] : 32 bits rgb image data
|
||||
// - width [out] : image width in pixels
|
||||
// - height [out] : image height in pixels
|
||||
// - flipvert [in] : flip vertically
|
||||
//
|
||||
// return value :
|
||||
// - -1 : no image data
|
||||
// - 0 : failure
|
||||
// - 1 : success
|
||||
//
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// accepted image formats :
|
||||
// # RGB 1-4-8-24-32 bits WINDOWS - OS/2
|
||||
// # RLE 4-8 bits WINDOWS
|
||||
// --------------------------------------------------
|
||||
|
||||
int LoadFileBMP( const char *filename, unsigned char **pixels, int *width, int *height, bool flipvert )
|
||||
{
|
||||
FILE *file; // file stream
|
||||
BITMAPFILEHEADER *bmfh; // bitmap file header
|
||||
BITMAPINFOHEADER *bmih; // bitmap info header (windows)
|
||||
BITMAPCOREHEADER *bmch; // bitmap core header (os/2)
|
||||
RGBTRIPLE *os2_palette; // pointer to the color palette os/2
|
||||
RGBQUAD *win_palette; // pointer to the color palette windows
|
||||
char *buffer; // buffer storing the entire file
|
||||
unsigned char *ptr; // pointer to pixels data
|
||||
int bitCount; // number of bits per pixel
|
||||
int compression; // compression type (rgb/rle)
|
||||
int row, col, i; // temporary variables
|
||||
int w, h; // width, height
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// read the entire file in the buffer
|
||||
|
||||
file = fopen(filename,"rb");
|
||||
|
||||
if( !file)
|
||||
return 0;
|
||||
|
||||
long flen = filelength(fileno(file));
|
||||
|
||||
buffer = new char[ flen + 1 ];
|
||||
int rd = fread(buffer, flen, 1, file);
|
||||
char *pBuff = buffer;
|
||||
|
||||
fclose(file);
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// read the header
|
||||
bmfh = (BITMAPFILEHEADER *)pBuff;
|
||||
pBuff += sizeof( BITMAPFILEHEADER );
|
||||
|
||||
// verify that it's a BITMAP file
|
||||
if( bmfh->bfType != BITMAP_ID )
|
||||
{
|
||||
delete [] buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bmch = (BITMAPCOREHEADER *)pBuff;
|
||||
bmih = (BITMAPINFOHEADER *)pBuff;
|
||||
|
||||
|
||||
if( (bmih->biCompression < 0) || (bmih->biCompression > 3) )
|
||||
{
|
||||
// OS/2 style
|
||||
pBuff += sizeof( BITMAPCOREHEADER );
|
||||
|
||||
bitCount = bmch->bcBitCount;
|
||||
compression = BI_OS2;
|
||||
|
||||
w = bmch->bcWidth;
|
||||
h = bmch->bcHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
// WINDOWS style
|
||||
pBuff += sizeof( BITMAPINFOHEADER );
|
||||
|
||||
bitCount = bmih->biBitCount;
|
||||
compression = bmih->biCompression;
|
||||
|
||||
w = bmih->biWidth;
|
||||
h = bmih->biHeight;
|
||||
}
|
||||
|
||||
|
||||
if( width )
|
||||
*width = w;
|
||||
|
||||
if( height )
|
||||
*height = h;
|
||||
|
||||
|
||||
if( !pixels )
|
||||
{
|
||||
delete [] buffer;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// read the palette
|
||||
|
||||
if( bitCount <= 8 )
|
||||
{
|
||||
// 24 and 32 bits images are not paletted
|
||||
|
||||
// ajust the palette pointer to the memory in the buffer
|
||||
os2_palette = (RGBTRIPLE *)pBuff;
|
||||
win_palette = (RGBQUAD *)pBuff;
|
||||
|
||||
// [number of colors in the palette] * [size of one pixel]
|
||||
pBuff += (1 << bitCount) * (bitCount >> 3) * sizeof( unsigned char );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// allocate memory to store pixel data
|
||||
*pixels = new unsigned char[ w * h * 3 ];
|
||||
ptr = &(*pixels)[0];
|
||||
|
||||
|
||||
// move the pixel data pointer to the begening of bitmap data
|
||||
pBuff = buffer + (bmfh->bfOffBits * sizeof( char ));
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// read pixel data following the image compression
|
||||
// type and the number of bits per pixels
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
switch( compression )
|
||||
{
|
||||
case BI_OS2:
|
||||
case BI_RGB:
|
||||
{
|
||||
for( row = h - 1; row >= 0; row-- )
|
||||
{
|
||||
if( flipvert )
|
||||
ptr = &(*pixels)[ row * w * 3 ];
|
||||
|
||||
switch( bitCount )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
// RGB 1 BITS
|
||||
for( col = 0; col < (int)(w / 8); col++ )
|
||||
{
|
||||
// read the current pixel
|
||||
unsigned char color = *((unsigned char *)(pBuff++));
|
||||
|
||||
for( i = 7; i >= 0; i--, ptr += 3 )
|
||||
{
|
||||
// convert indexed pixel (1 bit) into rgb (32 bits) pixel
|
||||
int clrIdx = ((color & (1<<i)) > 0);
|
||||
|
||||
if( compression == BI_OS2 )
|
||||
{
|
||||
ptr[2] = os2_palette[ clrIdx ].rgbtRed;
|
||||
ptr[1] = os2_palette[ clrIdx ].rgbtGreen;
|
||||
ptr[0] = os2_palette[ clrIdx ].rgbtBlue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr[2] = win_palette[ clrIdx ].rgbRed;
|
||||
ptr[1] = win_palette[ clrIdx ].rgbGreen;
|
||||
ptr[0] = win_palette[ clrIdx ].rgbBlue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
// RGB 4 BITS
|
||||
for( col = 0; col < (int)(w / 2); col++, ptr += 6 )
|
||||
{
|
||||
// read the current pixel
|
||||
unsigned char color = *((unsigned char *)(pBuff++));
|
||||
|
||||
// convert indexed pixel (4 bits) into rgb (32 bits) pixel
|
||||
int clrIdx;
|
||||
|
||||
if( compression == BI_OS2 )
|
||||
{
|
||||
clrIdx = (color >> 4);
|
||||
ptr[2] = os2_palette[ clrIdx ].rgbtRed;
|
||||
ptr[1] = os2_palette[ clrIdx ].rgbtGreen;
|
||||
ptr[0] = os2_palette[ clrIdx ].rgbtBlue;
|
||||
|
||||
clrIdx = (color & 0x0F);
|
||||
ptr[6] = os2_palette[ clrIdx ].rgbtRed;
|
||||
ptr[5] = os2_palette[ clrIdx ].rgbtGreen;
|
||||
ptr[4] = os2_palette[ clrIdx ].rgbtBlue;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
clrIdx = (color >> 4);
|
||||
ptr[2] = win_palette[ clrIdx ].rgbRed;
|
||||
ptr[1] = win_palette[ clrIdx ].rgbGreen;
|
||||
ptr[0] = win_palette[ clrIdx ].rgbBlue;
|
||||
|
||||
clrIdx = (color & 0x0F);
|
||||
ptr[6] = win_palette[ clrIdx ].rgbRed;
|
||||
ptr[5] = win_palette[ clrIdx ].rgbGreen;
|
||||
ptr[4] = win_palette[ clrIdx ].rgbBlue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
// RGB 8 BITS
|
||||
for( col = 0; col < w; col++, ptr += 3 )
|
||||
{
|
||||
// read the current pixel
|
||||
unsigned char color = *((unsigned char *)(pBuff++));
|
||||
|
||||
// convert indexed pixel (8 bits) into rgb (32 bits) pixel
|
||||
if( compression == BI_OS2 )
|
||||
{
|
||||
ptr[2] = os2_palette[ color ].rgbtRed;
|
||||
ptr[1] = os2_palette[ color ].rgbtGreen;
|
||||
ptr[0] = os2_palette[ color ].rgbtBlue;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr[2] = win_palette[ color ].rgbRed;
|
||||
ptr[1] = win_palette[ color ].rgbGreen;
|
||||
ptr[0] = win_palette[ color ].rgbBlue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 24:
|
||||
{
|
||||
// RGB 24 BITS
|
||||
for( col = 0; col < w; col++, ptr += 3 )
|
||||
{
|
||||
// convert bgr pixel (24 bits) into rgb (32 bits) pixel
|
||||
RGBTRIPLE *pix = (RGBTRIPLE *)pBuff;
|
||||
pBuff += sizeof( RGBTRIPLE );
|
||||
|
||||
ptr[2] = pix->rgbtRed;
|
||||
ptr[1] = pix->rgbtGreen;
|
||||
ptr[0] = pix->rgbtBlue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 32:
|
||||
{
|
||||
// RGB 32 BITS
|
||||
for( col = 0; col < w; col++, ptr += 3 )
|
||||
{
|
||||
// // convert bgr pixel (32 bits) into rgb (32 bits) pixel
|
||||
RGBQUAD *pix = (RGBQUAD *)pBuff;
|
||||
pBuff += sizeof( RGBQUAD );
|
||||
|
||||
ptr[2] = pix->rgbRed;
|
||||
ptr[1] = pix->rgbGreen;
|
||||
ptr[0] = pix->rgbBlue;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BI_RLE8:
|
||||
{
|
||||
// RLE 8 BITS
|
||||
for( row = h - 1; row >= 0; row-- )
|
||||
{
|
||||
if( flipvert )
|
||||
ptr = &(*pixels)[ row * w * 3 ];
|
||||
|
||||
for( col = 0; col < w; /* nothing */ )
|
||||
{
|
||||
// get one packet (2 bytes)
|
||||
unsigned char byte1 = *((unsigned char *)(pBuff++));
|
||||
unsigned char byte2 = *((unsigned char *)(pBuff++));
|
||||
|
||||
|
||||
if( byte1 == RLE_COMMAND )
|
||||
{
|
||||
// absolute encoding
|
||||
for( i = 0; i < byte2; i++, ptr += 3, col++ )
|
||||
{
|
||||
// read the current pixel
|
||||
unsigned char color = *((unsigned char *)(pBuff++));
|
||||
|
||||
// convert indexed pixel (8 bits) into rgb (32 bits) pixel
|
||||
ptr[2] = win_palette[ color ].rgbRed;
|
||||
ptr[1] = win_palette[ color ].rgbGreen;
|
||||
ptr[0] = win_palette[ color ].rgbBlue;
|
||||
}
|
||||
|
||||
if( (byte2 % 2) == 1 )
|
||||
pBuff++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// read next pixels
|
||||
for( i = 0; i < byte1; i++, ptr += 3, col++ )
|
||||
{
|
||||
// convert indexed pixel (8 bits) into rgb (32 bits) pixel
|
||||
ptr[2] = win_palette[ byte2 ].rgbRed;
|
||||
ptr[1] = win_palette[ byte2 ].rgbGreen;
|
||||
ptr[0] = win_palette[ byte2 ].rgbBlue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BI_RLE4:
|
||||
{
|
||||
// RLE 4 BITS
|
||||
unsigned char color;
|
||||
int bytesRead = 0; // number of bytes read
|
||||
|
||||
for( row = h - 1; row >= 0; row-- )
|
||||
{
|
||||
if( flipvert )
|
||||
ptr = &(*pixels)[ row * w * 3 ];
|
||||
|
||||
for( col = 0; col < w; /* nothing */ )
|
||||
{
|
||||
// get one packet (2 bytes)
|
||||
unsigned char byte1 = *((unsigned char *)(pBuff++));
|
||||
unsigned char byte2 = *((unsigned char *)(pBuff++));
|
||||
|
||||
bytesRead += 2;
|
||||
|
||||
|
||||
if( byte1 == RLE_COMMAND )
|
||||
{
|
||||
// absolute encoding
|
||||
unsigned char databyte;
|
||||
|
||||
for( i = 0; i < byte2; i++, ptr += 3, col++ )
|
||||
{
|
||||
if( (i % 2) == 0 )
|
||||
{
|
||||
// read the current pixel
|
||||
databyte = *((unsigned char *)(pBuff++));
|
||||
bytesRead++;
|
||||
|
||||
color = (databyte >> 4); // 4 first bits
|
||||
}
|
||||
else
|
||||
{
|
||||
color = (databyte & 0x0F); // 4 last bits
|
||||
}
|
||||
|
||||
// convert indexed pixel (4 bits) into rgb (32 bits) pixel
|
||||
ptr[2] = win_palette[ color ].rgbRed;
|
||||
ptr[1] = win_palette[ color ].rgbGreen;
|
||||
ptr[0] = win_palette[ color ].rgbBlue;
|
||||
}
|
||||
|
||||
while( (bytesRead % 2) != 0 )
|
||||
{
|
||||
pBuff++;
|
||||
bytesRead++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// read next pixels
|
||||
for( i = 0; i < byte1; i++, ptr += 3, col++ )
|
||||
{
|
||||
if( (i % 2) == 0 )
|
||||
color = (byte2 >> 4); // 4 first bits
|
||||
else
|
||||
color = (byte2 & 0x0F); // 4 last bits
|
||||
|
||||
// convert indexed pixel (4 bits) into rgb (32 bits) pixel
|
||||
ptr[2] = win_palette[ color ].rgbRed;
|
||||
ptr[1] = win_palette[ color ].rgbGreen;
|
||||
ptr[0] = win_palette[ color ].rgbBlue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// free buffer memory
|
||||
delete [] buffer;
|
||||
|
||||
|
||||
// return success
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user