BMP的圖像處理
阿新 • • 發佈:2017-07-08
off 紅色 類型 compress 技術 位圖 gets 圖像處理 lib
驗證下面圖片效果還能夠。
近期碰到了一個問題將圖片縮放:
進行了整理發現位圖一些主要的結構能夠進行整理,得出下面圖表:
進行圖片縮放的時候會進行一些處理(最臨近差值法):
詳細的代碼例如以下:
#include <stdio.h> #include <string.h> #include <math.h> #include <windows.h> #include <stdlib.h> LONG IWidth; //原圖像的寬 LONG IHeight; //原圖像的高 LONG biBitCount; //每像素位數 LONG INewWidth; //新圖像的寬 LONG INewHeight; //新圖像的高 LONG ILineByte; //原圖像數據每行的字節數 LONG INewLineByte; //新圖像數據每行的字節數 float zoomnumber=1; //初始放大倍數賦值為1 unsigned char *pIBuf; //原圖像像素指針 unsigned char *pINewBuf;//新圖像像素指針 int ReadBmp(const char* bmpName)//以二進制方式讀入指定的圖像文件 { FILE *fp=fopen(bmpName,"rb"); if(fp==0) { printf("打開文件失敗\n"); return 0; } fseek(fp,sizeof(BITMAPFILEHEADER),0);//跳過位圖文件頭 BITMAPINFOHEADER head;//定義位圖信息頭結構體變量。存放在變量head中 fread(&head,sizeof(BITMAPINFOHEADER),1,fp);//獲取圖像的高、寬和每像素所占的位數,接收地址head。單個元素大小文件頭大小。元素個數1個,輸入流fp IWidth = head.biWidth; IHeight = head.biHeight; biBitCount = head.biBitCount; ILineByte = (IWidth *biBitCount/8+3)/4*4;//計算原圖像每行字節數,/4*4以保證是4的倍數 pIBuf = new unsigned char [ILineByte *IHeight];//定義一個矩陣用以存放原圖像像素信息。pIBuf指向首地址 fread(pIBuf,1,ILineByte *IHeight,fp);//獲取源文件像素信息。接收地址pIBuf,單個元素大小1字節,元素個數每行字節數*行數,輸入流fp return 1;//成功返回1 } int SaveBmp(const char* bmpName,unsigned char *imgBuf,int width,int height,int biBitCount)//圖像存儲 { if(!imgBuf)//假設沒有像素數據傳入,則函數返回 return 0; INewLineByte = (width * biBitCount/8+3)/4*4;//計算新圖像每行字節數。/4*4以保證是4的倍數 FILE *fp = fopen(bmpName,"wb");//以二進制方式寫文件 if(fp == 0) return 0; BITMAPFILEHEADER fileHead;//申請位圖文件頭結構變量,填寫文件頭信息 fileHead.bfType= 0x4d42;//bmp類型 fileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+ INewLineByte *height;//位圖文件大小 fileHead.bfReserved1 = 0;//保留字 fileHead.bfReserved2 = 0;//保留字 fileHead.bfOffBits = 54;//文件頭到實際的位圖數據的偏移字節數。前三個部分字節數之和 fwrite(&fileHead,sizeof(BITMAPFILEHEADER),1,fp);//將新圖像數據寫入文件,獲取數據地址fileHead,單個元素大小文件頭大小,元素個數1個,輸入流fp BITMAPINFOHEADER head;//定義位圖信息頭結構變量,存放在變量head中 head.biBitCount = biBitCount;//24位 head.biClrImportant = 0;//位圖顯示過程中重要的顏色數,覺得全部的顏色都是重要的 head.biClrUsed = 0;//位圖實際用到的顏色數為2的biBitCount次冪 head.biCompression = 0;//位圖壓縮類型 head.biHeight = height;//新圖像高 head.biPlanes =1;//目標設備的級別 head.biSize = 40;//本結構體長度 head.biSizeImage = ILineByte *height;//實際的位圖數據占用的字節數 head.biWidth = width;//新圖像寬 head.biXPelsPerMeter = 0;//指定目標設備的水平分辨率 head.biYPelsPerMeter = 0;//指定目標設備的垂直分辨率 fwrite(&head,sizeof(BITMAPINFOHEADER),1,fp);//寫入信息頭 fwrite(imgBuf,height * INewLineByte,1,fp);//寫入像素數據 fclose(fp);//關閉文件 return 1; } int Zoom(const char* readPath )//圖像縮放 { char address[50]; ReadBmp(readPath);//讀取圖像 INewWidth = (int) ((IWidth * zoomnumber) +0.5);//新圖像的寬度。此處加0.5是因為強制轉換時不四舍五入,而是直接截去小數部分 INewHeight = (int) (IHeight * zoomnumber +0.5);//新圖像的高帶。此處加0.5是因為強制轉換時不四舍五入,而是直接截去小數部分 ILineByte =(IWidth*biBitCount/8+3)/4*4;//原圖像每行字節數 INewLineByte = (INewWidth * biBitCount/8+3)/4*4;//新圖像每行字節數 pINewBuf = new unsigned char [INewLineByte * INewHeight];//定義一個矩陣用以存放新圖像像素信息,pIBuf指向首地址 LONG i; //循環變量(像素在新圖像中的坐標) LONG j; LONG k; //色彩選擇,k=0時為藍色,k=1時為綠色,k=2時為紅色 LONG i0; //像素在原圖像中的坐標 LONG j0; if(biBitCount == 24) { for(i = 0;i < INewHeight;i++) { for(j = 0; j < INewWidth;j++) for(k=0;k<3;k++) { i0 = (int)(i/zoomnumber+0.5); j0 = (int)(j/zoomnumber+0.5); if((j0 >= 0) && (j0 < IWidth) && (i0 >=0)&& (i0 <IHeight)) { *(pINewBuf+i*INewLineByte+j*3+k) = *(pIBuf+i0*ILineByte+j0*3+k);//最鄰近插值 } else { *(pINewBuf+i*INewLineByte+j*3+k)=255; } } } } printf("輸入bmp圖像縮放後需保存的路徑名稱和後綴:"); gets(address); SaveBmp(address,pINewBuf,INewWidth,INewHeight,biBitCount);//調用SaveBmp函數保存圖像 delete []pINewBuf;//清除指針 return 1; } void main() { char filepath[256]; printf("請輸入bmp圖片路徑,名稱和後綴:(如E:\1.bmp)"); scanf("%s",filepath); ReadBmp(filepath);//調用ReadBmp函數 printf("請輸入所要縮放的倍數(小於1為縮小,大於1為放大):"); scanf("%f",&zoomnumber);getchar(); Zoom(filepath); }
驗證下面圖片效果還能夠。
BMP的圖像處理