2.2 BMP文件 灰度化 二值化 亮度调整有关BMP图像处理的底层函数

代码写的很水,把灰度化 二值化 亮度调整 算法全部注释掉了 ,根据自己的需要去掉相关注释就可以,快捷注释键ctrl+k+c 快捷取注释键ctrl+k+u;如果输入的位图文件不是24位的,在相关循环下面添加相应的算法即可 下面是自己写的代码:

#include<malloc.h>  
#include<stdlib.h>
#include<memory.h>
#include<time.h>
#include <stdio.h>
/*!
* \the bitmap struct
* \author whtr01
* \date SEP 2016
*/
#define WORD unsigned short
#define DWORD unsigned long
#define BYTE  unsigned char
#define WIDTHBYTES(bits) (((bits)+31)/32*4)  //用于使图像宽度所占字节数为4的整数倍
#define  BM    19778        // 位图的标志 
#pragma pack(2)   //两字节对齐,否则bmp_fileheader会占16Byte
typedef struct            //12byte,位图文件头
{
    WORD bfType;   //BM标志
    DWORD bfSize;   //文件大小 
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bfOffset;  //偏移量  起始位置距离数据区
}BitMapFileHeader;
typedef struct            //40字节 位图信息头
{
    DWORD biSize;//信息头大小  
    DWORD biWidth;//图像宽度,以像素为单位  
    DWORD biHeight;//图像高度,以像素为单位  
    WORD biPlanes;//位平面数,为1;  
    WORD biBitCount;//每像素位数,1,4,8,24  
    DWORD biCompression;//压缩类型,0为非压缩  
    DWORD biSizeImage;//压缩图像大小  
    DWORD biXpelspermeter;//水平分辨率  
    DWORD biYpelspermeter;//垂直分辨率  
    DWORD biClrUsed;//使用的色彩数  
    DWORD biClrImportant;//重要色彩数  
}BitMapInforHeader;
typedef struct             //位图颜色表
{
    BYTE rgbBlue; //该颜色的蓝色分量    
    BYTE rgbGreen; //该颜色的绿色分量    
    BYTE rgbRed; //该颜色的红色分量    
    BYTE rgbReserved; //保留值    
} RGBQuad;
 BYTE * ImgData;
 //为二维数组申请内存  
int **getArray(int row, int line)//行 列
{
    int **p = NULL;
    p = (int**)malloc(sizeof(int*)*row);
    int i = 0;
    for (; i < row; i++)
        p[i] = (int*)malloc(sizeof(int)*line);
    return p;
}
//释放数组内存
void freeArray(int row, int**p)
{
    for (int i = 0; i < row; i++)
    {
        free(p[i]);
    }
    free(p);
}
//位图文件是否能打开
FILE *IsOpen(char* srcFile)
{
    FILE* pFile = fopen(srcFile, "rb");
    if (pFile == NULL)
    {
        printf("打开位图失败\n");
        exit(-1);
    }
    return pFile;
}

//判断是否是位图,在0-1字节
int IsBitMap(char *srcFile)
{
    FILE *fp = fopen(srcFile, "rb");
    WORD s;
    fread(&s, 1, 2, fp);
    if (s != BM)
    {
        return -1;
    }
        return 0;
}
//获得图片的宽度,在18-21字节   
long getWidth(FILE *fp)
{
    long width;
    fseek(fp, 18, SEEK_SET);
    fread(&width, 1, 4, fp);
    return width;
}
//获得图片的高度 ,在22-25字节   
long getHeight(FILE *fp)
{
    long height;
    fseek(fp, 22, SEEK_SET);
    fread(&height, 1, 4, fp);
    return height;
}
//获得每个像素的位数,在28-29字节   
WORD getBit(char *srcFile)
{
    IsBitMap(srcFile);
    FILE *pFile = IsOpen(srcFile);
    WORD bit;
    fseek(pFile, 28, SEEK_SET);
    fread(&bit, 1, 2, pFile);
    return bit;
}
//获得数据的起始位置  
DWORD getOffSet(char *srcFile)
{
    DWORD OffSet;
    FILE *pFile = IsOpen(srcFile);
    fseek(pFile, 10L, SEEK_SET);
    fread(&OffSet, 4, 1, pFile);
    return OffSet;
}
void ToGray(char* srcFile, char* destFile)
{
    BitMapFileHeader fileHeader;// 位图头文件
    BitMapInforHeader infoHeader;// 位图信息头
    IsBitMap(srcFile);
    // 读取头信息
    FILE *pFile=IsOpen(srcFile);
    // 读取头信息
    fread(&fileHeader, sizeof(BitMapFileHeader), 1, pFile);
    fread(&infoHeader, sizeof(BitMapInforHeader), 1, pFile);
    WORD bitCount = infoHeader.biBitCount;//取表示色彩的位数
    if (bitCount == 16)
    {
        exit(-1);
    }
    int nColorUsed = 0;
    int i = 0, j = 0;
    RGBQuad *quad = NULL;
    if (bitCount < 16)
    {
        // 读取使用的调色板颜色数量,biClrUsed为0时,代表位数默认的调色板值
        nColorUsed = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount;
        if (nColorUsed > 256)
            nColorUsed = 0;
    }
        // 读取调色板
    if (nColorUsed > 0)//排除24位和32位没有调色板的
    {
        quad = (RGBQuad*)malloc(sizeof(RGBQuad)*nColorUsed);
        fread(quad, sizeof(RGBQuad)*nColorUsed, 1, pFile);
        for (i = 0; i < nColorUsed; i++)
        {
            quad[i].rgbRed = quad[i].rgbBlue = quad[i].rgbGreen =
                (BYTE)(0.3 * quad[i].rgbRed + 0.59 * quad[i].rgbGreen + 0.11 * quad[i].rgbBlue);//灰度化
        }
    }
    DWORD srcW = infoHeader.biWidth;
    DWORD srcH = infoHeader.biHeight;
    //图像数据区域
    int BufSize = (((srcW * bitCount + 31) & ~31) >> 3)*srcH;
    BYTE* Buf = (BYTE*)malloc(BufSize);
    int LineSize = (((srcW * bitCount + 31) & ~31) >> 3);  
    fread(Buf, BufSize, 1, pFile);
    if (nColorUsed == 0)         //图像处理可通过操作这部分数据加以实现,可将下面的示例修改为中值滤波等各种图像处理模块  
//                                     //在嵌入式开发环境下,大多数情况下已经得到图像数据区,是故将下面部分代码稍作修改就可以移植到嵌入式端  
//
//                                     /*******************图像处理部分******************/
//                                     /*******************示例,将图像亮度减半******************/
    {
        for (i = 0; i < srcH; i++)//行
        {
            if (bitCount == 24)
            {
                for (j = 0; j < srcW * 3; j = j + 3)// 列,因为每个像素占3个字节
                {
                    int n = i*LineSize + j;
                    /************************************************************************/
                    /*                             图像灰度化                               */
                    /************************************************************************/
                    Buf[n] = Buf[n + 1] = Buf[n + 2] = (BYTE)(0.3*Buf[n] + 0.59*Buf[n + 1] + 0.11*Buf[n + 2]);//灰度化
                    /************************************************************************/
                    /*                         改变图像亮度强弱部分                         */
                    /************************************************************************/
                    /*Buf[n] = (BYTE)Buf[n] * 0.5;
                    Buf[n + 1] = (BYTE)Buf[n + 1] * 0.5;
                    Buf[n + 2] = (BYTE)Buf[n + 2] * 0.5;*/
                    /************************************************************************/
                    /*                             图像二值化                               */
                    /************************************************************************/
                    //Buf[n] = Buf[n + 1] = Buf[n + 2] = (BYTE)(0.3*Buf[n] + 0.59*Buf[n + 1] + 0.11*Buf[n + 2]);//灰度化
                    //Buf[n] > 128 ? Buf[n] = 0 : Buf[n] = 255; // 此处设置阀值 即为此处的64  可根据需要改变64的值   eg:128 。。
                    //Buf[n+1] > 128 ? Buf[n+1] = 0 : Buf[n+1] = 255;
                    //Buf[n+2] > 128 ? Buf[n+2] = 0 : Buf[n+2] = 255;
                }
            }
            else
            {
                for (j = 0; j < srcW * 4; j = j + 4)// 列
                {
                    int n = i*LineSize + j;
                    //Buf[n] = Buf[n + 1] = Buf[n + 2] = 0.11*Buf[n] + 0.59*Buf[n + 1] + 0.3*Buf[n + 2];
                    Buf[n] = (BYTE)Buf[n] * 2;
                    Buf[n + 1] = (BYTE)Buf[n + 1] * 2;
                    Buf[n + 2] = (BYTE)Buf[n + 2] * 2;

                }
            }
        }
    }
                                           /*******************图像写入部分******************/
    //                                     /*******************无需再更改******************/
    //创建目标文件   
    FILE* pDfile = fopen(destFile, "wb");
    //写入数据 写入文件头
    fwrite(&fileHeader, sizeof(BitMapFileHeader), 1, pDfile);
    //写入Bitmap头信息  
    fwrite(&infoHeader, sizeof(BitMapInforHeader), 1, pDfile);
    if (quad)
    {
        fwrite(quad, sizeof(RGBQuad)* nColorUsed, 1, pDfile);
    }
    //写入图像数据  
    fwrite(Buf, BufSize, 1, pDfile);
    fclose(pDfile);
    if (quad)
    {
        free(quad);
        quad = NULL;
    }
    if (Buf)
    {
        free(Buf);
        Buf = NULL;
    }
}
int main()
{
    ToGray("F:\\Mypicture\\bmp\\Tulips.bmp", "F:\\Mypicture\\Test\\GrayTulips.bmp");
    //ReadData("F:\\Mypicture\\gray\\a4.bmp");
    system("pause");
    return 0;
}

效果图:这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值