//原创:在800*600*64K真彩色模式下显示BMP图片和画点(显存指针采用int far)
//原创:在800*600*64K真彩色模式下显示BMP图片和画点//作者:成都理工学院
#include <dos.h>
#include <stdio.h>
#include <mem.h>
#include <alloc.h>
#include <stdlib.h>
#include <conio.h>
#define VBE800X600X64K 0X114
#define RGB(r,g,b) ((((unsigned int)(r)>>3)<<11) + (((unsigned int)(g)>>2)<<5) + ((b)>>3))
#define SCREEN_WIDTH 800L
#define SCREEN_HIGH 600L
#define VARM_GRAPH_800_600_256(x,y) (((unsigned long)y<<9L)+((unsigned long)y<<8L)+((unsigned long)y<<5L)+((unsigned long)(x)))
#define VARM_GRAPH_800_600_16M(x,y) (((((unsigned long)y<<9L)+((unsigned long)y<<8L)+((unsigned long)y<<5L))<<1L) + (((unsigned long)x)<<1L))
#define PALETTE_READ 0x3C7 /*VGA系统调色板读端口*/
#define PALETTE_WRITE 0x3C8 /*VGA系统调色板写端口*/
#define PALETTE_DATA 0x3C9 /*VGA系统调色板数据端口*/
/*第一部分为位图文件头BITMAPFILEHEADER,其定义如下:*/
typedef struct tagBITMAPFILEHEADER
{
unsigned int bfType; /*指定文件类型,*.bmp文件的头两个字节都是"BM"*/
unsigned long bfSize; /*指定文件大小,包括这14个字节*/
unsigned int Reserved1; /*为保留字,不用考虑*/
unsigned int reserved2; /*为保留字,不用考虑*/
unsigned long bfOffset; /*为从文件头到实际的位图数据的偏移字节数,前三个部分的长度之和。*/
}BITMAPFILEHEADER;
/*第二部分为位图信息头BITMAPINFOHEADER,这个结构的长度是固定的,为40个字节其定义如下:*/
typedef struct tagBITMAPINFOHEADER
{
unsigned long biSize; /*指定这个结构的长度,为40*/
unsigned long biWidth; /*指定图象的宽度,单位是象素*/
unsigned long biHeight; /*指定图象的高度,单位是象素*/
unsigned int biPlanes; /*必须是1,不用考虑*/
unsigned int biBitCount; /*指定表示颜色时要用到的位数,常用的值为1(黑白二色图),4(16色图),8(256色),24(真彩色图)*/
unsigned long biCompression; /*指定位图是否压缩,有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS*/
unsigned long biSizeImage; /*指定实际的位图数据占用的字节数*/
unsigned long biXpolsPerMeter; /*指定目标设备的水平分辨率,单位是每米的象素个数。*/
unsigned long biYpelsPerMeter; /*指定目标设备的垂直分辨率,单位同上。*/
unsigned long biClrUsed; /*指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次方。*/
unsigned long biClrImportant; /*指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。*/
}BITMAPINFOHEADER;
typedef struct tagRGBQUAD /* 256 RGB像素类型 */
{
unsigned char Blue;
unsigned char Green;
unsigned char Red;
unsigned char Reserved;
}RGBQUAD;
typedef struct tagRGB16M /* 16M RGB像素类型 */
{
unsigned char Blue;
unsigned char Green;
unsigned char Red;
}RGB16M;
int g_cur_vbe_page = 0;
/////////////////////////////////////////////////////////////////////////////////////////////////
//图形模式初始化子程序
/////////////////////////////////////////////////////////////////////////////////////////////////
void _Cdecl InitGraph(unsigned int mode)
{
_AX = 0x4f02;
_BX = mode;
__int__(0x10);
if(_AH != 0)
{
puts("Can't Initialize the graphics mode!");
exit(1);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//关闭图形模式,回到文本模式子程序
/////////////////////////////////////////////////////////////////////////////////////////////////
void _Cdecl CloseGraph(void)
{
_AX = 0x4f02;
_BX = 0x03;
__int__(0x10);
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//显存换页函数
/////////////////////////////////////////////////////////////////////////////////////////////////
void _Cdecl set_vbe_page(int page)
{
if (g_cur_vbe_page != page)
{
_BX = 0;
_DX = g_cur_vbe_page = page;
_AX = 0x4F05;
__int__(0x10);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//16M真彩色800*600写点
/////////////////////////////////////////////////////////////////////////////////////////////////
void PutPixel16M(int x,int y,int Color)
{
/* int page;
char far *videoptr = (char far *)0xa0000000L;
long addr = VARM_GRAPH_800_600_16M(x,y);
if (x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HIGH)
{
page = (int)(addr >> 16);
set_vbe_page(page);
*(videoptr + (unsigned int)(addr & 0xFFFF))= Color & 0xFF;
*(videoptr + (unsigned int)(addr & 0xFFFF)+1)= Color>>0x08;
}
*/
long addr = VARM_GRAPH_800_600_256(x,y);
int far *videoptr16 = (int far *)MK_FP(0xa000, 0);
int page;
page = (int)(addr >> 15);
set_vbe_page(page);
*(videoptr16 + (unsigned int)(addr & 0xFFFF))= Color;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//在24位图像中,没有“DAC色表”,也没有“图像数据区”。唯一留给我们的只有图像上所有点的颜色值。
//因为每个颜色都用BGR三种颜色来表示,而每个颜色占用1个字节,所以在24位图像中,每1个点就占用了
//3个字节。那没有“DAC”色表,也没有‘数据图像区’我们怎么来显示图象呢?很简单, 24位图给我们提供了个更
//加简单的方法:“所有点的颜色值”。既然是所有点,那么只要把这些点按照他们的颜色重新画出来就是
//该图像完整的信息了。
/////////////////////////////////////////////////////////////////////////////////////////////////
void Show_BMP(char *File_Name)
{
int i, j, width ;
register BITMAPFILEHEADER *FileHead;
register BITMAPINFOHEADER *InfoHead;
FILE *fp;
if ((FileHead = (BITMAPFILEHEADER *)malloc(sizeof(BITMAPFILEHEADER))) == NULL)
return;
if ((InfoHead = (BITMAPINFOHEADER*)malloc(sizeof(BITMAPINFOHEADER))) == NULL)
return;
if ((fp = fopen(File_Name,"rb")) == NULL)
{
printf("BMP File not exist ...");
return;
}
fread(FileHead,sizeof(BITMAPFILEHEADER),1,fp);
if (FileHead->bfType!='BM')
{
printf("BMP File type Error ...");
fclose(fp);
return;
}
fread(InfoHead,sizeof(BITMAPINFOHEADER),1,fp);
if (InfoHead->biCompression !=0 || (InfoHead->biBitCount!=8 && InfoHead->biBitCount!=24))
{
printf("BMP File not Support Compression type ...");
fclose(fp);
return;
}
width =((int)InfoHead->biWidth+3)/4*4; // 每行字节数--4的整数倍
if ((int)InfoHead->biBitCount == 24)
{
register RGB16M *buffer;
if ((buffer = malloc(width*sizeof(RGB16M))) == NULL)
{
fclose(fp);
return;
}
for (j = (int)InfoHead->biHeight-1 ; j >= 0 ; j--)
{
fread(buffer,width,sizeof(RGB16M),fp);
for (i = 0 ; i < width ; i++)
PutPixel16M(i,j,RGB(buffer[i].Red,buffer[i].Green,buffer[i].Blue));
}
}
free(FileHead);
free(InfoHead);
fclose(fp);
}
void main(void)
{
InitGraph(VBE800X600X64K);
Show_BMP("d:\\logo.BMP");//显示一幅16M真彩色BMP图片
getch();
CloseGraph();
}
/*
//满屏显示RGB(71,201,61)=绿色,你可以用WINDOWS中的RGB其它颜色试试
void main(void)
{
int x,y;
int Color = RGB(71,201,61);
InitGraph(VBE800X600X64K);
for (y=0;y<600;y++)
for (x=0;x<800;x++)
PutPixel16M(x,y,Color);
getch();
CloseGraph();
}
*/