C語(yǔ)言實(shí)現(xiàn)BMP格式圖片轉(zhuǎn)化為灰度
更新時(shí)間:2021年10月25日 17:06:11 作者:爬行的菜鳥
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)BMP格式圖片轉(zhuǎn)化為灰度,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
本文實(shí)例為大家分享了C語(yǔ)言將BMP格式圖片轉(zhuǎn)化為灰度的具體代碼,供大家參考,具體內(nèi)容如下
代碼如下:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER
{
unsigned char bfType[2];//文件格式
unsigned long bfSize;//文件大小
unsigned short bfReserved1;//保留
unsigned short bfReserved2;
unsigned long bfOffBits; //DIB數(shù)據(jù)在文件中的偏移量
}fileHeader;
#pragma pack()
/*
位圖數(shù)據(jù)信息結(jié)構(gòu)
*/
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER
{
unsigned long biSize;//該結(jié)構(gòu)的大小
long biWidth;//文件寬度
long biHeight;//文件高度
unsigned short biPlanes;//平面數(shù)
unsigned short biBitCount;//顏色位數(shù)
unsigned long biCompression;//壓縮類型
unsigned long biSizeImage;//DIB數(shù)據(jù)區(qū)大小
long biXPixPerMeter;
long biYPixPerMeter;
unsigned long biClrUsed;//多少顏色索引表
unsigned long biClrImporant;//多少重要顏色
}fileInfo;
#pragma pack()
/*
調(diào)色板結(jié)構(gòu)
*/
#pragma pack(1)
typedef struct tagRGBQUAD
{
unsigned char rgbBlue; //藍(lán)色分量亮度
unsigned char rgbGreen;//綠色分量亮度
unsigned char rgbRed;//紅色分量亮度
unsigned char rgbReserved;
}rgbq;
#pragma pack()
int main()
{
FILE *fp1 = fopen("C:\\Users\\Administrator\\Desktop\\data\\bmp\\image.bmp", "rb+");
if (fp1 == NULL)
{
printf("打開文件fp1失敗");
exit(0);
}
FILE *fp2 = fopen("C:\\Users\\Administrator\\Desktop\\data\\bmp\\imageGray.bmp", "wb");
if (fp1 == NULL)
{
printf("打開文件fp2失敗");
exit(0);
}
fileHeader * fh;
fileInfo * fi;
fh = (fileHeader *)malloc(sizeof(fileHeader));
fi = (fileInfo *)malloc(sizeof(fileInfo));
//讀取位圖頭結(jié)構(gòu)和信息頭
fread(fh, sizeof(fileHeader), 1, fp1);
fread(fi, sizeof(fileInfo), 1, fp1);
printf("\\\\\\\\\\\\\\\\\\\\原始圖片信息\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
printf("bmp文件頭:\n");
printf("bfSize:%d\n", fh->bfSize);
printf("bfOffBits:%d\n", fh->bfOffBits);
printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
printf("bmp信息頭\n");
printf("結(jié)構(gòu)體長(zhǎng)度:%d \n", fi->biSize);
printf("位圖寬度:%d \n", fi->biWidth);
printf("位圖高度:%d \n", fi->biHeight);
printf("位圖平面數(shù):%d \n", fi->biPlanes);
printf("顏色位數(shù):%d \n", fi->biBitCount);
printf("壓縮方式:%d \n", fi->biCompression);
printf("實(shí)際位圖數(shù)據(jù)占用的字節(jié)數(shù):%d \n", fi->biSizeImage);
printf("X方向分辨率:%d \n", fi->biXPixPerMeter);
printf("Y方向分辨率:%d \n", fi->biYPixPerMeter);
printf("使用的顏色數(shù):%d \n", fi->biClrUsed);
printf("重要顏色數(shù):%d \n", fi->biClrImporant);
printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
//修改信息頭
fi->biBitCount = 8;
//fi->biSizeImage = ((fi->biWidth * 3 + 3) / 4) * 4 * fi->biHeight;
fi->biSizeImage = fi->biHeight*fi->biWidth;
//修改文件頭
fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
fh->bfSize = fh->bfOffBits + fi->biSizeImage;
printf("\\\\\\\\\\\\\\\\\\\\修改后的圖片信息\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
printf("bmp文件頭:\n");
printf("bfSize:%d\n", fh->bfSize);
printf("bfOffBits:%d\n", fh->bfOffBits);
printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
printf("bmp信息頭\n");
printf("結(jié)構(gòu)體長(zhǎng)度:%d \n", fi->biSize);
printf("位圖寬度:%d \n", fi->biWidth);
printf("位圖高度:%d \n", fi->biHeight);
printf("位圖平面數(shù):%d \n", fi->biPlanes);
printf("顏色位數(shù):%d \n", fi->biBitCount);
printf("壓縮方式:%d \n", fi->biCompression);
printf("實(shí)際位圖數(shù)據(jù)占用的字節(jié)數(shù):%d \n", fi->biSizeImage);
printf("X方向分辨率:%d \n", fi->biXPixPerMeter);
printf("Y方向分辨率:%d \n", fi->biYPixPerMeter);
printf("使用的顏色數(shù):%d \n", fi->biClrUsed);
printf("重要顏色數(shù):%d \n", fi->biClrImporant);
printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
//創(chuàng)建調(diào)色板
int i,j,k=0;
rgbq *fq = (rgbq *)malloc(256 * sizeof(rgbq));
for (i = 0; i<256; i++)
{
fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
}
//寫入文件頭、信息頭、調(diào)色板
fwrite(fh, sizeof(fileHeader), 1, fp2);
fwrite(fi, sizeof(fileInfo), 1, fp2);
fwrite(fq, sizeof(rgbq), 256, fp2);
//將位圖信息轉(zhuǎn)為灰度
//存儲(chǔ)bmp一行的像素點(diǎn)
//unsigned char ImgData[900][3];
unsigned char ImgData[3000][3];
//將灰度圖像存到一維數(shù)組中
//unsigned char grayData2[900];
unsigned char ImgData2[3000];
/*
//錯(cuò)誤的算法
for (i = 0; i < fi->biHeight; i++)
{
for (j = 0; j < (fi->biWidth * 3 + 3) / 4 * 4; j++)
{
for (k = 0; k < 3; k++)
{
fread(&ImgData[j][k], 1, 1, fp1);
}
}
for (j = 0; j < (fi->biWidth + 3) / 4 * 4; j++)
{
ImgData2[j] = int((float)ImgData[j][0] * 0.114 +
(float)ImgData[j][1] * 0.587 +
(float)ImgData[j][2] * 0.299);
}
//將灰度圖信息寫入
fwrite(ImgData2, j, 1, fp2);
}
*/
/*
//正確的算法(1)
for (i = 0; i<fi->biHeight; i++)
{
for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
{
for (k = 0; k<3; k++)
fread(&ImgData[j][k], 1, 1, fp1);
}
for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
{
ImgData2[j] = int((float)ImgData[j][0] * 0.114 +
(float)ImgData[j][1] * 0.587 +
(float)ImgData[j][2] * 0.299);
}
//將灰度圖信息寫入
fwrite(ImgData2, j, 1, fp2);
}
*/
//正確算法(2)
unsigned char * * bmp_data;
bmp_data = new unsigned char*[fi->biHeight]; //聲明一個(gè)指針數(shù)組
unsigned char *data288 = new unsigned char[fi->biHeight*fi->biWidth];
for (i = 0; i<fi->biHeight; i++)
bmp_data[i] = new unsigned char[(fi->biWidth * 3 + 3) / 4 * 4]; //每個(gè)數(shù)組元素也是一個(gè)指針數(shù)組
for (i = 0; i<fi->biHeight; i++)
for (j = 0; j<(fi->biWidth * 3 + 3) / 4 * 4; j++)
fread(&bmp_data[i][j], 1, 1, fp1);//每次只讀取一個(gè)字節(jié),存入數(shù)組
for (i = 0; i<fi->biHeight; i++)//將24位真彩色轉(zhuǎn)換成灰度圖
for (j = 0; j<fi->biWidth; j++){
data288[fi->biWidth*i + j] = ((unsigned char)((float)bmp_data[i][3 * j] * 0.114 + (float)bmp_data[i][3 * j + 1] * 0.587 + (float)bmp_data[i][3 * j + 2] * 0.299));
}
fwrite(data288, fi->biSizeImage, 1, fp2);
free(fh);
free(fi);
free(fq);
fclose(fp1);
fclose(fp2);
printf("success\n");
return 0;
}


以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言循環(huán)結(jié)構(gòu)深入刨析
C語(yǔ)言條件控制語(yǔ)句選擇結(jié)構(gòu),是屬于計(jì)算機(jī)的語(yǔ)言編輯,有在C語(yǔ)言條件控制中的語(yǔ)句選擇結(jié)構(gòu)的存在,即是C語(yǔ)言條件控制語(yǔ)句選擇結(jié)構(gòu),循環(huán)控制語(yǔ)句是一個(gè)基于C語(yǔ)言的編程語(yǔ)句,該語(yǔ)句主要有while循環(huán)語(yǔ)句、do-while循環(huán)語(yǔ)句和for循環(huán)語(yǔ)句來(lái)實(shí)現(xiàn)循環(huán)結(jié)構(gòu)2022-08-08
C++循環(huán)隊(duì)列實(shí)現(xiàn)模型
這篇文章主要介紹了C++循環(huán)隊(duì)列實(shí)現(xiàn)模型,較為詳細(xì)的分析了循環(huán)隊(duì)列算法的原理與實(shí)現(xiàn)方法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2014-12-12
C語(yǔ)言中函數(shù)棧幀的創(chuàng)建和銷毀的深層分析
在C語(yǔ)言中,每一個(gè)正在運(yùn)行的函數(shù)都有一個(gè)棧幀與其對(duì)應(yīng),棧幀中存儲(chǔ)的是該函數(shù)的返回地址和局部變量。從邏輯上講,棧幀就是一個(gè)函數(shù)執(zhí)行的環(huán)境:函數(shù)參數(shù)、函數(shù)的局部變量、函數(shù)執(zhí)行完后返回到哪里等等2022-04-04
VS Code 中搭建 Qt 開發(fā)環(huán)境方案分享
這篇文章主要介紹了VS Code 中搭建 Qt 開發(fā)環(huán)境方案分享的相關(guān)資料,需要的朋友可以參考下2022-12-12
C語(yǔ)言time.h庫(kù)函數(shù)的具體用法
C語(yǔ)言的time.h頭文件提供了一系列的函數(shù)和工具,用于處理時(shí)間和日期相關(guān)的操作,本文主要介紹了C語(yǔ)言time.h庫(kù)函數(shù)的具體用法,感興趣的可以了解一下2023-12-12
VS Code遠(yuǎn)程連接Linux服務(wù)器調(diào)試C程序的操作方法
這篇文章主要介紹了VS Code遠(yuǎn)程連接Linux服務(wù)器調(diào)試C程序的操作方法,打開遠(yuǎn)程 Linux 服務(wù)器上的文件夾本文以 /root/ 為例,給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12

