📄 pngdecode.c
字号:
int ix = ((pass < 0) || (pass > 7)) ? 7 : pass; int pixels = (data->width - pStartX[ix] + pIncX[ix] - 1) / pIncX[ix]; int channels = (data->colorType & CT_COLOR) ? 3 : 1; if (data->colorType & CT_ALPHA) ++channels; if (data->colorType & CT_PALETTE) channels = 1; /* palette is always 1 channel */ if (pixels <= 0) { return 0; } return 1 + ((pixels*data->depth*channels + 7) >> 3);}static unsigned longreadHeader(imageSrcPtr src, long length, pngData *data, unsigned long CRC){ unsigned char buf[13]; src->getBytes(src, buf, sizeof(buf)); data->width = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; data->height = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7]; data->depth = buf[8]; data->colorType = buf[9]; data->compress = buf[10]; data->filter = buf[11]; data->interlace = buf[12];#if 0fprintf(stderr, "reading PNG image, %dx%dx%d%s%s%s%s\n", data->width, data->height, data->depth, data->colorType & CT_PALETTE ? " palette" : "", data->colorType & CT_COLOR ? " color" : " grayscale", data->colorType & CT_ALPHA ? " w/alpha" : "", data->interlace ? ", INTERLACED" : "");#endif if (data->interlace) { data->pass = 0; } else { data->pass = 7; } switch (data->colorType) { case 0: case 3: data->bytesPerPixel = (data->depth + 7) / 8; break; case 2: data->bytesPerPixel = 3*data->depth / 8; break; case 4: data->bytesPerPixel = data->depth / 4; break; case 6: data->bytesPerPixel = data->depth / 2; break; } data->scanlength = findPassWidth(6, data); /* pass 6 => no winnowing */ CRC = update_crc(CRC, buf, sizeof(buf)); length -= sizeof(buf); while (length > 0) { int n = (length < sizeof(buf)) ? length : n; src->getBytes(src, buf, n); CRC = update_crc(CRC, buf, n); } return CRC;}static unsigned longreadPalette(imageSrcPtr src, long length, pngData *data, long *buffer, unsigned long CRC){ int i; data->paletteLength = length/3; data->palette = buffer; for (i = 0; i < data->paletteLength; ++i) { unsigned char buf[3]; src->getBytes(src, buf, 3); CRC = update_crc(CRC, buf, 3); data->palette[i] = (buf[0] << 16) | (buf[1] << 8) | buf[2]; } return CRC;}static unsigned longreadTransPal(imageSrcPtr src, long length, pngData *data, unsigned char *buffer, unsigned long CRC){ int i; data->transLength = length; data->trans = buffer; if (data->colorType & CT_PALETTE) { /* palette */ for (i = 0; i < data->transLength; i++) { unsigned char buf[1]; buf[0] = src->getByte(src); CRC = update_crc(CRC, buf, 1); data->trans[i] = buf[0]; } } else if ((data->colorType & CT_COLOR) == 0) { /* grayscale */ unsigned char buf[2]; src->getBytes(src, buf, 2); CRC = update_crc(CRC, buf, 2); data->trans[0] = buf[0]; data->trans[1] = buf[1]; data->transLength = 2; } else if (data->colorType & CT_COLOR) { /* truecolor */ unsigned char buf[6]; src->getBytes(src, buf, 6); CRC = update_crc(CRC, buf, 6); data->trans[0] = buf[0]; data->trans[1] = buf[1]; data->trans[2] = buf[2]; data->trans[3] = buf[3]; data->trans[4] = buf[4]; data->trans[5] = buf[5]; data->transLength = 6; } return CRC;}static voidapplyFilter(int filterType, unsigned char *buf, int n, unsigned char *prev, int bpp){ int x; if (filterType == 0) { return; } else if (prev == NULL) { if (filterType == 4) { filterType = 1; } else if (filterType == 3) { for (x = bpp; x < n; ++x) { buf[x] += buf[x - bpp] >> 1; } return; } else if (filterType == 2) { return; } } switch (filterType) { case 1: /* * We start at x == bpp because for x < bpp, buf[x - bpp] is * to be treated as zero. */ for (x = bpp; x < n; ++x) { buf[x] += buf[x - bpp]; } break; case 2: for (x = 0; x < n; ++x) { buf[x] += prev[x]; } break; case 3: /* * There is no valid "buf[x - bpp]" until (x == bpp), so the * first few values are treated as zero. */ for (x = 0; x < bpp; ++x) { buf[x] += prev[x] >> 1; } /* * But for x >= bpp we can do the full computation. */ for (x = bpp; x < n; ++x) { buf[x] += (prev[x] + (buf[x - bpp])) >> 1; } break; case 4: /* * There is no valid "buf[x - bpp]" or "prev[x - bpp]" until * (x == bpp). In the meantime, those values are treated as * zeroes, which causes the Paeth predictor to degenerate to * the value prev[x]. (Set a and c to zero and try it.) */ for (x = 0; x < bpp; ++x) { buf[x] += prev[x]; } /* * Now we can do the full computation. */ for (x = bpp; x < n; ++x) { int a, b, c, p, pa, pb, pc; a = buf[x - bpp]; b = prev[x]; c = prev[x - bpp]; p = a + b - c; pa = p > a ? p - a : a - p; pb = p > b ? p - b : b - p; pc = p > c ? p - c : c - p; buf[x] += ((pa <= pb) && (pa <= pc)) ? a : ((pb <= pc) ? b : c); } break; default: /* fprintf(stderr, "Illegal filter value %d\n", filterType); */ break; }}static voidfilterAllRows(unsigned char *pixels, pngData *data) { if (data->interlace) { int pass = 0; while (pass <= 6) { int n = data->lineBytes[pass]; unsigned char *end = pixels + data->passSize[pass]; unsigned char *rowBuf = pixels; unsigned char *prevRow = NULL; while (rowBuf < end) { applyFilter(rowBuf[0], rowBuf + 1, n - 1, prevRow, data->bytesPerPixel); prevRow = rowBuf + 1; rowBuf += n; } pixels = end; ++pass; } } else { unsigned char *rowBuf = pixels; unsigned char *prevRow = NULL; int n = data->lineBytes[6]; int y; for (y = 0; y < data->height; ++y) { applyFilter(rowBuf[0], rowBuf + 1, n - 1, prevRow, data->bytesPerPixel); prevRow = rowBuf + 1; rowBuf += n; } }}#define INIT_TRANS_PACK_RGB(b, x, a) \ (x) = ((b) > 8) ? 1 : 0; \ (a) = ((b) > 8) ? 6 : 3#define TRANS_PACK_RGB(d, s, x, a, tmap) \ *(d)++ = (s)[0]; \ *(d)++ = (s)[1 << x]; \ *(d)++ = (s)[2 << x]; \ if(x) { \ *(d)++ = (memcmp(s,tmap,a)) ? 0xFF: 0x00; \ } else { \ *(d)++ = ((s[0] == tmap[1]) && \ (s[1] == tmap[3]) && \ (s[2] == tmap[5])) \ ? 0x00: 0xFF; \ } \ (s) += (a)#define INIT_TRANS_PACK_GS(b, x, a) \ (x) = ((b) > 8) ? 1 : 0; \ (a) = ((b) > 8) ? 2 : 1#define TRANS_PACK_GS(d, s, x, a, tmap) \ *(d)++ = (s)[0]; \ if(x) { \ *(d)++ = ((s[0] == tmap[0]) && \ (s[1] == tmap[1]) ) \ ? 0x00: 0xFF; \ } else { \ *(d)++ = ((s[1] == tmap[1])) \ ? 0x00: 0xFF; \ } \ (s) += (a)#define INIT_TRANS_UNPACK_GS(b, x, m) \ (x) = (8 - (b)); \ (m) = 0xff ^ (0xff >> (x))#define TRANS_UNPACK_GS(d, s, x, m, b, x0, m0, tmap) \ *(d)++ = ((*s) & (m)) >> (x); \ *(d)++ = (*(d-1) == tmap[1]) \ ? 0x00 : 0xFF; \ if (x) { \ (m) >>= (b); \ (x) -= (b); \ } else { \ (x) = (x0); \ (m) = (m0); \ ++(s); \ }#define INIT_UNPACK(b, x, m) \ (x) = (8 - (b)); \ (m) = 0xff ^ (0xff >> (x))#define UNPACK(d, s, x, m, b, x0, m0) \ *(d)++ = ((*s) & (m)) >> (x); \ if (x) { \ (m) >>= (b); \ (x) -= (b); \ } else { \ (x) = (x0); \ (m) = (m0); \ ++(s); \ }#define INIT_PACK3(b, t, x, a) \ (x) = ((b) > 8) ? 1 : 0; \ (a) = ((t) ? 4 : 3) << (x)#define PACK3(d, s, x, a, cta) \ *(d)++ = (s)[0]; \ *(d)++ = (s)[1 << x]; \ *(d)++ = (s)[2 << x]; \ if (cta) *(d)++ = (s)[3 << x]; \ (s) += (a)#define INIT_PACK1(b, t, x, a) \ (x) = ((b) > 8) ? 1 : 0; \ (a) = ((t) ? 2 : 1) << (x)#define PACK1(d, s, x, a, cta) \ *(d)++ = (s)[0]; \ if (cta) *(d)++ = (s)[1 << x]; \ (s) += (a)static voidunpack1(unsigned char *dst, unsigned char *src, pngData *data){ int i; int shift, inc, x0; unsigned char mask, m0; if (data->trans != NULL && data->colorType != 3) { /*transparency is possible for grayscale, palette and rgb triples. compare the pixel values with the 16-bit per channel transparency map. if it matches then write alpha as 0x00 else write alpha as 0xff */ if (data->colorType == 2) { /* each pixel is RGB with 8 or 16 bits per channel */ INIT_TRANS_PACK_RGB(data->depth, shift, inc); for (i = 0; i < data->width; ++i) { TRANS_PACK_RGB(dst, src, shift, inc, data->trans); } } else if (data->colorType == 0) { /* each pixel is a grayscale value. if it is with a bit depth less than 8 we have to unpack the data. */ if(data->depth < 8) { /* unpack function that handles transparency. takes 1, 2, 4 bit grayscale values with transparency info and converts them to an 8-bit grayscale with 8-bit alpha value. */ INIT_TRANS_UNPACK_GS(data->depth, shift, mask); x0 = shift; m0 = mask; for (i = 0; i < data->width; ++i) { TRANS_UNPACK_GS(dst, src, shift, mask, data->depth, x0, m0, data->trans); } } else { INIT_TRANS_PACK_GS(data->depth, shift, inc); for (i = 0; i < data->width; ++i) { TRANS_PACK_GS(dst, src, shift, inc, data->trans); } } } } else if (data->depth < 8) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -