以下代碼只有最簡單的讀寫。地址定位啥的,個別注釋中有。如果要改動png的格式甚么的就要再了解一下png的數據結構如果要十進制的話就跟着注釋改一下:
/*! * \file CC++二進制讀寫png文件.cpp * * \author ranjiewen * \date 2017/02/12 13:08 * */ #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, "C_write_image.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("C++_write_image.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; }