node 16位 转24位_同时将24位和32位BMP图像顺时针旋转90度
上一次我們將24位的皮卡丘旋轉(zhuǎn)了90度,但是后來改需求了。。。要求把32位的.bmp文件也能夠旋轉(zhuǎn)90度。上次就懵逼的我繼續(xù)懵逼,只好繼續(xù)轉(zhuǎn)向CSDN求助。
瀏覽了各種求助帖(還找到了數(shù)年前的信科大一學(xué)長(zhǎng)),終于發(fā)現(xiàn)了32位和24位的區(qū)別:32位圖的每一個(gè)像素信息占4個(gè)字節(jié),除了RGB三個(gè)顏色值以外,還有一個(gè)字節(jié)存儲(chǔ)的是透明度。在讀取和寫入32位圖的時(shí)候,每一個(gè)像素就要多讀(寫)一個(gè)字節(jié)。這就導(dǎo)致了24位和32位的DATA結(jié)構(gòu)體不一樣。如果定義兩個(gè)DATA結(jié)構(gòu)體,之后每次涉及到它的時(shí)候都要判斷一下圖的位數(shù),好像很麻煩的亞子。為了解決這個(gè)問題,我們就不得不放棄上一次所用的DATA結(jié)構(gòu)體了 。
//Farewell my DATA~ struct DATA {BYTE blue;BYTE green;BYTE red; };我們轉(zhuǎn)而直接按字節(jié)(BYTE)讀取,不再將一個(gè)像素的信息裝在結(jié)構(gòu)體中,而是將其分開讀取。需要在原來的代碼上做一些改變,先把所有DATA類型的指針改為BYTE類型,分配存儲(chǔ)空間的時(shí)候把空間大小也調(diào)整一下。
//32位就分配size*4,24位就分配size*3 BYTE *imgdata=new BYTE[size * srcInfo.biBitCount / 8];然后我們把原來代碼中的所有數(shù)字3改成biBitCount/8:
fread(imgdata + i * w * srcInfo.biBitCount / 8, srcInfo.biBitCount / 8, w, p);這里因?yàn)閕mgdata的類型已經(jīng)是unsigned char*了,只占1個(gè)字節(jié),所以不用再進(jìn)行指針類型轉(zhuǎn)換(char*)了。
原先在旋轉(zhuǎn)操作中賦值的時(shí)候只用賦值一次,就能將DATA結(jié)構(gòu)體賦值給新的target指針。但現(xiàn)在沒有DATA結(jié)構(gòu)體了,我們就需要對(duì)每個(gè)像素的字節(jié)依次賦值:
for (int i=0; i<newH; i++){for (int j=0; j<newW; j++){*(target + (i * newW + j)*newInfo.biBitCount / 8) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 1) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 1);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 2) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 2);if (newInfo.biBitCount == 32) {*(target + (i * newW + j) * newInfo.biBitCount / 8 + 3) =*(src + (j * w + newH - i - 1) * newInfo.biBitCount / 8 + 3);}}}這樣主體就完成了,但是如果只修改這些的話,會(huì)發(fā)現(xiàn)最終生成的32位圖無法打開。原因在于32位圖和24位圖的信息頭有一點(diǎn)點(diǎn)差異:多了一些不知道是啥的內(nèi)容。我們就把這些東西放在一個(gè)新的結(jié)構(gòu)體Plus里吧。在讀取和寫入的時(shí)候判斷一下圖像位數(shù),如果是32位就把這個(gè)Plus也讀/寫一下。
struct Plus{DWORD bV5RedMask;DWORD bV5GreenMask;DWORD bV5BlueMask;DWORD bV5AlphaMask;DWORD bV5CSType;CIEXYZTRIPLE bV5Endpoints;DWORD bV5GammaRed;DWORD bV5GammaGreen;DWORD bV5GammaBlue;DWORD bV5Intent;DWORD bV5ProfileData;DWORD bV5ProfileSize;DWORD bV5Reserved; };Plus的內(nèi)容來自CSDN,其中那個(gè)醒目的CIEXYZTRIPLE是啥...我也不知道 。所以只好開始了漫長(zhǎng)的搜索之路,最終找到了他的定義:
CIEXYZTRIPLE的定義圖中FXPT2DOT30表示它們是帶有2位元整數(shù)部分和30位元小數(shù)部分的定點(diǎn)值,這說的是啥我也不懂,只需要知道FXPT2DOT30其實(shí)就和int差不多就好了:
typedef int FXPT2DOT30;現(xiàn)在就把所有東西全部定義好了,試著轉(zhuǎn)一下這個(gè)年代久遠(yuǎn)的32位圖:
原圖順時(shí)針旋轉(zhuǎn)90度最后附上完整的代碼:
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> using namespace std;typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef int FXPT2DOT30;typedef struct tagCIEXYZ {FXPT2DOT30 ciexyzX ;FXPT2DOT30 ciexyzY ;FXPT2DOT30 ciexyzZ ; } CIEXYZ, * LPCIEXYZ ;typedef struct tagCIEXYZTRIPLE {CIEXYZ ciexyzRed ;CIEXYZ ciexyzGreen ;CIEXYZ ciexyzBlue ; }CIEXYZTRIPLE;//位圖文件頭定義; struct Header{DWORD bfSize;//文件大小WORD bfReserved1;//保留字WORD bfReserved2;//保留字DWORD bfOffBits;//從文件頭到實(shí)際位圖數(shù)據(jù)的偏移字節(jié)數(shù) };//位圖信息頭定義 struct Info{DWORD biSize;//信息頭大小DWORD biWidth;//圖像寬度DWORD biHeight;//圖像高度WORD biPlanes;//位平面數(shù),必須為1WORD biBitCount;//每像素位數(shù)DWORD biCompression; //壓縮類型DWORD biSizeImage; //壓縮圖像大小字節(jié)數(shù)DWORD biXPelsPerMeter; //水平分辨率DWORD biYPelsPerMeter; //垂直分辨率DWORD biClrUsed; //位圖實(shí)際用到的色彩數(shù)DWORD biClrImportant; //本位圖中重要的色彩數(shù) };struct Plus{DWORD bV5RedMask;DWORD bV5GreenMask;DWORD bV5BlueMask;DWORD bV5AlphaMask;DWORD bV5CSType;CIEXYZTRIPLE bV5Endpoints;DWORD bV5GammaRed;DWORD bV5GammaGreen;DWORD bV5GammaBlue;DWORD bV5Intent;DWORD bV5ProfileData;DWORD bV5ProfileSize;DWORD bV5Reserved; };WORD bfType;//文件類型 Header srcHead;//原文件文件頭 Info srcInfo;//原文件信息頭 Plus srcPlus; int h,w,size;//原圖像的高度、寬度和尺寸int getDiff(Info & info) {int DataSizePerline = (info.biWidth * info.biBitCount+31) / 8;DataSizePerline -= DataSizePerline % 4;return DataSizePerline - info.biWidth * info.biBitCount / 8; }void rotation(const BYTE* src){int newH = w;int newW = h;//圖片旋轉(zhuǎn)90度之后寬度、高度互換int newSize = newH * newW;FILE *p;p=fopen("dest.bmp","wb");Header newHead = srcHead;Info newInfo = srcInfo;Plus newPlus = srcPlus;//修改旋轉(zhuǎn)后圖片的尺寸、寬度和高度newHead.bfSize = (DWORD)(newHead.bfSize);newInfo.biHeight = (DWORD)newH;newInfo.biWidth = (DWORD)newW;int newdiff = getDiff(newInfo);newInfo.biSizeImage = (DWORD)((newInfo.biWidth * newInfo.biBitCount / 8 + newdiff) * newInfo.biHeight);//將種類、文件頭、信息頭寫入新bmp文件fwrite(&bfType,1, sizeof(WORD),p);fwrite(&newHead,1, sizeof(Header),p);fwrite(&newInfo,1, sizeof(Info),p);if (newInfo.biBitCount == 32){fwrite(&newPlus, 1, sizeof(Plus), p);}BYTE* target = new BYTE[newSize * newInfo.biBitCount / 8];for (int i=0; i<newH; i++){for (int j=0; j<newW; j++){*(target + (i * newW + j)*newInfo.biBitCount / 8) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 1) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 1);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 2) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 2);if (newInfo.biBitCount == 32) {*(target + (i * newW + j) * newInfo.biBitCount / 8 + 3) =*(src + (j * w + newH - i - 1) * newInfo.biBitCount / 8 + 3);}}}for (int i=0; i<newH; i++){fwrite(target + i * newW * (newInfo.biBitCount / 8), newInfo.biBitCount / 8, newW, p);fseek(p, newdiff, SEEK_CUR);}fclose(p);delete []target; }int main(){FILE* p;p = fopen("src.bmp", "rb");if (p != NULL){//先讀取文件類型fread(&bfType, 1, sizeof(WORD), p);//讀取bmp文件的文件頭和信息頭fread(&srcHead,1, sizeof(Header), p);fread(&srcInfo,1, sizeof(Info), p);if (srcInfo.biBitCount == 32){fread(&srcPlus, 1, sizeof(Plus), p);}h=srcInfo.biHeight;w=srcInfo.biWidth;size = w * h;BYTE *imgdata=new BYTE[size * srcInfo.biBitCount / 8];int diff = getDiff(srcInfo);//讀取原圖片像素信息for (int i=0;i<h;i++){fread(imgdata + i * w * srcInfo.biBitCount / 8, srcInfo.biBitCount / 8, w, p);fseek(p, diff, SEEK_CUR);}fclose(p);rotation(imgdata);delete []imgdata;}else{cout<<"無法打開文件"<<endl;}return 0; } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的node 16位 转24位_同时将24位和32位BMP图像顺时针旋转90度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信用卡怎样注销
- 下一篇: 续航超1000公里!蔚来ET5亮相:4.