為了弄OpenGl的紋理程式碼,發現書上沒有圖片畫素的獲取,然後就想寫個來獲取png的,結果花了一天的時間沒弄清楚為什麼出現資料個別正確其他的卻是205
突然想起來以前弄軟工的時候雖然那個網站只完成了登入註冊和文字顯示,但是想在資料庫中儲存圖片的時候瞭解到1存圖片地址,2存圖片二進位制資料。
沒錯就是二進位制。然後拿起C++的翻開找啊找,弄了個ifstream ios::binary的,成功資料正常。
時隔一天才又想起來r和rb好像是有區別的。沒錯,那些知識確實沒有記住。然後就把C的也改ok了
以下程式碼只有最簡單的讀寫。地址定位啥的,個別註釋中有。如果要改動png的格式甚麼的就要再瞭解一下png的資料結構
如果要十進位制的話就跟著註釋改一下
mm.png
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
#include<iostream> #include<fstream> using namespace std; typedef unsigned char byte; /* class PngMsg { private : unsigned char markMsg[8]; //十進位制,相當於16進位制89.50.4e.47.0d.0a.1a.0a; char widthloc; char heigtMsgloc; char BitDepthloc;//影像深度 char ColorTypeloc; char CompressionMethodloc;//壓縮方法(LZ77派生演算法) char FilterMethodloc;//濾波器方法 char InterlaceMethodloc; public: PngMsg() { markMsg[0] = 137;markMsg[1] = 80; markMsg[2] = 78;markMsg[3] = 71; markMsg[4] = 13;markMsg[5] = 10; markMsg[6] = 26; markMsg[7] = 10; widthloc = 'a'; heigtMsgloc = 'b'; BitDepthloc = 'c';//影像深度 ColorTypeloc = 'd'; CompressionMethodloc = 'e';//壓縮方法(LZ77派生演算法) FilterMethodloc = 'f';//濾波器方法 InterlaceMethodloc = 'g'; } long int getMsg(char loc) { if (loc == 'a')return 0x10; if (loc == 'b')return 0x14; if (loc == 'c')return 0x15; if (loc == 'd')return 0x16; if (loc == 'e')return 0x17; if (loc == 'f')return 0x18; if (loc == 'g')return 0x19; } unsigned char width[4];//影像寬度,單位畫素 unsigned char height[4];//影像高度,單位畫素 unsigned char BitDepth; //影像深度 //索引彩色1.2.4.8;灰度1.2.4.8.16;真彩色8.16 unsigned char ColorType; //0灰度1.2.4.8.16;2真彩色8.16;3索引彩色1.2.4.8 //4帶α通道資料的灰度8.16;6帶α通道資料的真彩色8.16 unsigned char CompressionMethod;//壓縮方法(LZ77派生演算法) unsigned char FilterMethod;//濾波器方法 unsigned char InterlaceMethod;//0:非隔行掃描;1:Adam7 };*/ //=============================== //=============== //二進位制讀入。書上寫ASCII碼讀取和二進位制讀取,如果物件是字母,那麼一致。如果是數字,那麼不一致 //書中說明【檔案中資料的組織形式,分為ASCII檔案(一個位元組存放一個ASCII程式碼)和二進位制檔案(內部檔案,儲存形式原樣在磁碟上存放),】 //字元,記憶體儲存=ASCII=二進位制形式 //數值資料,記憶體儲存和ASCII碼不同。 //樣例記憶體整數100000. //---------------------------------------------------------------- //記憶體地址 0x00 01 02 03 //記憶體 00000000 00000000 00100111 00010000【大端模式下】 //---------------------------------------------------------------- //二進位制 00000000 00000000 00100111 00010000 //---------------------------------------------------------------- //ASCII 00110001 00110000 00110000 00110000 00110000 00110000【6個位元組】 //ASCII碼對應 1的49 0的48 0的48 0的48 0的48 0的48 //---------------------------------------------------------------- //只有含‘寫’的不存在的檔案會新建,其他會報錯 //r只讀;w只寫;a尾增(附加/寫);文字ASCII //rb讀;wb寫;ab尾增;二進位制 //以下讀寫↓ //r+;w+;a+;文字ASCII //rb+;wb+;ab+二進位制 void writeImage(byte*imgbuf, int size) { //FILE* fp = fopen(shaderFile, "wb"); //由於vs甚麼安全性的原因,不讓使用fopen,用下面的fopen_s代替; FILE*imgPo; fopen_s(&imgPo, "mag.png", "wb");//這裡是用二進位制讀取,read-r;binary-b;因為只弄r結果出錯!!弄了後面那個的再來看這個才發現是這個的問題!! if (imgPo == NULL)return; fwrite(imgbuf, sizeof(char),size,imgPo); fclose(imgPo); } void readImageFile(const char* Imgname) { //FILE* fp = fopen(shaderFile, "rb"); //由於vs甚麼安全性的原因,不讓使用fopen,用下面的fopen_s代替; FILE*imgP; fopen_s(&imgP,Imgname,"rb");//這裡是用二進位制讀取,read-r;binary-b;因為只弄r結果出錯!!弄了後面那個的再來看這個才發現是這個的問題!! if (imgP == NULL)return ; fseek(imgP, 0L, SEEK_END); long size = ftell(imgP); byte*imgbuf = new byte[size+ 1]; fseek(imgP,0x0L,SEEK_SET);//圖片源 fread(imgbuf, sizeof(imgbuf[0]), size, imgP); /*for (int j = 0; j < size; j++) cout << (imgbuf[j] & 0xff) << ":";*/ fclose(imgP); writeImage(imgbuf, size); } //=========================================================== void WriteImage(byte*imgbuf, int size) { ofstream imgFo("Image2.png", ios::binary); if (!imgFo) { cerr << "open error!" << endl; abort(); } imgFo.write((char*)imgbuf, size);//一次性寫入後面註釋的是迴圈寫入 /* for (int i = 0; i < size; i++) { char ct = (imgbuf[i] & 0xFF); imgFo.write(&ct, sizeof(char)); //byte ct = (imgbuf[i] & 0xFF); //imgFo.write((char*)&ct, sizeof(byte)); //嘗試這樣輸出的是否正確. //byte是我自己給名的unsigned char,出來的是對的,用char也可以。都是一個位元組。 }*/ imgFo.close(); } void ReadImageFile(const char* Imgname) { ifstream imgF(Imgname, ios::binary); if (!imgF) { cerr << "open error!" << endl; abort(); } imgF.seekg(0, ios::end); int size = imgF.tellg(); //查了C++Library Reference才知道怎麼得到size。 /*int pixscnt; byte width[4], height[4]; imgF.seekg(0x10); imgF.read((char*)&width, sizeof(width)); imgF.seekg(0x14); imgF.read((char*)&height, sizeof(height)); for (int i = 0; i < 4; i++) cout << (width[i] & 0xff) << ":"; for (int i = 0; i < 4; i++) cout << (height[i] & 0xff) << ":"; pixscnt = (width[2] * (0x100) + width[3])*(height[2] * (0x100) + height[3]); cout << pixscnt << endl;//畫素 cout << size << endl;*/ byte*imgbuf = new byte[size]; //imgF.seekg(0x10); imgF.seekg(0,ios::beg); imgF.read((char*)imgbuf, size);//一次性讀入,書上的不知是錯的還是舊的不可行。後面註釋的是迴圈讀入 /*for (int i = 0; i<size; i++) imgF.read( (char*)&imgbuf[i], sizeof(byte));*/ imgF.close(); /*for (int i = 0; i < size; i++) { cout << hex << (imgbuf[i] & 0xff) << ":"; if (i % 4 == 0)cout << endl; } */ WriteImage(imgbuf, size); } int main() { readImageFile("mm.png");//C/C++的 ReadImageFile("mm.png");//C++的 system("pause"); return 0; } |