1 20 50 150 500
欢迎来到瑞博软件站,找素材,搜软件,就上瑞博软件站!
当前位置 >首页 >软件下载 >电脑软件 >编程开发 >编程软件

24位bmp位图转灰度图 免费版带源码

软件信息
  • 分类:编程软件
  • 大小:2.6M
  • 语言: 中文
  • 环境: WinAll, WinXP, Win7
  • 更新:2024-11-13
  • 评级:
  • 系统: Windows Linux Mac Ubuntu
  • 软件类别: 国产软件 / 免费软件 / 编程辅助
  • 插件情况:
  • 相关链接: http://www.cr173.com

实现位图的读取显示保存,能完成24位位图的转换,是一个典型的图像处理基础程序,程序很好,很简单清晰,容易看懂,但是所有图像信息头和数据的处理全在响应函数和ondrow函数里!

将24位真彩色图转换为灰度图

在图像处理中,我们经常需要将真彩色图像转换为黑白图像。严格的讲应该是灰度图,因为真正的黑白图像是二色,即只有纯黑,纯白二色。开始之前,我们先简单补充一下计算机中图像的表示原理。

计算机中的图像大致可以分成两类:位图(Bitmap)和矢量图(Metafile)。 位图可以视为一个二维的网格,整个图像就是由很多个点组成的,点的个数等于位图的宽乘以高。每个点被称为一个像素点,每个像素点有确定的颜色,当很多个像素合在一起时就形成了一幅完整的图像。

我们通常使用的图像大部分都是位图,如数码相机拍摄的照片,都是位图。因为位图可以完美的表示图像的细节,能较好的 还原图像的原景。

但位图也有缺点:第一是体积比较大,所以人们开发了很多压缩图像格式来储存位图图像,目前应用最广的是JPEG格式,在WEB上得到了广泛应用,另外还有GIF,PNG等 等。第二是位图在放大时,不可避免的会出现“锯齿”现象,这也由位图的本质特点决定的。

所以在现实中,我们还需要使用到另一种图像格式:矢量图。同位图不 同,矢量图同位图的原理不同,矢量图是利用数学公式通过圆,线段等绘制出来的,所以不管如何放大都不会出现变形,但矢量图不能描述非常复杂的图像。所以矢量图都是用来描述图形图案,各种CAD软件等等都是使用矢量格式来保存文件的。

24位真色位图转化为8位灰度位图

(C语言实现) 

//最近在学习图像处理有关的基础知识,并试着编程实践,这样有助于自己的理解和学习。首先遇到的第一个问题就是bmp位图的基础知识、bmp位图的C语言读入、操作、存入等。以下便是有关这期间学习的知识经验总结:欢迎分享!欢迎建议!谢谢!

//要理解的基础问题:bmp位图文件格式(掌握了bmp位图文件的具体格式后,才有可能更好的对其进行编程操作实践!):

位图文件(bitmap file)保存顺序如下:

位图头文件(BITMAPFILEHEADER)

位图信息头文件(BITMAPINFOHEADER)

调色板RGBQUAD(真彩色位图没有调色板)

图像数据

##释义1##位图头文件(BITMAPFILEHEADER):

typedef struct tagBITMAPFILEHEADER

{ /*14 bytes BMP文件头数据结构含有BMP文件的类型、

                               文件大小和位图起始位置等信息*/

    WORD bfType; /*2,位图文件的类型,必须为BM(0-1字节)*/

    DWORD bfSize; /*4,位图文件的大小,以字节为单位(2-5字节)*/

    WORD bfReserved1; /*2,位图文件保留字,必须为0(6-7字节)*/

    WORD bfReserved2; /*2,位图文件保留字,必须为0(6-7字节)*/

    DWORD bfOffBits; /*4,位图数据的起始位置,以相对于位图(10-13字节) */

}BITMAPFILEHEADER,*PBITMAPFILEHEADER;

##释义2##位图信息头文件(BITMAPINFOHEADER):

typedef struct tagBITMAPINFOHEADER

{ /*40 bytes BMP位图信息头数据用于说明位图的尺寸等信息。*/

    DWORD biSize; /*4,本结构所占用字节数(14-17字节) */

    LONG biWidth; /*4,位图的宽度,以像素为单位(18-21字节)*/

    LONG biHeight; /*4,位图的高度,以像素为单位(22-25字节) */

    WORD biPlanes; /*2,目标设备的级别,必须为1(26-27字节) */

    WORD biBitCount;/*2每个像素所需的位数,必须是1(双色),(28-29字节)

                          4(16色),8(256色)或24(真彩色)之一 */

    DWORD biCompression;/*4,位图压缩类型,必须是 0(不压缩),(30-33字节)

                       1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 */

    DWORD biSizeImage; /*4,位图的大小,以字节为单位(34-37字节) */

    LONG biXPelsPerMeter;/*4,位图水平分辨率,每米像素数(38-41字节) */

    LONG biYPelsPerMeter; /*4,位图垂直分辨率,每米像素数(42-45字节) */

    DWORD biClrUsed;/*4, 位图实际使用的颜色表中的颜色数(46-49字节) */

    DWORD biClrImportant;/*4,位图显示过程中重要的颜色数(50-53字节) */

} BITMAPINFOHEADER,*PBITMAPINFOHEADER;

##释义3##调色板RGBQUAD(真彩色位图没有调色板):

typedef struct tagRGBQUAD

{ /*颜色表用于说明位图中的颜色,它有若干个表项

                      ,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。*/

    BYTE rgbBlue; /*蓝色的亮度(值范围为0-255)*/

    BYTE rgbGreen; /*绿色的亮度(值范围为0-255) */

    BYTE rgbRed;/*红色的亮度(值范围为0-255)*/

    BYTE rgbReserved; /*保留,必须为0 */

}RGBQUAD;

##释义4##图像数据:

    对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值。对于真彩色图像,图像数据就是实际的R、G、B值,一个像素由3个字节24位组成,第一个字节表示B,第二个字节表示G,第三个字节表示R。

    注意:BMP文件是从下到上、从左都右排列的。读文件时,最先读到的是图像的最下面一行的左边的第一个像素,最后读到的是最上面一行的最右一个像素。

//C源程序:本C程序由两部分组成(.c文件和.h文件)。(注:VC6编译链接运行通过)

*********************************************************************************************

rgbtogray.h文件:

*****************

/* C语言读入图像 位图文件结构声明 */

#ifndef BMP_H_INCLUDED

#define BMP_H_INCLUDED



typedef unsigned short WORD;//2*8=16

typedef unsigned long DWORD;//4*8=32

typedef long LONG;//4*8=32

typedef unsigned char BYTE;//1*8=8


#pragma pack(1)

typedef struct tagBITMAPFILEHEADER

{ /*14 bytes BMP文件头数据结构含有BMP文件的类型、

                               文件大小和位图起始位置等信息*/

    WORD bfType; /*2,位图文件的类型,必须为BM(0-1字节)*/

    DWORD bfSize; /*4,位图文件的大小,以字节为单位(2-5字节)*/

    WORD bfReserved1; /*2,位图文件保留字,必须为0(6-7字节)*/

    WORD bfReserved2; /*2,位图文件保留字,必须为0(6-7字节)*/

    DWORD bfOffBits; /*4,位图数据的起始位置,以相对于位图(10-13字节) */

}BITMAPFILEHEADER,*PBITMAPFILEHEADER;

#pragma pack()


#pragma pack(1)

typedef struct tagBITMAPINFOHEADER

{ /*40 bytes BMP位图信息头数据用于说明位图的尺寸等信息。*/

    DWORD biSize; /*4,本结构所占用字节数(14-17字节) */

    LONG biWidth; /*4,位图的宽度,以像素为单位(18-21字节)*/

    LONG biHeight; /*4,位图的高度,以像素为单位(22-25字节) */

    WORD biPlanes; /*2,目标设备的级别,必须为1(26-27字节) */

    WORD biBitCount;/*2每个像素所需的位数,必须是1(双色),(28-29字节)

                          4(16色),8(256色)或24(真彩色)之一 */

    DWORD biCompression;/*4,位图压缩类型,必须是 0(不压缩),(30-33字节)

                       1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 */

    DWORD biSizeImage; /*4,位图的大小,以字节为单位(34-37字节) */

    LONG biXPelsPerMeter;/*4,位图水平分辨率,每米像素数(38-41字节) */

    LONG biYPelsPerMeter; /*4,位图垂直分辨率,每米像素数(42-45字节) */

    DWORD biClrUsed;/*4, 位图实际使用的颜色表中的颜色数(46-49字节) */

    DWORD biClrImportant;/*4,位图显示过程中重要的颜色数(50-53字节) */

} BITMAPINFOHEADER,*PBITMAPINFOHEADER;

#pragma pack()


#pragma pack(1)

typedef struct tagRGBQUAD

{ /*颜色表用于说明位图中的颜色,它有若干个表项

                      ,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。*/

    BYTE rgbBlue; /*蓝色的亮度(值范围为0-255)*/

    BYTE rgbGreen; /*绿色的亮度(值范围为0-255) */

    BYTE rgbRed;/*红色的亮度(值范围为0-255)*/

    BYTE rgbReserved; /*保留,必须为0 */

}RGBQUAD;/*颜色表中RGBQUAD结构数据的个数有biBitCount来确定:

   当biBitCount=1,4,8时,分别有2,16,256个表项;

   当biBitCount=24时,没有颜色表项。*/

#pragma pack()


#pragma pack(1)

typedef struct tagBITMAPIMAGE

{ /*位图信息头和颜色表组成位图信息*/

    BITMAPFILEHEADER bmiHeader; /*位图信息头*/

    RGBQUAD bmiColors[1]; /*颜色表*/

}BITMAPIMAGE;

#pragma pack()


#endif

*********************************************************************************************

rgbtogray.h文件:

******************

/*******************************************************************************/

#include<stdio.h>

#include<stdlib.h>

#include<malloc.h>

#include<string.h>

/********************************************************************/

//自定义的有关图像处理的头文件为rgbtogray.h


//系统定义有关图像处理的头文件为windows.h


//目前,引用系统的windows.h程序工作正常,但自己的头文件有问题,待改正!


//最终实现引用自己的头文件rgbtogray.h


//太棒了:头文件的问题终于解决了


  //#include<windows.h>


#include "rgbtogray.h"

/********************************************************************/

/*****************************************************************************/

//全局变量声明


FILE * fpSrcBmpfile;//定义文件指针,用于读入和存储图像文件


FILE * fpDestBmpfile;


/******************************************************************************/

//程序子函数声明


void GetBmpHeader(PBITMAPFILEHEADER, PBITMAPINFOHEADER);//获得位图的文件头和信息头


void ChangeBmpHeader(PBITMAPFILEHEADER, PBITMAPINFOHEADER, WORD);//改变位图的文件头和信息头


void SetBmpHeader(const PBITMAPFILEHEADER, const PBITMAPINFOHEADER);//将修改后的文件头和信息头存入新位图文件


void SetRGBQUAD();//建立颜色板并存入灰度图文件中


int RgbToGray();//24位真色图转化为8位灰度图的主要函数



/******************************************************************************/

//主函数框架,菜单!(方便调用其他程序,以便拓展)


void main()

{

    int command=1;

    while(command)//菜单选项,可拓展


    {

    printf(" *****************************Image Processing Menu*************************** ");

    printf("|--------1:RGB To GRAY transform!--------| ");

    printf("|--------0:End!---------| ");

    printf("***************************************************************************** ");    

    printf("Hint:Processor Number? ");

    scanf("%d",&command);

        switch(command)

        {

        case 1:

            RgbToGray();

            break;

        case 0:

            printf("---Bye-bye--- ");

            break;

        default:

            printf("---Not defined number! ");

            break;

        }    

    }

}


/******************************************************************************/

//函数体部分(副)


void GetBmpHeader(PBITMAPFILEHEADER pbfheader, PBITMAPINFOHEADER pbiheader)

{

    fread(pbfheader, sizeof(BITMAPFILEHEADER), 1,fpSrcBmpfile);

    fread(pbiheader, sizeof(BITMAPINFOHEADER), 1,fpSrcBmpfile);

}

void ChangeBmpHeader(PBITMAPFILEHEADER pbfheader, PBITMAPINFOHEADER pbiheader, WORD wType)

{

    pbiheader->biBitCount = wType; // 24 或者 8


    pbiheader->biClrUsed = (wType == 24) ? 0 : 256;

    pbfheader->bfOffBits = 54 + pbiheader->biClrUsed * sizeof(RGBQUAD);

    pbiheader->biSizeImage = ((((pbiheader->biWidth * pbiheader->biBitCount) + 31) & ~31) / 8) * pbiheader->biHeight;

    pbfheader->bfSize = pbfheader->bfOffBits + pbiheader->biSizeImage;

}

void SetBmpHeader(const PBITMAPFILEHEADER pbfheader, const PBITMAPINFOHEADER pbiheader)

{

    fwrite(pbfheader, sizeof(BITMAPFILEHEADER), 1, fpDestBmpfile);

    fwrite(pbiheader, sizeof(BITMAPINFOHEADER), 1, fpDestBmpfile);

}

void SetRGBQUAD()

{

    int i;

    RGBQUAD rgbquad[256];

    for(i=0;i<256;i++) {

        rgbquad[i].rgbBlue = i;

        rgbquad[i].rgbGreen = i;

        rgbquad[i].rgbRed = i;

        rgbquad[i].rgbReserved = 0;

    }

    fwrite(rgbquad, 256 * sizeof(RGBQUAD), 1, fpDestBmpfile);

}

/******************************************************************************/

//函数体部分(主)


int RgbToGray()

{

    LONG w,h;

    BYTE r,g,b;

    BYTE gray;

    BYTE count24,count8;

    BYTE Bmpnul=0;


    char SrcBmpfile[256];

    char DestBmpfile[256];

    BITMAPFILEHEADER bmfh; // bmp文件头


    BITMAPINFOHEADER bmih; // 位图信息头


    BYTE *data;


    memset(&bmfh, 0, sizeof(BITMAPFILEHEADER));//内存初始化


    memset(&bmih, 0, sizeof(BITMAPINFOHEADER));

    data=(BYTE *)malloc(3*sizeof(BYTE));

    if(!data)

        {

           printf("Error:Can not allocate memory . ");

           free(data);

           return -1;

        }


    getchar();

    printf("Input the path of SrcBmpfile: ");

    gets(SrcBmpfile);


    if((fpSrcBmpfile=fopen(SrcBmpfile,"rb"))==NULL) 

    {

        printf("Error:Open the file of SrcBmpfile failed! ");//输入源位图文件


        free(data);

        return -1;

    }

    rewind(fpSrcBmpfile);

    GetBmpHeader(&bmfh,&bmih);

//ceshie_start


    printf("The contents in the file header of the BMP file: ");

    printf("bfType:%ld ",bmfh.bfType);

    printf("bfSize:%ld ",bmfh.bfSize);

    printf("bfReserved1:%ld ",bmfh.bfReserved1);

    printf("bfReserved2:%ld ",bmfh.bfReserved2);

    printf("bfOffBits:%ld ",bmfh.bfOffBits);

    printf("The contents in the info header: ");

    printf("biSize:%ld ",bmih.biSize);

//ceshi_end


    if(bmfh.bfType!=0x4D42)

    {

        printf("Error:This file is not bitmap file! ");

        free(data);

        return -1;

    }

    if(bmih.biBitCount!=24)

    {

        printf("Error:This bmpfile is not 24bit bitmap! ");

        free(data);

        return -1;

    }

    if(bmih.biCompression!=0)

    {

        printf("Error:This 8bit bitmap file is not BI_RGB type! ");

        free(data);

        return -1;

    }


    printf("Input the path of the DestBmpfile: ");//输入目标位图文件


    gets(DestBmpfile);


    if((fpDestBmpfile=fopen(DestBmpfile,"wb"))==NULL)

    {

        printf("Error:Open the file of DestBmpfile failed! ");

        free(data);

        return -1;

    }


    ChangeBmpHeader(&bmfh,&bmih,8);

    SetBmpHeader(&bmfh,&bmih);

    SetRGBQUAD();


    count24=(4-(bmih.biWidth*3)%4)%4;

    count8=(4-(bmih.biWidth)%4)%4;


    for(h=bmih.biHeight-1;h>=0;h--)

    {

        for(w=0;w<bmih.biWidth;w++)

        {

            fread(data,3,1,fpSrcBmpfile);

            if(feof(fpSrcBmpfile))

            {

                printf("Error:Read Pixel data failed! ");

                free(data);

                return -1;

            }

            b=*data;

            g=*(data+1);

            r=*(data+2);

            gray=(299*r+587*g+114*b)/1000;

            //if(gray>120)gray=250;


            fwrite(&gray,sizeof(gray),1,fpDestBmpfile);

        }

        fseek(fpSrcBmpfile,count24,SEEK_CUR);

        fwrite(&Bmpnul,1,count8,fpDestBmpfile);

    }

    printf("Hint:Convert RGB To GRAY Successfully! ");

    free(data);//释放内存空间


    fclose(fpDestBmpfile);//关闭文件指针


    fclose(fpSrcBmpfile);

    return 0;

}

/******************************************************************************/

*******************************************************************************************

****当时困扰了本人很长时间的一个程序问题,最后终于解决:

#prama pack(n)

结构体定义;

#prama pack()

##释义##:关于struct的使用方法:

     struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

    自然对界是指按结构体的成员中size最大的成员对齐。

#pragma pack规定的对齐长度,实际使用的规则是:

    结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和结构体的自然对齐长度中比较小的那个进行。

    也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。

    结构体的对齐,按照结构体中size最大的数据成员和#pragma pack指定值之间,较小的那个进行。

下载地址

热门软件

Top