node 16位 转24位_同时将24位和32位BMP图像顺时针旋转90度
上一次我們將24位的皮卡丘旋轉了90度,但是后來改需求了。。。要求把32位的.bmp文件也能夠旋轉90度。上次就懵逼的我繼續懵逼,只好繼續轉向CSDN求助。
瀏覽了各種求助帖(還找到了數年前的信科大一學長),終于發現了32位和24位的區別:32位圖的每一個像素信息占4個字節,除了RGB三個顏色值以外,還有一個字節存儲的是透明度。在讀取和寫入32位圖的時候,每一個像素就要多讀(寫)一個字節。這就導致了24位和32位的DATA結構體不一樣。如果定義兩個DATA結構體,之后每次涉及到它的時候都要判斷一下圖的位數,好像很麻煩的亞子。為了解決這個問題,我們就不得不放棄上一次所用的DATA結構體了 。
//Farewell my DATA~ struct DATA {BYTE blue;BYTE green;BYTE red; };我們轉而直接按字節(BYTE)讀取,不再將一個像素的信息裝在結構體中,而是將其分開讀取。需要在原來的代碼上做一些改變,先把所有DATA類型的指針改為BYTE類型,分配存儲空間的時候把空間大小也調整一下。
//32位就分配size*4,24位就分配size*3 BYTE *imgdata=new BYTE[size * srcInfo.biBitCount / 8];然后我們把原來代碼中的所有數字3改成biBitCount/8:
fread(imgdata + i * w * srcInfo.biBitCount / 8, srcInfo.biBitCount / 8, w, p);這里因為imgdata的類型已經是unsigned char*了,只占1個字節,所以不用再進行指針類型轉換(char*)了。
原先在旋轉操作中賦值的時候只用賦值一次,就能將DATA結構體賦值給新的target指針。但現在沒有DATA結構體了,我們就需要對每個像素的字節依次賦值:
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);}}}這樣主體就完成了,但是如果只修改這些的話,會發現最終生成的32位圖無法打開。原因在于32位圖和24位圖的信息頭有一點點差異:多了一些不知道是啥的內容。我們就把這些東西放在一個新的結構體Plus里吧。在讀取和寫入的時候判斷一下圖像位數,如果是32位就把這個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的內容來自CSDN,其中那個醒目的CIEXYZTRIPLE是啥...我也不知道 。所以只好開始了漫長的搜索之路,最終找到了他的定義:
CIEXYZTRIPLE的定義圖中FXPT2DOT30表示它們是帶有2位元整數部分和30位元小數部分的定點值,這說的是啥我也不懂,只需要知道FXPT2DOT30其實就和int差不多就好了:
typedef int FXPT2DOT30;現在就把所有東西全部定義好了,試著轉一下這個年代久遠的32位圖:
原圖順時針旋轉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;//從文件頭到實際位圖數據的偏移字節數 };//位圖信息頭定義 struct Info{DWORD biSize;//信息頭大小DWORD biWidth;//圖像寬度DWORD biHeight;//圖像高度WORD biPlanes;//位平面數,必須為1WORD biBitCount;//每像素位數DWORD biCompression; //壓縮類型DWORD biSizeImage; //壓縮圖像大小字節數DWORD biXPelsPerMeter; //水平分辨率DWORD biYPelsPerMeter; //垂直分辨率DWORD biClrUsed; //位圖實際用到的色彩數DWORD biClrImportant; //本位圖中重要的色彩數 };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;//圖片旋轉90度之后寬度、高度互換int newSize = newH * newW;FILE *p;p=fopen("dest.bmp","wb");Header newHead = srcHead;Info newInfo = srcInfo;Plus newPlus = srcPlus;//修改旋轉后圖片的尺寸、寬度和高度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; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的node 16位 转24位_同时将24位和32位BMP图像顺时针旋转90度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信用卡怎样注销
- 下一篇: 怎么提交 checkbox 表单_8.