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++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性