您的位置:首页 > 编程语言 > C语言/C++

png数据块IHDR_IDAT_END读取

2016-04-11 15:32 489 查看
弄了这么些天,还没有找到我要的像素点的RGBA值。先这样放下。va_arg几个月的间断。数组传递又一塌糊涂。。。
#include<iostream>
#include<fstream>
#include <stdarg.h> //--尝试用那个三个点的可变参数...所以要这个头文件,不用头文件就要像宽度高度一样连续5个读取
using namespace std;
typedef unsigned char byte;//新名

//------------------下面这些是宏,左边名换右边的字符串或数字或代码
#define mark_NUm 8
#define IS_PNG(x) (0x89==x[0])&&(0x50==x[1])&&(0x4E==x[2])&&(0x47==x[3])&&(0x0D==x[4])&&(0x0A==x[5])&&(0x1A==x[6])&&(0x0A==x[7])
#define MARK_LOC(loc_0x) (loc_0x+0x04)//返回此块标识在文件中头地址
#define DATA_LOC(loc_0x) (loc_0x+0x08)//返回此块数据在文件中头地址
#define END_LOC(loc_0x,imp_0x)  (loc_0x+0xC+imp_0x)//返回此块的下一块地址
#define FIND_IHDR(x,off)(('I'==x[off])&&('H'==x[off+1])&&('D'==x[off+2])&&('R'==x[off+3]))
#define FIND_IDAT(x,off)(('I'==x[off])&&('D'==x[off+1])&&('A'==x[off+2])&&('T'==x[off+3]))
#define FIND_IEND(x,off)(('I'==x[off])&&('E'==x[off+1])&&('N'==x[off+2])&&('D'==x[off+3]))
#define IHDRloc 0x08
#define widthloc   0x10
#define heigtloc  0x14
#define BitDepthloc 0x15//图像深度
#define ColorTypeloc 0x16
#define CompressionMethodloc 0x17//压缩方法(LZ77派生算法)
#define FilterMethodloc 0x18//滤波器方法
#define InterlaceMethodloc 0x19

//--------------自己定义的class类,主要是IHDR块
class PngMsg
{
private :
byte width[4];//图像宽度,单位像素
byte height[4];//图像高度,单位像素
byte BitDepth;
//图像深度
//索引彩色1.2.4.8;灰度1.2.4.8.16;真彩色8.16
byte ColorType;
//0灰度1.2.4.8.16;2真彩色8.16;3索引彩色1.2.4.8
//4带α通道数据的灰度8.16;6带α通道数据的真彩色8.16
byte CompressionMethod;//压缩方法(LZ77派生算法)
byte FilterMethod;//滤波器方法
byte InterlaceMethod;//0:非隔行扫描;1:Adam7
int IDATloc;
int DATNUM;
int IENDloc;
int offSet;
public:
void PNGReadImageFile(const char* Imgname);
void display();
template<typename T>
void Dis(int count, T* O_O, ...);
template<typename T>
void Read(ifstream* imgF,int count, T  *O_O, ...);//写过java的数据库。发现有三个点表可扩展的。C的就来试试啦yoho!
};

//-----用来测试输出的
template<typename T>//函数模版
void PngMsg::Dis( int count,T* O_O, ...)
{
va_list theThis;
va_start(theThis,count);// _crt_va_start(a,b)把b的地址+b这个的偏移量加给进去=下一个的地址;
for (; count > 0; count--)
{
T* temp=va_arg(theThis, T*);
cout << hex << ((*temp) &(0xFF))<< endl;
}
va_end(theThis);
}

//---使用三个点的读取。传入的是地址。
template<typename T>
void PngMsg::Read(ifstream *imgF, int count, T *O_O, ...)
{
va_list theThis;//参数串
va_start(theThis, count);//定位在给出的参数名的下一个位置O_O
for (; count > 0; count--)
{
//T** temp;
//temp = new T*;
//(*temp) = va_arg(theThis, T*);
//imgF->read((char*)(*temp), sizeof(T));
//cout << hex << ((*(*temp)) &(0xFF)) << " ";
//delete temp;
//================================
T* temp = va_arg(theThis, T*); //_crt_va_start(curLOC,type)把curLOC的当前地址上的数值返回;并把原来curLOC+type长度=下一个的地址;
imgF->read((char*)temp, sizeof(*temp));
//cout <<((*temp) &(0xFF)) << " ";
}
va_end(theThis);
}

//暂时没有用处
void PngMsg::display()
{
cout << "宽" << hex << width << endl;
cout << "高" << height << endl;
}

void PngMsg::PNGReadImageFile(const char* Imgname)
{
ifstream imgF(Imgname, ios::binary);
if (!imgF) {
cerr << "open error!" << endl;
abort();
}
byte mark[mark_NUm];
imgF.read((char*)mark, sizeof(mark));
if (!(IS_PNG(mark)))
{
imgF.close();
cerr << "no PNG!" << endl;
abort();
}
//=========================================================基础数据获取
imgF.seekg(widthloc);
imgF.read((char*)width, sizeof(width));

//imgF.seekg(heigtloc);//顺序与上面连接就注释掉了
imgF.read((char*)height, sizeof(height));

//imgF.seekg(BitDepthloc);//顺序与上面连接就注释掉了
Read(&imgF, 5,&BitDepth, &ColorType,& CompressionMethod, &FilterMethod, &InterlaceMethod);//循环读入对应数据
//Dis(5, &BitDepth, &ColorType, &CompressionMethod, &FilterMethod, &InterlaceMethod); //测试显示对应数值
for (int i = 0; i < 4; i++)
cout << (width[i] & 0xff) << ":";

for (int i = 0; i < 4; i++)
cout << (height[i] & 0xff) << ":";
//==========================================================定位IDAT块
imgF.seekg(0, ios::end);
int size = imgF.tellg();
offSet = IHDRloc;
int imp = 0;
for (bool fg = true; fg&& offSet < size;)
{
//cout << "offset:" << offSet << " size:" << size << "imp" << imp << endl;
imgF.seekg(offSet);
imgF.read((char*)mark, sizeof(mark));

//cout << (0xff & mark[0]) << (0xff & mark[1]) << (0xff & mark[2]) << (0xff & mark[3]) << endl;
imp = mark[2]* 0x100 + mark[3];
//cout << "offset:"<<offSet << " size:" << size <<"imp"<<imp<< endl;
cout << (0xff & mark[4]) << (0xff & mark[5]) << (0xff & mark[6]) << (0xff & mark[7]) << endl;
if (FIND_IDAT(mark, 4)) fg = false;
else
{
offSet = END_LOC(offSet,imp);
}
}
if (offSet >= size )
{
imgF.close();
cerr << "PNG 数据丢失:IDAT" << endl;
abort();
}
IDATloc = MARK_LOC(offSet);
DATNUM = imp;
//-----------------------------------------------------------------------
int pixscnt;
pixscnt = (width[2] * (0x100) + width[3])*(height[2] * (0x100) + height[3]);
cout << pixscnt << endl;//像素

//---------------------------------------------------------------------------
offSet = END_LOC(offSet, imp);
imp = 0;
for (bool fg = true; fg&& offSet < size;)
{
cout << "offset:" << offSet << " size:" << size << "imp" << imp << endl;
imgF.seekg(offSet);
imgF.read((char*)mark, sizeof(mark));

cout << (0xff & mark[0]) << (0xff & mark[1]) << (0xff & mark[2]) << (0xff & mark[3]) << endl;
imp = mark[2] * 0x100 + mark[3];
cout << "offset:" << offSet << " size:" << size << "imp" << imp << endl;
cout << (0xff & mark[4]) << (0xff & mark[5]) << (0xff & mark[6]) << (0xff & mark[7]) << endl;
if (FIND_IEND(mark, 4)) fg = false;
else
{
offSet = END_LOC(offSet, imp);
}
}
if (offSet >= size)
{
imgF.close();
cerr << "PNG 数据丢失:IEND" << endl;
abort();
}
IENDloc = MARK_LOC(offSet);

//==================================================

/*

int i = 0;
for (; i < 4; i++)
cout << (width[i] & 0xff) << ":";
for (int i = 0; i < size; i++)
{
cout << hex << (mark[i] & 0xff) << ":";
if (i % 4 == 0)cout << endl;
}
*/

imgF.close();

//WriteImage(imgbuf, size);
}
int main()

{
//readImageFile("mm.png");//C/C++的
//ReadImageFile("mm.png");//C++的
PngMsg t;
t.PNGReadImageFile("mm.png");
system("pause");
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ va_arg va_start fstream