📄 winbmp.c
字号:
/* $Id: winbmp.c,v 1.14 2004/10/19 07:34:54 weiym Exp $
**
** Low-level Windows bitmap read/save function.
**
** Copyright (C) 2003 Feynman Software.
** Copyright (C) 2000 ~ 2002 Wei Yongming.
**
** Create date: 2000/08/26, derived from original bitmap.c
**
** Current maintainer: Wei Yongming.
*/
/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "gdi.h"
#include "readbmp.h"
/************************* Bitmap-related structures ************************/
typedef struct tagRGBTRIPLE
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} RGBTRIPLE;
typedef RGBTRIPLE* PRGBTRIPLE;
typedef struct tagRGBQUAD
{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
typedef RGBQUAD* PRGBQUAD;
#define SIZEOF_RGBQUAD 4
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#define SIZEOF_BMFH 14
#define SIZEOF_BMIH 40
#define OS2INFOHEADERSIZE 12
#define WININFOHEADERSIZE 40
typedef struct BITMAPFILEHEADER
{
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER;
/* Used for both OS/2 and Windows BMP.
* Contains only the parameters needed to load the image
*/
typedef struct BITMAPINFOHEADER
{
unsigned long biWidth;
unsigned long biHeight;
unsigned short biBitCount;
unsigned long biCompression;
} BITMAPINFOHEADER;
typedef struct WINBMPINFOHEADER /* size: 40 */
{
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
unsigned long biXPelsPerMeter;
unsigned long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} WINBMPINFOHEADER;
typedef struct OS2BMPINFOHEADER /* size: 12 */
{
unsigned long biSize;
unsigned short biWidth;
unsigned short biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
} OS2BMPINFOHEADER;
/* read_bmfileheader:
* Reads a BMP file header and check that it has the BMP magic number.
*/
static int read_bmfileheader(MG_RWops *f, BITMAPFILEHEADER *fileheader)
{
fileheader->bfType = fp_igetw(f);
fileheader->bfSize= fp_igetl(f);
fileheader->bfReserved1= fp_igetw(f);
fileheader->bfReserved2= fp_igetw(f);
fileheader->bfOffBits= fp_igetl(f);
if (fileheader->bfType != 19778)
return -1;
return 0;
}
/* read_win_bminfoheader:
* Reads information from a BMP file header.
*/
static int read_win_bminfoheader(MG_RWops *f, BITMAPINFOHEADER *infoheader)
{
WINBMPINFOHEADER win_infoheader;
win_infoheader.biWidth = fp_igetl(f);
win_infoheader.biHeight = fp_igetl(f);
win_infoheader.biPlanes = fp_igetw(f);
win_infoheader.biBitCount = fp_igetw(f);
win_infoheader.biCompression = fp_igetl(f);
win_infoheader.biSizeImage = fp_igetl(f);
win_infoheader.biXPelsPerMeter = fp_igetl(f);
win_infoheader.biYPelsPerMeter = fp_igetl(f);
win_infoheader.biClrUsed = fp_igetl(f);
win_infoheader.biClrImportant = fp_igetl(f);
infoheader->biWidth = win_infoheader.biWidth;
infoheader->biHeight = win_infoheader.biHeight;
infoheader->biBitCount = win_infoheader.biBitCount;
infoheader->biCompression = win_infoheader.biCompression;
return 0;
}
/* read_os2_bminfoheader:
* Reads information from an OS/2 format BMP file header.
*/
static int read_os2_bminfoheader(MG_RWops *f, BITMAPINFOHEADER *infoheader)
{
OS2BMPINFOHEADER os2_infoheader;
os2_infoheader.biWidth = fp_igetw(f);
os2_infoheader.biHeight = fp_igetw(f);
os2_infoheader.biPlanes = fp_igetw(f);
os2_infoheader.biBitCount = fp_igetw(f);
infoheader->biWidth = os2_infoheader.biWidth;
infoheader->biHeight = os2_infoheader.biHeight;
infoheader->biBitCount = os2_infoheader.biBitCount;
infoheader->biCompression = 0;
return 0;
}
/* read_bmicolors:
* Loads the color palette for 1,4,8 bit formats.
*/
static void read_bmicolors (int ncols, RGB *pal, MG_RWops *f, int win_flag)
{
int i;
for (i=0; i<ncols; i++) {
pal[i].b = fp_getc(f);
pal[i].g = fp_getc(f);
pal[i].r = fp_getc(f);
if (win_flag)
fp_getc(f);
}
}
/* read_RLE8_compressed_image:
* For reading the 8 bit RLE compressed BMP image format.
*/
static void read_RLE8_compressed_image (MG_RWops *f, BYTE *bits, int pitch, BITMAPINFOHEADER *infoheader)
{
unsigned char count, val, val0;
int j, pos, line;
int eolflag, eopicflag;
eopicflag = 0;
line = infoheader->biHeight - 1;
while (eopicflag == 0) {
pos = 0; /* x position in bitmap */
eolflag = 0; /* end of line flag */
while ((eolflag == 0) && (eopicflag == 0)) {
count = fp_getc(f);
val = fp_getc(f);
if (count > 0) { /* repeat pixel count times */
for (j=0;j<count;j++) {
bits [pos] = val;
pos++;
}
}
else {
switch (val) {
case 0: /* end of line flag */
eolflag=1;
break;
case 1: /* end of picture flag */
eopicflag=1;
break;
case 2: /* displace picture */
count = fp_getc(f);
val = fp_getc(f);
pos += count;
line -= val;
break;
default: /* read in absolute mode */
for (j=0; j<val; j++) {
val0 = fp_getc(f);
bits [pos] = val0;
pos++;
}
if (j%2 == 1)
val0 = fp_getc(f); /* align on word boundary */
break;
}
}
if (pos-1 > (int)infoheader->biWidth)
eolflag=1;
}
bits += pitch;
line--;
if (line < 0)
eopicflag = 1;
}
}
/* read_RLE4_compressed_image:
* For reading the 4 bit RLE compressed BMP image format.
*/
static void read_RLE4_compressed_image (MG_RWops *f, BYTE *bits, int pitch, BITMAPINFOHEADER *infoheader)
{
unsigned char b[8];
unsigned char count;
unsigned short val0, val;
int j, k, pos, line;
int eolflag, eopicflag;
eopicflag = 0; /* end of picture flag */
line = infoheader->biHeight - 1;
while (eopicflag == 0) {
pos = 0;
eolflag = 0; /* end of line flag */
while ((eolflag == 0) && (eopicflag == 0)) {
count = fp_getc(f);
val = fp_getc(f);
if (count > 0) { /* repeat pixels count times */
b[1] = val & 15;
b[0] = (val >> 4) & 15;
for (j=0; j<count; j++) {
if (pos % 2 == 0)
bits [pos/2] = b[j%2] << 4;
else
bits [pos/2] = bits [pos/2] | b[j%2];
pos++;
}
}
else {
switch (val) {
case 0: /* end of line */
eolflag=1;
break;
case 1: /* end of picture */
eopicflag=1;
break;
case 2: /* displace image */
count = fp_getc(f);
val = fp_getc(f);
pos += count;
line -= val;
break;
default: /* read in absolute mode */
for (j=0; j<val; j++) {
if ((j%4) == 0) {
val0 = fp_igetw(f);
for (k=0; k<2; k++) {
b[2*k+1] = val0 & 15;
val0 = val0 >> 4;
b[2*k] = val0 & 15;
val0 = val0 >> 4;
}
}
if (pos % 2 == 0)
bits [pos/2] = b[j%4] << 4;
else
bits [pos/2] = bits [pos/2] | b[j%4];
pos++;
}
break;
}
}
if (pos-1 > (int)infoheader->biWidth)
eolflag=1;
}
bits += pitch;
line--;
if (line < 0)
eopicflag = 1;
}
}
/* read_16bit_image:
* For reading the 16-bit BMP image format.
* This only support bit masks specific to Windows 95.
*/
static void read_16bit_image (MG_RWops *f, BYTE *bits, int pitch, BITMAPINFOHEADER *infoheader, DWORD gmask)
{
int i, j;
WORD pixel;
BYTE *line;
for (i = 0; i < infoheader->biHeight; i++) {
line = bits;
for (j = 0; j < infoheader->biWidth; j++) {
pixel = fp_igetw (f);
if (gmask == 0x03e0) /* 5-5-5 */
{
line [2] = ((pixel >> 10) & 0x1f) << 3;
line [1] = ((pixel >> 5) & 0x1f) << 3;
line [0] = (pixel & 0x1f) << 3;
}
else /* 5-6-5 */
{
line [2] = ((pixel >> 11) & 0x1f) << 3;
line [1] = ((pixel >> 5) & 0x3f) << 2;
line [0] = (pixel & 0x1f) << 3;
}
line += 3;
}
if (infoheader->biWidth & 0x01)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -