C/C++二進制讀寫png文件


 

       以下代碼只有最簡單的讀寫。地址定位啥的,個別注釋中有。如果要改動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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM