📄 bitmap.cpp
字号:
#include "graphics.h"
// 建立一个位图
BMP* create_bitmap(int w, int h, WORD c)
{
BMP *bmp;
bmp = (BMP *)malloc(sizeof(BMP));
put_message(bmp == NULL, "错误,没有足够的内存。");
bmp->type = NORMAL_BITMAP;
bmp->width = w;
bmp->height = h;
bmp->pitch_byte = w * 2;
bmp->pitch_word = w;
bmp->pitch_dword = w / 2;
bmp->surface_byte = w * h * 2;
bmp->surface_word = w * h;
bmp->surface_dword = w * h / 2;
bmp->clipleft = 0;
bmp->cliptop = 0;
bmp->clipright = w - 1;
bmp->clipbottom = h - 1;
if (Is555)
bmp->pixelbitcount = 15;
else
bmp->pixelbitcount = 16;
bmp->colorkey = 0x0;
bmp->bit = (WORD *)malloc(w * h * 2);
put_message(bmp->bit == NULL, "错误,没有足够的内存。");
bmp->draw_x = bmp->draw_y = 0;
bmp->draw_ptr = bmp->bit;
clrscr_bitmap(bmp, c);
return bmp;
}
// 建立一个位图(不预先填充颜色)
BMP* create_bitmap(int w, int h)
{
BMP *bmp;
bmp = (BMP *)malloc(sizeof(BMP));
put_message(bmp == NULL, "错误,没有足够的内存。");
bmp->type = NORMAL_BITMAP;
bmp->width = w;
bmp->height = h;
bmp->pitch_byte = w * 2;
bmp->pitch_word = w;
bmp->pitch_dword = w / 2;
bmp->surface_byte = w * h * 2;
bmp->surface_word = w * h;
bmp->surface_dword = w * h / 2;
bmp->clipleft = 0;
bmp->cliptop = 0;
bmp->clipright = w - 1;
bmp->clipbottom = h - 1;
if (Is555)
bmp->pixelbitcount = 15;
else
bmp->pixelbitcount = 16;
bmp->colorkey = 0x0;
bmp->bit = (WORD *)malloc(w * h * 2);
put_message(bmp->bit == NULL, "错误,没有足够的内存。");
bmp->draw_x = bmp->draw_y = 0;
bmp->draw_ptr = bmp->bit;
return bmp;
}
// 建立镜像位图
BMP *create_mirror_bitmap(BMP *src_bmp)
{
BMP *bmp;
bmp = (BMP *)malloc(sizeof(BMP));
put_message(bmp == NULL, "错误,没有足够的内存。");
bmp->type = NORMAL_BITMAP;
bmp->width = src_bmp->width;
bmp->height = src_bmp->height;
bmp->pitch_byte = src_bmp->pitch_byte;
bmp->pitch_word = src_bmp->pitch_word;
bmp->pitch_dword = src_bmp->pitch_dword;
bmp->surface_byte = src_bmp->surface_byte;
bmp->surface_word = src_bmp->surface_word;
bmp->surface_dword = src_bmp->surface_dword;
bmp->clipleft = src_bmp->clipleft;
bmp->cliptop = src_bmp->cliptop;
bmp->clipright = src_bmp->clipright;
bmp->clipbottom = src_bmp->clipbottom;
bmp->pixelbitcount = src_bmp->pixelbitcount;
bmp->colorkey = src_bmp->colorkey;
bmp->bit = (WORD *)malloc(src_bmp->surface_byte);
put_message(bmp->bit == NULL, "错误,没有足够的内存。");
bmp->draw_x = src_bmp->draw_x;
bmp->draw_y = src_bmp->draw_y;
bmp->draw_ptr = src_bmp->draw_ptr;
draw_bitmap(bmp, 0, 0, src_bmp);
return bmp;
}
// 建立指针位图
BMP *create_ptr_bitmap(int w, int h, WORD *p)
{
BMP *bmp;
bmp = (BMP *)malloc(sizeof(BMP));
put_message(bmp == NULL, "错误,没有足够的内存。");
bmp->type = PTR_BITMAP;
bmp->width = w;
bmp->height = h;
bmp->pitch_byte = w * 2;
bmp->pitch_word = w;
bmp->pitch_dword = w / 2;
bmp->surface_byte = w * h * 2;
bmp->surface_word = w * h;
bmp->surface_dword = w * h / 2;
bmp->clipleft = 0;
bmp->cliptop = 0;
bmp->clipright = w - 1;
bmp->clipbottom = h - 1;
if (Is555)
bmp->pixelbitcount = 15;
else
bmp->pixelbitcount = 16;
bmp->colorkey = 0x0;
bmp->bit = p;
bmp->draw_x = bmp->draw_y = 0;
bmp->draw_ptr = bmp->bit;
return bmp;
}
// 交换位图
void swap_bitmap(BMP **bmp1, BMP **bmp2)
{
put_message(bmp1 == NULL || bmp2 == NULL, "错误,企图对不存在的位图进行操作。");
BMP **temp;
temp = bmp1;
bmp1 = bmp2;
bmp2 = temp;
}
// 释放一个位图
void free_bitmap(BMP **bmp)
{
BMP *b = *bmp;
if (b == NULL)
return;
if (b->type != PTR_BITMAP)
{
if (b->bit != NULL)
free(b->bit);
}
free(b);
*bmp = NULL;
}
// 计算颜色值
WORD create_color(WORD r, WORD g, WORD b)
{
_asm
{
CMP Is555, 1;
JZ _is_555;
MOV ax, r;
AND ax, 0x1f;
MOV bx, g;
AND bx, 0x3f;
MOV cx, b;
AND cx, 0x1f;
SHL ax, 11;
SHL bx, 5;
JMP _create_end;
_is_555:
MOV ax, r;
AND ax, 0x1f;
MOV bx, g;
AND bx, 0x1f;
MOV cx, b;
AND cx, 0x1f;
SHL ax, 10;
SHL bx, 5;
_create_end:
OR ax, bx;
OR ax, cx;
MOV r, ax;
}
return r;
}
// 将一种颜色值从555转换到565
WORD con_555_to_565(WORD c)
{
return ((c << 1) & 0xffe0) | (c & 0x1f);
}
// 将一种颜色值从565转换到555
WORD con_565_to_555(WORD c)
{
return ((c >> 1) & 0xffe0) | (c & 0x1f);
}
// 将555格式的图像转换为565
void image_to_565(BMP* bmp)
{
put_message(bmp == NULL,
"错误,企图对不存在的位图进行操作。");
WORD color1, color2;
_asm
{
PUSH esi;
MOV ebx, bmp;
CMP [ebx]BMP.pixelbitcount, 15;
JZ _image_con_565_end;
MOV ecx, [ebx]BMP.surface_word;
MOV esi, [ebx]BMP.bit;
ALIGN 4
_con_loop:
MOV ax, [esi];
MOV color1, ax;
MOV color2, ax;
SHL color1, 1;
AND color1, 0xffe0;
AND color2, 0x1f;
MOV ax, color1;
OR ax, color2;
SUB esi, 2;
MOV [esi], ax;
INC esi;
ALIGN 4
LOOP _con_loop;
_image_con_565_end:
POP esi;
}
}
// 将565格式的图像转换为555
void image_to_555(BMP* bmp)
{
put_message(bmp == NULL,
"错误,企图对不存在的位图进行操作。");
WORD color1, color2;
_asm
{
PUSH esi;
MOV ebx, bmp;
CMP [ebx]BMP.pixelbitcount, 16;
JZ _image_con_565_end;
MOV ecx, [ebx]BMP.surface_word;
MOV esi, [ebx]BMP.bit;
ALIGN 4
_con_loop:
MOV ax, [esi];
MOV color1, ax;
MOV color2, ax;
SHR color1, 1;
AND color1, 0xffe0;
AND color2, 0x1f;
MOV ax, color1;
OR ax, color2;
SUB esi, 2;
MOV [esi], ax;
INC esi;
ALIGN 4
LOOP _con_loop;
_image_con_565_end:
POP esi;
}
}
// 读入一个标准WindowsBMP(8位色 或 24位色)
BMP *load_win_bitmap(LPSTR filename)
{
BMP *bmp;
FILE *fp;
if ((fp = fopen(filename, "rb")) == NULL)
put_message(TRUE,
"错误,文件%s不存在。", filename);
BITMAPFILEHEADER bmpheader; // 取BMP文件头信息
if (fread(&bmpheader, sizeof(bmpheader), 1, fp) == NULL)
{
fclose(fp);
put_message(TRUE,
"错误,读取文件头失败。");
}
if (bmpheader.bfType != 19778)
{
fclose(fp);
put_message(TRUE,
"错误,不是标准Windows BMP文件。");
}
BITMAPINFOHEADER bmpinfo;// 取BMP文件信息
if (fread(&bmpinfo, sizeof(bmpinfo), 1, fp) == NULL)
{
fclose(fp);
put_message(TRUE,
"错误,读取图象信息失败。");
}
if ((bmpinfo.biCompression != BI_RGB) || ((bmpinfo.biBitCount!=8)&&(bmpinfo.biBitCount != 24)))
{
fclose(fp); // 是否未压缩且为8 or 24位色
put_message(TRUE,
"错误,这个Windows BMP是已压缩的。");
}
bmp = new BMP;
put_message(bmp == NULL, "错误,没有足够的内存。");
bmp->height = bmpinfo.biHeight ;
bmp->width = bmpinfo.biWidth ;
bmp->cliptop = bmp->clipleft = 0;
bmp->clipright = bmp->width - 1;
bmp->clipbottom = bmp->height - 1;
bmp->pitch_byte = WORD(bmp->width << 1);
bmp->pitch_word = bmp->width;
bmp->pitch_dword = bmp->width / 2;
bmp->surface_byte = bmp->pitch_byte * bmp->height;
bmp->surface_word = bmp->pitch_word * bmp->height;
bmp->surface_dword = bmp->pitch_dword * bmp->height;
bmp->colorkey = 0x0;
bmp->bit = new WORD [bmp->surface_word];
if (Is555)
bmp->pixelbitcount = 15;
else
bmp->pixelbitcount = 16;
put_message(bmp->bit == NULL, "错误,没有足够的内存。");
if (bmpinfo.biBitCount == 8) // 8位色的处理
{
RGBQUAD *quad;
quad = new RGBQUAD[256];
if (quad == NULL)
{
fclose(fp);
put_message(TRUE,
"错误,没有足够的内存。");
return NULL;
}
WORD *pal;
pal = new WORD[256];
if (pal == NULL)
{
delete quad;
fclose(fp);
put_message(TRUE,
"错误,没有足够的内存。");
return NULL;
}
fread(quad, sizeof(RGBQUAD) * 256, 1, fp);
DWORD c;
for (int i = 0; i < 256; i++) // 调色板
{
c = ((((DWORD)quad[i].rgbRed) << 16) | (((DWORD)quad[i].rgbGreen) << 8) | ((DWORD)quad[i].rgbBlue));
pal[i] = true_to_hi(c);
}
for (int ii = 0; ii < 256; ii++)
pal[ii] = true_to_hi(*((DWORD *)(quad + ii)));
WORD* Offset = bmp->bit;
DWORD linesize;
BYTE* buffer;
linesize = (bmpinfo.biWidth + 3) & 0xfffffffc;
buffer = (BYTE *)malloc(linesize);
for (i = bmpinfo.biHeight - 1; i >= 0; i--)
{
Offset = bmp->bit + i * bmpinfo.biWidth ;
fread(buffer, linesize, 1, fp);
for (int j = 0; j < bmpinfo.biWidth; j++)
Offset[j] = pal[buffer[j]];
}
delete buffer;
Offset = NULL;
delete pal;
delete quad;
fclose(fp);
return bmp;
}
// 24位色处理
fseek(fp, bmpheader.bfOffBits, SEEK_SET);
int linesize = (bmpinfo.biWidth * 3 + 3) & 0xfffffffc;
BYTE *Buffer;
Buffer = new BYTE[linesize];
if (Buffer == NULL)
{
fclose(fp);
put_message(TRUE,
"错误,没有足够的内存。");
return NULL;
}
WORD *Offset;
for (int i = bmpinfo.biHeight - 1; i >= 0; i--)
{
fread(Buffer, linesize, 1, fp);
Offset = bmp->bit + i * bmpinfo.biWidth;
for (int j = 0; j < bmpinfo.biWidth; j++)
Offset[j] = true_to_hi((*(DWORD *)(Buffer + j * 3)));
}
delete Buffer;
Offset = NULL;
fclose(fp);
return bmp;
}
// 24位色--》15位色(555版)
WORD true_to_hi_555(DWORD color)
{
return WORD(((color >> 9) & 0x7c00) | ((color >> 6) & 0x3e0) | ((color >> 3) & 0x1f));
}
// 24位色--》16位色(565版)
WORD true_to_hi_565(DWORD color)
{
return (WORD)(((color >> 8) & 0xf800) | ((color >> 5) & 0x7e0) | ((color >> 3) & 0x1f));
}
// 15位色--》24位色(555版)
DWORD hi_to_true_555(WORD color)
{
return (DWORD)((((DWORD)color << 9) & 0xf80000) | (((DWORD)color << 6) & 0xf800) | (((DWORD)color << 3) & 0xf8));
}
// 16位色--》24位色(565版)
DWORD hi_to_true_565(WORD color)
{
return (DWORD)((((DWORD)color << 8) & 0xf80000) | (((DWORD)color << 5) & 0xfc00) | (((DWORD)color << 3) & 0xf8));
}
// 将位图存入磁盘
void write_to_file(BMP *bmp, char *filename)
{
FILE *fp;
fp = fopen(filename, "wb+");
put_message(fp == NULL, "错误,建立新文件失败。");
fwrite(bmp, sizeof(BMP), 1, fp);
fwrite(bmp->bit, bmp->surface_byte, 1, fp);
fclose(fp);
}
// 将位图文件读入
BMP *load_to_file(char *filename)
{
FILE *fp;
BMP *bmp;
bmp = new BMP;
fp = fopen(filename, "rb");
put_message(fp == NULL, "错误,打开位图文件失败。");
fread(bmp, sizeof(BMP), 1, fp);
char *buffer = new char [bmp->surface_byte];
fread(buffer, bmp->surface_byte, 1, fp);
bmp->bit = (WORD *)buffer;
if (bmp->pixelbitcount == 15 || !Is555)
image_to_565(bmp);
if (bmp->pixelbitcount == 16 || Is555)
image_to_555(bmp);
return bmp;
}
// 将位图存为标准Windows BMP文件
void write_win_bmp(BMP *bmp, char *filename)
{
FILE *fp;
BITMAPFILEHEADER bithead;
BITMAPINFOHEADER bitinfo;
int headsize, linesize, s;
unsigned long color;
linesize = (bmp->width * 3 + 3) & 0xfffffffc;
s = linesize - bmp->width * 3;
if ((fp = fopen(filename, "wb+")) == NULL)
{
put_message(fp == NULL, "错误,建立新文件失败。");
return;
}
headsize = sizeof(bithead) + sizeof(bitinfo);
bithead.bfType = 'MB';
bithead.bfSize = headsize + linesize * bmp->height;
bithead.bfReserved1 = bithead.bfReserved2 = 0;
bithead.bfOffBits = headsize;
fwrite(&bithead, 1, sizeof(bithead), fp);
bitinfo.biSize = sizeof(bitinfo);
bitinfo.biWidth = bmp->width;
bitinfo.biHeight = bmp->height;
bitinfo.biPlanes = 1;
bitinfo.biBitCount = 24;
bitinfo.biCompression = BI_RGB;
bitinfo.biSizeImage = 0;
bitinfo.biXPelsPerMeter = 72;
bitinfo.biYPelsPerMeter = 72;
bitinfo.biClrUsed = 0;
bitinfo.biClrImportant = 0;
fwrite(&bitinfo, 1, sizeof(bitinfo), fp);
for(int i = bmp->height - 1; i >= 0; i--)
{
for(int j = 0; j < bmp->width; j++)
{
color = hi_to_true(*(bmp->bit + i * bmp->width + j));
fwrite(&color, 1, 3, fp);
}
fwrite(&color, 1, s, fp);
}
fclose(fp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -