📄 winbmp.c
字号:
pixel = fp_igetw (f); /* read the gap */
bits += pitch;
}
}
/* __mg_load_bmp:
* Loads a Windows BMP file, returning in the my_bitmap structure and storing
* the palette data in the specified palette (this should be an array of
* at least 256 RGB structures).
*
* Thanks to Seymour Shlien for contributing this function.
*/
int __mg_load_bmp (MG_RWops* fp, MYBITMAP* bmp, RGB* pal)
{
BITMAPFILEHEADER fileheader;
BITMAPINFOHEADER infoheader;
int effect_depth;
DWORD rmask = 0x001f, gmask = 0x03e0, bmask = 0x7c00;
unsigned long biSize;
BYTE* bits;
int pitch;
int ncol;
if (read_bmfileheader (fp, &fileheader) != 0) {
return ERR_BMP_IMAGE_TYPE;
}
biSize = fp_igetl (fp);
if (biSize >= WININFOHEADERSIZE) {
if (read_win_bminfoheader (fp, &infoheader) != 0) {
return ERR_BMP_LOAD;
}
MGUI_RWseek (fp, biSize - WININFOHEADERSIZE, SEEK_CUR);
/* compute number of colors recorded */
ncol = (fileheader.bfOffBits - biSize - 14) / 4;
read_bmicolors (ncol, pal, fp, 1);
}
else if (biSize == OS2INFOHEADERSIZE) {
if (read_os2_bminfoheader (fp, &infoheader) != 0) {
return ERR_BMP_LOAD;
}
/* compute number of colors recorded */
ncol = (fileheader.bfOffBits - 26) / 3;
read_bmicolors (ncol, pal, fp, 0);
}
else
return ERR_BMP_LOAD;
/* Compute the size and pitch of the image */
if (infoheader.biBitCount == 16)
effect_depth = 24;
else
effect_depth = infoheader.biBitCount;
bmpComputePitch (effect_depth, infoheader.biWidth, &pitch, TRUE);
biSize = pitch * infoheader.biHeight;
if( !(bits = malloc (biSize)) ) {
return ERR_BMP_MEM;
}
bmp->bits = bits;
bmp->flags = MYBMP_TYPE_BGR | MYBMP_FLOW_UP;
switch (infoheader.biCompression) {
case BI_BITFIELDS: /* ignore the bit fileds */
MGUI_RWseek (fp, -16, SEEK_CUR);
rmask = fp_igetl (fp);
gmask = fp_igetl (fp);
bmask = fp_igetl (fp);
//fprintf (stderr, "__mg_load_bmp: discard the bit masks: %lx, %lx, %lx.\n", rmask, gmask, bmask);
case BI_RGB:
if (infoheader.biBitCount == 16) {
bmp->flags |= MYBMP_RGBSIZE_3;
read_16bit_image (fp, bits, pitch, &infoheader, gmask);
}
else if (infoheader.biBitCount == 32) {
bmp->flags |= MYBMP_RGBSIZE_4;
MGUI_RWread (fp, bits, sizeof(char), biSize);
}
else {
bmp->flags |= MYBMP_RGBSIZE_3;
MGUI_RWread (fp, bits, sizeof(char), biSize);
}
break;
case BI_RLE8:
read_RLE8_compressed_image (fp, bits, pitch, &infoheader);
break;
case BI_RLE4:
read_RLE4_compressed_image (fp, bits, pitch, &infoheader);
break;
default:
return ERR_BMP_NOT_SUPPORTED;
}
bmp->depth = effect_depth;
bmp->w = infoheader.biWidth;
bmp->h = infoheader.biHeight;
bmp->pitch = pitch;
bmp->frames = 1;
bmp->size = biSize;
return ERR_BMP_OK;
}
BOOL __mg_check_bmp (MG_RWops* fp)
{
WORD bfType = fp_igetw (fp);
if (bfType != 19778)
return FALSE;
return TRUE;
}
#ifdef _SAVE_BITMAP
static void bmpGet16CScanline (BYTE* bits, BYTE* scanline,
int pixels)
{
int i;
for (i = 0; i < pixels; i++) {
if (i % 2 == 0)
*scanline = (bits [i] << 4) & 0xF0;
else {
*scanline |= bits [i] & 0x0F;
scanline ++;
}
}
}
static inline void bmpGet256CScanline (BYTE* bits, BYTE* scanline,
int pixels)
{
memcpy (scanline, bits, pixels);
}
inline void pixel2rgb (gal_pixel pixel, GAL_Color* color, int depth)
{
switch (depth) {
case 24:
case 32:
color->r = (gal_uint8) ((pixel >> 16) & 0xFF);
color->g = (gal_uint8) ((pixel >> 8) & 0xFF);
color->b = (gal_uint8) (pixel & 0xFF);
break;
case 15:
color->r = (gal_uint8)((pixel & 0x7C00) >> 7) | 0x07;
color->g = (gal_uint8)((pixel & 0x03E0) >> 2) | 0x07;
color->b = (gal_uint8)((pixel & 0x001F) << 3) | 0x07;
break;
case 16:
color->r = (gal_uint8)((pixel & 0xF800) >> 8) | 0x07;
color->g = (gal_uint8)((pixel & 0x07E0) >> 3) | 0x03;
color->b = (gal_uint8)((pixel & 0x001F) << 3) | 0x07;
break;
}
}
static void bmpGetHighCScanline (BYTE* bits, BYTE* scanline,
int pixels, int bpp, int depth)
{
int i;
gal_pixel c;
GAL_Color color;
for (i = 0; i < pixels; i++) {
c = *((gal_pixel*)bits);
pixel2rgb (c, &color, depth);
*(scanline) = color.b;
*(scanline + 1) = color.g;
*(scanline + 2) = color.r;
bits += bpp;
scanline += 3;
}
}
inline static int depth2bpp (int depth)
{
switch (depth) {
case 4:
case 8:
return 1;
case 15:
case 16:
return 2;
case 24:
return 3;
case 32:
return 4;
}
return 1;
}
int __mg_save_bmp (MG_RWops* fp, MYBITMAP* bmp, RGB* pal)
{
BYTE* scanline = NULL;
int i, bpp;
int scanlinebytes;
BITMAPFILEHEADER bmfh;
WINBMPINFOHEADER bmih;
memset (&bmfh, 0, sizeof (BITMAPFILEHEADER));
bmfh.bfType = MAKEWORD ('B', 'M');
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
memset (&bmih, 0, sizeof (WINBMPINFOHEADER));
bmih.biSize = (DWORD)(WININFOHEADERSIZE);
bmih.biWidth = (DWORD)(bmp->w);
bmih.biHeight = (DWORD)(bmp->h);
bmih.biPlanes = 1;
bmih.biCompression = BI_RGB;
bpp = depth2bpp (bmp->depth);
switch (bmp->depth) {
case 4:
scanlinebytes = (bmih.biWidth + 1)>>1;
scanlinebytes = ((scanlinebytes + 3)>>2)<<2;
#ifdef HAVE_ALLOCA
if (!(scanline = alloca (scanlinebytes))) return ERR_BMP_MEM;
#else
if (!(scanline = malloc (scanlinebytes))) return ERR_BMP_MEM;
#endif
memset (scanline, 0, scanlinebytes);
bmih.biSizeImage = (DWORD)(bmih.biHeight*scanlinebytes);
bmfh.bfOffBits = SIZEOF_BMFH + SIZEOF_BMIH
+ (SIZEOF_RGBQUAD<<4);
bmfh.bfSize = (DWORD)(bmfh.bfOffBits + bmih.biSizeImage);
bmih.biBitCount = 4;
bmih.biClrUsed = 16L;
bmih.biClrImportant = 16L;
MGUI_RWwrite (fp, &bmfh.bfType, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfSize, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmfh.bfReserved1, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfReserved2, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfOffBits, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biSize, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biWidth, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biHeight, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biPlanes, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmih.biBitCount, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmih.biCompression, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biSizeImage, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biXPelsPerMeter, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biYPelsPerMeter, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biClrUsed, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biClrImportant, sizeof (DWORD), 1);
for (i = 0; i < 16; i++) {
RGBQUAD rgbquad;
rgbquad.rgbRed = pal [i].r;
rgbquad.rgbBlue = pal [i].b;
rgbquad.rgbGreen = pal [i].g;
MGUI_RWwrite (fp, &rgbquad, sizeof (char), sizeof (RGBQUAD));
}
for (i = bmp->h - 1; i >= 0; i--) {
bmpGet16CScanline (bmp->bits + i * bmp->pitch, scanline, bmp->w);
MGUI_RWwrite (fp, scanline, sizeof (char), scanlinebytes);
}
break;
case 8:
scanlinebytes = bmih.biWidth;
scanlinebytes = ((scanlinebytes + 3)>>2)<<2;
#ifdef HAVE_ALLOCA
if (!(scanline = alloca (scanlinebytes))) return ERR_BMP_MEM;
#else
if (!(scanline = malloc (scanlinebytes))) return ERR_BMP_MEM;
#endif
memset (scanline, 0, scanlinebytes);
bmih.biSizeImage = bmih.biHeight*scanlinebytes;
bmfh.bfOffBits = SIZEOF_BMFH + SIZEOF_BMIH
+ (SIZEOF_RGBQUAD<<8);
bmfh.bfSize = bmfh.bfOffBits + bmih.biSizeImage;
bmih.biBitCount = 8;
bmih.biClrUsed = 256;
bmih.biClrImportant = 256;
MGUI_RWwrite (fp, &bmfh.bfType, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfSize, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmfh.bfReserved1, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfReserved2, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfOffBits, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biSize, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biWidth, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biHeight, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biPlanes, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmih.biBitCount, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmih.biCompression, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biSizeImage, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biXPelsPerMeter, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biYPelsPerMeter, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biClrUsed, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biClrImportant, sizeof (DWORD), 1);
for (i = 0; i < 256; i++) {
RGBQUAD rgbquad;
rgbquad.rgbRed = pal [i].r;
rgbquad.rgbBlue = pal [i].b;
rgbquad.rgbGreen = pal [i].g;
MGUI_RWwrite (fp, &rgbquad, sizeof (char), sizeof (RGBQUAD));
}
for (i = bmp->h - 1; i >= 0; i--) {
bmpGet256CScanline (bmp->bits + bmp->pitch * i, scanline, bmp->w);
MGUI_RWwrite (fp, scanline, sizeof (char), scanlinebytes);
}
break;
default:
scanlinebytes = bmih.biWidth*3;
scanlinebytes = ((scanlinebytes + 3)>>2)<<2;
#ifdef HAVE_ALLOCA
if (!(scanline = alloca (scanlinebytes))) return ERR_BMP_MEM;
#else
if (!(scanline = malloc (scanlinebytes))) return ERR_BMP_MEM;
#endif
memset (scanline, 0, scanlinebytes);
bmih.biSizeImage = bmih.biHeight*scanlinebytes;
bmfh.bfOffBits = SIZEOF_BMFH + SIZEOF_BMIH;
bmfh.bfSize = bmfh.bfOffBits + bmih.biSizeImage;
bmih.biBitCount = 24;
MGUI_RWwrite (fp, &bmfh.bfType, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfSize, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmfh.bfReserved1, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfReserved2, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmfh.bfOffBits, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biSize, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biWidth, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biHeight, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biPlanes, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmih.biBitCount, sizeof (WORD), 1);
MGUI_RWwrite (fp, &bmih.biCompression, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biSizeImage, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biXPelsPerMeter, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biYPelsPerMeter, sizeof (LONG), 1);
MGUI_RWwrite (fp, &bmih.biClrUsed, sizeof (DWORD), 1);
MGUI_RWwrite (fp, &bmih.biClrImportant, sizeof (DWORD), 1);
for (i = bmp->h - 1; i >= 0; i--) {
bmpGetHighCScanline (bmp->bits + i * bmp->pitch, scanline,
bmp->w, bpp, bmp->depth);
MGUI_RWwrite (fp, scanline, sizeof (char), scanlinebytes);
}
break;
}
#ifndef HAVE_ALLOCA
free (scanline);
#endif
return ERR_BMP_OK;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -