回 帖 发 新 帖 刷新版面

主题:[原创]16色BMP位图 之 TC篇

运行环境 TurboC 2.0 
先在tc目录下新建一个16色位图 test.bmp (这里假定大小是 320*240)
并将 bmp16.h 文件也保存在该文件夹下
然后运行下面程序

/*
  loadbmp.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include "bmp16.h"

#define PATH "d:\\turboc2"

void main()
{
    FILE *fp;
    int VedioMode=VGA;
    int VedioDriver=VGAHI;
    initgraph(&VedioMode,&VedioDriver,PATH);

    if((fp=fopen("test.bmp","rb"))==NULL){
        closegraph();
        printf("file cannot open\n");
        exit(0);
    }
    ShowBMP16(fp,10,10,320,240,16);
    ShowBMP16Ex(fp,300,300,50,50,200,100,16);
    fclose(fp);
    getch();
    closegraph();
}

两个显示图像的函数 暂时都还存在一些问题
1.显示区域的宽度为奇数时,实际并是按偶数显示 少显示了一列
2.截取区域的起始列为奇数时,实际并是按起始列偶数显示 显示区域向左移了一列

回复列表 (共6个回复)

沙发

/*
  BMP16.h

  2006/3/23
*/
typedef struct tagBITMAPFILEHEADER {
    unsigned int bfType;
    unsigned long bfSize;
    unsigned int bfReserved1;
    unsigned int bfReserved2;
    unsigned long bfOffBits;
}BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
    unsigned long biSize;
    long biWidth;
    long biHeight;
    unsigned int biPanes;
    unsigned int biBitCount;
    unsigned long biCompression;
    unsigned long biSizeImage;
    long biXPelsPerMeter;
    long biYPelsPerMeter;
    unsigned long biClrUsed;
    unsigned long biClrImportant;
}BITMAPINFOHEADER;

typedef struct tagRGBQUAD {
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
}RGBQUAD;

/*
windows画图 中选色框各个颜色所对应的 颜色索引号如下:
0 7 1 3 2 6 4 5
F 8 9 B A E C D 
*/
void SetVGAPalette(FILE *fp)
{
    /*tc 中颜色索引号0~15 所对应的 调色板号*/
    int i, palIndex[16]={0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63};
    RGBQUAD quad[16];

    /*tc VGA的调色板 设置为.BMP的调色板*/
    fseek(fp,54L,SEEK_SET);
    fread(quad,sizeof(RGBQUAD),16,fp);
    for(i=0; i<16; i++){
        setrgbpalette(palIndex[i], quad[i].rgbRed/4, quad[i].rgbGreen/4, quad[i].rgbBlue/4);
    }
}

/*恢复到原始调色板*/
void ResumeVGAPalette()
{
    /*tc 中颜色索引号0~15 所对应的 调色板号*/
    int i, palIndex[16]={0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63};
    RGBQUAD quad;
    for(i=0; i<8; i++){
        quad.rgbRed=42*(i&0x04?1:0);
        quad.rgbGreen=42*(i&0x02?1:0);
        quad.rgbBlue=42*(i&0x01?1:0);
        setrgbpalette(palIndex[i], quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
        setrgbpalette(palIndex[15-i], 63-quad.rgbRed, 63-quad.rgbGreen, 63-quad.rgbBlue);
    }
}

/*
  ShowBMP16()说明:
  FILE *fp                    bmp文件头指针
  int winLeft, int winTop     显示区左上角位置
  int winWidth, int winHeight 显示区范围 超出范围的图像不会被显示
  unsigned char TranColor     图像透明色 (正常值为0~15) 图像中该种颜色的区域 不于显示;
                              设置为16 或者大于16 时,显示全部颜色 此处通常设置为16
*/
int ShowBMP16(FILE *fp, int winLeft, int winTop, int winWidth, int winHeight, unsigned char TranColor)
{
    long x,y;
    long Height,Width;
    long WBytes,DataOffset;
    unsigned char SrcData,data;

    BITMAPFILEHEADER bfh;
    BITMAPINFOHEADER bih;

    /*读取文件头信息*/
    fseek(fp,0L,SEEK_SET);
    fread(&bfh,sizeof(BITMAPFILEHEADER),1,fp);
    fread(&bih,sizeof(BITMAPINFOHEADER),1,fp);

    /*测试文件是否是16色BMP图像文件*/
    if(bfh.bfType!='M'*256+'B' || bih.biBitCount!=4){
        return 1;
    }

    /*图像宽度 对4 向上取整*/
    WBytes=(bih.biWidth*bih.biBitCount+31)/8;
    WBytes=WBytes/4*4;

    /*显示的图像 限制在显示区内部*/
    Width=bih.biWidth<winWidth ? bih.biWidth : winWidth;
    Height=bih.biHeight<winHeight ?    bih.biHeight : winHeight;

    /*设置数据段起始地址*/
    DataOffset=118;
    if(bih.biHeight > winHeight) {
        DataOffset+=(bih.biHeight-winHeight)*WBytes;
    }

    /*显示图像  预先设置调色板*/
    SetVGAPalette(fp);
    for(y=0; y<Height; y++) {
        fseek(fp, DataOffset+y*WBytes, SEEK_SET);
        for(x=0; x<Width; x+=2) {
            fread(&SrcData,1,1,fp);

            /*ScrData的低4位 高4位 分别存储一个象素点的颜色值
              TranColor 为透明色 0~15 大于等于十六 无作用
            */
            if( (data=SrcData/16) != TranColor) {
                putpixel(winLeft+x,winTop+Height-y-1,data);
            }
            if( (data=SrcData%16) != TranColor) {
                putpixel(winLeft+x+1,winTop+Height-y-1,data);
            }
        }
    }
    return 0;
}

/*
  ShowBMP16Ex()说明:
  FILE *fp                    bmp文件头指针
  int winLeft, int winTop     显示区左上角位置

  int bmpLeft, int bmpTop     bmp图像截取区域左上角位置
  int bmpWidth, int bmpHeight bmp图像截取区域范围
  unsigned char TranColor     图像透明色 (正常值为0~15) 图像中该种颜色的区域 不于显示;
                              设置为16 或者大于16 时,显示全部颜色 此处通常设置为16
*/
int ShowBMP16Ex(FILE *fp, int winLeft, int winTop, int bmpLeft, int bmpTop, int bmpWidth, int bmpHeight, unsigned char TranColor)
{
    long x,y;
    long WBytes,DataOffset;
    unsigned char SrcData,data;

    BITMAPFILEHEADER bfh;
    BITMAPINFOHEADER bih;
    /*指向文件头*/
    fseek(fp,0L,SEEK_SET);
    fread(&bfh,sizeof(BITMAPFILEHEADER),1,fp);
    fread(&bih,sizeof(BITMAPINFOHEADER),1,fp);

    /*测试文件是否是16色BMP图像文件*/
    if(bfh.bfType!='M'*256+'B' || bih.biBitCount!=4){
        return 1;
    }

    /*图像宽度 对4 向上取整*/
    WBytes=(bih.biWidth*bih.biBitCount+31)/8;
    WBytes=WBytes/4*4;

    /*设置数据段起始地址*/
    DataOffset=54+16*sizeof(RGBQUAD)+bmpLeft/2;
    DataOffset+=(bih.biHeight-bmpHeight-bmpTop)*WBytes;

    /*显示图像  预先设置调色板*/
    SetVGAPalette(fp);
    for(y=0; y<bmpHeight; y++) {
        fseek(fp, DataOffset+y*WBytes, SEEK_SET);
        for(x=0; x<bmpWidth; x+=2) {
            fread(&SrcData,1,1,fp);

            /*ScrData的低4位 高4位 分别存储一个象素点的颜色值
              TranColor 为透明色 0~15 大于等于十六 无作用
            */
            if( (data=SrcData/16) != TranColor) {
                putpixel(winLeft+x,winTop+bmpHeight-y-1,data);
            }
            if( (data=SrcData%16) != TranColor) {
                putpixel(winLeft+x+1,winTop+bmpHeight-y-1,data);
            }
        }
    }
    return 0;
}

板凳

good,怎么不加精?

3 楼

呵呵 谢谢支持

4 楼


很不错学习了,
希望你去看看的的一个问题吧[url=http://bbs.pfan.cn/post-289627.html]http://bbs.pfan.cn/post-289627.html[/url]

5 楼


你可以帮忙解决一下这个问题吗:http://bbs.pfan.cn/post-284042.html

6 楼

呵呵,不错,有一次处理简单图片,我整了两天愣是没把程序写出来。。
收回去研究了哈,歇息诶楼主。

我来回复

您尚未登录,请登录后再回复。点此登录或注册