📄 pngdecode.c
字号:
/* * @(#)pngDecode.c 1.30 02/09/17 @(#) * * Copyright (c) 2000-2002 Sun Microsystems, Inc. All rights reserved. * PROPRIETARY/CONFIDENTIAL * Use is subject to license terms. */#include <kni.h>#include <defaultLCDUI.h>#include <imageDecode.h>#include <midpMalloc.h>#include <midpServices.h>#define IHDR_CHUNK 0x49484452#define PLTE_CHUNK 0x504C5445#define IDAT_CHUNK 0x49444154#define IEND_CHUNK 0x49454E44#define tRNS_CHUNK 0x74524E53#define CT_PALETTE 0x01#define CT_COLOR 0x02#define CT_ALPHA 0x04#define freeBytes(p) midpFree((p))typedef struct _pngData { signed int width; signed int height; /* current location, for writing pixels */ int y; unsigned int scanlength; unsigned short bytesPerPixel; /* palette in stream is RGB (3 bytes) but we store it as XRGB (int) */ long *palette; unsigned short paletteLength; unsigned char *trans; unsigned short transLength; unsigned char pass; /* pass #, for interlace loading */ unsigned char depth; /* bits per pixel: 1,2,4,8,16 */ unsigned char colorType; /* 1=palette 2=hasColor 4=hasAlpha */ unsigned char compress; /* compression type, must be zero */ unsigned char filter; /* filter type, must be zero */ unsigned char interlace; /* interlacing: 0 (none) or 1 (adam7) */ unsigned short lineBytes[7]; unsigned short passSize[7];} pngData;static unsigned long readHeader(imageSrcPtr, long, pngData *, unsigned long);static unsigned long readPalette(imageSrcPtr, long, pngData *, long *, unsigned long);static unsigned long readTransPal(imageSrcPtr, long, pngData *, unsigned char *, unsigned long);static jboolean handleImageData(unsigned char *, int, imageDstPtr, pngData *);static unsigned long getInt(imageSrcPtr);static unsigned long skip(imageSrcPtr, int, unsigned long);static jboolean getChunk(imageSrcPtr, unsigned long *, long *);static jboolean signatureOK(imageSrcPtr);static jboolean headerOK(pngData *);static unsigned long init_CRC(unsigned long);static jboolean check_CRC(imageSrcPtr, unsigned long);static unsigned long update_crc(unsigned long, unsigned char *, int);static int findPassWidth(int, pngData *);typedef struct _iid { imageSrcPtr src; long clen;} idatInflateData;unsigned intPNGdecodeImage_getByte(void *p){ idatInflateData *d = (idatInflateData *)p; imageSrcPtr src = d->src; unsigned long chunkType; unsigned int byte; /* while, because it's possible to have 0-length chunks! */ while (d->clen == 0) { /* unsigned long CRC = */ (void)getInt(src); getChunk(src, &chunkType, &(d->clen)); if (chunkType != IDAT_CHUNK) { return -1; } } --(d->clen); byte = src->getByte(src); return byte;}unsigned intPNGdecodeImage_getBytes(unsigned char *buffer, int count, void *p){ idatInflateData *d = (idatInflateData *)p; imageSrcPtr src = d->src; unsigned long chunkType; /* while, because it's possible to have 0-length chunks! */ while (d->clen == 0) { /* unsigned long CRC = */ (void)getInt(src); getChunk(src, &chunkType, &(d->clen)); if (chunkType != IDAT_CHUNK) { return 0; } } if (d->clen <= count) { count = d->clen; } count = src->getBytes(src, buffer, count); d->clen -= count; return count;}jbooleanPNGdecodeImage_real(imageSrcPtr src, imageDstPtr dst, long *paletteData, unsigned char *transData) { jboolean OK = KNI_TRUE; jboolean saw_IDAT = KNI_FALSE, saw_PLTE = KNI_FALSE, saw_tRNS = KNI_FALSE; pngData data; unsigned long chunkType; long chunkLength; unsigned long CRC; if (!signatureOK(src)) { goto formaterror; /* not a PNG image */ } memset(&data, 0, sizeof(data)); while (getChunk(src, &chunkType, &chunkLength)) { CRC = init_CRC(chunkType); if (chunkType == IHDR_CHUNK) { /* size of header is known. headerOK => IHDR_CHUNK already seen */ if ((chunkLength < 13) || headerOK(&data)) { goto formaterror; } CRC = readHeader(src, chunkLength, &data, CRC); if (!headerOK(&data)) { goto formaterror; } dst->setSize(dst, data.width, data.height); if ((data.colorType & CT_COLOR) == 0) { /* grayscale--set up a palette */ int n = 0; long _p[4]; switch (data.depth) { case 1: _p[0] = 0; _p[1] = 0xffffff; n = 2; dst->setColormap(dst, _p, n); break; case 2: _p[0] = 0; _p[1] = 0x555555; _p[2] = 0xaaaaaa; _p[3] = 0xffffff; n = 4; dst->setColormap(dst, _p, n); break; case 4: { long p[16]; for (n = 0; n < 16; ++n) { p[n] = n*0x111111; } dst->setColormap(dst, p, n); } break; default: { long p[256]; for (n = 0; n < 256; ++n) { p[n] = (n << 16) | (n << 8) | n; } dst->setColormap(dst, p, n); } break; } } } else if (chunkType == PLTE_CHUNK) { if ((chunkLength > 768) || ((chunkLength % 3) != 0)) { goto formaterror; } if ((data.paletteLength > 0) || saw_IDAT || saw_tRNS) { goto formaterror; } CRC = readPalette(src, chunkLength, &data, paletteData, CRC); if (data.palette == NULL) { goto formaterror; } if (data.colorType & CT_PALETTE) { dst->setColormap(dst, data.palette, data.paletteLength); } saw_PLTE = KNI_TRUE; } else if (chunkType == tRNS_CHUNK) { if (saw_IDAT || data.colorType == 4 || data.colorType == 6) { goto formaterror; } CRC = readTransPal(src, chunkLength, &data, transData, CRC); if (data.trans == NULL) { goto formaterror; } dst->setTransMap(dst, data.trans, data.transLength, saw_PLTE ? data.paletteLength : -1); saw_tRNS = KNI_TRUE; } else if (chunkType == IDAT_CHUNK) { idatInflateData _data; int compLen = 0; int decompLen = data.scanlength * data.height; unsigned char *decompBuf; long startPos = 0, lastGoodPos = 0; saw_IDAT = KNI_TRUE; if (data.interlace) { int i; /* decompLen is harder to calculate--there are extra rows! */ decompLen = 0; for (i = 0; i < 7; ++i) { int off = 7 >> (i/2); /* 7 7 3 3 1 1 0 */ int shift = 3 - (((i - 1) / 2)); /* 3 3 3 2 2 1 1 */ int height = ((data.height + off) >> shift); int width = findPassWidth(i, &data); data.lineBytes[i] = width; data.passSize[i] = width * height; decompLen += data.passSize[i]; } } else { data.lineBytes[6] = data.scanlength; data.passSize[6] = decompLen; } if ((data.colorType & CT_PALETTE) && (data.palette == NULL)) { goto formaterror; } /* * we need to decompress all of the IDAT chunks en masse. * first step is to find out how much actual data there is. * While we're at it, we can look at the CRCs for all of * the blocks. */ _data.src = src; _data.clen = chunkLength; lastGoodPos = startPos = src->getpos(src); do { /* Make sure we only process IDAT chunks */ if (chunkType != IDAT_CHUNK) break; CRC = init_CRC(chunkType); compLen += chunkLength; CRC = skip(src, chunkLength, CRC); lastGoodPos = src->getpos(src); if (!check_CRC(src, CRC)) { goto formaterror; } } while (getChunk(src, &chunkType, &chunkLength)); /* * IMPORTANT: CRC now contains the correct value for * the last IDAT_CHUNK. This is checked at the bottom * of the loop so it must contain the right value. */ src->seek(src, startPos); /* reset to the first IDAT_CHUNK */ decompBuf = (unsigned char*)midpMalloc(decompLen); if (decompBuf == NULL) { OK = KNI_FALSE; goto done; } /* * inflate ignores the method and flags */ compLen -= 2; PNGdecodeImage_getByte(&_data); PNGdecodeImage_getByte(&_data); /* subtract 4 bytes from compLen -- it's the ZLIB trailer */ if (!midp_pngInflate(&_data, compLen - 4, &decompBuf, decompLen)) { freeBytes(decompBuf); goto formaterror; } OK = handleImageData(decompBuf, decompLen, dst, &data); freeBytes(decompBuf); src->seek(src, lastGoodPos); } else if (chunkType == IEND_CHUNK) { /* shouldn't happen because getChunk checks for this! */ } else { /* unrecognized -- skip */ CRC = skip(src, chunkLength, CRC); } if (!check_CRC(src, CRC)) { /* fprintf(stderr, "PNG data corrupted (CRC mismatch)\n"); */ goto formaterror; } } done: return OK; formaterror: OK = KNI_FALSE; KNI_ThrowNew("java/lang/IllegalArgumentException", ""); goto done;}jbooleanPNGdecodeImage(imageSrcPtr src, imageDstPtr dst) { long * paletteData; unsigned char * transData; paletteData = midpMalloc(sizeof(long) * 256); if (paletteData == NULL) { /* out of memory */ return KNI_FALSE; } else { transData = midpMalloc(sizeof(unsigned char) * 256); if (transData == NULL) { /* out of memory */ midpFree(paletteData); return KNI_FALSE; } else { jboolean retval = PNGdecodeImage_real(src, dst, paletteData, transData); midpFree(paletteData); midpFree(transData); return retval; } }}/** Interlacing parameters for ADAM7 interlace pattern:** 1 6 4 6 2 6 4 6* 7 7 7 7 7 7 7 7* 5 6 5 6 5 6 5 6* 7 7 7 7 7 7 7 7* 3 6 4 6 3 6 4 6* 7 7 7 7 7 7 7 7* 5 6 5 6 5 6 5 6* 7 7 7 7 7 7 7 7**/static char *pStartX = "\000\004\000\002\000\001\000\000";static char *pIncX = "\010\010\004\004\002\002\001\001";/* pass number 1 2 3 4 5 6 7 - *//* static char *pStartY = "\000\000\004\000\002\000\001\000"; *//* static char *pIncY = "\010\010\010\004\004\002\002\001"; */static intfindPassWidth(int pass, pngData *data){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -