⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitmap.cpp

📁 vc写的源程序,是关于游戏类的程序。调用了系统的很多API
💻 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 + -