利用C/C++二進(jìn)制讀寫png文件的方法示例
前言
二進(jìn)制文件不是以ASCII代碼存放數(shù)據(jù)的,它將內(nèi)存中數(shù)據(jù)存儲(chǔ)形式不加轉(zhuǎn)換地傳送到磁盤文件,因此它又稱為內(nèi)存數(shù)據(jù)的映像文件。因?yàn)槲募械男畔⒉皇亲址麛?shù)據(jù),而是字節(jié)中的二進(jìn)制形式的信息,因此它又稱為字節(jié)文件。
對(duì)二進(jìn)制文件的操作也需要先打開文件,用完后要關(guān)閉文件。在打開時(shí)要用ios::binary指定為以二進(jìn)制形式傳送和存儲(chǔ)。二進(jìn)制文件除了可以作為輸入文件或輸出文件外,還可以是既能輸入又能輸出的文件。這是和ASCII文件不同的地方。
需求
最近為了弄OpenGl的紋理代碼,發(fā)現(xiàn)書上沒(méi)有圖片像素的獲取,然后就想寫個(gè)來(lái)獲取png的,結(jié)果花了一天的時(shí)間沒(méi)弄清楚為什么出現(xiàn)數(shù)據(jù)個(gè)別正確其他的卻是205
突然想起來(lái)以前弄軟工的時(shí)候雖然那個(gè)網(wǎng)站只完成了登入注冊(cè)和文本顯示,但是想在數(shù)據(jù)庫(kù)中存儲(chǔ)圖片的時(shí)候了解到1存圖片地址,2存圖片二進(jìn)制數(shù)據(jù)。
沒(méi)錯(cuò)就是二進(jìn)制。然后拿起C++的翻開找啊找,弄了個(gè)ifstream iOS::binary的,成功數(shù)據(jù)正常。
時(shí)隔一天才又想起來(lái)r和rb好像是有區(qū)別的。沒(méi)錯(cuò),那些知識(shí)確實(shí)沒(méi)有記住。然后就把C的也改ok了
以下代碼只有最簡(jiǎn)單的讀寫。地址定位啥的,個(gè)別注釋中有。如果要改動(dòng)png的格式甚么的就要再了解一下png的數(shù)據(jù)結(jié)構(gòu)
如果要十進(jìn)制的話就跟著注釋改一下
mm.png
實(shí)例代碼如下
#include<iostream> #include<fstream> using namespace std; typedef unsigned char byte; /* class PngMsg { private : unsigned char markMsg[8]; //十進(jìn)制,相當(dāng)于16進(jìn)制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帶α通道數(shù)據(jù)的灰度8.16;6帶α通道數(shù)據(jù)的真彩色8.16 unsigned char CompressionMethod;//壓縮方法(LZ77派生算法) unsigned char FilterMethod;//濾波器方法 unsigned char InterlaceMethod;//0:非隔行掃描;1:Adam7 };*/ //=============================== //=============== //二進(jìn)制讀入。書上寫ASCII碼讀取和二進(jìn)制讀取,如果對(duì)象是字母,那么一致。如果是數(shù)字,那么不一致 //書中說(shuō)明【文件中數(shù)據(jù)的組織形式,分為ASCII文件(一個(gè)字節(jié)存放一個(gè)ASCII代碼)和二進(jìn)制文件(內(nèi)部文件,存儲(chǔ)形式原樣在磁盤上存放),】 //字符,內(nèi)存存儲(chǔ)=ASCII=二進(jìn)制形式 //數(shù)值數(shù)據(jù),內(nèi)存存儲(chǔ)和ASCII碼不同。 //樣例內(nèi)存整數(shù)100000. //---------------------------------------------------------------- //內(nèi)存地址 0x00 01 02 03 //內(nèi)存 00000000 00000000 00100111 00010000【大端模式下】 //---------------------------------------------------------------- //二進(jìn)制 00000000 00000000 00100111 00010000 //---------------------------------------------------------------- //ASCII 00110001 00110000 00110000 00110000 00110000 00110000【6個(gè)字節(jié)】 //ASCII碼對(duì)應(yīng) 1的49 0的48 0的48 0的48 0的48 0的48 //---------------------------------------------------------------- //只有含‘寫'的不存在的文件會(huì)新建,其他會(huì)報(bào)錯(cuò) //r只讀;w只寫;a尾增(附加/寫);文本ASCII //rb讀;wb寫;ab尾增;二進(jìn)制 //以下讀寫↓ //r+;w+;a+;文本ASCII //rb+;wb+;ab+二進(jìn)制 void writeImage(byte*imgbuf, int size) { //FILE* fp = fopen(shaderFile, "wb"); //由于vs甚么安全性的原因,不讓使用fopen,用下面的fopen_s代替; FILE*imgPo; fopen_s(&imgPo, "mag.png", "wb");//這里是用二進(jìn)制讀取,read-r;binary-b;因?yàn)橹慌猺結(jié)果出錯(cuò)??!弄了后面那個(gè)的再來(lái)看這個(gè)才發(fā)現(xiàn)是這個(gè)的問(wèn)題!! 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");//這里是用二進(jìn)制讀取,read-r;binary-b;因?yàn)橹慌猺結(jié)果出錯(cuò)??!弄了后面那個(gè)的再來(lái)看這個(gè)才發(fā)現(xiàn)是這個(gè)的問(wèn)題??! 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);//一次性寫入后面注釋的是循環(huán)寫入 /* 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,出來(lái)的是對(duì)的,用char也可以。都是一個(gè)字節(jié)。 }*/ 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);//一次性讀入,書上的不知是錯(cuò)的還是舊的不可行。后面注釋的是循環(huán)讀入 /*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; }
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
上一篇:linux C++ 獲取文件絕對(duì)路徑的實(shí)例代碼
欄 目:C語(yǔ)言
下一篇:C語(yǔ)言 strftime 格式化顯示日期時(shí)間的實(shí)現(xiàn)
本文標(biāo)題:利用C/C++二進(jìn)制讀寫png文件的方法示例
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/1868.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解
- 01-10深入理解C/C++混合編程


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文