📄 bmp.c
字号:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <dos.h>
#include <malloc.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include "bbgui.h"
#define BUF_SIZE 0xc000 //分配16K*3内存堆栈
#define bbBLACK 0x00 //黑色
#define bbLIGHTBLUE 0x03 //浅蓝
#define bbLIGHTGREEN 0x1c //浅绿
#define bbLIGHTCYAN 0x1f //雪青
#define bbLIGHTRED 0xe0 //浅红
#define bbLIGHTMAGENTA 0xe3 //粉色
#define bbBROWN 0xd0 //0x90//棕色
#define bbLIGHTGRAY 0x92 //浅灰
#define bbDARKGRAY 0x49 //深灰
#define bbBLUE 0x02 //蓝色
#define bbGREEN 0x18 //0x1c//绿色
#define bbCYAN 0x12 //青色
#define bbRED 0xc0 //0xe0//红色
#define bbMAGENTA 0x82 //洋红
#define bbYELLOW 0xfc //黄色
#define bbWHITE 0xFF //白色
struct time t,tt; //全局变量,用来存放系统时间
//位头文件头,共占用14个字节。
//位图文件头包含文件类型、文件大小、存放位置等信息。
typedef struct
{
int bfType; //表明位图文件的类型,该值必需是0x4D42('BM')
long bfSize; //表明位图文件的大小,以字节为单位
int bfReserved1; //属于保留字,必须为本0
int bfReserved2; //也是保留字,必须为本0
long bfOffBits; //表明从文件头开始到实际的图象数据之间的字节的偏移量
//因为位图信息头和调色板的长度会根据不同情况而变化,
//所以你可以用这个偏移值迅速的从文件中读取到位数据以字节为单位
}BITMAPFILEHEADER;
//位头信息由位头信息头和彩色表组成
//位头信息头,共占用40个字节。
//位图信息头包含位图的大小、压缩类型、和颜色格式
typedef struct
{
long biSize; //指出本数据结构所需要的字节数
long biWidth; //以象素为单位,给出BMP图象的宽度
long biHeight; //以象素为单位,给出BMP图象的高度
//同时也说明该图像是倒向还是正向的位图。如果该值是一个正数,说明图像是倒向的
//如果该值是一个负数,则说明图像是正向的。(大多数的BMP文件都是倒向的位图)
//当高度值是一个负数时(正向图像),图像将不能被压缩(也就是说biCompression成员将不能是BI_RLE8或BI_RLE4)
int biPlanes; //输出设备的位平面数,必须置为1
int biBitCount; //给出每个象素的位数,单色为1,256色为8,24位色为24
long biCompress; //给出位图的压缩类型
//0:表示无压缩(BI_RGB)
//1:表示8位RLE压缩(BI_RLE8)每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);
//2:表示4位RLE压缩(BI_RLE4)每个象素4比特的RLE压缩编码,压缩格式由2字节组成
//3:表示Bitfields-位域存放方式(BI_BITFIELDS)每个象素的比特由指定的掩码决定
long biSizeImage; //给出图象字节数的多少,无压缩为0
long biXPelsPerMeter; //图像的水平分辨率
long biYPelsPerMeter; //图象的垂直分辨率
long biClrUsed; //調色板中图象实际使用的颜色素数
long biClrImportant; //给出重要颜色的索引值
}BITMAPINFOHEADER;
//位图彩色表,点用4的倍的字字。
//彩色表包含的元素与位图所具有的颜色数目相同,
//像素颜色用结构RGBQUAD来表示
typedef struct tagRGBQUAD
{
unsigned char rgbBlue; //兰色的强度
unsigned char rgbGreen; //绿色的强度
unsigned char rgbRed; //红色的强度
unsigned char rgbReserved; //保留,设为0
}RGBQUAD;
//紧跟在彩色表后的是图像数据阵列,
//图像每一扫描行有连续的字节组成,
//扫描行由底向上存储,阵列中第一字节为左下角像素,
//最后一字节为右上角像素。
typedef struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColor[ ];
}BITMAPINFO;
/****************************************************************
函数名称: int PutBmp(int x,int y,int page,char *fpath);
功能描述: 将真彩24位的BMP文件读出,将图片存放在显存中,最大图片1024*768
参数: 图片的起始位置,图片存放的页,显示图片文件路径名称
日期:
****************************************************************/
int PutBmp(int x,int y,int mode,char *fpath)
{
BITMAPFILEHEADER BitHeader; //BMP文件结构的头
BITMAPINFOHEADER BitInfoHeader; //BMP位图信息头
FILE *Fp; //BMP文件指针
unsigned char far *PBmp; //内存堆栈指针
unsigned int far *Mp; //显存指针
long FOffset; //指针偏移量
long Size = 0; //累加数据指针的长度
unsigned long h = 0; //行循环计数变量
unsigned long w = 0; //列循环计数变量
unsigned char temp;
unsigned long j=0;
//打开需要显示的BMP文件
Fp = fopen(fpath,"rb");
if(Fp== NULL)
{
printf("can not open BMP files");
return -1;
}
//打开BMP位图文件头
fread(&BitHeader,sizeof(BitHeader),1,Fp);
//读BMP文件信息,判断文件的合法性。
if(BitHeader.bfType !='M'*256+'B')
{
printf("This Is Not A Bmp File.\n");
fclose(Fp);
return -1;
}
//打开BMP位图信息头
fread(&BitInfoHeader,sizeof(BitInfoHeader),1,Fp);
//24位色限定(只能识别真彩24位)
if(BitInfoHeader.biBitCount != 24)
{
printf("This Programme Only For 24bit Colors Bitmap.\n");
fclose(Fp);
return -1;
}
//压缩限定(识别无压缩格式)
if(BitInfoHeader.biCompress!=0)
{
printf("This Programme Only For no rar Bitmap.\n");
fclose(Fp);
return -1;
}
//图片大小限定最大1024*768
if(BitInfoHeader.biWidth > 1024 || BitInfoHeader.biHeight > 768)
{
printf("Bitmap is too big.\n");
fclose(Fp);
return -1;
}
//定位到文件尾,扫描行由底向上存储,阵列中第一字节为左下角像素,最后一字节为右上角像素。
fseek(Fp,0,SEEK_END);
//分配一个16K大小的内存堆栈,当系统没有这么大的用户内存时退出。
//图片是分窗口显于,一个窗口的大小为16K。
PBmp = NULL;
PBmp = (unsigned char far *)farmalloc(BUF_SIZE);
if(PBmp == NULL)
{
printf("Memory is small.\n");
fclose(Fp);
return -1;
}
//算出图片的首地址。
Size=(unsigned long)y*GUI_WIDTH*2+(unsigned long)x*2;
for(h = 1;h<BitInfoHeader.biHeight;h++)
{
//计算出指针的偏移量,指针从最后住前偏移。
//地址为偶地址方式,所以采用了下面的偶地址对齐方式。
//一行的宽度=像素宽度*色彩数*32/4
FOffset = h*(((BitInfoHeader.biWidth*BitInfoHeader.biBitCount+31)>>5)<<2);
fseek(Fp,0-FOffset,SEEK_END);
//读出一行的数据。
fread((void far *)PBmp,BitInfoHeader.biWidth*3,1,Fp);
//将真彩24位的数据转换成真彩16位,高位为0,R=5,G=5,B=5。
for (w=0;w<BitInfoHeader.biWidth;w++)
{
if (BitInfoHeader.biSizeImage!=0)
{
//现在是将R B G型的BMP文件转换成B G R方式存放在指针中,然后由指针存放在显存中
//用Photo处理过的图片是这种特性。
temp=*(PBmp+3*w+0);
*(PBmp+3*w+0)=*(PBmp+3*w+1);
*(PBmp+3*w+1)=temp;
temp=*(PBmp+3*w+1);
*(PBmp+3*w+1)=*(PBmp+3*w+2);
*(PBmp+3*w+2)=temp;
}
//现在是将B G R型的BMP文件转换成R G B方式存放在显存中
//用ACDSee处理过的图片是这种特性。
*(PBmp+w+0)=((*(PBmp+w*3+0)&0xc0)>>6)+((*(PBmp+w*3+1)&0xe0)>>3)+(*(PBmp+w*3+2)&0xe0);
}
//LcdBmpFloat(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
switch(mode)
{
case 0: GuiBmp(0,h-1,BitInfoHeader.biWidth,h-1,PBmp);
break;
case 1: GuiBmpXor(0,h-1,BitInfoHeader.biWidth,h-1,PBmp);
break;
case 2: GuiBmpOr(0,h-1,BitInfoHeader.biWidth,h-1,PBmp);
break;
case 3: GuiBmpAnd(0,h-1,BitInfoHeader.biWidth,h-1,PBmp);
break;
case 4: GuiBmpNot(0,h-1,BitInfoHeader.biWidth,h-1);
break;
case 5: GuiBmpAlpha(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
break;
case 6: GuiBmpFloat(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
break;
case 7: GuiBmpFloatAnd(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
break;
case 8: GuiBmpFloatXor(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
break;
case 9: GuiBmpFloatOr(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
break;
case 10: GuiBmpFloatNot(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA);
break;
case 11: GuiBmpFloatAlpha(0,h-1,BitInfoHeader.biWidth,h-1,PBmp,bbMAGENTA,bbMAGENTA);
break;
}
}
farfree(PBmp);
fclose(Fp);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -