📄 fstbitmap.cpp
字号:
#include "graphics.h"
#define FST_PIXEL 0x1
#define FST_TRANS_COLOR 0x2
#define FST_LINE_END 0x3
#define FST_END 0x4
// 建立一个FST位图
FST_BMP *create_fst(BMP *bmp)
{
FST_BMP *fst_bmp;
fst_bmp = new FST_BMP;
put_message(fst_bmp == NULL, "错误,没有足够的内存。");
fst_bmp->width = bmp->width;
fst_bmp->height = bmp->height;
fst_bmp->pixelbitcount = bmp->pixelbitcount;
fst_bmp->colorkey = bmp->colorkey;
WORD *p_bmp = bmp->bit;
WORD *temp = new WORD [bmp->width * bmp->height * 2], *p_temp = temp;
WORD *buffer = new WORD [65535], *p_buffer;
if (temp == NULL)
{
delete fst_bmp;
put_message(TRUE, "错误,没有足够的内存。");
return NULL;
}
WORD c = 0;
for (DWORD i = 0; i < bmp->surface_word;)
{
c = 0;
p_buffer = buffer;
if (*p_bmp == bmp->colorkey)
{
// 压缩透明点
do
{
c++;
i++;
p_bmp++;
}while(c < 65535 && i < bmp->surface_word &&
*p_bmp == bmp->colorkey && i % bmp->width != 0);
if (i % bmp->width == 0)
*p_temp++ = FST_LINE_END;
else
{
*p_temp++ = FST_TRANS_COLOR;
*p_temp++ = c;
}
if (i >= bmp->surface_word)
{
*p_temp++ = FST_END;
break;
}
}
else
{
// 不透明的点的处理
do
{
c++;
i++;
*p_buffer++ = *p_bmp++;
}while(c < 65535 && i < bmp->surface_word &&
*p_bmp != bmp->colorkey && i % bmp->width != 0);
*p_temp++ = FST_PIXEL;
*p_temp++ = c;
memcpy(p_temp, buffer, c << 1);
p_temp += c;
if (i % bmp->width == 0)
*p_temp++ = FST_LINE_END;
if (i >= bmp->surface_word)
{
*p_temp++ = FST_END;
break;
}
}
}
DWORD size = (p_temp - temp) << 1;
fst_bmp->bit = new WORD [size >> 1];
memcpy(fst_bmp->bit, temp, size);
fst_bmp->surface_byte = size;
fst_bmp->surface_word = size >> 1;
fst_bmp->surface_dword = size >> 2;
delete temp;
delete buffer;
return fst_bmp;
}
// 将一个FST位图保存到文件
void write_fst_to_file(FST_BMP *fst, char *filename)
{
FILE *fp;
fp = fopen(filename, "wb+");
put_message(fp == NULL, "错误,建立新文件失败。");
fwrite(fst, sizeof(FST_BMP), 1, fp);
fwrite(fst->bit, fst->surface_byte, 1, fp);
fclose(fp);
}
// 释放FST位图所占的内存空间
void free_fst(FST_BMP **fst)
{
FST_BMP *f = *fst;
if (f == NULL)
return;
if (f->bit != NULL)
free(f->bit);
free(f);
*fst = NULL;
}
// 复制FST位图到BMP位图
void bitblt_fst(BMP *dest_bmp, int x, int y, FST_BMP *src_fst, int srcx, int srcy, int w, int h)
{
put_message(dest_bmp == NULL || src_fst == NULL,
"错误,企图对不存在的位图进行操作。");
_asm
{
#include "clipblit.inc"
}
if (w <= 0 || h <= 0)
return;
if (w == src_fst->width && h == src_fst->height)
{
// 没有需要剪裁的部分
DWORD offset_w;
_asm
{
PUSH edi;
PUSH esi;
MOV ebx, dest_bmp; // 把dest_bmp.bit的地址保存在edi
MOV edi, [ebx]BMP.bit;
MOV edx, src_fst; // 把src_bmp.bit的地址保存在edi
MOV esi, [edx]FST_BMP.bit;
ADD edi, x;
ADD edi, x;
PUSH edx;
MOV eax, y;
IMUL [ebx]BMP.pitch_byte;
ADD edi, eax;
POP edx;
MOV eax, [ebx]BMP.width;
SUB eax, [edx]FST_BMP.width;
SHL eax, 1;
MOV offset_w, eax;
MOV edx, [edx]FST_BMP.width;
MOV ebx, 0;
_loop_line:
LODSW;
CMP ax, FST_PIXEL;
JZ _pixel; // 不透明点处理
CMP ax, FST_TRANS_COLOR;
JZ _trans_color; // 透明点处理
CMP ax, FST_LINE_END;
JZ _line_end; // 行结束
CMP ax, FST_END;
JZ _bitblt_end; // FST文件结束
JMP _bitblt_end;
_pixel:
LODSW;
MOV ecx, 0;
MOV cx, ax;
ADD ebx, ecx;
REP MOVSW;
JMP _loop_line;
_trans_color:
MOV eax, 0;
LODSW;
ADD edi, eax;
ADD edi, eax;
ADD ebx, eax;
JMP _loop_line;
_line_end:
MOV eax, edx;
SUB eax, ebx;
SHL eax, 1;
ADD edi, eax;
ADD edi, offset_w;
MOV ebx, 0;
JMP _loop_line;
_bitblt_end:
POP esi;
POP edi;
}
}
else
{
// 有需要剪裁的
int i;
WORD *p = src_fst->bit, *pbmp = dest_bmp->bit;
if (srcy > 0)
{
// 剪裁上面的
for (i = 0; i < srcy; i++)
{
while(TRUE)
{
if (*p == FST_PIXEL)
{
p++;
p += *p;
p++;
}
else if (*p == FST_TRANS_COLOR)
{
p += 2;
}
else if (*p = FST_LINE_END)
{
p++;
break;
}
else if (*p == FST_END)
return;
}
}
}
// 复制FST位图
pbmp += y * dest_bmp->width;
if (x >= 0)
pbmp += x;
int size = dest_bmp->width - w, ew;
if (w == src_fst->width)
{
// 左右不须要剪裁
for (i = 0; i < h; i++)
{
ew = 0;
while(TRUE)
{
if (*p == FST_PIXEL)
{
p++;
WORD count;
count = *p;
p++;
memcpy(pbmp, p, count * 2);
p += count;
pbmp += count;
ew += count;
}
else if (*p == FST_TRANS_COLOR)
{
p++;
pbmp += *p;
ew += *p;
p++;
}
else if (*p == FST_LINE_END)
{
p++;
if (ew <= w)
{
int temp = w - ew;
pbmp += temp;
}
pbmp += size;
break;
}
else if (*p == FST_END)
{
return;
}
}
}
}
else
{
// 左右须要剪裁
for (i = 0; i < h; i++)
{
int left = 0;
ew = 0;
while(TRUE)
{
if (*p == FST_PIXEL)
{
p++;
WORD count;
count = *p;
p++;
for (int j = 0; j < count; j++)
{
if (ew >= srcx)
{
if (ew < w)
{
*pbmp++ = *p++;
left++;
}
else
p++;
}
else
p++;
ew++;
}
}
else if (*p == FST_TRANS_COLOR)
{
p++;
WORD count;
count = *p;
p++;
for (int j = 0; j < count; j++)
{
if (ew >= srcx)
{
if (ew < w)
{
pbmp++;
left++;
}
}
ew++;
}
}
else if (*p == FST_LINE_END)
{
p++;
if (left <= w)
{
int temp = w - left;
pbmp += temp;
}
pbmp += size;
break;
}
else if (*p == FST_END)
{
return;
}
}
}
}
}
}
// 复制FST位图到BMP位图(Additive方式555)
void additive_fst_565(BMP *dest_bmp, int x, int y, FST_BMP *src_fst, int srcx, int srcy, int w, int h)
{
put_message(dest_bmp == NULL || src_fst == NULL,
"错误,企图对不存在的位图进行操作。");
_asm
{
#include "clipblit.inc"
}
if (w <= 0 || h <= 0)
return;
if (w == src_fst->width && h == src_fst->height)
{
// 没有需要剪裁的部分
DWORD offset_w;
_asm
{
PUSH edi;
PUSH esi;
MOV ebx, dest_bmp; // 把dest_bmp.bit的地址保存在edi
MOV edi, [ebx]BMP.bit;
MOV edx, src_fst; // 把src_bmp.bit的地址保存在edi
MOV esi, [edx]FST_BMP.bit;
ADD edi, x;
ADD edi, x;
PUSH edx;
MOV eax, y;
IMUL [ebx]BMP.pitch_byte;
ADD edi, eax;
POP edx;
MOV eax, [ebx]BMP.width;
SUB eax, [edx]FST_BMP.width;
SHL eax, 1;
MOV offset_w, eax;
MOV edx, [edx]FST_BMP.width;
MOV ebx, 0;
_loop_line:
LODSW;
CMP ax, FST_PIXEL;
JZ _pixel; // 不透明点处理
CMP ax, FST_TRANS_COLOR;
JZ _trans_color; // 透明点处理
CMP ax, FST_LINE_END;
JZ _line_end; // 行结束
CMP ax, FST_END;
JZ _bitblt_end; // FST文件结束
JMP _bitblt_end;
_pixel:
LODSW;
MOV ecx, 0;
MOV cx, ax;
ADD ebx, ecx;
PUSH ebx;
_pixel_loop:
LODSW;
MOV bx, [edi];
AND ax, 0xf7bf; // 0111 0111 1101 1111
AND bx, 0xf7bf;
ADC ax, bx;
JNC _rnc;
OR ax, 0xf000;
_rnc:
TEST ax, 0x20; // 10 0000
JZ _bnc;
OR ax, 0x1f;
_bnc:
TEST ax, 0x800; // 1000 0000 0000
JZ _gnc;
OR ax, 0x7e0; // 111 1110 0000
_gnc:
STOSW;
LOOP _pixel_loop;
POP ebx;
JMP _loop_line;
_trans_color:
MOV eax, 0;
LODSW;
ADD edi, eax;
ADD edi, eax;
ADD ebx, eax;
JMP _loop_line;
_line_end:
MOV eax, edx;
SUB eax, ebx;
SHL eax, 1;
ADD edi, eax;
ADD edi, offset_w;
MOV ebx, 0;
JMP _loop_line;
_bitblt_end:
POP esi;
POP edi;
}
}
else
{
// 有需要剪裁的
int i;
WORD *p = src_fst->bit, *pbmp = dest_bmp->bit;
if (srcy > 0)
{
// 剪裁上面的
for (i = 0; i < srcy; i++)
{
while(TRUE)
{
if (*p == FST_PIXEL)
{
p++;
p += *p;
p++;
}
else if (*p == FST_TRANS_COLOR)
{
p += 2;
}
else if (*p = FST_LINE_END)
{
p++;
break;
}
else if (*p == FST_END)
return;
}
}
}
// 复制FST位图
pbmp += y * dest_bmp->width;
if (x >= 0)
pbmp += x;
int size = dest_bmp->width - w, ew;
if (w == src_fst->width)
{
// 左右不须要剪裁
for (i = 0; i < h; i++)
{
ew = 0;
while(TRUE)
{
if (*p == FST_PIXEL)
{
p++;
WORD count;
count = *p;
p++;
_asm
{
PUSH edi;
PUSH esi;
MOV edi, pbmp;
MOV esi, p;
MOV ecx, 0;
MOV cx, count;
_line_loopf:
LODSW;
MOV bx, [edi];
AND ax, 0xf7bf; // 0111 0111 1101 1111
AND bx, 0xf7bf;
ADC ax, bx;
JNC _rncf;
OR ax, 0xf000;
_rncf:
TEST ax, 0x20; // 10 0000
JZ _bncf;
OR ax, 0x1f;
_bncf:
TEST ax, 0x800; // 1000 0000 0000
JZ _gncf;
OR ax, 0x7e0; // 111 1110 0000
_gncf:
STOSW;
LOOP _line_loopf;
POP esi;
POP edi;
}
p += count;
pbmp += count;
ew += count;
}
else if (*p == FST_TRANS_COLOR)
{
p++;
pbmp += *p;
ew += *p;
p++;
}
else if (*p == FST_LINE_END)
{
p++;
if (ew <= w)
{
int temp = w - ew;
pbmp += temp;
}
pbmp += size;
break;
}
else if (*p == FST_END)
{
return;
}
}
}
}
else
{
// 左右须要剪裁
for (i = 0; i < h; i++)
{
int left = 0;
ew = 0;
while(TRUE)
{
if (*p == FST_PIXEL)
{
p++;
WORD count;
count = *p;
p++;
for (int j = 0; j < count; j++)
{
if (ew >= srcx)
{
if (ew < w)
{
_asm
{
PUSH edi;
PUSH esi;
MOV edi, pbmp;
MOV esi, p;
LODSW;
MOV bx, [edi];
AND ax, 0xf7bf; // 0111 0111 1101 1111
AND bx, 0xf7bf;
ADC ax, bx;
JNC _rncc;
OR ax, 0xf000;
_rncc:
TEST ax, 0x20; // 10 0000
JZ _bncc;
OR ax, 0x1f;
_bncc:
TEST ax, 0x800; // 1000 0000 0000
JZ _gncc;
OR ax, 0x7e0; // 111 1110 0000
_gncc:
STOSW;
POP esi;
POP edi;
}
pbmp++;
p++;
left++;
}
else
p++;
}
else
p++;
ew++;
}
}
else if (*p == FST_TRANS_COLOR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -