static void applyfilter2(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) { int x; unsigned char lasta=0; unsigned char lastb=0; unsigned char upperlasta=0; unsigned char upperlastb=0; if(mode==0) { for(x=0; x<width; x++) { dest[0] = src[0]; dest[1] = src[1]; dest+=2; src+=2; } } else if(mode==1) { for(x=0; x<width; x++) { dest[0] = src[0]+lasta; dest[1] = src[1]+lastb; lasta = dest[0]; lastb = dest[1]; dest+=2; src+=2; } } else if(mode==2) { for(x=0; x<width; x++) { dest[0] = src[0]+old[0]; dest[1] = src[1]+old[1]; dest+=2; old+=2; src+=2; } } else if(mode==3) { for(x=0; x<width; x++) { dest[0] = src[0]+(old[0]+lasta)/2; dest[1] = src[1]+(old[1]+lastb)/2; lasta = dest[0]; lastb = dest[1]; dest+=2; old+=2; src+=2; } } else if(mode==4) { for(x=0; x<width; x++) { dest[0] = src[0]+PaethPredictor(lasta,old[0],upperlasta); dest[1] = src[1]+PaethPredictor(lastb,old[1],upperlastb); lasta = dest[0]; lastb = dest[1]; upperlasta = old[0]; upperlastb = old[1]; dest+=2; old+=2; src+=2; } } }
static void applyfilter1(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) { int x; unsigned char last=0; unsigned char upperlast=0; if(mode==0) { for(x=0; x<width; x++) { *dest = *src; dest++; src++; } } else if(mode==1) { for(x=0; x<width; x++) { *dest = *src+last; last = *dest; dest++; src++; } } else if(mode==2) { for(x=0; x<width; x++) { *dest = *src+*old; dest++; old++; src++; } } else if(mode==3) { for(x=0; x<width; x++) { *dest = *src+(*old+last)/2; last = *dest; dest++; old++; src++; } } else if(mode==4) { for(x=0; x<width; x++) { *dest = *src+PaethPredictor(last,*old,upperlast); last = *dest; upperlast = *old; dest++; old++; src++; } } }
static void inline applyfilter4(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) { int x; unsigned char lastr=0; unsigned char lastg=0; unsigned char lastb=0; unsigned char lasta=0; unsigned char upperlastr=0; unsigned char upperlastg=0; unsigned char upperlastb=0; unsigned char upperlasta=0; if(mode==0) { for(x=0; x<width; x++) { dest[0] = src[3]; dest[1] = src[0]; dest[2] = src[1]; dest[3] = src[2]; dest+=4; src+=4; } } else if(mode==1) { for(x=0; x<width; x++) { dest[0] = src[3]+lasta; dest[1] = src[0]+lastr; dest[2] = src[1]+lastg; dest[3] = src[2]+lastb; lasta = dest[0]; lastr = dest[1]; lastg = dest[2]; lastb = dest[3]; dest+=4; src+=4; } } else if(mode==2) { for(x=0; x<width; x++) { dest[0] = src[3]+old[0]; dest[1] = src[0]+old[1]; dest[2] = src[1]+old[2]; dest[3] = src[2]+old[3]; dest+=4; old+=4; src+=4; } } else if(mode==3) { for(x=0; x<width; x++) { dest[0] = src[3]+(old[0]+lasta)/2; dest[1] = src[0]+(old[1]+lastr)/2; dest[2] = src[1]+(old[2]+lastg)/2; dest[3] = src[2]+(old[3]+lastb)/2; lasta = dest[0]; lastr = dest[1]; lastg = dest[2]; lastb = dest[3]; dest+=4; old+=4; src+=4; } } else if(mode==4) { for(x=0; x<width; x++) { dest[0] = src[3]+PaethPredictor(lasta,old[0],upperlasta); dest[1] = src[0]+PaethPredictor(lastr,old[1],upperlastr); dest[2] = src[1]+PaethPredictor(lastg,old[2],upperlastg); dest[3] = src[2]+PaethPredictor(lastb,old[3],upperlastb); lasta = dest[0]; lastr = dest[1]; lastg = dest[2]; lastb = dest[3]; upperlasta = old[0]; upperlastr = old[1]; upperlastg = old[2]; upperlastb = old[3]; dest+=4; old+=4; src+=4; } } }
void PNG_DecompressBGRX(PNGChunkIHDR *ihdr, // IN uint32 *framebuffer, // OUT uint32 pitch) // OUT { uint32 width = bswap32(ihdr->width); uint32 height = bswap32(ihdr->height); /* * Size of raw decompressed image: 3 bytes per pixel, plus one byte * (filter type) per scanline. */ uint32 rawPitch = (width * 3) + 1; unsigned long rawSize = height * rawPitch; /* * Size of final decompressed image */ uint32 finalSize = height * pitch; /* * Use the bottom of the framebuffer for temporary memory. The * final raw-to-final conversion must read from higher addresses * and write to lower addresses, so we don't overwrite our * temporary buffer prematurely. To do this with all filter types, * we need to use one extra line of temporary space. */ uint8 *rawBuffer = (uint8*)framebuffer + finalSize - rawSize + pitch; /* * Decompress all IDAT data into our raw buffer. We need to join * all IDAT chunks to get a raw zlib data stream, then strip off * the 2-byte ZLIB header and 4-byte checksum to get a raw DEFLATE * stream. */ PNGChunk *idat = PNGJoinIDAT(&ihdr->hdr); unsigned long compressedSize = bswap32(idat->length) - 6; puff(rawBuffer, &rawSize, idat->data + 2, &compressedSize); /* * Line-by-line, expand the decompressed filtered data into BGRX. */ uint32 lines = height; Bool notFirstRow = FALSE; while (lines--) { uint8 *rawLine = rawBuffer; uint32 *fbLine = framebuffer; uint32 pixels = width; framebuffer = (uint32*) (pitch + (uint8*)framebuffer); rawBuffer += rawPitch; uint8 filterType = *(rawLine++); Bool notFirstColumn = FALSE; while (pixels--) { /* * Undo the per-scanline filtering. */ uint8 *up = rawLine - rawPitch; uint8 *left = rawLine - 3; uint8 *upLeft = rawLine - 3 - rawPitch; uint32 i; for (i = 0; i < 3; i++) { switch (filterType) { case 0: // None break; case 1: // Sub if (notFirstColumn) { rawLine[i] += left[i]; } break; case 2: // Up if (notFirstRow) { rawLine[i] += up[i]; } break; case 3: // Average rawLine[i] += ((notFirstColumn ? left[i] : 0) + (notFirstRow ? up[i] : 0)) >> 1; break; case 4: // Paeth rawLine[i] += PaethPredictor(notFirstColumn ? left[i] : 0, notFirstRow ? up[i] : 0, (notFirstRow && notFirstColumn) ? upLeft[i] : 0); break; } } /* * Decode RGB to BGRX. */ uint8 r = rawLine[0]; uint8 g = rawLine[1]; uint8 b = rawLine[2]; *(fbLine++) = (r << 16) | (g << 8) | b; rawLine += 3; notFirstColumn = TRUE; } notFirstRow = TRUE; } }
static void ReconstructImage(uint8_t *pixels, uint8_t *encoded, int width, int height, int pixelWidth) { int row = width * pixelWidth; int i; for (i = 0; i < height; i++) { uint8_t method = *encoded++; if (method == 2 && i == 0) method = 0; if (method == 4 && i == 0) method = 1; /* * Filters are applied to bytes, not to pixels, regardless of the bit depth * or colour type of the image. The filters operate on the byte sequence * formed by a scanline. */ if (method == 0) { memcpy(pixels, encoded, row); encoded += row; pixels += row; } else if (method == 1) { uint8_t *left = pixels; int16_t j = row - 1; *pixels++ = *encoded++; do { *pixels++ = *encoded++ + *left++; } while (--j); } else if (method == 2) { uint8_t *up = pixels - row; int16_t j = row; do { *pixels++ = *encoded++ + *up++; } while (--j); } else if (method == 3) { uint8_t *left = pixels; int16_t j = row - 1; if (i > 0) { uint8_t *up = pixels - row; *pixels++ = *encoded++ + *up++ / 2; do { *pixels++ = *encoded++ + (*left++ + *up++) / 2; } while (--j); } else { *pixels++ = *encoded++; do { *pixels++ = *encoded++ + *left++ / 2; } while (--j); } } else if (method == 4) { uint8_t *left = pixels; uint8_t *leftup = pixels - row; uint8_t *up = pixels - row; int16_t j = row - 1; *pixels++ = *encoded++ + *up++; do { *pixels++ = *encoded++ + PaethPredictor(*left++, *up++, *leftup++); } while (--j); } } }