png数据块IHDR_IDAT_END读取

弄了这么些天,还没有找到我要的像素点的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;
	 

}


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值