1. 程式人生 > >C/C++ 二進位制讀寫 png 檔案

C/C++ 二進位制讀寫 png 檔案

突然想起來以前弄軟工的時候雖然那個網站只完成了登入註冊和文字顯示,但是想在資料庫中儲存圖片的時候瞭解到1存圖片地址,2存圖片二進位制資料。

沒錯就是二進位制。然後拿起C++的翻開找啊找,弄了個ifstream ios::binary的,成功資料正常。

時隔一天才又想起來r和rb好像是有區別的。沒錯,那些知識確實沒有記住。然後就把C的也改ok了

以下程式碼只有最簡單的讀寫。地址定位啥的,個別註釋中有。如果要改動png的格式甚麼的就要再瞭解一下png的資料結構

如果要十進位制的話就跟著註釋改一下

mm.png


123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 #include<iostream>   #include<fstream>  using namespacestd;typedefunsignedcharbyte;/* 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+二進位制  voidwriteImage(byte*imgbuf,intsize){//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);}voidreadImageFile(constchar*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);longsize=ftell(imgP);byte*imgbuf=newbyte[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);}//===========================================================  voidWriteImage(byte*imgbuf,intsize){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();}voidReadImageFile(constchar*Imgname){ifstream imgF(Imgname,ios::binary);if(!imgF){cerr<<"open error!"<<endl;abort();}imgF.seekg(0,ios::end);intsize=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=newbyte[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);}intmain(){readImageFile("mm.png");//C/C++的  ReadImageFile("mm.png");//C++的  system("pause");return0;}