#include "opc/opc.h"
#include "ctl/ctldef.h"
Go to the source code of this file.
Defines | |
#define | BMI_SIZE (sizeof(BITMAPINFO) + (255 * sizeof(RGBQUAD))) |
#define | BMI_ParseData(image, bmi, bits) |
Given a pointer to a bitmap loaded into memory, find bmi, bits NOTE: Only valid on Wintel architecture. | |
#define | BMI_Init(bmi, wide, high, bpp) |
Initialize bmi as generic Windows bitmap. | |
#define | BMI_Create(bmi, bits) { (bits) = calloc( BMI_LineSize(bmi), BMI_High(bmi) ); } |
Allocate a bitmap for 'bmi'. | |
#define | BMI_Release(bmi, bits) { free( bits ); } |
Free image allocated with BMI_Create. | |
Functions | |
int | RGBQUAD_Nearest (const RGBQUAD *clut, size_t count, const RGBQUAD *color) |
Work out the best match in 'clut'. | |
bool | BMI_ReadRow (RGBQUAD *pixel, const BITMAPINFO *bmi, const void *bits, int row) |
Get color values from each pixel in a row of bmi/bits as an RGBQUAD Half of translation from one BMI format to another. | |
bool | BMI_WriteRow (const BITMAPINFO *bmi, void *bits, const RGBQUAD *pixel, int row) |
void | BMI_Translate (const BITMAPINFO *dst, void *bdst, const BITMAPINFO *src, const void *bsrc) |
Copy/Translate src bitmap to target bitmap. | |
void * | BMI_Unpack (const BITMAPINFO *bmi, const void *bits) |
Unpack certain BMP formats. | |
size_t | BMI_MakeClut (RGBQUAD *dstlut, size_t clut, const BITMAPINFO *bmi, const void *bits) |
Build a color lookup table of a given size from true-color source pixels Truly an ugly and time-consuming ordeal, but this should make it "simple", or at least less horrible. | |
void | BMI_Clut_Begin (BMIClut *clut) |
Prepare palette accumulator for new data. | |
void | BMI_Clut_AddColor (BMIClut *clut, const RGBQUAD *rgb) |
Add a color to the accumulator. | |
size_t | BMI_Clut_Make (BMIClut *clut, RGBQUAD *dstlut, size_t cClut) |
Manufacutre the palette. | |
bool | BMI_Save (const char *path, const BITMAPINFO *bmi, const void *bits) |
Save a bitmap. | |
bool | BMI_Load (const char *path, BITMAPINFO **bmi, void **bits) |
Load a bitmap. | |
void | BMI_OPC (OPC *opc, const BITMAPINFO *bmi, void *bits) |
Convert bmi,bits to native OPC NOTE: Assumes OPC is same format as bmi,bits. |
Definition in file bmp.h.
#define BMI_Create | ( | bmi, | |||
bits | ) | { (bits) = calloc( BMI_LineSize(bmi), BMI_High(bmi) ); } |
#define BMI_Init | ( | bmi, | |||
wide, | |||||
high, | |||||
bpp | ) |
Value:
{\
BITMAPINFOHEADER* pbmi = &(bmi)->bmiHeader;\
pbmi->biSize = sizeof(BITMAPINFOHEADER);\
pbmi->biWidth = (wide);\
pbmi->biHeight = (high);\
pbmi->biPlanes = 1;\
pbmi->biBitCount = (bpp);\
pbmi->biCompression = BI_RGB;\
pbmi->biSizeImage = 0;\
pbmi->biXPelsPerMeter = 0;\
pbmi->biYPelsPerMeter = 0;\
pbmi->biClrUsed = 0;\
pbmi->biClrImportant = 0;\
}
bmi | Pointer to BITMAPINFO to initialize | |
wide | Width of bmp | |
high | Height of bmp | |
bpp | Bits per pixel, i.e. 1,4,8,16,24,32 |
#define BMI_ParseData | ( | image, | |||
bmi, | |||||
bits | ) |
Value:
{\ if( *((uint16 *)(image)) == *((uint16 *)"BM") ) \ {\ /* Loaded from a file; strip file header out */\ (bmi) = (BITMAPINFO *)( (uint8 *)(image) + sizeof(BITMAPFILEHEADER) );\ (bits) = (uint8 *)(image) + ((BITMAPFILEHEADER *)image)->bfOffBits;\ }\ else \ {\ /* <Probably> loaded from a resource */\ (bmi) = (BITMAPINFO *)(image);\ (bits) = (uint8 *)(bmi) + BMI_BMI_Size( bmi );\ }\ }
image | Pointer to image to parse | |
bmi | BITMAPINFO Pointer to be initialized | |
bits | Pixel data |
Definition at line 118 of file bmp.h.
Referenced by BMI_Load().
#define BMI_Release | ( | bmi, | |||
bits | ) | { free( bits ); } |
#define BMI_SIZE (sizeof(BITMAPINFO) + (255 * sizeof(RGBQUAD))) |
void BMI_Clut_AddColor | ( | BMIClut * | clut, | |
const RGBQUAD * | rgb | |||
) |
Add a color to the accumulator.
clut | Instance of clut | |
rgb | Color to add |
Definition at line 486 of file bmp.c.
References type_max.
Referenced by BMI_MakeClut().
00487 { 00488 #define CLI(RGBQUAD) ( (((RGBQUAD).rgbBlue&0xf8)>>3) | (((RGBQUAD).rgbGreen&0xf8)<<2) | (((RGBQUAD).rgbRed&0xf8)<<7) ) 00489 int index = CLI(*rgb); 00490 struct BMIClutEntry* curr = clut->cluts + index; 00491 curr->rgb = *rgb; 00492 if( curr->count < type_max(uint32) ) 00493 curr->count++; 00494 }
void BMI_Clut_Begin | ( | BMIClut * | clut | ) |
Prepare palette accumulator for new data.
clut | Instance of clut to initialize |
Definition at line 477 of file bmp.c.
Referenced by BMI_MakeClut().
size_t BMI_Clut_Make | ( | BMIClut * | clut, | |
RGBQUAD * | dstlut, | |||
size_t | cClut | |||
) |
Manufacutre the palette.
clut | Instance of clut | |
dstlut | Array to receive official colors | |
cClut | Number of colors array will accept |
Definition at line 532 of file bmp.c.
References array_qsort, and countof.
Referenced by BMI_MakeClut().
00533 { 00534 array_qsort( struct BMIClutEntry, clut->cluts, countof(clut->cluts), qsclutz ); 00535 array_qsort( struct BMIClutEntry, clut->cluts, cClut, qspretty ); 00536 { 00537 const struct BMIClutEntry* curr = clut->cluts; 00538 size_t remain = cClut; 00539 while( remain ) 00540 { 00541 remain--; 00542 if( curr->count ) 00543 *dstlut++ = (curr++)->rgb; 00544 else 00545 break; 00546 } 00547 cClut -= remain; 00548 return cClut; 00549 } 00550 }
bool BMI_Load | ( | const char * | path, | |
BITMAPINFO ** | bmi, | |||
void ** | bits | |||
) |
Load a bitmap.
path | Path to reat file from | |
bmi | Pointer to pointer to receive bitmap header | |
bits | Pointer to pointer to receive bitmap content |
Definition at line 735 of file bmp.c.
References BMI_ParseData, BMI_Unpack(), and ctl_mmap_open().
00736 { 00737 /* 00738 * TODO: Replace with target independent code 00739 */ 00740 ctl_mmap image; 00741 ctl_mmap_open( &image, path ); 00742 if( ctl_mmap_ready(&image) ) 00743 { 00744 const BITMAPINFO* bmiIn; 00745 const void* bitsIn; 00746 BMI_ParseData( ctl_mmap_ptr(&image), bmiIn, bitsIn ); 00747 *bmi = BMI_BMI_Copy(bmiIn); 00748 *bits = BMI_Unpack( bmiIn, bitsIn ); 00749 return true; 00750 } 00751 return false; 00752 }
size_t BMI_MakeClut | ( | RGBQUAD * | dstlut, | |
size_t | cClut, | |||
const BITMAPINFO * | bmi, | |||
const void * | bits | |||
) |
Build a color lookup table of a given size from true-color source pixels Truly an ugly and time-consuming ordeal, but this should make it "simple", or at least less horrible.
dstlut | Buffer to receive color lookup table (sorted most to least popular) | |
cClut | Maximum count of colors to match up | |
bmi | BITMAPINFO we're generating a CLUT from | |
bits | Bitmap data |
Definition at line 462 of file bmp.c.
References BMI_Clut_AddColor(), BMI_Clut_Begin(), and BMI_Clut_Make().
00463 { 00464 BMIClut clutz; 00465 BMI_Clut_Begin( &clutz ); 00466 { 00467 BMI_foreach( bmi, bits, pixel ) 00468 BMI_Clut_AddColor( &clutz, pixel ); 00469 } 00470 return BMI_Clut_Make( &clutz, dstlut, cClut ); 00471 }
void BMI_OPC | ( | OPC * | opc, | |
const BITMAPINFO * | bmi, | |||
void * | bits | |||
) |
Convert bmi,bits to native OPC NOTE: Assumes OPC is same format as bmi,bits.
opc | OPC to be filled in with data from bmi, bits | |
bmi | BITMAPINFO describing size/format of data | |
bits | Pointer to pixel data |
Definition at line 20 of file bmp.c.
References Rect::bottom, OPC::clip, Rect::left, OPC::origin, OPC::pitch, Rect::right, and Rect::top.
00021 { 00022 OPC* out = (opc); 00023 const BITMAPINFO* bmin = (bmi); 00024 out->origin = (uint8*)BMI_Origin(bmin,bits); 00025 out->pitch = BMI_LineOffset(bmin); 00026 out->clip.left = out->clip.top = 0; 00027 out->clip.right = BMI_Wide(bmin); 00028 out->clip.bottom = BMI_High(bmin); 00029 }
bool BMI_ReadRow | ( | RGBQUAD * | pixel, | |
const BITMAPINFO * | bmi, | |||
const void * | bits, | |||
int | row | |||
) |
Get color values from each pixel in a row of bmi/bits as an RGBQUAD Half of translation from one BMI format to another.
pixel | Buffer to receive pixels, must have at least BMI_Wide(bmi) members | |
bmi | bitmap header | |
bits | bitmap content | |
row | Row from bitmap to get data from |
Definition at line 100 of file bmp.c.
References assert.
Referenced by BMI_Translate().
00101 { 00102 /* Don't choke on bad row */ 00103 assert(bmi); 00104 assert(bits); 00105 if( row < 0 || row >= BMI_High(bmi) || (bmi->bmiHeader.biCompression != BI_RGB && bmi->bmiHeader.biCompression != BI_BITFIELDS && bmi->bmiHeader.biCompression != BI_RLE4 && bmi->bmiHeader.biCompression != BI_RLE8) ) 00106 { 00107 memset( pixel, 0, sizeof(RGBQUAD)*BMI_Wide(bmi) ); 00108 return false; 00109 } 00110 switch( bmi->bmiHeader.biBitCount ) 00111 { 00112 case 1: 00113 { 00114 const RGBQUAD* colors = BMI_ColorData(bmi); 00115 const uint8* pixels = (const uint8*)BMI_LinePtr(bmi,bits,row); 00116 int wordlen = BMI_Wide(bmi); 00117 while( wordlen ) 00118 { 00119 uint8 bit = 0x80; 00120 while( bit && wordlen ) 00121 { 00122 *pixel++ = colors[0 != (*pixels & bit)]; 00123 wordlen--; 00124 bit >>= 1; 00125 } 00126 pixels++; 00127 } 00128 } 00129 return true; 00130 00131 case 4: 00132 { 00133 const RGBQUAD* colors = BMI_ColorData(bmi); 00134 const uint8* pixels = (const uint8*)BMI_LinePtr(bmi,bits,row); 00135 int wordlen = BMI_Wide(bmi); 00136 int curr; 00137 for( curr = 0; curr < wordlen; ++curr ) 00138 { 00139 if( curr&1 ) 00140 { 00141 *pixel++ = colors[*pixels&0xf]; 00142 pixels++; 00143 } 00144 else 00145 { 00146 *pixel++ = colors[(*pixels>>4)&0xf]; 00147 } 00148 } 00149 } 00150 return true; 00151 00152 case 8: 00153 { 00154 const RGBQUAD* colors = BMI_ColorData(bmi); 00155 const uint8* pixels = (const uint8*)BMI_LinePtr(bmi,bits,row); 00156 int wordlen = BMI_Wide(bmi); 00157 while( wordlen-- ) 00158 *pixel++ = colors[*pixels++]; 00159 } 00160 return true; 00161 00162 case 16: 00163 if( bmi->bmiHeader.biCompression == BI_BITFIELDS ) 00164 { 00165 const uint32* masks = (const uint32*)BMI_ColorData(bmi); 00166 uint16 mRed = (uint16)masks[0]; 00167 uint16 mGreen = (uint16)masks[1]; 00168 uint16 mBlue = (uint16)masks[2]; 00169 int bRed = lsb(mRed); 00170 int bGreen = lsb(mGreen); 00171 int bBlue = lsb(mBlue); 00172 int nRed = nbits( mRed ); 00173 int nGreen = nbits( mGreen ); 00174 int nBlue = nbits( mBlue ); 00175 const uint16* pixels = (const uint16*)BMI_LinePtr(bmi,bits,row); 00176 int wordlen = BMI_Wide(bmi); 00177 while( wordlen-- ) 00178 { 00179 pixel->rgbBlue = (uint8)(((mBlue & *pixels) >> bBlue) << (8-nBlue)); 00180 pixel->rgbGreen = (uint8)(((mGreen & *pixels) >> bGreen) << (8-nGreen)); 00181 pixel->rgbRed = (uint8)(((mRed & *pixels) >> bRed) << (8-nRed)); 00182 pixel->rgbReserved = 0; 00183 pixel++; 00184 pixels++; 00185 } 00186 } 00187 else 00188 { 00189 const uint16* pixels = (const uint16*)BMI_LinePtr(bmi,bits,row); 00190 int wordlen = BMI_Wide(bmi); 00191 while( wordlen-- ) 00192 { 00193 pixel->rgbBlue = (uint8)((*pixels & 0x1f) << 3); 00194 pixel->rgbGreen = (uint8)(((*pixels >> 5) & 0x1f) << 3); 00195 pixel->rgbRed = (uint8)(((*pixels >> 10) & 0x1f) << 3); 00196 pixel->rgbReserved = 0; 00197 pixels++; 00198 pixel++; 00199 } 00200 } 00201 return true; 00202 00203 case 24: 00204 { 00205 const uint8* pixels = (const uint8*)BMI_LinePtr(bmi,bits,row); 00206 int wordlen = BMI_Wide(bmi); 00207 while( wordlen-- ) 00208 { 00209 pixel->rgbBlue = *pixels++; 00210 pixel->rgbGreen = *pixels++; 00211 pixel->rgbRed = *pixels++; 00212 pixel->rgbReserved = 0; 00213 pixel++; 00214 } 00215 } 00216 return true; 00217 00218 case 32: 00219 if( bmi->bmiHeader.biCompression == BI_BITFIELDS ) 00220 { 00221 const uint32* masks = (const uint32*)BMI_ColorData(bmi); 00222 uint32 mRed = (uint32)masks[0]; 00223 uint32 mGreen = (uint32)masks[1]; 00224 uint32 mBlue = (uint32)masks[2]; 00225 int bRed = lsb(mRed); 00226 int bGreen = lsb(mGreen); 00227 int bBlue = lsb(mBlue); 00228 int nRed = nbits( mRed ); 00229 int nGreen = nbits( mGreen ); 00230 int nBlue = nbits( mBlue ); 00231 const uint32* pixels = (const uint32*)BMI_LinePtr(bmi,bits,row); 00232 int wordlen = BMI_Wide(bmi); 00233 while( wordlen-- ) 00234 { 00235 pixel->rgbBlue = (uint8)(((mBlue & *pixels) >> bBlue) << (8-nBlue)); 00236 pixel->rgbGreen = (uint8)(((mGreen & *pixels) >> bGreen) << (8-nGreen)); 00237 pixel->rgbRed = (uint8)(((mRed & *pixels) >> bRed) << (8-nRed)); 00238 pixel->rgbReserved = 0; 00239 pixels++; 00240 pixel++; 00241 } 00242 } 00243 else 00244 { 00245 const uint8* pixels = (const uint8*)BMI_LinePtr(bmi,bits,row); 00246 int wordlen = BMI_Wide(bmi); 00247 while( wordlen-- ) 00248 { 00249 pixel->rgbBlue = *pixels++; 00250 pixel->rgbGreen = *pixels++; 00251 pixel->rgbRed = *pixels++; 00252 pixel->rgbReserved = 0; 00253 pixel++; 00254 pixels++; 00255 } 00256 } 00257 return true; 00258 00259 default: 00260 break; 00261 } 00262 return false; 00263 }
bool BMI_Save | ( | const char * | path, | |
const BITMAPINFO * | bmi, | |||
const void * | bits | |||
) |
Save a bitmap.
path | Path to write file to | |
bmi | bitmap header | |
bits | bitmap content |
Definition at line 677 of file bmp.c.
References assert.
00678 { 00679 /* 00680 * TODO: Replace with target independent code 00681 */ 00682 /* Save BMI/bits as a BITMAP */ 00683 FILE *fp = fopen( path, "wb" ); 00684 assert( bmi ); 00685 assert( bits ); 00686 assert( bmi->bmiHeader.biWidth > 0 ); 00687 assert( bmi->bmiHeader.biHeight ); 00688 if( fp ) 00689 { 00690 BITMAPFILEHEADER bmf; 00691 bmf.bfType = *((uint16 *)"BM"); 00692 bmf.bfSize = sizeof(bmf) + BMI_BMI_Size(bmi) + BMI_BitmapSize(bmi); 00693 bmf.bfReserved1 = 0; 00694 bmf.bfReserved2 = 0; 00695 bmf.bfOffBits = sizeof(bmf) + BMI_BMI_Size(bmi); 00696 if( 1 != fwrite( &bmf, sizeof(bmf), 1, fp ) ) 00697 { 00698 fclose( fp ); 00699 return false; 00700 } 00701 { 00702 /* Tell it form is 'rightside up' */ 00703 BITMAPINFO *bmiScratch = BMI_Alloc(); 00704 memcpy( bmiScratch, bmi, BMI_BMI_Size(bmi) ); 00705 bmiScratch->bmiHeader.biHeight = abs(bmiScratch->bmiHeader.biHeight); 00706 if( 1 != fwrite( bmiScratch, BMI_BMI_Size(bmiScratch), 1, fp ) ) 00707 { 00708 fclose( fp ); 00709 return false; 00710 } 00711 BMI_Free(bmiScratch); 00712 } 00713 { 00714 /* Always write image upside-down */ 00715 int line = BMI_High(bmi); 00716 while( line-- ) 00717 { 00718 if( 1 != fwrite( BMI_LinePtr(bmi,bits,line), BMI_LineSize(bmi), 1, fp ) ) 00719 break; 00720 } 00721 } 00722 fclose( fp ); 00723 return true; 00724 } 00725 return false; 00726 }
void BMI_Translate | ( | const BITMAPINFO * | dst, | |
void * | bdst, | |||
const BITMAPINFO * | src, | |||
const void * | bsrc | |||
) |
Copy/Translate src bitmap to target bitmap.
dst | Destination bitmap definition | |
bdst | Destination bitmap data | |
src | Source bitmap definition | |
bsrc | Source bitmap data |
Definition at line 560 of file bmp.c.
References BMI_ReadRow(), and BMI_WriteRow().
00561 { 00562 RGBQUAD* colors = (RGBQUAD*)malloc( sizeof(RGBQUAD) * max(BMI_Wide(dst),BMI_Wide(src)) ); 00563 int rowCurr = min( BMI_High(dst), BMI_High(src) ); 00564 while( rowCurr-- ) 00565 { 00566 BMI_ReadRow( colors, src, bsrc, rowCurr ); 00567 BMI_WriteRow( dst, bdst, colors, rowCurr ); 00568 } 00569 free(colors); 00570 }
void* BMI_Unpack | ( | const BITMAPINFO * | bmi, | |
const void * | bits | |||
) |
Unpack certain BMP formats.
bmi | Describes BMP format | |
bits | (Presumably) packed source data |
Definition at line 579 of file bmp.c.
Referenced by BMI_Load().
00580 { 00581 switch( bmi->bmiHeader.biCompression ) 00582 { 00583 default: 00584 case BI_BITFIELDS: 00585 case BI_RGB: 00586 return NULL; 00587 00588 case BI_RLE4: 00589 case BI_RLE8: 00590 { 00591 size_t current = BMI_BitmapSize(bmi); 00592 size_t lineSize = BMI_LineSize(bmi); 00593 size_t needs = lineSize * BMI_High(bmi); 00594 void* ret = malloc(needs); 00595 const uint8* pSrc = (const uint8*)bits; 00596 const uint8* pEnd = pSrc + current; 00597 uint8* pDstEdge = (uint8*)ret; 00598 uint8* pDst = pDstEdge; 00599 const uint8* pdEnd = pDst + needs; 00600 while( pSrc < pEnd ) 00601 { 00602 int count = *pSrc++; 00603 if( count ) 00604 { 00605 uint8 fill = *pSrc++; 00606 count = min(count,(int)(pdEnd-pDst)); 00607 if( bmi->bmiHeader.biCompression == BI_RLE8 ) 00608 { 00609 memset( pDst, fill, count ); 00610 pDst += count; 00611 } 00612 else 00613 { 00614 count>>=1; 00615 memset( pDst, fill, count ); 00616 pDst += count; 00617 } 00618 } 00619 else /* Escape */ 00620 { 00621 count = *pSrc++; /* Get code */ 00622 if( count == 0 ) 00623 { 00624 pDst = pDstEdge += lineSize; 00625 } 00626 else if( count == 1 ) 00627 break; 00628 else if( count == 2 ) 00629 { 00630 int x = *pSrc++; 00631 int y = *pSrc++; 00632 pDstEdge += (lineSize*y); 00633 pDst = pDstEdge + x; 00634 } 00635 else 00636 { 00637 count = min(count,(int)(pdEnd-pDst)); 00638 count = min(count,(int)(pEnd-pSrc)); 00639 if( bmi->bmiHeader.biCompression == BI_RLE4 ) 00640 { 00641 memcpy( pDst, pSrc, count>>1 ); 00642 pDst += count>>1; 00643 pSrc += count; 00644 } 00645 else 00646 { 00647 memcpy( pDst, pSrc, count ); 00648 pDst += count; 00649 pSrc += count; 00650 } 00651 /* Read mysterious excess byte */ 00652 if( bmi->bmiHeader.biCompression == BI_RLE8 ) 00653 { 00654 if( count & 1 ) 00655 pSrc++; 00656 } 00657 else 00658 { 00659 if( (count & 3) == 1 || (count & 3) == 2 ) 00660 pSrc++; 00661 } 00662 } 00663 } 00664 } 00665 return ret; 00666 } 00667 break; 00668 } 00669 }
bool BMI_WriteRow | ( | const BITMAPINFO * | bmi, | |
void * | bits, | |||
const RGBQUAD * | pixel, | |||
int | row | |||
) |
Set color values from a line of RGBQUADs to whatever format map Half of translation from one BMI format to another
pixel | Buffer containing colors to write, must have at least BMI_Wide(bmi) members | |
bmi | bitmap header | |
bits | bitmap content | |
row | Row in bitmap to put data in |
Definition at line 275 of file bmp.c.
References assert, and RGBQUAD_Nearest().
Referenced by BMI_Translate().
00276 { 00277 /* Don't choke on bad row */ 00278 assert(bmi); 00279 assert(bits); 00280 if( row < 0 || row >= BMI_High(bmi) || (bmi->bmiHeader.biCompression != BI_RGB && bmi->bmiHeader.biCompression != BI_BITFIELDS) ) 00281 { 00282 return false; 00283 } 00284 switch( bmi->bmiHeader.biBitCount ) 00285 { 00286 case 1: 00287 { 00288 /* 1 bit color indexes */ 00289 const RGBQUAD* colors = BMI_ColorData(bmi); 00290 uint8* pixels = (uint8*)BMI_LinePtr(bmi,bits,row); 00291 int wordlen = BMI_Wide(bmi); 00292 while( wordlen ) 00293 { 00294 uint8 bit = 0x80; 00295 *pixels = 0; 00296 while( bit && wordlen ) 00297 { 00298 if( RGBQUAD_Nearest( colors, 2, pixel++ ) ) 00299 *pixels |= bit; 00300 bit>>=1; 00301 wordlen--; 00302 } 00303 pixels++; 00304 } 00305 } 00306 return true; 00307 00308 case 4: 00309 { 00310 const RGBQUAD* colors = BMI_ColorData(bmi); 00311 uint8* pixels = (uint8*)BMI_LinePtr(bmi,bits,row); 00312 int wordlen = BMI_Wide(bmi); 00313 int curr; 00314 for( curr = 0; curr < wordlen; ++curr ) 00315 { 00316 unsigned index = (unsigned)RGBQUAD_Nearest( colors, 16, pixel++ ); 00317 if( wordlen & 1 ) 00318 *pixels++ = (uint8)index; 00319 else 00320 *pixels |= (uint8)(index<<4); 00321 } 00322 } 00323 return true; 00324 00325 case 8: 00326 { 00327 /* 8 bit color indexes */ 00328 const RGBQUAD* colors = BMI_ColorData(bmi); 00329 uint8* pixels = (uint8*)BMI_LinePtr(bmi,bits,row); 00330 int wordlen = BMI_Wide(bmi); 00331 while( wordlen-- ) 00332 *pixels++ = (uint8)RGBQUAD_Nearest( colors, 256, pixel++ ); 00333 } 00334 return true; 00335 00336 case 16: 00337 if( bmi->bmiHeader.biCompression == BI_BITFIELDS ) 00338 { 00339 /* 16 bit masks */ 00340 const uint32* masks = (const uint32*)BMI_ColorData(bmi); 00341 uint16 mRed = (uint16)masks[0]; 00342 uint16 mGreen = (uint16)masks[1]; 00343 uint16 mBlue = (uint16)masks[2]; 00344 int bRed = lsb(mRed); 00345 int bGreen = lsb(mGreen); 00346 int bBlue = lsb(mBlue); 00347 int nRed = nbits( mRed ); 00348 int nGreen = nbits( mGreen ); 00349 int nBlue = nbits( mBlue ); 00350 uint16* pixels = (uint16*)BMI_LinePtr(bmi,bits,row); 00351 int wordlen = BMI_Wide(bmi); 00352 while( wordlen-- ) 00353 { 00354 *pixels = 0; 00355 *pixels |= (((uint16)pixel->rgbBlue & ((1<<nBlue)-1)) >> (8-nBlue)) << bBlue; 00356 *pixels |= (((uint16)pixel->rgbGreen & ((1<<nGreen)-1)) >> (8-nGreen)) << bGreen; 00357 *pixels |= (((uint16)pixel->rgbRed & ((1<<nRed)-1)) >> (8-nRed)) << bRed; 00358 pixel++; 00359 pixels++; 00360 } 00361 } 00362 else 00363 { 00364 /* lsb 5 bits of blue, green, red, msb=0 */ 00365 uint16* pixels = (uint16*)BMI_LinePtr(bmi,bits,row); 00366 int wordlen = BMI_Wide(bmi); 00367 while( wordlen-- ) 00368 { 00369 *pixels = 0; 00370 *pixels |= ((uint16)pixel->rgbBlue & 0xf8) >> 3; 00371 *pixels |= ((uint16)pixel->rgbGreen & 0xf8) << 2; 00372 *pixels |= ((uint16)pixel->rgbRed & 0xf8) << 7; 00373 pixels++; 00374 pixel++; 00375 } 00376 } 00377 return true; 00378 00379 case 24: 00380 { 00381 /* 24 bits of blue,green,red */ 00382 uint8* pixels = (uint8*)BMI_LinePtr(bmi,bits,row); 00383 int wordlen = BMI_Wide(bmi); 00384 while( wordlen-- ) 00385 { 00386 *pixels++ = pixel->rgbBlue; 00387 *pixels++ = pixel->rgbGreen; 00388 *pixels++ = pixel->rgbRed; 00389 pixel++; 00390 } 00391 } 00392 return true; 00393 00394 case 32: 00395 if( bmi->bmiHeader.biCompression == BI_BITFIELDS ) 00396 { 00397 /* 32 bit masks */ 00398 const uint32* masks = (const uint32*)BMI_ColorData(bmi); 00399 uint32 mRed = (uint32)masks[0]; 00400 uint32 mGreen = (uint32)masks[1]; 00401 uint32 mBlue = (uint32)masks[2]; 00402 int bRed = lsb(mRed); 00403 int bGreen = lsb(mGreen); 00404 int bBlue = lsb(mBlue); 00405 int nRed = nbits( mRed ); 00406 int nGreen = nbits( mGreen ); 00407 int nBlue = nbits( mBlue ); 00408 uint32* pixels = (uint32*)BMI_LinePtr(bmi,bits,row); 00409 int wordlen = BMI_Wide(bmi); 00410 while( wordlen-- ) 00411 { 00412 *pixels = 0; 00413 *pixels |= (((uint32)pixel->rgbBlue & ((1<<nBlue)-1)) >> (8-nBlue)) << bBlue; 00414 *pixels |= (((uint32)pixel->rgbGreen & ((1<<nGreen)-1)) >> (8-nGreen)) << bGreen; 00415 *pixels |= (((uint32)pixel->rgbRed & ((1<<nRed)-1)) >> (8-nRed)) << bRed; 00416 pixel++; 00417 pixels++; 00418 } 00419 } 00420 else 00421 { 00422 /* Default is 8 bits each of blue, green, red */ 00423 uint8* pixels = (uint8*)BMI_LinePtr(bmi,bits,row); 00424 int wordlen = BMI_Wide(bmi); 00425 while( wordlen-- ) 00426 { 00427 *pixels++ = pixel->rgbBlue; 00428 *pixels++ = pixel->rgbGreen; 00429 *pixels++ = pixel->rgbRed; 00430 *pixels++ = 0; 00431 pixel++; 00432 } 00433 } 00434 return true; 00435 00436 default: 00437 break; 00438 } 00439 return false; 00440 }