PNG图片数据解析

PNG是一种非常流行的图片格式,它不仅支持透明效果,而且图片数据经过了压缩处理,所以广泛用于web等应用。

PNG的文件格式:

  PNG文件中的数据,总是以一个固定的8个字节开头:

    (图片来自http://blog.csdn.net/bisword/article/details/2777121

  除此之外,PNG的其他数据都是以数据块的方式组织,它们被分为标准数据块和辅助数据块,其中的辅助数据块是可选的。关键数据块包含我们必须的图片信息,我们之后要重点解析的也是关键数据块。

  

  (图片来自http://blog.csdn.net/bisword/article/details/2777121

每种数据块的结构:

  

    (图片来自http://blog.csdn.net/bisword/article/details/2777121

  Length:该数据块的中Chunk Data的长度;

  Chunk Type Code:数据类型,就是指上面提到的IHDR,IEND等;

  Chunk Data:数据区域,如果是IDAT,就表示存储的还未解压的图片数据;

  CRC:循环冗余效验码;

具体实现:(实现中没有处理png数据中变形的情况,部分头中的宏定义来自libpng,实例不具备实用性,仅作参考)

头文件:

  1 #ifndef __PNG__
  2 #define __PNG__
  3
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 #include <math.h>
  7 #include "zlib/zlib.h"
  8
  9 /**
 10  * 类型标志
 11  */
 12 #define PNG_FLAG_HEX "89504E470D0A1A0A"
 13
 14 /**
 15  * 数据块类型
 16  */
 17 #define DATA_CHUNK_TYPE_IHDR "IHDR"
 18 #define DATA_CHUNK_TYPE_IDAT "IDAT"
 19 #define DATA_CHUNK_TYPE_IEND "IEND"
 20 #define DATA_CHUNK_TYPE_tEXt "tEXt"
 21 #define DATA_CHUNK_TYPE_iTXt "iTXt"
 22
 23 /**
 24  * 过滤方式
 25  */
 26 #define DATA_FILTER_TYPE_DEFAULT 0
 27 #define DATA_FILTER_TYPE_ADD_ROW 1
 28 #define DATA_FILTER_TYPE_ADD_UP  2
 29 #define DATA_FILTER_TYPE_AVERGE  3
 30 #define DATA_FILTER_TYPE_PAETH   4
 31
 32 /* color type masks */
 33 #define PNG_COLOR_MASK_PALETTE    1
 34 #define PNG_COLOR_MASK_COLOR      2
 35 #define PNG_COLOR_MASK_ALPHA      4
 36
 37 /* color types.  Note that not all combinations are legal */
 38 #define PNG_COLOR_TYPE_GRAY           0
 39 #define PNG_COLOR_TYPE_PALETTE    (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
 40 #define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
 41 #define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
 42 #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
 43
 44 #define RGB_USE_ALPHA(vr, vg, vb, va)  45     (unsigned)(((unsigned)((unsigned char)(vr) * ((unsigned char)(va) + 1)) >> 8) |  46     ((unsigned)((unsigned char)(vg) * ((unsigned char)(va) + 1) >> 8) << 8) |  47     ((unsigned)((unsigned char)(vb) * ((unsigned char)(va) + 1) >> 8) << 16) |  48     ((unsigned)(unsigned char)(va) << 24))
 49
 50 /**
 51  * 一次解压图片数据的限制
 52  */
 53 #define DECOMPRESSION_MAX_BYTES 8192
 54
 55 /**
 56  * 数据块信息
 57  */
 58 typedef struct _DataChunkHeader
 59 {
 60     // 数据长度
 61     unsigned char length[4];
 62     // 数据类型
 63     unsigned char type[4];
 64 } DataChunkHeader;
 65
 66 /**
 67  * IHDR数据
 68  */
 69 typedef struct _IDHRData
 70 {
 71     unsigned char width[4];
 72     unsigned char height[4];
 73     unsigned char bitDepth[1];
 74     unsigned char colorType[1];
 75     unsigned char compressionMethod[1];
 76     unsigned char filterMethod[1];
 77     unsigned char interlaceMethod[1];
 78 } IDHRData;
 79
 80 /**
 81  * PNG图片类
 82  */
 83 class PNG
 84 {
 85 public:
 86     PNG();
 87     PNG(const char* filePath);
 88
 89     ~PNG();
 90
 91     int getWindth();
 92     int getHeight();
 93
 94     /**
 95      * 获取图片宽度
 96      */
 97     unsigned char* getImageData();
 98
 99 private:
100     int m_width;
101     int m_height;
102
103     unsigned char m_bitDepth;
104     unsigned char m_colorType;
105     unsigned char m_compressionMethod;
106     unsigned char m_filterMethod;
107     unsigned char m_interlaceMethod;
108     unsigned char m_chanels;
109
110     unsigned char* m_imageData;
111
112     /**
113      * 从文件加载图片数据
114      */
115     bool loadImageDataFromFile(const char* filePath);
116
117     /**
118      * 解析数值
119      */
120     int parseNumber(const unsigned char* data, int len);
121
122     /**
123      * 解压数据
124      */
125     int decompressData(z_stream* zStream, unsigned char* data, int dataLen, int leftLen, FILE *pFile);
126
127     /**
128      * 生成图片数据
129      */
130     void generateImageData(unsigned char* data, unsigned long dataLen);
131
132     /**
133      * 默认的过滤方式
134      */
135     void defaultFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
136
137     /**
138      * 当前行相加的过滤方式
139      */
140     void addCurrentRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
141
142     /**
143      * 前一行相加的过滤方式
144      */
145     void addUpRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
146
147     /**
148      * 平均的过滤方式
149      */
150     void avergeFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
151
152     /**
153      * paeth的过滤方式
154      */
155     void paethFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes);
156
157     /**
158      * 解析IHDR数据
159      */
160     void parseIHDRData(DataChunkHeader& dataChunkHeader, FILE* pFile);
161
162     /**
163      * 解析IDAT数据
164      */
165     void parseIDATData(DataChunkHeader& dataChunkHeader, FILE* pFile);
166
167     /**
168      * 解析IEND数据
169      */
170     void parseIENDData(DataChunkHeader& dataChunkHeader, FILE *pFile);
171
172     /**
173      * 解析其他数据
174      */
175     void parseCommonData(DataChunkHeader& dataChunkHeader, FILE *pFile);
176 };
177
178 #endif

cpp文件:

  1 #include "png.h"
  2 #include "utils/cUtil.h"
  3 #include <stdlib.h>
  4
  5 #include <windows.h>
  6
  7 /**
  8  * 默认构造函数
  9  */
 10 PNG::PNG()
 11 {
 12     this->m_width = 0;
 13     this->m_height = 0;
 14
 15     this->m_imageData = 0;
 16 }
 17
 18 /**
 19  * 构造函数
 20  * @param filePath 图片路径
 21  */
 22 PNG::PNG(const char *filePath)
 23 {
 24     this->m_width = 0;
 25     this->m_height = 0;
 26
 27     this->loadImageDataFromFile(filePath);
 28 }
 29
 30 /**
 31  * 析构函数
 32  */
 33 PNG::~PNG()
 34 {
 35
 36 }
 37
 38 /**
 39  * 从文件加载图片数据
 40  */
 41 bool PNG::loadImageDataFromFile(const char* filePath)
 42 {
 43     FILE* pFile = fopen(filePath, "rb");
 44     if (!pFile)
 45         return false;
 46
 47     // 解析PNG标志
 48     char flag[8];
 49     char hexFlag[17];
 50     fread(flag, 1, 8, pFile);
 51     toHexStr(flag, 8, hexFlag);
 52     if (strcmp(hexFlag, PNG_FLAG_HEX) != 0)
 53         return false;
 54
 55     // 解析图片数据
 56     DataChunkHeader dataChunkHeader;
 57     char dataChunkHeaderType[5];
 58     do {
 59         fread(&dataChunkHeader, 1, sizeof(DataChunkHeader), pFile);
 60
 61         memcpy(dataChunkHeaderType, dataChunkHeader.type, 4);
 62         dataChunkHeaderType[4] = ‘\0‘;
 63
 64         // IHDR
 65         if ( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IHDR) == 0 ) {
 66             this->parseIHDRData(dataChunkHeader, pFile);
 67         }
 68         // IDAT
 69         else if ( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IDAT) == 0 ) {
 70             this->parseIDATData(dataChunkHeader, pFile);
 71         }
 72         // IEND
 73         else if ( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IEND) == 0 ) {
 74             this->parseIENDData(dataChunkHeader, pFile);
 75         }
 76         // 其他数据
 77         else {
 78             this->parseCommonData(dataChunkHeader, pFile);
 79         }
 80     } while( strcmp(dataChunkHeaderType, DATA_CHUNK_TYPE_IEND) != 0 );
 81
 82     int i = 1;
 83
 84     return true;
 85 }
 86
 87 /**
 88  * 解析数值
 89  */
 90 int PNG::parseNumber(const unsigned char* data, int len)
 91 {
 92     char localNum[4];
 93
 94     bool isLittleEndian = checkEndian();
 95     for (int i = 0; i<4; i++) {
 96         char ch;
 97
 98         if (isLittleEndian) {
 99             if (i <= len-1)
100                 ch = data[len - 1 - i];
101             else
102                 ch = ‘\0‘;
103         }
104         else {
105             if (i <= len-1)
106                 ch = data[i];
107             else
108                 ch = ‘\0‘;
109         }
110         localNum[i] = ch;
111     }
112
113     int num;
114     memcpy(&num, localNum, 4);
115     return num;
116 }
117
118 /**
119  * 解析IHDR数据
120  */
121 void PNG::parseIHDRData(DataChunkHeader& dataChunkHeader, FILE* pFile)
122 {
123     int dataLen = this->parseNumber(dataChunkHeader.length, 4);
124
125     IDHRData idhrData;
126     char crc[4];
127
128     fread(&idhrData, 1, sizeof(IDHRData), pFile);
129     fread(crc, 1, 4, pFile);
130
131     this->m_width              = this->parseNumber(idhrData.width, 4);
132     this->m_height              = this->parseNumber(idhrData.height, 4);
133     this->m_bitDepth          = this->parseNumber(idhrData.bitDepth, 1);
134     this->m_colorType          = this->parseNumber(idhrData.colorType, 1);
135     this->m_compressionMethod = this->parseNumber(idhrData.compressionMethod, 1);
136     this->m_filterMethod      = this->parseNumber(idhrData.filterMethod, 1);
137     this->m_interlaceMethod   = this->parseNumber(idhrData.interlaceMethod, 1);
138     this->m_chanels              = 0;
139
140     switch (this->m_colorType) {
141         case PNG_COLOR_TYPE_GRAY:
142         case PNG_COLOR_TYPE_PALETTE:
143             this->m_chanels = 1;
144         break;
145         case PNG_COLOR_TYPE_RGB:
146             this->m_chanels = 3;
147         break;
148         case PNG_COLOR_TYPE_GRAY_ALPHA:
149             this->m_chanels = 2;
150         break;
151         case PNG_COLOR_TYPE_RGB_ALPHA:
152             this->m_chanels = 4;
153         break;
154         default:
155             this->m_chanels = 0;
156         break;
157    }
158 }
159
160 /**
161  * 解压数据
162  */
163 int PNG::decompressData(z_stream* zStream, unsigned char* data, int dataLen, int leftLen, FILE *pFile)
164 {
165     int result = 0;
166
167     int leftBytesCount = leftLen;
168     int avail_out = -1;
169     do {
170         if (zStream->avail_in == 0) {
171             if (avail_out == 0)
172                 break;
173             else {
174                 if (leftBytesCount == 0) {
175                     DataChunkHeader dataChunkHeader;
176                     fread(&dataChunkHeader, 1, sizeof(DataChunkHeader), pFile);
177
178                     int newDataLen = this->parseNumber(dataChunkHeader.length, 4);
179                     unsigned char* newData = new unsigned char[dataLen + newDataLen];
180                     char crc[4];
181
182                     fread(newData + dataLen, 1, newDataLen, pFile);
183                     fread(crc, 1, 4, pFile);
184                     memcpy(newData, data, dataLen);
185
186                     delete data;
187                     data = newData;
188
189                     zStream->next_in = newData + dataLen;
190                     zStream->avail_in = newDataLen;
191
192                     dataLen = dataLen + newDataLen;
193
194                     return this->decompressData(zStream, data, dataLen, 0, pFile);
195                 }
196             }
197
198             // 导出数据是否超过限制
199             if (leftBytesCount > DECOMPRESSION_MAX_BYTES)
200                 zStream->avail_in = DECOMPRESSION_MAX_BYTES;
201             else
202                 zStream->avail_in = leftBytesCount;
203
204             leftBytesCount -= zStream->avail_in;
205         }
206
207         if (avail_out > 0)
208             zStream->avail_out = avail_out;
209         else
210             zStream->avail_out = m_width * 4 + 1;
211
212         result = inflate(zStream, Z_NO_FLUSH);
213         if (result != Z_OK)
214             break;
215
216         avail_out = zStream->avail_out;
217     } while (zStream->avail_in >= 0);
218
219     return result;
220 }
221
222 /**
223  * 生成图片数据
224  */
225 void PNG::generateImageData(unsigned char* data, unsigned long dataLen)
226 {
227     // 行字节数
228     int rowBytes = this->m_chanels * this->m_width;
229
230     // 初始化图片数据
231     this->m_imageData = new unsigned char[rowBytes * this->m_height];
232
233     unsigned char* pImageData = this->m_imageData;
234     unsigned char* pRowData = data;
235
236     for (int rowIndex = 0; rowIndex < this->m_height; rowIndex++) {
237         // 过滤类型
238         unsigned char filterType = pRowData[0];
239
240         pRowData += 1;
241
242         switch (filterType) {
243             // 不需要过滤处理
244             case DATA_FILTER_TYPE_DEFAULT:
245                 this->defaultFilterType(pImageData, pRowData, rowBytes);
246             break;
247             // 当前行相加
248             case DATA_FILTER_TYPE_ADD_ROW:
249                 this->addCurrentRowFilterType(pImageData, pRowData, rowBytes);
250             break;
251             // 和前一行相加
252             case DATA_FILTER_TYPE_ADD_UP:
253                 this->addUpRowFilterType(pImageData, pRowData, rowBytes);
254             break;
255             // 求平均
256             case DATA_FILTER_TYPE_AVERGE:
257                 this->avergeFilterType(pImageData, pRowData, rowBytes);
258             break;
259             // Paeth
260             case DATA_FILTER_TYPE_PAETH:
261                 this->paethFilterType(pImageData, pRowData, rowBytes);
262             break;
263             // 类型错误
264             default:
265             break;
266         }
267
268         pImageData += rowBytes;
269         pRowData += rowBytes;
270
271         char text[100];
272         sprintf(text, "filter type:%d, rowIndex:%d \n", filterType, rowIndex);
273         OutputDebugString(text);
274     }
275
276     int channel = rowBytes / this->m_width;
277     if (channel == 4) {
278         unsigned int *tmp = (unsigned int *)this->m_imageData;
279
280         for (unsigned short i = 0; i < this->m_height; i++) {
281             for (unsigned int j = 0; j < rowBytes; j+=4) {
282                 unsigned int offset = i * rowBytes + j;
283
284                 *tmp++ = RGB_USE_ALPHA(
285                     this->m_imageData[offset],
286                     this->m_imageData[offset+1],
287                     this->m_imageData[offset+2],
288                     this->m_imageData[offset+3]
289                 );
290             }
291         }
292     }
293 }
294
295 /**
296  * 默认的过滤方式
297  */
298 void PNG::defaultFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
299 {
300     for (int i = 0; i < rowBytes; i++) {
301         *pImageData++ = *pRowData++;
302     }
303 }
304
305 /**
306  * 当前行相加的过滤方式
307  */
308 void PNG::addCurrentRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
309 {
310     for (int i = 0; i < rowBytes; i++) {
311         if (i == 0) {
312             memcpy(pImageData, pRowData, 4);
313             i += 3;
314             pImageData += 4;
315             pRowData += 4;
316         }
317         else {
318             *pImageData++ = (unsigned char)(((int)*(pRowData++) + (int)*(pImageData-4)) & 0xFF);
319         }
320     }
321 }
322
323 /**
324  * 前一行相加的过滤方式
325  */
326 void PNG::addUpRowFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
327 {
328     for (int i = 0; i < rowBytes; i++) {
329         *pImageData++ = (unsigned char)(((int)*(pRowData++) + (int)*(pImageData-rowBytes)) & 0xFF);
330     }
331 }
332
333 /**
334  * 平均的过滤方式
335  */
336 void PNG::avergeFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
337 {
338     for (int i = 0; i < rowBytes; i++) {
339         int averge = 0;
340
341         if (i <= 3) {
342             averge = ((int)*(pImageData-rowBytes)) / 2;
343
344             *pImageData++ = (unsigned char)((averge + (int)*(pRowData++)) & 0xFF);
345         }
346         else {
347             averge = (((int)*(pImageData-4)) + ((int)*(pImageData-rowBytes))) / 2;
348
349             *pImageData++ = (unsigned char)((averge + (int)*(pRowData++)) & 0xFF);
350         }
351     }
352 }
353
354 /**
355  * paeth的过滤方式
356  */
357 int Paeth(int a, int b, int c)
358 {
359     int p  = a + b - c;
360     int pa = abs(p - a);
361     int pb = abs(p - b);
362     int pc = abs(p - c);
363
364     int Paeth;
365     if(pa <= pb && pa <= pc)
366         Paeth = a;
367     else if (pb <= pc)
368         Paeth = b;
369     else
370         Paeth = c;
371     return Paeth ;
372 }
373 void PNG::paethFilterType(unsigned char* pImageData, unsigned char* pRowData, int rowBytes)
374 {
375     for (int i = 0; i < rowBytes; i++) {
376         if (i <= 3) {
377             *pImageData++ = (unsigned char)(((int)*(pRowData++) + (int)*(pImageData-rowBytes)) & 0xFF);
378         }
379         else {
380             unsigned char left = *(pImageData - 4);
381             unsigned char up = *(pImageData - rowBytes);
382             unsigned char leftUp = *(pImageData - rowBytes - 4);
383
384             int value = Paeth((int)left, (int)up, (int)leftUp);
385
386             *pImageData++ = (unsigned char)(((int)*(pRowData++) + value) & 0xFF);
387         }
388     }
389 }
390
391 /**
392  * 解析IDAT数据
393  */
394 void PNG::parseIDATData(DataChunkHeader& dataChunkHeader, FILE* pFile)
395 {
396     // 解压后的图片数据
397     unsigned char* imageData = new unsigned char[m_width * m_height * 4];
398
399     int dataLen = this->parseNumber(dataChunkHeader.length, 4);
400     // 解压前的图片数据
401     unsigned char* data = new unsigned char[dataLen];
402     char crc[4];
403     // 提取数据
404     fread(data, 1, dataLen, pFile);
405     fread(crc, 1, 4, pFile);
406
407     // 存放临时的解压数据
408     unsigned long decompressDataLen = m_width * m_height * 4 + m_height;
409     unsigned char* decompressData = new unsigned char[decompressDataLen];
410
411     z_stream* zStream = new z_stream();
412     zStream->next_in = data;
413     zStream->next_out = decompressData;
414
415     inflateInit(zStream);
416
417     // 解压数据
418     this->decompressData(zStream, data, dataLen, dataLen, pFile);
419     // 生成图片数据
420     this->generateImageData(decompressData, decompressDataLen);
421
422     /*
423     int result = 0;
424     // 开始解压数据
425     int leftBytesCount = dataLen;
426     int avail_out = -1;
427     do {
428         if (zStream->avail_in == 0) {
429             if (avail_out == 0)
430                 break;
431             else {
432                 if (leftBytesCount == 0) {
433
434                 }
435             }
436
437             // 导出数据是否超过限制
438             if (leftBytesCount > DECOMPRESSION_MAX_BYTES)
439                 zStream->avail_in = DECOMPRESSION_MAX_BYTES;
440             else
441                 zStream->avail_in = leftBytesCount;
442
443             leftBytesCount = dataLen - zStream->avail_in;
444         }
445
446         if (avail_out > 0)
447             zStream->avail_out = avail_out;
448         else
449             zStream->avail_out = m_width * 4 + 1;
450
451         result = inflate(zStream, Z_NO_FLUSH);
452         if (result != Z_OK)
453             break;
454
455         avail_out = zStream->avail_out;
456     } while (zStream->avail_in >= 0);
457     // 数据解压是否成功
458     if (result == Z_STREAM_END) {
459         int i = 1;
460     }
461     */
462 }
463
464 /**
465  * 解析IEND数据
466  */
467 void PNG::parseIENDData(DataChunkHeader& dataChunkHeader, FILE *pFile)
468 {
469     char crc[4];
470     fread(crc, 1, 4, pFile);
471 }
472
473 /**
474  * 解析其他数据
475  */
476 void PNG::parseCommonData(DataChunkHeader& dataChunkHeader, FILE *pFile)
477 {
478     int dataLen = this->parseNumber(dataChunkHeader.length, 4);
479     fseek(pFile, dataLen + 4, SEEK_CUR);
480 }
481
482 /**
483  * 获取图片宽度
484  */
485 unsigned char* PNG::getImageData()
486 {
487     return this->m_imageData;
488 }
489
490 /**
491  * 获取图片宽度
492  */
493 int PNG::getWindth()
494 {
495     return this->m_width;
496 }
497
498 /**
499  * 获取图片高度
500  */
501 int PNG::getHeight()
502 {
503     return this->m_height;
504 }

如果需要绘制图片,可以使用opengl库

参考代码:

 1 glViewport(0, 0, winWidth, winHeight);
 2
 3 glMatrixMode(GL_PROJECTION);
 4 glLoadIdentity();
 5 glOrtho(0.0f, winWidth - 1.0, 0.0, winHeight - 1.0, -10.0, 10.0);
 6
 7 glMatrixMode(GL_MODELVIEW);
 8 glLoadIdentity();
 9
10 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
11
12 glEnable(GL_TEXTURE_2D);
13
14 int width = png->getWindth();
15 int height = png->getHeight();
16 unsigned char* data = png->getImageData();
17
18 GLuint name1;
19 glGenTextures(1, &name1);
20 glBindTexture(GL_TEXTURE_2D, name1);
21 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
22 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
23 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,      GL_REPEAT);
24 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,      GL_REPEAT);
25 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,GL_RGBA, GL_UNSIGNED_BYTE, data);
26 glBegin(GL_POLYGON);
27     glTexCoord2f(1, 1);
28     glVertex3d(800, 800, 2);
29     glTexCoord2f(0, 1);
30     glVertex3d(0, 800, 2);
31     glTexCoord2f(0, 0);
32     glVertex3d(0, 0, 2);
33     glTexCoord2f(1, 0);
34     glVertex3d(800, 0, 2);
35 glEnd();
时间: 2024-07-29 20:25:22

PNG图片数据解析的相关文章

iOS基础8:自定义MyData/自定义SQLite用于网络判断,版本判断,图片缓存处理,下载或者上传的GET或POST请求,加密手段,.数据解析

镔哥,这篇文章是用自己的工程项目来的,主要是代码为主,但是会有注释,让大家能更好理解,让大家做工程更多一个选择,这其实就是自己自定义SQLite,不多说,见代码例子 MyDAta的.h文件 /* MyData这一个基本上每个工程都能用到的Demo,他包含了很多内容: 1.iPhone机网络判断: 2.iPhone机软件版本判断(主要是看是否是大于IOS7): 3.图片缓存处理: 4.下载或者上传的GET或POST请求: 5.加密手段: 6.数据解析: */ //*****************

Silverlight项目笔记7:xml/json数据解析、MVVM下实现多级树形结构TreeView、忽视引用类型导致数据绑定错误、通过流或动态空间加载图片、虚拟目录设置、silverlight安全机制引发的问题、WebClient缓存问题

涉及的内容主要有: 1.xml/json数据解析 2.多级树形结构TreeView 3.忽视引用类型导致数据绑定错误 4.通过流或动态空间加载图片 5.虚拟目录设置 6.silverlight安全机制引发的问题 7.webclient缓存问题 1.xml/json数据解析 (1)xml数据解析 使用WebClient获取数据,获取到的数据实例化为一个XDocument,使用XDocument的Descendants(XName)方法获得对应节点的数据集合,再通过Element这个方法对数据集合进

【ListViewJson】【MainActivity功能性分析,不讨论具体工具类的实现】【android解析json数据(包含对图片数据的异步缓存处理),并将其加载到listview中】

最近遇到了一个相当好.对初学者相当友善的项目,是描述如何将json数据解析,并加载到listview中. 但是个人认为以后所有类似功能的实现都可以使用这套工具. 项目也可以使用这套架构. 这个项目是处理每个news只有一个imgurl,应该考虑一下当imgurl数量不定的时候具体应该怎么解决. 首先项目源码结构如下: 项目下载链接:http://download.csdn.net/download/y562810463/8004245 在这个项目中的com.demo.app.common包完全可

Gprinter光栅位图点阵数据解析工具

最近参与的项目有一个需求,解析佳博热敏打印机的光栅位图点阵数据并保存为图片文件.数据是通过Bus Hound抓取的,如下图所示. 其中1b 40为初始化打印机的指令,对应的ASCII码为ESC @,1b 4a 18为打印并走纸的指令,对应的ASCII码为ESC J,1d 76 30为打印光栅位图的指令,对应的ASCII码为GS v 0,其后紧跟光栅位图模式(0x00).水平方向位图字节数(0x0036)和垂直方向位图点数(0x0018),后面则为本帧的位图数据(0x36*0x18=1296字节)

Android中XML数据解析

转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38296207 XML初步 今天我们来学习另一种非常重要的数据交换格式-XML.XML(Extensible Markup Language的缩写,意为可扩展的标记语言),它是一种元标记语言,即定义了用于定义其他特定领域有关语义的.结构化的标记语言,这些标记语言将文档分成许多部件并对这些部件加以标识.XML 文档定义方式有:文档类型定义(DTD)和XML Schema.DTD定义了文

XML数据解析 Dom方式解析

这是一份XML数据,与上一篇文章的JSON数据内容是相同的,上一篇是JSON格式,这篇文章使用的是XML格式的数据 本文以上篇文章的代码为基础修改: 1>数据形式变为XML数据,所以要修改文件的路径 2>因为数据格式不同,所以解析方式不同先采用GData方式解析XML文档 需求:将此XML文档中的数据解析出来,通过tableView展示出来,上一篇文章的需求相同,只是数据与解析方法不同 此处只给出解析本分代码,即JSON解析2文章中代码部分,61--89行部分,开始部分修改文件路径. 使用GD

iOS开发——实战篇Swift篇&amp;UItableView结合网络请求,多线程,数据解析,MVC实战

UItableView结合网络请求,多线程,数据解析,MVC实战 学了这么久的swift都没有做过什么东西,今天就以自己的一个小小的联系,讲一下,怎么使用swift在实战中应用MVC,并且结合后面的高级知识:网络请求,JSON数据解析一起应用到一个项目中来. 好了,废话不多说,我们直接开始吧. 首先看看最终的效果: 是不是很简单,就是个UItableView显示一些简单的数据,如果你真的觉得太简单了,那么请绕道,寻找更深入东西,但或者没有你想的那么简单,这不仅仅是一个tableView,为什么呢

iOS之网络数据下载和Json数据解析

iOS之网络数据下载和Json数据解析 简介 在本文中笔者将要给大家介绍iOS中如何利用NSURLConnection从网络上下载数据,如何解析下载下来的JSON数据,以及如何显示数据和图片的异步下载显示 涉及到的知识点: 1.NSURLConnection异步下载封装 2.JSON格式和JSON格式解析 3.数据显示和使用SDWebImage异步显示图片 内容 1.网络下载基础知识介绍 (1)什么是网络应用? 一般情况下, iPhone的计算机, 照相机不需要从网络上下载数据也能运行, 所以这

AFN 获取数据,数据解析:JSON 介绍

AFN的介绍: 可以自动对服务器返回的数据进行解析,默认将服务器返回的数据当做 JSON 数据解析 是集XML解析,Json解析,网络图片下载,plist解析,数据流请求操作,上传,下载,缓存等网络众多功能于一身的强大的类库. 网络获取数据一直是手机软件的重中之重,如果处理的不好,会造成很差的用户体验.随着ASIHTTPRequest的停止更新,更换网络库是必然的事情,AFNetworking就是很好的替代品.而且都是轻量级,不要担心加入太多库会多软件性能有影响. AFN使用的注意事项:  (1