PSD GdDecodePNG(buffer_t * src) { unsigned char hdr[8], **rows; png_structp state; png_infop pnginfo; png_uint_32 width, height; int bit_depth, color_type, i; double file_gamma; int channels, data_format; PSD pmd; GdImageBufferSeekTo(src, 0UL); if(GdImageBufferRead(src, hdr, 8) != 8) return NULL; if(png_sig_cmp(hdr, 0, 8)) return NULL; if(!(state = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto nomem; if(!(pnginfo = png_create_info_struct(state))) { png_destroy_read_struct(&state, NULL, NULL); goto nomem; } if(setjmp(png_jmpbuf(state))) { png_destroy_read_struct(&state, &pnginfo, NULL); return NULL; } /* Set up the input function */ png_set_read_fn(state, src, png_read_buffer); /* png_init_io(state, src); */ png_set_sig_bytes(state, 8); png_read_info(state, pnginfo); png_get_IHDR(state, pnginfo, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); /* set-up the transformations */ /* transform paletted images into full-color rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand (state); /* expand images to bit-depth 8 (only applicable for grayscale images) */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand (state); /* transform transparency maps into full alpha-channel */ if (png_get_valid (state, pnginfo, PNG_INFO_tRNS)) png_set_expand (state); /* downgrade 16-bit images to 8 bit */ if (bit_depth == 16) png_set_strip_16 (state); /* Handle transparency... */ if (png_get_valid(state, pnginfo, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(state); /* transform grayscale images into full-color */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (state); /* only if file has a file gamma, we do a correction */ if (png_get_gAMA (state, pnginfo, &file_gamma)) png_set_gamma (state, (double) 2.2, file_gamma); /* all transformations have been registered; now update pnginfo data, * get rowbytes and channels, and allocate image memory */ png_read_update_info (state, pnginfo); /* get the new color-type and bit-depth (after expansion/stripping) */ png_get_IHDR (state, pnginfo, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); /* calculate new number of channels and store alpha-presence */ if (color_type == PNG_COLOR_TYPE_RGB) channels = 3; else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) channels = 4; // else if (color_type == PNG_COLOR_TYPE_GRAY) // channels = 1; // else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) // channels = 2; else { /* GdDrawImage currently only supports 32bpp alpha channel*/ DPRINTF("GdDecodePNG: Gray image type not supported: %d\n", color_type); return NULL; } /* set image data format*/ data_format = (channels == 4)? MWIF_RGBA8888: MWIF_RGB888; //pimage->pitch = width * channels * (bit_depth / 8); //bpp = channels * 8; pmd = GdCreatePixmap(&scrdev, width, height, data_format, NULL, 0); if (!pmd) { png_destroy_read_struct(&state, &pnginfo, NULL); goto nomem; } //DPRINTF("png %dbpp\n", channels*8); if(!(rows = malloc(height * sizeof(unsigned char *)))) { png_destroy_read_struct(&state, &pnginfo, NULL); goto nomem; } for(i = 0; i < height; i++) rows[i] = ((unsigned char *)pmd->addr) + i * pmd->pitch; png_read_image(state, rows); png_read_end(state, NULL); free(rows); png_destroy_read_struct(&state, &pnginfo, NULL); return pmd; nomem: EPRINTF("GdDecodePNG: Out of memory\n"); return NULL; }
int ExtractBits(PNG_CONST TCHAR *inname, PNG_CONST TCHAR *outname) { static HANDLE fpin; static HANDLE fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; png_structp write_ptr = NULL; png_infop write_info_ptr = NULL; png_infop write_end_info_ptr = NULL; png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; char inbuf[256], outbuf[256]; row_buf = NULL; if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } if ((fpout = CreateFile(outname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not open output file %s\n", outname); FCLOSE(fpin); return (1); } png_debug(0, "Allocating read and write structures"); read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); png_debug(0, "Allocating read_info, write_info and end_info structures"); read_info_ptr = png_create_info_struct(read_ptr); end_info_ptr = png_create_info_struct(read_ptr); png_debug(0, "Setting jmpbuf for read struct"); if (setjmp(png_jmpbuf(read_ptr))) { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); png_free(read_ptr, row_buf); row_buf = NULL; png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); FCLOSE(fpin); FCLOSE(fpout); return (1); } png_debug(0, "Initializing input and output streams"); png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); if (status_dots_requested == 1) { png_set_read_status_fn(read_ptr, read_row_callback); } else { png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); } png_debug(0, "Reading info struct"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type); } } { int intent; if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) png_set_sRGB(write_ptr, write_info_ptr, intent); } { png_colorp palette; int num_palette; if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); } { png_color_8p sig_bit; if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) png_set_sBIT(write_ptr, write_info_ptr, sig_bit); } { png_bytep trans; int num_trans; png_color_16p trans_values; if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, &trans_values)) { int sample_max = (1 << read_info_ptr->bit_depth); /* libpng doesn't reject a tRNS chunk with out-of-range samples */ if (!((read_info_ptr->color_type == PNG_COLOR_TYPE_GRAY && (int)trans_values->gray > sample_max) || (read_info_ptr->color_type == PNG_COLOR_TYPE_RGB && ((int)trans_values->red > sample_max || (int)trans_values->green > sample_max || (int)trans_values->blue > sample_max)))) png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, trans_values); } } png_debug(0, "Writing row data"); num_pass = png_set_interlace_handling(read_ptr); for(pass = 0; pass < num_pass; pass++) { png_debug1(0, "Writing row data for pass %d", pass); for(y = 0; y < height; y++) { png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); row_buf = (png_bytep)png_malloc(read_ptr, png_get_rowbytes(read_ptr, read_info_ptr)); png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, png_get_rowbytes(read_ptr, read_info_ptr)); png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); png_free(read_ptr, row_buf); row_buf = NULL; } } png_debug(0, "Reading and writing end_info data"); png_read_end(read_ptr, end_info_ptr); { png_uint_32 iwidth, iheight; iwidth = png_get_image_width(write_ptr, write_info_ptr); iheight = png_get_image_height(write_ptr, write_info_ptr); fprintf(STDERR, "\n Image width = %lu, height = %lu\n", (unsigned long)iwidth, (unsigned long)iheight); } png_debug(0, "Destroying data structs"); png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_debug(0, "Destruction complete."); FCLOSE(fpin); FCLOSE(fpout); png_debug(0, "Opening files for comparison"); if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find file %s\n", inname); return (1); } if ((fpout = CreateFile(outname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) { fprintf(STDERR, "Could not find file %s\n", outname); FCLOSE(fpin); return (1); } for(;;) { DWORD num_in, num_out; READFILE(fpin, inbuf, 1, num_in); READFILE(fpout, outbuf, 1, num_out); if (num_in != num_out) { fprintf(STDERR, "\nFiles %s and %s are of a different size\n", inname, outname); if (wrote_question == 0) { fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } FCLOSE(fpin); FCLOSE(fpout); return (0); } if (!num_in) break; if (png_memcmp(inbuf, outbuf, num_in)) { fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); if (wrote_question == 0) { fprintf(STDERR, " Was %s written with the same maximum IDAT chunk size (%d bytes),", inname, PNG_ZBUF_SIZE); fprintf(STDERR, "\n filtering heuristic (libpng default), compression"); fprintf(STDERR, " level (zlib default),\n and zlib version (%s)?\n\n", ZLIB_VERSION); wrote_question = 1; } FCLOSE(fpin); FCLOSE(fpout); return (0); } } FCLOSE(fpin); FCLOSE(fpout); return (0); }
int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { GLint pack, unpack; unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data, data2; png_bytep *row_p; double fileGamma; png_uint_32 width, height, rw, rh; int depth, color; png_uint_32 i; fread(header, 1, 8, fp); if (!png_check_sig(header, 8)) return 0; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(png); endinfo = png_create_info_struct(png); // DH: added following lines if (setjmp(png->jmpbuf)) { png_destroy_read_struct(&png, &info, &endinfo); return 0; } // ~DH png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); if (pinfo != NULL) { pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; } if (MaxTextureSize == 0) glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); #ifdef SUPPORTS_PALETTE_EXT #ifdef _WIN32 if (PalettedTextures == -1) PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL); if (PalettedTextures) { if (glColorTableEXT == NULL) { glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); if (glColorTableEXT == NULL) PalettedTextures = 0; } } #endif #endif if (PalettedTextures == -1) PalettedTextures = 0; if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) { png_set_strip_alpha(png); color &= ~PNG_COLOR_MASK_ALPHA; } if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID)) if (color == PNG_COLOR_TYPE_PALETTE) png_set_expand(png); /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); rw = SafeSize(width), rh = SafeSize(height); if (rw != width || rh != height) { const int channels = png_get_rowbytes(png, info)/width; data2 = (png_bytep) malloc(rw*rh*channels); /* Doesn't work on certain sizes */ /* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0) return 0; */ Resize(channels, data, width, height, data2, rw, rh); width = rw, height = rh; free(data); data = data2; } { /* OpenGL stuff */ glGetIntegerv(GL_PACK_ALIGNMENT, &pack); glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); #ifdef SUPPORTS_PALETTE_EXT if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) { png_colorp pal; int cols; GLint intf; if (pinfo != NULL) pinfo->Alpha = 0; png_get_PLTE(png, info, &pal, &cols); switch (cols) { case 1<<1: intf = GL_COLOR_INDEX1_EXT; break; case 1<<2: intf = GL_COLOR_INDEX2_EXT; break; case 1<<4: intf = GL_COLOR_INDEX4_EXT; break; case 1<<8: intf = GL_COLOR_INDEX8_EXT; break; case 1<<12: intf = GL_COLOR_INDEX12_EXT; break; case 1<<16: intf = GL_COLOR_INDEX16_EXT; break; default: /*printf("Warning: Colour depth %i not recognised\n", cols);*/ return 0; } glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal); glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); } else #endif if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) { GLenum glformat; GLint glcomponent; switch (color) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: glformat = GL_RGB; glcomponent = 3; if (pinfo != NULL) pinfo->Alpha = 0; break; case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA: glformat = GL_RGBA; glcomponent = 4; if (pinfo != NULL) pinfo->Alpha = 8; break; default: /*puts("glformat not set");*/ return 0; } if (mipmap == PNG_BUILDMIPMAPS) Build2DMipmaps(glcomponent, width, height, glformat, data, 1); else if (mipmap == PNG_SIMPLEMIPMAPS) Build2DMipmaps(glcomponent, width, height, glformat, data, 0); else glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data); } else { png_bytep p, endp, q; int r, g, b, a; p = data, endp = p+width*height*3; q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4); if (pinfo != NULL) pinfo->Alpha = 8; #define FORSTART \ do { \ r = *p++; /*red */ \ g = *p++; /*green*/ \ b = *p++; /*blue */ \ *q++ = r; \ *q++ = g; \ *q++ = b; #define FOREND \ q++; \ } while (p != endp); #define ALPHA *q switch (trans) { case PNG_CALLBACK: FORSTART ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b); FOREND break; case PNG_STENCIL: FORSTART if (r == StencilRed && g == StencilGreen && b == StencilBlue) ALPHA = 0; else ALPHA = 255; FOREND break; case PNG_BLEND1: FORSTART a = r+g+b; if (a > 255) ALPHA = 255; else ALPHA = a; FOREND break; case PNG_BLEND2: FORSTART a = r+g+b; if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND break; case PNG_BLEND3: FORSTART ALPHA = (r+g+b)/3; FOREND break; case PNG_BLEND4: FORSTART a = r*r+g*g+b*b; if (a > 255) ALPHA = 255; else ALPHA = a; FOREND break; case PNG_BLEND5: FORSTART a = r*r+g*g+b*b; if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND break; case PNG_BLEND6: FORSTART a = r*r+g*g+b*b; if (a > 255*3) ALPHA = 255; else ALPHA = a/3; FOREND break; case PNG_BLEND7: FORSTART a = r*r+g*g+b*b; if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a); FOREND break; } #undef FORSTART #undef FOREND #undef ALPHA if (mipmap == PNG_BUILDMIPMAPS) Build2DMipmaps(4, width, height, GL_RGBA, data2, 1); else if (mipmap == PNG_SIMPLEMIPMAPS) Build2DMipmaps(4, width, height, GL_RGBA, data2, 0); else glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2); free(data2); } glPixelStorei(GL_PACK_ALIGNMENT, pack); glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); } /* OpenGL end */ png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); free(data); return 1; }
BitmapImage * PNGImageIO_loadPNGData(const void * data, size_t length, int pixelFormat, bool flipVertical) { png_byte headerBytes[PNG_HEADER_SIZE]; png_structp pngReadStruct; png_infop pngInfoStruct; struct memreadContext readContext; unsigned int width, height; png_int_32 bitDepth, colorType; png_bytep * rows = NULL; unsigned char * pixels = NULL; unsigned int rowIndex; enum BitmapPixelFormat chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGBA_8888; BitmapImage * image; readContext = memreadContextInit(data, length); if (!memread(&readContext, PNG_HEADER_SIZE, headerBytes) || png_sig_cmp(headerBytes, 0, PNG_HEADER_SIZE)) { return NULL; } pngReadStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); pngInfoStruct = png_create_info_struct(pngReadStruct); if (setjmp(png_jmpbuf(pngReadStruct))) { png_destroy_read_struct(&pngReadStruct, &pngInfoStruct, NULL); free(rows); free(pixels); return NULL; } png_set_read_fn(pngReadStruct, &readContext, pngReadFnMemread); png_set_sig_bytes(pngReadStruct, PNG_HEADER_SIZE); png_read_info(pngReadStruct, pngInfoStruct); width = png_get_image_width(pngReadStruct, pngInfoStruct); height = png_get_image_height(pngReadStruct, pngInfoStruct); bitDepth = png_get_bit_depth(pngReadStruct, pngInfoStruct); colorType = png_get_color_type(pngReadStruct, pngInfoStruct); if (colorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(pngReadStruct); colorType = PNG_COLOR_TYPE_RGB; } if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) { png_set_expand_gray_1_2_4_to_8(pngReadStruct); } if (png_get_valid(pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(pngReadStruct); } if (bitDepth == 16) { png_set_strip_16(pngReadStruct); } switch (pixelFormat) { case PNG_PIXEL_FORMAT_AUTOMATIC: switch (colorType) { case PNG_COLOR_TYPE_GRAY: chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAY_8; break; case PNG_COLOR_TYPE_GRAY_ALPHA: chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAYALPHA_88; break; case PNG_COLOR_TYPE_RGB: chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGB_888; break; case PNG_COLOR_TYPE_RGB_ALPHA: chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGBA_8888; break; } png_read_update_info(pngReadStruct, pngInfoStruct); break; case BITMAP_PIXEL_FORMAT_RGBA_8888: if (!(colorType & PNG_COLOR_MASK_ALPHA)) { png_set_add_alpha(pngReadStruct, 0xFF, PNG_FILLER_AFTER); } png_read_update_info(pngReadStruct, pngInfoStruct); if (!(colorType & PNG_COLOR_MASK_COLOR)) { png_set_gray_to_rgb(pngReadStruct); } chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGBA_8888; break; case BITMAP_PIXEL_FORMAT_RGB_888: if (colorType & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(pngReadStruct); } png_read_update_info(pngReadStruct, pngInfoStruct); if (!(colorType & PNG_COLOR_MASK_COLOR)) { png_set_gray_to_rgb(pngReadStruct); } chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGB_888; break; case BITMAP_PIXEL_FORMAT_GRAYALPHA_88: if (!(colorType & PNG_COLOR_MASK_ALPHA)) { png_set_add_alpha(pngReadStruct, 0xFF, PNG_FILLER_AFTER); } png_read_update_info(pngReadStruct, pngInfoStruct); if (colorType & PNG_COLOR_MASK_COLOR) { png_set_rgb_to_gray(pngReadStruct, 1, (float) 0x55 / 0xFF, (float) 0x55 / 0xFF); } chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAYALPHA_88; break; case BITMAP_PIXEL_FORMAT_GRAY_8: if (colorType & PNG_COLOR_MASK_ALPHA) { png_set_strip_alpha(pngReadStruct); } png_read_update_info(pngReadStruct, pngInfoStruct); if (colorType & PNG_COLOR_MASK_COLOR) { png_set_rgb_to_gray(pngReadStruct, 1, (float) 0x55 / 0xFF, (float) 0x55 / 0xFF); } chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAY_8; break; } pixels = calloc(width * height, BitmapImage_pixelFormatBytes(chosenPixelFormat)); rows = malloc(sizeof(png_bytep) * height); for (rowIndex = 0; rowIndex < height; rowIndex++) { rows[rowIndex] = pixels + ((flipVertical ? height - rowIndex - 1 : rowIndex) * width * BitmapImage_pixelFormatBytes(chosenPixelFormat)); } png_read_rows(pngReadStruct, rows, NULL, height); png_read_end(pngReadStruct, NULL); png_destroy_read_struct(&pngReadStruct, &pngInfoStruct, NULL); free(rows); image = BitmapImage_createWithPixelsNoCopy(chosenPixelFormat, width, height, width * BitmapImage_pixelFormatBytes(chosenPixelFormat), pixels, true); return image; }
int LoadPNG(void *pRaw, int rawlen, unsigned int *puWidth, unsigned int *puHeight, void **ppData) { png_bytep *row_pointers; png_uint_32 w, h; png_structp png_ptr; png_infop info_ptr; int bit_depth, color_type, interlace_type; int i; int number_of_passes; void *pixels; mypngio_t *pMy; png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; if( png_sig_cmp((png_bytep)pRaw, 0, 8) != 0 ) { goto err_exit; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(!png_ptr) { goto err_exit; } info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { goto err_exit; } if (setjmp (png_jmpbuf (png_ptr))) { goto err_exit; } pMy = (mypngio_t*)calloc(1,sizeof(mypngio_t)); pMy->pPtr = pRaw; pMy->off = 8; png_set_read_fn(png_ptr, (void *)pMy, user_read_fn); png_set_sig_bytes(png_ptr, 8); png_read_info (png_ptr, info_ptr); png_get_IHDR (png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, &interlace_type, 0, 0); /*** Set up some transformations to get everything in our nice ARGB format. ***/ /* 8 bits per channel: */ if (bit_depth == 16) png_set_strip_16 (png_ptr); /* Convert palette to RGB: */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png_ptr), color_type = PNG_COLOR_TYPE_RGB; /* Extract 1/2/4bpp to 8bpp: */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8 (png_ptr); /* Convert colorkey to alpha: */ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png_ptr); /* Convert gray to RGB: */ if (color_type == PNG_COLOR_TYPE_GRAY) png_set_gray_to_rgb (png_ptr), color_type = PNG_COLOR_TYPE_RGB; if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr), color_type = PNG_COLOR_TYPE_RGB_ALPHA; /* Convert RGB to RGBA */ if (color_type == PNG_COLOR_TYPE_RGB) png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER); //png_set_bgr(png_ptr); number_of_passes = png_set_interlace_handling (png_ptr); /* Update the info struct. */ png_read_update_info (png_ptr, info_ptr); /* Allocate our surface. */ pixels = malloc( w * h * 4 ); if (!pixels) { goto err_exit; } row_pointers = (png_bytep*)malloc (h * sizeof(png_bytep)); if (!row_pointers) { goto err_exit; } /* Build the array of row pointers. */ for (i = 0; i < (int)h; i++) { row_pointers[i] = (png_bytep)( (unsigned char*)pixels + (i * w * 4) ); } /* Read the thing. */ png_read_image (png_ptr, row_pointers); /* Read the rest. */ png_read_end (png_ptr, info_ptr); if (png_ptr) png_destroy_read_struct (&png_ptr, info_ptr? &info_ptr : 0, 0); if (row_pointers) free (row_pointers); *puWidth = w; *puHeight = h; *ppData = pixels; return 0; err_exit: if (png_ptr) png_destroy_read_struct (&png_ptr, info_ptr? &info_ptr : 0, 0); if (row_pointers) free (row_pointers); return -1; }
/* This routine is based in part on the Chapter 13 demo code in "PNG: The * Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html). */ gdImagePtr gdImageCreateFromPngCtx (gdIOCtx * infile) { png_byte sig[8]; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height, rowbytes; int bit_depth, color_type, interlace_type; int num_palette, num_trans; png_colorp palette; png_color_16p trans_gray_rgb; png_color_16p trans_color_rgb; png_bytep trans; png_bytep image_data = NULL; png_bytepp row_pointers = NULL; gdImagePtr im = NULL; int i, j, *open = NULL; volatile int transparent = -1; volatile int palette_allocated = FALSE; /* Make sure the signature can't match by dumb luck -- TBB */ /* GRR: isn't sizeof(infile) equal to the size of the pointer? */ memset (infile, 0, sizeof (infile)); /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ gdGetBuf (sig, 8, infile); if (!png_check_sig (sig, 8)) return NULL; /* bad signature */ #ifndef PNG_SETJMP_NOT_SUPPORTED png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct, gdPngErrorHandler, NULL); #else png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); #endif if (png_ptr == NULL) { fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n"); return NULL; } info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n"); png_destroy_read_struct (&png_ptr, NULL, NULL); return NULL; } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every non-callback function that calls a * PNG-reading libpng function */ #ifndef PNG_SETJMP_NOT_SUPPORTED if (setjmp (gdPngJmpbufStruct.jmpbuf)) { fprintf (stderr, "gd-png error: setjmp returns error condition\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } #endif png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */ png_set_read_fn (png_ptr, (void *) infile, gdPngReadData); png_read_info (png_ptr, info_ptr); /* read all PNG info up to image data */ png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) { im = gdImageCreateTrueColor ((int) width, (int) height); } else { im = gdImageCreate ((int) width, (int) height); } if (im == NULL) { fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); gdFree (image_data); gdFree (row_pointers); return NULL; } if (bit_depth == 16) png_set_strip_16 (png_ptr); else if (bit_depth < 8) png_set_packing (png_ptr); /* expand to 1 byte per pixel */ switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette); #ifdef DEBUG fprintf (stderr, "gd-png color_type is palette, colors: %d\n", num_palette); #endif /* DEBUG */ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { /* gd 2.0: we support this rather thoroughly now. Grab the first fully transparent entry, if any, as the value of the simple-transparency index, mostly for backwards binary compatibility. The alpha channel is where it's really at these days. */ int firstZero = 1; png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL); for (i = 0; i < num_trans; ++i) { im->alpha[i] = gdAlphaMax - (trans[i] >> 1); if ((trans[i] == 0) && (firstZero)) { /* 2.0.5: long-forgotten patch from Wez Furlong */ transparent = i; firstZero = 0; } } } break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: /* create a fake palette and check for single-shade transparency */ if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL) { fprintf (stderr, "gd-png error: cannot allocate gray palette\n"); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return NULL; } palette_allocated = TRUE; if (bit_depth < 8) { num_palette = 1 << bit_depth; for (i = 0; i < 256; ++i) { j = (255 * i) / (num_palette - 1); palette[i].red = palette[i].green = palette[i].blue = j; } } else { num_palette = 256; for (i = 0; i < 256; ++i) { palette[i].red = palette[i].green = palette[i].blue = i; } } if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb); if (bit_depth == 16) /* png_set_strip_16() not yet in effect */ transparent = trans_gray_rgb->gray >> 8; else transparent = trans_gray_rgb->gray; /* Note slight error in 16-bit case: up to 256 16-bit shades * may get mapped to a single 8-bit shade, and only one of them * is supposed to be transparent. IOW, both opaque pixels and * transparent pixels will be mapped into the transparent entry. * There is no particularly good way around this in the case * that all 256 8-bit shades are used, but one could write some * custom 16-bit code to handle the case where there are gdFree * palette entries. This error will be extremely rare in * general, though. (Quite possibly there is only one such * image in existence.) */ } break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: /* gd 2.0: we now support truecolor. See the comment above for a rare situation in which the transparent pixel may not work properly with 16-bit channels. */ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) { png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb); if (bit_depth == 16) /* png_set_strip_16() not yet in effect */ transparent = gdTrueColor (trans_color_rgb->red >> 8, trans_color_rgb->green >> 8, trans_color_rgb->blue >> 8); else transparent = gdTrueColor (trans_color_rgb->red, trans_color_rgb->green, trans_color_rgb->blue); }
/* Read a PNG file. You may want to return an error code if the read * fails (depending upon the failure). There are two "prototypes" given * here - one where we are given the filename, and we need to open the * file, and the other where we are given an open file (possibly with * some or all of the magic bytes read - see comments above). */ #ifdef open_file /* prototype 1 */ void read_png(char *file_name) /* We need to open the file */ { png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE *fp; if ((fp = fopen(file_name, "rb")) == NULL) return (ERROR); #else no_open_file /* prototype 2 */ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; #endif no_open_file /* Only use one prototype! */ /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return (ERROR); } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, NULL, NULL); return (ERROR); } /* Set error handling if you are using the setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); /* If we get here, we had a problem reading the file */ return (ERROR); } /* One of the following I/O initialization methods is REQUIRED */ #ifdef streams /* PNG file I/O method 1 */ /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, fp); #else no_streams /* PNG file I/O method 2 */ /* If you are using replacement read functions, instead of calling * png_init_io() here you would call: */ png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); /* where user_io_ptr is a structure you want available to the callbacks */ #endif no_streams /* Use only one I/O method! */ /* If we have already read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); #ifdef hilevel /* * If you have enough memory to read in the entire image at once, * and you need to specify only transforms that can be controlled * with one of the PNG_TRANSFORM_* bits (this presently excludes * quantizing, filling, setting background, and doing gamma * adjustment), then you can read the entire image (including * pixels) into the info structure with this call: */ png_read_png(png_ptr, info_ptr, png_transforms, NULL); #else /* OK, you're doing it the hard way, with the lower-level functions */ /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). REQUIRED */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* Set up the data transformations you want. Note that these are all * optional. Only call them if you want/need them. Many of the * transformations only work on specific types of images, and many * are mutually exclusive. */ /* Tell libpng to strip 16 bit/color files down to 8 bits/color. * Use accurate scaling if it's available, otherwise just chop off the * low byte. */ #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED png_set_scale_16(png_ptr); #else png_set_strip_16(png_ptr); #endif /* Strip alpha bytes from the input data without combining with the * background (not recommended). */ png_set_strip_alpha(png_ptr); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ png_set_packswap(png_ptr); /* Expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); /* Expand paletted or RGB images with transparency to full alpha channels * so the data will be available as RGBA quartets. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. Note that * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one. */ png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* Some suggestions as to how to get a screen gamma value * * Note that screen gamma is the display_exponent, which includes * the CRT_exponent and any correction for viewing conditions */ if (/* We have a user-defined screen gamma value */) { screen_gamma = user-defined screen_gamma; } /* This is one way that applications share the same screen gamma value */ else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
int loadPNG(const char *filename) { GLuint texture; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_bytep *row_pointers = NULL; int bitDepth, colourType; FILE *pngFile = fopen(filename, "rb"); if (!pngFile) return 0; png_byte sig[8]; fread(&sig, 8, sizeof(png_byte), pngFile); rewind(pngFile); if (!png_check_sig(sig, 8)) { //SDL_Log("png sig failure\n"); return 0; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { //SDL_Log("png ptr not created\n"); return 0; } if (setjmp(png_jmpbuf(png_ptr))) { //SDL_Log("set jmp failed\n"); return 0; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { //SDL_Log("cant get png info ptr\n"); return 0; } png_init_io(png_ptr, pngFile); png_read_info(png_ptr, info_ptr); bitDepth = png_get_bit_depth(png_ptr, info_ptr); colourType = png_get_color_type(png_ptr, info_ptr); if (colourType == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (colourType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) //png_set_gray_1_2_4_to_8(png_ptr); png_set_expand_gray_1_2_4_to_8(png_ptr); // thanks to Jesse Jaara for bug fix for newer libpng... if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if (bitDepth == 16) png_set_strip_16(png_ptr); else if (bitDepth < 8) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colourType, NULL, NULL, NULL); int components; // = GetTextureInfo(colourType); switch (colourType) { case PNG_COLOR_TYPE_GRAY: components = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: components = 2; break; case PNG_COLOR_TYPE_RGB: components = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: components = 4; break; default: components = -1; } if (components == -1) { if (png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, NULL); //SDL_Log("%s broken?\n", filename); return 0; } GLubyte *pixels = (GLubyte *) malloc(sizeof(GLubyte) * (width * height * components)); row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * height); int i = 0; for (i = 0; i < height; ++i) { row_pointers[i] = (png_bytep) (pixels + (i * width * components)); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, NULL); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GLuint glcolours; (components == 4) ? (glcolours = GL_RGBA) : (0); (components == 3) ? (glcolours = GL_RGB) : (0); (components == 2) ? (glcolours = GL_LUMINANCE_ALPHA) : (0); (components == 1) ? (glcolours = GL_LUMINANCE) : (0); //SDL_Log("%s has %i colour components\n",filename,components); //glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, glcolours, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, glcolours, width, height, 0, glcolours, GL_UNSIGNED_BYTE, pixels); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(pngFile); free(row_pointers); free(pixels); return texture; }
void DisplaySplashImage() { FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE); if (f == NULL) return; png_byte header[8]; fread(header, sizeof(png_byte), 8, f); if (png_sig_cmp(header, 0, 8) != 0) { fclose(f); return; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, png_my_error, png_my_warning); if (png_ptr == NULL) { fclose(f); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(f); return; } png_infop end_info = png_create_info_struct(png_ptr); if (end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(f); return; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; } png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); uint width = png_get_image_width(png_ptr, info_ptr); uint height = png_get_image_height(png_ptr, info_ptr); uint bit_depth = png_get_bit_depth(png_ptr, info_ptr); uint color_type = png_get_color_type(png_ptr, info_ptr); if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; } if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; } png_colorp palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr); if (width > (uint) _screen.width) width = _screen.width; if (height > (uint) _screen.height) height = _screen.height; uint xoff = (_screen.width - width) / 2; uint yoff = (_screen.height - height) / 2; switch (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) { case 8: { uint8 *dst_ptr = (uint8 *)_screen.dst_ptr; /* Initialize buffer */ MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height); for (uint y = 0; y < height; y++) { uint8 *src = row_pointers[y]; uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff; memcpy(dst, src, width); } for (int i = 0; i < num_palette; i++) { _cur_palette[i].a = i == 0 ? 0 : 0xff; _cur_palette[i].r = palette[i].red; _cur_palette[i].g = palette[i].green; _cur_palette[i].b = palette[i].blue; } _cur_palette[0xff].a = 0xff; _cur_palette[0xff].r = 0; _cur_palette[0xff].g = 0; _cur_palette[0xff].b = 0; _pal_first_dirty = 0; _pal_count_dirty = 256; } break; case 32: { uint32 *dst_ptr = (uint32 *)_screen.dst_ptr; /* Initialize buffer */ MemSetT(dst_ptr, 0, _screen.pitch * _screen.height); for (uint y = 0; y < height; y++) { uint8 *src = row_pointers[y]; uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff; for (uint x = 0; x < width; x++) { dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000; } } } break; } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; }
/* pngReadImage: Reads an image from a memory buffer. Returns: non-zero if successful. */ int pngReadImage(int w, int h, int d, char* bits, char *data, int nBytes) { png_bytep *row_pointers = NULL; pngReadState rs; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; DBG("pngReadImage: png_sig_cmp"); /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */ if(png_sig_cmp(data, (png_size_t)0, PNG_BYTES_TO_CHECK)) return 0; DBG("pngReadImage: png_create_read_struct"); /* Create the png_struct */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) return 0; DBG("pngReadImage: png_create_info_struct"); /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); return 0; } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_read_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { DBG("pngReadImage: triggered png_error"); /* If we get here, we had a problem reading the file */ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); if(row_pointers) free(row_pointers); return 0; } rs.data = data; rs.position = 0; rs.length = nBytes; png_set_read_fn(png_ptr, (void *)&rs, readBytes); DBG("pngReadImage: png_read_info"); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). REQUIRED */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); /* Set up the data transformations you want. Note that these are all * optional. Only call them if you want/need them. Many of the * transformations only work on specific types of images, and many * are mutually exclusive. */ /* tell libpng to strip 16 bit/color files down to 8 bits/color */ png_set_strip_16(png_ptr); /* flip the RGB pixels to BGR (or RGBA to BGRA) */ if (color_type & PNG_COLOR_MASK_COLOR) { DBG("pngReadImage: png_set_bgr"); png_set_bgr(png_ptr); } if(d == 32 && color_type == PNG_COLOR_TYPE_RGB) { /* Add filler (or alpha) byte (before/after each RGB triplet) */ DBG("pngReadImage: png_set_filler"); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } if(0) { /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ png_set_packswap(png_ptr); /* Expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); } /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); /* Expand paletted or RGB images with transparency to full alpha channels * so the data will be available as RGBA quartets. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if(0) { /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. Note that * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one */ png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } if(0) { /* Tell libpng to handle the gamma conversion for you. The final call * is a good guess for PC generated images, but it should be configurable * by the user at run time by the user. It is strongly suggested that * your application support gamma correction. */ int intent; double screen_gamma = 1.2; if (png_get_sRGB(png_ptr, info_ptr, &intent)) png_set_gamma(png_ptr, screen_gamma, 0.45455); else { double image_gamma; if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) png_set_gamma(png_ptr, screen_gamma, image_gamma); else png_set_gamma(png_ptr, screen_gamma, 0.45455); } } if(0) { /* If you want to shift the pixel values from the range [0,255] or * [0,65535] to the original [0,7] or [0,31], or whatever range the * colors were originally in: */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); } } if(0) { /* flip the RGB pixels to BGR (or RGBA to BGRA) */ if (color_type & PNG_COLOR_MASK_COLOR) png_set_bgr(png_ptr); /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ png_set_swap_alpha(png_ptr); /* swap bytes of 16 bit files to least significant byte first */ png_set_swap(png_ptr); } { /* initialize the png row pointers */ int row, ppw = 32 / d; int pitch = ((w + ppw - 1) / ppw) * 4; int rowbytes = png_get_rowbytes(png_ptr, info_ptr); if(0) { char info[100]; sprintf(info, "Form pitch: %d\nPNG rowbytes: %d",pitch, rowbytes); DBG(info); } /* XXXX: It seems that this test is pretty pointless; PNG appears to return the raw rowbytes value, not the padded one. A better test is probably to compare the w/h/d values of png with the form values to ensure correctness. */ if(pitch < rowbytes) { png_error(png_ptr, "Row bytes mismatch"); } row_pointers = (png_bytep*) calloc(h, sizeof(void*)); for (row = 0; row < h; row++) { row_pointers[row] = bits + (row*pitch); } } DBG("pngReadImage: png_read_image"); /* Read the entire image in one go */ png_read_image(png_ptr, row_pointers); DBG("pngReadImage: Cleaning up"); /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); if(row_pointers) free(row_pointers); return 1; }
bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) { #ifndef USE_INTERNAL_PNG_DECODER png_structp png_ptr = NULL; png_infop info_ptr = NULL; int bitDepth; int colorType; int interlaceType; int i; // Check for valid PNG signature if (!doIsCorrectImageFormat(fileDataPtr, fileSize)) { error("png_check_sig failed"); } // Die beiden PNG Strukturen erstellen png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { error("Could not create libpng read struct."); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { error("Could not create libpng info struct."); } // Alternative Lesefunktion benutzen const byte **ref = &fileDataPtr; png_set_read_fn(png_ptr, (void *)ref, png_user_read_data); // PNG Header einlesen png_read_info(png_ptr, info_ptr); // PNG Informationen auslesen png_uint_32 w, h; png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL); width = w; height = h; // Pitch des Ausgabebildes berechnen pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width); // Speicher für die endgültigen Bilddaten reservieren // Dieses geschieht vor dem reservieren von Speicher für temporäre Bilddaten um die Fragmentierung des Speichers gering zu halten uncompressedDataPtr = new byte[pitch * height]; if (!uncompressedDataPtr) { error("Could not allocate memory for output image."); } // Bilder jeglicher Farbformate werden zunächst in ARGB Bilder umgewandelt if (bitDepth == 16) png_set_strip_16(png_ptr); if (colorType == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (bitDepth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); png_set_bgr(png_ptr); if (colorType != PNG_COLOR_TYPE_RGB_ALPHA) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); // Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL); width = w; height = h; if (interlaceType == PNG_INTERLACE_NONE) { // PNGs without interlacing can simply be read row by row. for (i = 0; i < height; i++) { png_read_row(png_ptr, uncompressedDataPtr + i * pitch, NULL); } } else { // PNGs with interlacing require us to allocate an auxillary // buffer with pointers to all row starts. // Allocate row pointer buffer png_bytep *pRowPtr = new png_bytep[height]; if (!pRowPtr) { error("Could not allocate memory for row pointers."); } // Initialize row pointers for (i = 0; i < height; i++) pRowPtr[i] = uncompressedDataPtr + i * pitch; // Read image data png_read_image(png_ptr, pRowPtr); // Free row pointer buffer delete[] pRowPtr; } // Read additional data at the end. png_read_end(png_ptr, NULL); // Destroy libpng structures png_destroy_read_struct(&png_ptr, &info_ptr, NULL); #else Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO); Graphics::PNG *png = new Graphics::PNG(); if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done error("Error while reading PNG image"); Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); Graphics::Surface *pngSurface = png->getSurface(format); width = pngSurface->w; height = pngSurface->h; uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h]; memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h); pngSurface->free(); delete pngSurface; delete png; #endif // Signal success return true; }
int naMain(JNIEnv* env, jobject pObj, jstring pCmdStr, jobject pMainActObj) { char progBuf[500]; jmethodID updateProgMID, toStringMID; jstring progStr; jclass mainActivityClass = (*env)->GetObjectClass(env, pMainActObj); cachedMainActObj = (*env)->NewGlobalRef(env, pMainActObj); // toStringMID = (*env)->GetMethodID(env, mainActivityClass, "toString", "()Ljava/lang/String;"); // jstring name = (*env)->CallObjectMethod(env, pMainActObj, toStringMID); // const jbyte* nameStr = (*env)->GetStringUTFChars(env, name, NULL); // LOGI(2, "toString: %s", nameStr); // (*env)->ReleaseStringUTFChars(env, name, nameStr); updateProgMID = (*env)->GetMethodID(env, mainActivityClass, "updateProgress", "(Ljava/lang/String;I)V"); if (NULL == updateProgMID) { LOGE(1, "error finding method updateProgress"); return EXIT_FAILURE; } // char* test = "test"; // jstring jtest = (*env)->NewStringUTF(env, test); // (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, jtest); int argc = 0; char** argv = (char**) malloc (sizeof(char*)*4); //the first input argument should be the program name itself *argv = "fusch"; char** targv = argv + 1; argc++; jboolean isCopy; char *cmdstr = (*env)->GetStringUTFChars(env, pCmdStr, &isCopy); if (NULL == cmdstr) { LOGI(2, "get string failed"); return EXIT_FAILURE; } char* pch; pch = strtok(cmdstr, " "); while (NULL != pch) { *targv = pch; argc++; targv++; pch = strtok(NULL, " "); } LOGI(1, "No. of arguments: %d", argc); LOGI(1, "%s %s %s %s", argv[0], argv[1], argv[2], argv[3]); #else int main(int argc, char *argv[]) { #endif setlocale(LC_ALL, ""); setvbuf(stdout, (char*)NULL, _IONBF, 0); if(argc != 4) { fprintf(stderr, MSG[I_HELP1], argv[0]); fputs(MSG[I_HELP2], stderr); return EXIT_FAILURE; } char *inname = argv[1], *outname = argv[2], *valarg = argv[3]; /* Quelldatei oeffnen und auf PNG-Signatur ueberpruefen **********************/ #ifdef ANDROID_BUILD // progStr = (*env)->NewStringUTF(env, MSG[I_OPEN]); // (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else puts(MSG[I_OPEN]); #endif FILE *f; f = fopen(inname, "rb"); if (f == NULL) { fputs(inname, stderr); fputs(MSG[E_OPEN], stderr); fputc('\n', stderr); return EXIT_FAILURE; } unsigned char sig[SIG_BYTES]; fread(sig, 1, SIG_BYTES, f); if (png_sig_cmp(sig, 0, SIG_BYTES)) { fputs(inname, stderr); fputs(MSG[E_CORRUPTED], stderr); fputc('\n', stderr); fclose(f); return EXIT_FAILURE; } /* PNG-Lesevorgang initialisieren *****************************************/ png_struct *png_ptr; png_info *info_ptr, *end_info; png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); if (png_ptr == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); fclose(f); return EXIT_FAILURE; } info_ptr = png_create_info_struct(png_ptr); end_info = png_create_info_struct(png_ptr); try_png_read( (info_ptr == NULL) || (end_info == NULL), &png_ptr, &info_ptr, &end_info, f, (char*)NULL ); try_png_read( setjmp(png_jmpbuf(png_ptr)), &png_ptr, &info_ptr, &end_info, f, MSG[E_READ] ); png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, SIG_BYTES); /* Bildinfo lesen: Bilddimensionen und ggf. Farbpalette. * Palette ggf. konvertieren. *********************************************/ long int width, height, pwidth, pheight; // png_uint_32 width, height, pwidth, pheight; comp_t *image, **row, *rwp; png_read_info(png_ptr, info_ptr); width = info_ptr->width; height = info_ptr->height; const long int original_width = info_ptr->width; const int bit_depth = info_ptr->bit_depth, color_type = info_ptr->color_type; const bool image_is_pal = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE); const bool image_is_gray = ( (color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ); const bool alpha = ( (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA) ); int num_palette = 0; png_color *png_pal_got = NULL; if (image_is_pal) try_png_read( !png_get_PLTE(png_ptr, info_ptr, &png_pal_got, &num_palette), &png_ptr, &info_ptr, &end_info, f, MSG[E_READPAL] ); png_color png_pal[num_palette]; comp_t comp_pal[num_palette]; if (image_is_pal) for (int i = 0; i < num_palette; i++) { png_pal[i] = png_pal_got[i]; comp_t c; c = png_pal[i].red; c <<= CHAR_BIT; c |= png_pal[i].green; c <<= CHAR_BIT; c |= png_pal[i].blue; comp_pal[i] = c; } png_color_16 *img_bkgd; png_color_16 background; if (png_get_bKGD(png_ptr, info_ptr, &img_bkgd)) background = *img_bkgd; /* Parameter fuer Groessenaenderung auswerten: * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher), * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ******************/ long int diff; bool vert; bool aspp = false, asp2 = false, enlg = false, sign = true; switch (tolower(*valarg++)) { case 'h': vert = false; break; case 'v': vert = true; break; case '%': aspp = true; break; case '@': asp2 = true; break; default : try_png_read(true, &png_ptr, &info_ptr, &end_info, f, MSG[E_DIM]); } switch (*valarg) { case '+': enlg = true; break; case '-': enlg = false; break; default: sign = false; break; } diff = atol(valarg); bool valargok = !!diff; if (aspp || asp2) { try_png_read(!sign, &png_ptr, &info_ptr, &end_info, f, MSG[E_SIGN]); const float fheight = (float)height, fwidth = (float)width, casp = fheight / fwidth; float nasp; if (asp2) { const char *aspsw = strtok(valarg, ":"), *aspsh = strtok((char*)NULL, ":"); valargok = ((aspsw != NULL) && (aspsh != NULL)); const float aspw = valargok? atol(aspsw): 0, asph = valargok? atol(aspsh): 0; nasp = valargok? fabs(asph / aspw): 0; } else nasp = ((float)labs(diff) / 100.0f); vert = ((nasp < casp) ^ enlg); diff = valargok? labs(vert? (height - (fwidth * nasp)): (width - (fheight / nasp)) ): 0; if (!enlg) diff = -diff; } if (!diff) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); if (valargok) { #ifdef ANDROID_BUILD progStr = (*env)->NewStringUTF(env, MSG[I_NOTHINGTODO]); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else puts(MSG[I_NOTHINGTODO]); #endif // const char copycmd[] = "copy /b /y"; const char copycmd[] = "cp"; char copycmdln[ strlen(copycmd) + strlen(argv[1]) + strlen(argv[2]) + 7 ]; sprintf( copycmdln, "%s \"%s\" \"%s\"", copycmd, argv[1], argv[2] ); return system(copycmdln); } try_png_read(!valargok, &png_ptr, &info_ptr, &end_info, f, MSG[E_PAR]); } if (!(aspp || asp2 || sign)) diff -= vert? height: width; try_png_read( labs(diff) > (vert? height: width), &png_ptr, &info_ptr, &end_info, f, MSG[E_SIZE] ); /* Bild- sowie Zeilenzeigerspeicher anfordern und Zeiger setzen. **********/ image = malloc(width * height * sizeof(comp_t)); try_png_read(image == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL); row = malloc(height * sizeof(comp_t*)); try_png_read(row == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL); rwp = image; for (int i = 0; i < height; i++) { row[i] = rwp; rwp += width; } /* Bild laden. * Falls Alphakanal vorhanden, Alpha invertieren: hoher Wert => hohe Deckung. * Falls Nicht-Palettenbild ohne Alphakanal (24 bpp) oder Graubild * (8 oder 16 bpp), mit "png_set_filler" die Bilddaten auf 32 bzw. 16 bpp * ausweiten. 32 Bit ist die * comp_t-Breite. ****************************/ #ifdef ANDROID_BUILD // progStr = (*env)->NewStringUTF(env, MSG[I_LOAD]); // (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else puts(MSG[I_LOAD]); #endif if (alpha) png_set_invert_alpha(png_ptr); else if (!image_is_pal) png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); png_read_image(png_ptr, (void*)row); /* Falls 8 oder 16 bpp, Bilddaten auf "Pixel = comp_t-Element" ausweiten. */ // trw: Temporaere Zeile. void *trw = malloc(image_is_gray? (width * 2): width); try_png_read(trw == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL); // Zunaechst Bildzeile nach Temporaerzeile kopieren, dann Elemente einzeln zurueck. if (image_is_pal) { for (int i = 0; i < height; i++) { uint8_t *trwp = trw; rwp = row[i]; memcpy(trw, row[i], width * sizeof *trwp); for (int j = 0; j < width; j++) *rwp++ = *trwp++; } } if (image_is_gray) { for (int i = 0; i < height; i++) { uint16_t *trwp = trw; rwp = row[i]; memcpy(trw, row[i], width * sizeof *trwp); for (int j = 0; j < width; j++) *rwp++ = *trwp++; } } /* Lesevorgang beenden und Quelldatei schliessen. ************************/ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); #ifdef ANDROID_BUILD sprintf(progBuf, "%s: %d*%d > %d*%d: %s %+d", MSG[I_MEASURES], width, height, vert? width: width + diff, vert? height + diff: height, vert? MSG[I_VERT]: MSG[I_HORI], diff ); progStr = (*env)->NewStringUTF(env, progBuf); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else printf( "%s: %d*%d > %d*%d: %s %+d\n", MSG[I_MEASURES], width, height, vert? width: width + diff, vert? height + diff: height, vert? MSG[I_VERT]: MSG[I_HORI], diff ); #endif /* Hier kommt Fugenschnitzer zum Einsatz. * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher), * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ****************/ sc_init(); sc_load(image, &width, &height, 0); const int prep = sc_prepare( vert, diff, // Bild ggf. erweitern false, alpha? MARK_ALPHA: MARK_KEEP, // Ggf. Alpha-Markierung (mark_t*)NULL, // keine Markierung sonst &width, &height, &pwidth, &pheight ); if (prep < 0) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); free(image); free(row); return EXIT_FAILURE; } if (prep & 2) { #ifdef ANDROID_BUILD progStr = (*env)->NewStringUTF(env, MSG[E_ALPHA]); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else puts(MSG[E_ALPHA]); #endif } // Bildspeicher erweitern, falls das Bild vergroessert wurde: if (prep & 1) { image = realloc(image, (size_t)width * (size_t)height * sizeof(comp_t)); if (image == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); return EXIT_FAILURE; } if (vert) { row = realloc(row, (size_t)height * sizeof(comp_t*)); if (row == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); free(image); return EXIT_FAILURE; } } } pthread_t seam_th; pthread_create(&seam_th, NULL, seam_progress, (void*)(&diff)); // sc_seam(diff); seam_paral(diff); pthread_join(seam_th, NULL); #ifdef ANDROID_BUILD progStr = (*env)->NewStringUTF(env, MSG[I_RESIZING]); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else putchar('\n'); printf(MSG[I_RESIZING]); #endif // sc_carve(diff, &width, &height, &pwidth, &pheight); carve_paral(diff, &width, &height, &pwidth, &pheight); sc_fix( false, // Nicht wiederherstellen &width, &height, &pwidth, &pheight ); sc_eject(image); sc_close(); /* Das war's mit Fugenschnitzer. -- Zeilenzeiger neu setzen. **************/ rwp = image; for (int i = 0; i < height; i++) { row[i] = rwp; rwp += width; } /* Zieldatei oeffnen und Schreibvorgang initialisieren. ********************/ #ifdef ANDROID_BUILD progStr = (*env)->NewStringUTF(env, MSG[I_SAVE]); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else putchar('\n'); printf(MSG[I_SAVE]); #endif f = fopen(outname, "wb"); if (f == NULL) { fputs(outname, stderr); fputs(MSG[E_SAVE], stderr); fputc('\n', stderr); return EXIT_FAILURE; } png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); if (png_ptr == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); fclose(f); return EXIT_FAILURE; } info_ptr = png_create_info_struct(png_ptr); try_png_write(info_ptr == NULL, &png_ptr, &info_ptr, f, (char*)NULL); try_png_write( setjmp(png_jmpbuf(png_ptr)), &png_ptr, &info_ptr, f, MSG[E_WRITE] ); png_init_io(png_ptr, f); /* Bildparameter setzen. **************************************************/ png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); if (image_is_pal) png_set_PLTE(png_ptr, info_ptr, png_pal, num_palette); if (alpha) png_set_bKGD(png_ptr, info_ptr, &background); png_write_info(png_ptr, info_ptr); /* Falls 8 oder 16 bpp, Bilddaten wieder zusammenschieben. ****************/ trw = realloc(trw, image_is_gray? (width * 2): width); try_png_write(trw == NULL, &png_ptr, &info_ptr, f, (char*)NULL); if (image_is_pal) { for (int i = 0; i < height; i++) { uint8_t *trwp = trw; rwp = row[i]; for (int j = 0; j < width; j++) *trwp++ = *rwp++; memcpy(row[i], trw, width * sizeof *trwp); } } if (image_is_gray) { for (int i = 0; i < height; i++) { uint16_t *trwp = trw; rwp = row[i]; for (int j = 0; j < width; j++) *trwp++ = *rwp++; memcpy(row[i], trw, width * sizeof *trwp); } } /* Bild speichern. Wieder Alpha invertieren (hoher Wert => hohe Transparenz) * sowie mit "png_set_filler" 32/16 bpp => 24/8 bpp setzen. ***************/ if (alpha) png_set_invert_alpha(png_ptr); else png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); png_write_image(png_ptr, (void*)row); png_write_end(png_ptr, (png_info*)NULL); #ifdef ANDROID_BUILD progStr = (*env)->NewStringUTF(env, MSG[I_FINISHED]); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 2); #else puts(MSG[I_FINISHED]); #endif /* Schreibvorgang beenden, Datei schliessen, Speicher freigeben, fertig. ***/ png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); free(trw); free(image); free(row); #ifdef ANDROID_BUILD progStr = (*env)->NewStringUTF(env, MSG[I_COMPLETED]); (*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0); #else puts(MSG[I_COMPLETED]); #endif #ifdef ANDROID_BUILD (*env)->ReleaseStringUTFChars(env, pCmdStr, cmdstr); (*env)->DeleteGlobalRef(env, cachedMainActObj); cachedMainActObj = NULL; #endif return EXIT_SUCCESS; }
void TextureLoader::loadPNGTexture(std::ifstream& textureFile, unsigned int& width, unsigned int& height, unsigned char*& data) { // Read and validate header png_byte header[8]; textureFile.read((char*) header, 8); if (png_sig_cmp(header, 0, 8)) { return; } // Create PNG structs png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); return; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); return; } // PNG error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return; } // Setup stream read function png_set_read_fn(png_ptr, (png_voidp)& textureFile, readPNGData); // Read PNG info png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_set_strip_16(png_ptr); png_set_expand_gray_1_2_4_to_8(png_ptr); png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } png_read_update_info(png_ptr, info_ptr); int channels = png_get_channels(png_ptr, info_ptr); if(channels != 4) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return; } width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); // Allocate memory for data int rowbytes = png_get_rowbytes(png_ptr, info_ptr); data = new unsigned char[rowbytes * height]; png_bytep *row_pointers = new png_bytep[height]; if (!data || !row_pointers) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return; } // Set up row_pointers to point at the correct offsets of data[] for(unsigned int i = 0; i < height; ++i) { //row_pointers[height - 1 - i] = data + i * rowbytes; // same thing row_pointers[i] = data + (height - 1 - i) * rowbytes; } // Read the data png_read_image(png_ptr, row_pointers); }
int read_png (const char *filename, char **data, unsigned int *width, unsigned int *height) { int i; FILE *file; static const int PNG_SIG_SIZE = 8; unsigned char png_sig[PNG_SIG_SIZE]; int sig_bytes; png_struct *png; png_info *info; png_uint_32 png_width, png_height; int depth, color_type, interlace; unsigned int pixel_size; png_byte **row_pointers; file = fopen (filename, "rb"); if (file == NULL) return 1; sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file); if (png_check_sig (png_sig, sig_bytes) == 0) { fclose (file); return 2; } /* XXX: Perhaps we'll want some other error handlers? */ png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png == NULL) { fclose (file); return 3; } info = png_create_info_struct (png); if (info == NULL) { fclose (file); png_destroy_read_struct (&png, NULL, NULL); return 3; } png_init_io (png, file); png_set_sig_bytes (png, sig_bytes); png_read_info (png, info); png_get_IHDR (png, info, &png_width, &png_height, &depth, &color_type, &interlace, NULL, NULL); *width = png_width; *height = png_height; /* convert palette/gray image to rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (png); /* expand gray bit depth if needed */ if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8) png_set_gray_1_2_4_to_8 (png); /* transform transparency to alpha */ if (png_get_valid(png, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha (png); if (depth == 16) png_set_strip_16 (png); if (depth < 8) png_set_packing (png); /* convert grayscale to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png); if (interlace != PNG_INTERLACE_NONE) png_set_interlace_handling (png); png_set_bgr (png); png_set_filler (png, 0xff, PNG_FILLER_AFTER); png_set_read_user_transform_fn(png, premultiply_data); png_read_update_info (png, info); pixel_size = 4; *data = (char *) malloc (png_width * png_height * pixel_size); if (*data == NULL) { fclose (file); return 3; } row_pointers = (png_byte **) malloc (png_height * sizeof(char *)); for (i=0; i < png_height; i++) row_pointers[i] = (png_byte *) (*data + i * png_width * pixel_size); png_read_image (png, row_pointers); png_read_end (png, info); free (row_pointers); fclose (file); png_destroy_read_struct (&png, &info, NULL); return 0; }
int read_png(const char *filename, int *width, int *height, unsigned char **rgb, unsigned char **alpha) { int ret = 0; png_structp png_ptr; png_infop info_ptr; png_bytepp row_pointers; unsigned char *ptr = NULL; png_uint_32 w, h; int bit_depth, color_type, interlace_type; int i; FILE *infile = fopen(filename, "rb"); if (infile == NULL) { fprintf(stderr, "Can not fopen file: %s\n",filename); return ret; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL); if (!png_ptr) goto file_close; info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); } #if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 4 if (setjmp(png_jmpbuf((png_ptr)))) #else if (setjmp(png_ptr->jmpbuf)) #endif goto png_destroy; png_init_io(png_ptr, infile); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, &interlace_type, (int *) NULL, (int *) NULL); /* Prevent against integer overflow */ if(w >= MAX_DIMENSION || h >= MAX_DIMENSION) { fprintf(stderr, "Unreasonable dimension found in file: %s\n",filename); goto png_destroy; } *width = (int) w; *height = (int) h; if (color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { alpha[0] = malloc(*width * *height); if (alpha[0] == NULL) { fprintf(stderr, "Can't allocate memory for alpha channel in PNG file.\n"); goto png_destroy; } } /* Change a paletted/grayscale image to RGB */ if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_expand(png_ptr); /* Change a grayscale image to RGB */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); /* If the PNG file has 16 bits per channel, strip them down to 8 */ if (bit_depth == 16) png_set_strip_16(png_ptr); /* use 1 byte per pixel */ png_set_packing(png_ptr); row_pointers = malloc(*height * sizeof(png_bytep)); if (row_pointers == NULL) { fprintf(stderr, "Can't allocate memory for PNG file.\n"); goto png_destroy; } for (i = 0; i < *height; i++) { row_pointers[i] = malloc(4 * *width); if (row_pointers == NULL) { fprintf(stderr, "Can't allocate memory for PNG line.\n"); goto rows_free; } } png_read_image(png_ptr, row_pointers); rgb[0] = malloc(3 * *width * *height); if (rgb[0] == NULL) { fprintf(stderr, "Can't allocate memory for PNG file.\n"); goto rows_free; } if (alpha[0] == NULL) { ptr = rgb[0]; for (i = 0; i < *height; i++) { memcpy(ptr, row_pointers[i], 3 * *width); ptr += 3 * *width; } } else { int j; ptr = rgb[0]; for (i = 0; i < *height; i++) { int ipos = 0; for (j = 0; j < *width; j++) { *ptr++ = row_pointers[i][ipos++]; *ptr++ = row_pointers[i][ipos++]; *ptr++ = row_pointers[i][ipos++]; alpha[0][i * *width + j] = row_pointers[i][ipos++]; } } } ret = 1; /* data reading is OK */ rows_free: for (i = 0; i < *height; i++) { if (row_pointers[i] != NULL ) { free(row_pointers[i]); } } free(row_pointers); png_destroy: png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); file_close: fclose(infile); return(ret); }
void RawImage::loadPNG(FILE* file) throw(ImageException) { png_structp pngData = NULL; png_infop pngInfo = NULL; unsigned char** rowPtrs = NULL; try { pngData = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, // error_ptr NULL, // error_fn NULL // warn_fn ); pngInfo = png_create_info_struct(pngData); unsigned char header[8]; if (fread(header, 1, 8, file) < 8) throw ImageException("Missing PNG header data."); if (png_sig_cmp(header, 0, 8) != 0) throw ImageException("Not a PNG file!"); if (setjmp(png_jmpbuf(pngData))) throw ImageException("PNG library error."); png_init_io(pngData, file); png_set_sig_bytes(pngData, 8); png_read_info(pngData, pngInfo); png_uint_32 width, height; int bitDepth, colorType, iMethod, cMethod, fMethod; png_get_IHDR(pngData, pngInfo, &width, &height, &bitDepth, &colorType, &iMethod, &cMethod, &fMethod); int bytesPerChannel = (bitDepth / 8); if (bitDepth % 8 != 0) ++bytesPerChannel; _width = width; _height = height; switch (colorType) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(pngData); _type = GL_RGB; _bytesPerPixel = bytesPerChannel * 3; break; case PNG_COLOR_TYPE_RGBA: _type = GL_RGBA; _bytesPerPixel = bytesPerChannel * 4; break; case PNG_COLOR_TYPE_RGB: _type = GL_RGB; _bytesPerPixel = bytesPerChannel * 3; break; case PNG_COLOR_TYPE_GRAY: if (bitDepth < 8) png_set_gray_1_2_4_to_8(pngData); _type = GL_ALPHA; _bytesPerPixel = bytesPerChannel; break; default: throw ImageException("Unknown PNG type."); } _pixels = new unsigned char[_bytesPerPixel * _width * _height]; rowPtrs = new unsigned char*[_height]; for (size_t i = 0; i < _height; ++i) rowPtrs[i] = &_pixels[_bytesPerPixel * _width * (_height - i - 1)]; png_read_image(pngData, rowPtrs); png_destroy_read_struct(&pngData, &pngInfo, NULL); delete[] rowPtrs; } catch (ImageException& e) { png_destroy_read_struct(&pngData, &pngInfo, NULL); if (rowPtrs != NULL) delete[] rowPtrs; throw e; } }
int readpng2_init(mainprog_info *mainprog_ptr) { png_structp png_ptr; /* note: temporary variables! */ png_infop info_ptr; /* could also replace libpng warning-handler (final NULL), but no need: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, readpng2_error_handler, readpng2_warning_handler); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every function that calls a PNG-reading * libpng function, unless an alternate error handler was installed-- * but compatible error handlers must either use longjmp() themselves * (as in this program) or exit immediately, so here we are: */ if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED /* prepare the reader to ignore all recognized chunks whose data won't be * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT, * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */ { /* These byte strings were copied from png.h. If a future version * of readpng2.c recognizes more chunks, add them to this list. */ static PNG_CONST png_byte chunks_to_process[] = { 98, 75, 71, 68, '\0', /* bKGD */ 103, 65, 77, 65, '\0', /* gAMA */ 115, 82, 71, 66, '\0', /* sRGB */ }; /* Ignore all chunks except for IHDR, PLTE, tRNS, IDAT, and IEND */ png_set_keep_unknown_chunks(png_ptr, -1 /* PNG_HANDLE_CHUNK_NEVER */, NULL, -1); /* But do not ignore chunks in the "chunks_to_process" list */ png_set_keep_unknown_chunks(png_ptr, 0 /* PNG_HANDLE_CHUNK_AS_DEFAULT */, chunks_to_process, sizeof(chunks_to_process)/5); } #endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ /* instead of doing png_init_io() here, now we set up our callback * functions for progressive decoding */ png_set_progressive_read_fn(png_ptr, mainprog_ptr, readpng2_info_callback, readpng2_row_callback, readpng2_end_callback); /* make sure we save our pointers for use in readpng2_decode_data() */ mainprog_ptr->png_ptr = png_ptr; mainprog_ptr->info_ptr = info_ptr; /* and that's all there is to initialization */ return 0; }
static void *read_png_raw(const char *fname, size_t * nxp, size_t * nyp, size_t * ncp, int transform, int dtype) { png_byte png_sig[PNG_SIG_LEN]; png_structp png_ptr; png_infop info_ptr; png_bytepp row_pointers; png_bytep row_ptr; /* volatile : because of setjmp/longjmp */ FILE *volatile fp = NULL; void *data = NULL; unsigned char *data_u8 = NULL; unsigned char *data_u8_ptr = NULL; float *data_f32 = NULL; float *data_f32_ptr = NULL; size_t size; size_t i, j, k; /* parameters check */ if (NULL == fname || NULL == nxp || NULL == nyp || NULL == ncp) return NULL; if (IO_PNG_U8 != dtype && IO_PNG_F32 != dtype) return NULL; /* open the PNG input file */ if (0 == strcmp(fname, "-")) fp = stdin; else if (NULL == (fp = fopen(fname, "rb"))) return NULL; /* read in some of the signature bytes and check this signature */ if ((PNG_SIG_LEN != fread(png_sig, 1, PNG_SIG_LEN, fp)) || 0 != png_sig_cmp(png_sig, (png_size_t) 0, PNG_SIG_LEN)) return read_png_abort(fp, NULL, NULL); /* * create and initialize the png_struct * with the default stderr and error handling */ if (NULL == (png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) return read_png_abort(fp, NULL, NULL); /* allocate/initialize the memory for image information */ if (NULL == (info_ptr = png_create_info_struct(png_ptr))) return read_png_abort(fp, &png_ptr, NULL); /* set error handling */ if (0 != setjmp(png_jmpbuf(png_ptr))) /* if we get here, we had a problem reading the file */ /* free all of the memory associated with the png_ptr and info_ptr */ return read_png_abort(fp, &png_ptr, &info_ptr); /* set up the input control using standard C streams */ png_init_io(png_ptr, fp); /* let libpng know that some bytes have been read */ png_set_sig_bytes(png_ptr, PNG_SIG_LEN); /* * set the read filter transforms, to get 8bit RGB whatever the * original file may contain: * PNG_TRANSFORM_STRIP_16 strip 16-bit samples to 8 bits * PNG_TRANSFORM_PACKING expand 1, 2 and 4-bit * samples to bytes */ transform |= (PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING); /* read in the entire image at once */ png_read_png(png_ptr, info_ptr, transform, NULL); /* get image informations */ *nxp = (size_t) png_get_image_width(png_ptr, info_ptr); *nyp = (size_t) png_get_image_height(png_ptr, info_ptr); *ncp = (size_t) png_get_channels(png_ptr, info_ptr); row_pointers = png_get_rows(png_ptr, info_ptr); /* * allocate the output data RGB array * deinterlace and convert png RGB RGB RGB 8bit to RRR GGG BBB * the image is deinterlaced layer after layer * this generic loop also works for one single channel */ size = *nxp * *nyp * *ncp; switch (dtype) { case IO_PNG_U8: if (NULL == (data_u8 = (unsigned char *) malloc(size * sizeof(unsigned char)))) return read_png_abort(fp, &png_ptr, &info_ptr); data = (void *) data_u8; for (k = 0; k < *ncp; k++) { /* channel loop */ data_u8_ptr = data_u8 + (size_t) (*nxp * *nyp * k); for (j = 0; j < *nyp; j++) { /* row loop */ row_ptr = row_pointers[j] + k; for (i = 0; i < *nxp; i++) { /* pixel loop */ *data_u8_ptr++ = (unsigned char) *row_ptr; row_ptr += *ncp; } } } break; case IO_PNG_F32: if (NULL == (data_f32 = (float *) malloc(size * sizeof(float)))) return read_png_abort(fp, &png_ptr, &info_ptr); data = (void *) data_f32; for (k = 0; k < *ncp; k++) { /* channel loop */ data_f32_ptr = data_f32 + (size_t) (*nxp * *nyp * k); for (j = 0; j < *nyp; j++) { /* row loop */ row_ptr = row_pointers[j] + k; for (i = 0; i < *nxp; i++) { /* pixel loop */ *data_f32_ptr++ = (float) *row_ptr; row_ptr += *ncp; } } } break; } /* clean up and free any memory allocated, close the file */ (void) read_png_abort(fp, &png_ptr, &info_ptr); return data; }
bool Image::loadPng(const std::string& filename) { // check that the file is a png file png_byte buf[8]; FILE* in = std::fopen(filename.c_str(), "rb"); if (!in) return false; for (int i = 0; i < 8; i++) { if (!(buf[i] = fgetc(in))) return false; } if (png_sig_cmp(buf, 0, 8)) return false; png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, 0, 0); return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, 0, 0); return false; } // png_set_read_fn(png_ptr, reinterpret_cast<void*>(&in), my_istream_read_data); png_init_io(png_ptr, in); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); if (bit_depth % 8) { png_destroy_read_struct(&png_ptr, 0, 0); std::ostringstream os; os << "Invalid bit elements " << bit_depth; return false; } int colour_type = png_get_color_type(png_ptr, info_ptr); if (colour_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); colour_type = PNG_COLOR_TYPE_RGB; } if (colour_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_gray_1_2_4_to_8(png_ptr); } if (colour_type != PNG_COLOR_TYPE_RGB && colour_type != PNG_COLOR_TYPE_GRAY && colour_type != PNG_COLOR_TYPE_RGBA) { png_destroy_read_struct(&png_ptr, 0, 0); return false; } delete [] m_data; m_width = png_get_image_width(png_ptr, info_ptr); m_height = png_get_image_height(png_ptr, info_ptr); switch (colour_type) { case PNG_COLOR_TYPE_RGB: m_elements = 3; break; case PNG_COLOR_TYPE_RGBA: m_elements = 4; break; default: m_elements = 1; break; } png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr); m_data = new double[m_width * m_height * m_elements]; for (int y = 0; y < m_height; y++) { for (int x = 0; x < m_width; x++) { for (int i = 0; i < m_elements; i++) { png_byte *row = row_pointers[y]; int index = m_elements * (y * m_width + x) + i; long element = 0; for (int j = bit_depth/8 - 1; j >= 0; j--) { element <<= 8; element += row[(x * m_elements + i) * bit_depth/8 + j]; } m_data[index] = element / static_cast<double>((1 << bit_depth) - 1); } } } png_destroy_read_struct(&png_ptr, &info_ptr, 0); return true; }
int load_png(char * file_name, int * w, int * h, int * depth, char ** data) { #if COMPILE_PNG_CODE FILE *fp; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_type; int rowbytes, channels; unsigned int i; char * buff; char ** row_pointers; fp = fopen(file_name, "rb"); if (!fp){ error_print("Cannot load required png-file (%s). Terminating!",file_name); sys_exit(1); } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (png_voidp)NULL/*user_error_ptr*/, NULL/*user_error_fn*/, NULL/*user_warning_fn*/); if (!png_ptr) { error_print("Error png-ptr png-file (%s). Terminating!",file_name); sys_exit(1); } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); error_print("Error create info struct png-file (%s). Terminating!",file_name); sys_exit(1); } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type); channels = png_get_channels(png_ptr, info_ptr); rowbytes = png_get_rowbytes(png_ptr, info_ptr); buff = (char *) malloc(height*rowbytes); row_pointers = (char **) malloc(height*sizeof(char *)); for(i=0;i<height;i++){ row_pointers[i]=&buff[rowbytes*i]; } png_read_image(png_ptr, (png_bytepp)row_pointers); //fprintf(stderr,"load_png: rgstereo=%d\n",options_rgstereo_on); if( options_rgstereo_on ){ //fprintf(stderr,"load_png: graying out texture\n"); for(i=0;i<height;i++){ int j,k,d; for(j=0;j<rowbytes;j+=channels){ d=0; for(k=0;k<channels;k++) d+=(unsigned char)row_pointers[i][j+k]; d/=channels; for(k=0;k<channels;k++) row_pointers[i][j+k]=d; } } } free(row_pointers); free(info_ptr); free(png_ptr); fclose(fp); *data = buff; *w = width; *h = height; *depth = channels*bit_depth; return 1; #else *data = 0; *w = 0; *h = 0; *depth = 0; return 1; #endif }
/** * loadTexture takes a filename and returns a Texture pointer to the texture place in memory */ Texture *Graphics::loadTexture(const char *filename) { // log it out Log::info("Loading texture \"%s\"...", filename); // header for testing if it is a png png_byte header[8]; // open file as binary FILE *fp = fopen(filename, "rb"); if (!fp) { Log::error("File failed to load!"); return NULL; } // read the header fread(header, 1, 8, fp); // test if png int is_png = !png_sig_cmp(header, 0, 8); if (!is_png) { Log::error("Image is not a PNG!"); fclose(fp); return NULL; } // create png struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { Log::error("png_ptr failed to create read struct!"); fclose(fp); return NULL; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { Log::error("info_ptr failed to create struct!"); png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); fclose(fp); return NULL; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { Log::error("end_info failed to create struct!"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return NULL; } // png error stuff, not sure libpng man suggests this. if (setjmp(png_jmpbuf(png_ptr))) { Log::error("png_jumpbuf overflow!"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return NULL; } // init png reading png_init_io(png_ptr, fp); //let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); //variables to pass to get info int bit_depth, color_type; png_uint_32 twidth, theight; // get info about png png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL); // update width and height based on png info int width = twidth; int height = theight; // update the png info struct. png_read_update_info(png_ptr, info_ptr); // row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // allocate the image_data as a big block, to be given to opengl png_byte *image_data = new png_byte[rowbytes * height]; if (!image_data) { Log::error("image_data failed to create a new png_byte!"); //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return NULL; } // row_pointers is for pointing to image_data for reading the png with libpng png_bytep *row_pointers = new png_bytep[height]; if (!row_pointers) { Log::error("row_pointers failed to create a new png_bytep!"); //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] image_data; fclose(fp); return NULL; } // set the individual row_pointers to point at the correct offsets of image_data for (int i = 0; i < height; ++i) row_pointers[height - 1 - i] = image_data + i * rowbytes; //read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); // now generate the OpenGL texture object GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data); // gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image_data); //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] image_data; delete[] row_pointers; fclose(fp); // create the texture struct Texture *_texture = new Texture; _texture->texture = texture; _texture->width = width; _texture->height = height; // store the texture in the vector this->texturePile.push_back(_texture); // log the texture being loaded Log::info("Loaded texture \"%s\" at %i...", filename, _texture->texture); // return the texture return this->texturePile.at(texture - 1); }
void PNGCodec::decode(std::vector<uint8_t> &in, std::vector<uint8_t> *out, unsigned int *width, unsigned int *height, ColorFormat *format, uint8_t level) { if (level != 0) { // TODO: Error handling. return; } if (png_check_sig(in.data(), SIGNATURE_LENGTH) == false) { // TODO: Error handling. return; } png_structp pngPtr = png_create_read_struct( PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (pngPtr == nullptr) { // TODO: Error handling. return; } png_infop pngInfoPtr = png_create_info_struct(pngPtr); if (pngInfoPtr == nullptr) { // TODO: Error handling. png_destroy_read_struct(&pngPtr, nullptr, nullptr); return; } PNGVectorStream stream; stream.vec = ∈ stream.offset = 0; png_set_read_fn(pngPtr, &stream, PNGReadCallback); png_read_info(pngPtr, pngInfoPtr); int bitDepth = 0; int colorType = -1; png_uint_32 retval = png_get_IHDR(pngPtr, pngInfoPtr, width, height, &bitDepth, &colorType, nullptr, nullptr, nullptr); if (retval != 1) { // TODO: Error handling. png_destroy_read_struct(&pngPtr, &pngInfoPtr, nullptr); return; } switch (colorType) { case PNG_COLOR_TYPE_RGB: *format = ColorFormat::RGB; break; case PNG_COLOR_TYPE_RGBA: *format = ColorFormat::RGBA; break; default: // TODO: Error handling. png_destroy_read_struct(&pngPtr, &pngInfoPtr, nullptr); return; } out->resize((*width) * (*height) * static_cast<unsigned int>(*format)); for (unsigned int i = 0; i < *height; ++i) png_read_row(pngPtr, &(*out)[i * (*width) * static_cast<unsigned int>(*format)], nullptr); png_destroy_read_struct(&pngPtr, &pngInfoPtr, nullptr); }
GLubyte* glmReadPNG(const char* filename, GLboolean alpha, int* width_ret, int* height_ret, int* type_ret) { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE *fp; unsigned char *buffer; int y, bytes_per_row; int channels; int format; png_bytepp row_pointers; if ((fp = fopen(filename, "rb")) == NULL) { pngerror = ERR_OPEN; return NULL; } /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ /*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *)user_error_ptr, user_error_fn, user_warning_fn);*/ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, err_callback, warn_callback); if (png_ptr == NULL) { pngerror = ERR_MEM; fclose(fp); return 0; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { pngerror = ERR_MEM; fclose(fp); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return 0; } /* Set error handling if you are using the setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ buffer = NULL; if (setjmp(setjmp_buffer)) { pngerror = ERR_PNGLIB; /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); /* If we get here, we had a problem reading the file */ if (buffer) free(buffer); return NULL; } /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, fp); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). REQUIRED */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /**** Set up the data transformations you want. Note that these are all **** optional. Only call them if you want/need them. Many of the **** transformations only work on specific types of images, and many **** are mutually exclusive. ****/ /* tell libpng to strip 16 bit/color files down to 8 bits/color */ png_set_strip_16(png_ptr); /* strip alpha bytes from the input data without combining with th * background (not recommended) */ /* png_set_strip_alpha(png_ptr); */ /* extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ /* png_set_packing(png_ptr); */ /* change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ /* png_set_packswap(png_ptr); */ /* expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); /* expand paletted or RGB images with transparency to full alpha channels * so the data will be available as RGBA quartets */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); /* Add filler (or alpha) byte (before/after each RGB triplet) */ /* png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); */ png_read_update_info(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); /* allocate the memory to hold the image using the fields of info_ptr. */ bytes_per_row = png_get_rowbytes(png_ptr, info_ptr); buffer = (unsigned char*) malloc(bytes_per_row*height); format = channels; row_pointers = (png_bytepp) malloc(height*sizeof(png_bytep)); for (y = 0; y < height; y++) { row_pointers[height-y-1] = buffer + y*bytes_per_row; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); free(row_pointers); /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* close the file */ fclose(fp); /* that's it */ if (buffer) { *width_ret = width; *height_ret = height; switch(format) { case 1: *type_ret = GL_LUMINANCE; break; case 2: *type_ret = GL_LUMINANCE_ALPHA; break; case 3: *type_ret = GL_RGB; break; case 4: *type_ret = GL_RGBA; break; } pngerror = ERR_NO_ERROR; } else { pngerror = ERR_MEM; } return buffer; }
int loadPNG(ePtr<gPixmap> &result, const char *filename) { __u8 header[8]; FILE *fp=fopen(filename, "rb"); if (!fp) { // eDebug("couldn't open %s", filename ); return 0; } if (!fread(header, 8, 1, fp)) { eDebug("couldn't read"); fclose(fp); return 0; } if (png_sig_cmp(header, 0, 8)) { fclose(fp); return 0; } png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { eDebug("no pngptr"); fclose(fp); return 0; } png_infop info_ptr=png_create_info_struct(png_ptr); if (!info_ptr) { eDebug("no info ptr"); png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0); fclose(fp); return 0; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { eDebug("no end"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); return 0; } if (setjmp(png_ptr->jmpbuf)) { eDebug("das war wohl nix"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); result = 0; return 0; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_set_invert_alpha(png_ptr); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth; int color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type == PNG_COLOR_TYPE_GRAY || color_type & PNG_COLOR_MASK_PALETTE) { result=new gPixmap(eSize(width, height), bit_depth); gSurface *surface = result->surface; png_bytep *rowptr=new png_bytep[height]; for (unsigned int i=0; i<height; i++) rowptr[i]=((png_byte*)(surface->data))+i*surface->stride; png_read_rows(png_ptr, rowptr, 0, height); delete [] rowptr; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_color *palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); if (num_palette) surface->clut.data=new gRGB[num_palette]; else surface->clut.data=0; surface->clut.colors=num_palette; for (int i=0; i<num_palette; i++) { surface->clut.data[i].a=0; surface->clut.data[i].r=palette[i].red; surface->clut.data[i].g=palette[i].green; surface->clut.data[i].b=palette[i].blue; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_byte *trans; png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0); for (int i=0; i<num_palette; i++) surface->clut.data[i].a=255-trans[i]; } } else { surface->clut.data=0; surface->clut.colors=0; } surface->clut.start=0; png_read_end(png_ptr, end_info); } else { result=0; eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type); } png_destroy_read_struct(&png_ptr, &info_ptr,&end_info); fclose(fp); return 0; }
GLuint png_texture_load(const char * file_name, int * width, int * height) { png_byte header[8]; FILE *fp = fopen(file_name, "rb"); if (fp == 0) { perror(file_name); return 0; } // read the header fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); if (width){ *width = temp_width; } if (height){ *height = temp_height; } //printf("%s: %lux%lu %d\n", file_name, temp_width, temp_height, color_type); if (bit_depth != 8) { fprintf(stderr, "%s: Unsupported bit depth %d. Must be 8.\n", file_name, bit_depth); return 0; } GLint format; switch(color_type) { case PNG_COLOR_TYPE_RGB: format = GL_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: format = GL_RGBA; break; default: fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type); return 0; } // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data = (png_byte *)malloc(rowbytes * temp_height * sizeof(png_byte)+15); if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // row_pointers is for pointing to image_data for reading the png with libpng png_byte ** row_pointers = (png_byte **)malloc(temp_height * sizeof(png_byte *)); if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); fclose(fp); return 0; } // set the individual row_pointers to point at the correct offsets of image_data for (unsigned int i = 0; i < temp_height; i++) { row_pointers[temp_height - 1 - i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); // Generate the OpenGL texture object GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); free(row_pointers); fclose(fp); return texture; }
void* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) { AbstractFile* imageFile; unsigned char header[8]; InfoIBootIM* info; png_uint_32 i; png_bytepp row_pointers; uint8_t* imageBuffer; void* buffer; png->read(png, header, 8); if(png_sig_cmp(header, 0, 8) != 0) { XLOG(0, "error: not a valid png file\n"); return NULL; } png->seek(png, 0); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn); if (!png_ptr) { return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { XLOG(0, "error reading png\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(buffer); return NULL; } png_set_read_fn(png_ptr, png, pngRead); png_read_info(png_ptr, info_ptr); if(info_ptr->bit_depth > 8) { XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", info_ptr->bit_depth); } if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) { XLOG(0, "notice: attempting to add dummy transparency channel\n"); } if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "notice: attempting to expand palette into full rgb\n"); } png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_bgr(png_ptr); png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER); png_set_invert_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); if(info_ptr->width > 320 || info_ptr->height > 480) { XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", info_ptr->width, info_ptr->height); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(info_ptr->bit_depth != 8) { XLOG(0, "error: bit depth per channel must be 8 not %d!\n", info_ptr->bit_depth); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(info_ptr->color_type != PNG_COLOR_TYPE_GRAY_ALPHA && info_ptr->color_type != PNG_COLOR_TYPE_RGB_ALPHA) { XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n"); if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) { XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n"); } if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n"); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info_ptr->height); imageBuffer = malloc(info_ptr->height * info_ptr->rowbytes); for(i = 0; i < info_ptr->height; i++) { row_pointers[i] = imageBuffer + (info_ptr->rowbytes * i); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, end_info); buffer = malloc(1); *fileSize = 0; if(key != NULL) { imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL); } else { imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize)); } info = (InfoIBootIM*) (imageFile->data); info->header.width = (uint16_t) info_ptr->width; info->header.height = (uint16_t) info_ptr->height; if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { info->header.format = IBOOTIM_GREY; } else { info->header.format = IBOOTIM_ARGB; } imageFile->write(imageFile, imageBuffer, info_ptr->height * info_ptr->rowbytes); imageFile->close(imageFile); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png->close(png); free(row_pointers); free(imageBuffer); return buffer; }
int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) { unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data; png_bytep *row_p; double fileGamma; png_uint_32 width, height; int depth, color; png_uint_32 i; if (pinfo == NULL) return 0; fread(header, 1, 8, fp); if (!png_check_sig(header, 8)) return 0; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(png); endinfo = png_create_info_struct(png); // DH: added following lines if (setjmp(png->jmpbuf)) { png_destroy_read_struct(&png, &info, &endinfo); return 0; } // ~DH png_init_io(png, fp); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); if (color == PNG_COLOR_TYPE_PALETTE) { int cols; png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols); } else { pinfo->Palette = NULL; } if (color&PNG_COLOR_MASK_ALPHA) { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA) pinfo->Components = 2; else pinfo->Components = 4; pinfo->Alpha = 8; } else { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY) pinfo->Components = 1; else pinfo->Components = 3; pinfo->Alpha = 0; } pinfo->Data = data; png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); return 1; }
Canvas * read_png(char * file_name) { unsigned char header[8]; // 8 is the maximum size that can be checked // open file and test for it being a png FILE *fp = fopen(file_name, "rb"); if (!fp) abort_("[read_png_file] File %s could not be opened for reading", file_name); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); // initialize stuff png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) abort_("[read_png_file] png_create_read_struct failed"); png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) abort_("[read_png_file] png_create_info_struct failed"); if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during init_io"); png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); int width = png_get_image_width(png_ptr, info_ptr); int height = png_get_image_height(png_ptr, info_ptr); png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); // read file if (setjmp(png_jmpbuf(png_ptr))) abort_("[read_png_file] Error during read_image"); png_bytep * row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); int y; for (y = 0; y < height; y++) row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr)); png_read_image(png_ptr, row_pointers); Canvas * canvas = new_canvas(width, height); int x; for (y=0; y < canvas->h; y++) { png_byte * row = row_pointers[y]; for(x = 0; x < canvas->w; x++) { png_byte * ptr = &(row[x * 3]); set_pixel(x, y, rgb(ptr[0], ptr[1], ptr[2]), canvas); } } // cleanup heap allocation for (y=0; y < canvas->h; y++) free(row_pointers[y]); free(row_pointers); fclose(fp); return canvas; }
BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, volatile BOOL raw, BOOL alpha) { png_struct *png_ptr = NULL; png_info *info_ptr = NULL; png_byte buf[8]; png_byte *png_pixels = NULL; png_byte **row_pointers = NULL; png_byte *pix_ptr = NULL; png_uint_32 row_bytes; png_uint_32 width; png_uint_32 height; int bit_depth; int channels; int color_type; int alpha_present; int row, col; int ret; int i; long dep_16; /* read and check signature in PNG file */ ret = fread (buf, 1, 8, png_file); if (ret != 8) return FALSE; ret = png_sig_cmp (buf, 0, 8); if (ret) return FALSE; /* create png and info structures */ png_ptr = png_create_read_struct (png_get_libpng_ver(NULL), NULL, NULL, NULL); if (!png_ptr) return FALSE; /* out of memory */ info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) { png_destroy_read_struct (&png_ptr, NULL, NULL); return FALSE; /* out of memory */ } if (setjmp (png_jmpbuf(png_ptr))) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return FALSE; } /* set up the input control for C streams */ png_init_io (png_ptr, png_file); png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */ /* read the file information */ png_read_info (png_ptr, info_ptr); /* get size and bit-depth of the PNG-image */ png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); /* set-up the transformations */ /* transform paletted images into full-color rgb */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand (png_ptr); /* expand images to bit-depth 8 (only applicable for grayscale images) */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand (png_ptr); /* transform transparency maps into full alpha-channel */ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand (png_ptr); #ifdef NJET /* downgrade 16-bit images to 8-bit */ if (bit_depth == 16) png_set_strip_16 (png_ptr); /* transform grayscale images into full-color */ if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb (png_ptr); /* only if file has a file gamma, we do a correction */ if (png_get_gAMA (png_ptr, info_ptr, &file_gamma)) png_set_gamma (png_ptr, (double) 2.2, file_gamma); #endif /* all transformations have been registered; now update info_ptr data, * get rowbytes and channels, and allocate image memory */ png_read_update_info (png_ptr, info_ptr); /* get the new color-type and bit-depth (after expansion/stripping) */ png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); /* check for 16-bit files */ if (bit_depth == 16) { raw = FALSE; #ifdef __TURBOC__ pnm_file->flags &= ~((unsigned) _F_BIN); #endif } /* calculate new number of channels and store alpha-presence */ if (color_type == PNG_COLOR_TYPE_GRAY) channels = 1; else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) channels = 2; else if (color_type == PNG_COLOR_TYPE_RGB) channels = 3; else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) channels = 4; else channels = 0; /* should never happen */ alpha_present = (channels - 1) % 2; /* check if alpha is expected to be present in file */ if (alpha && !alpha_present) { fprintf (stderr, "PNG2PNM\n"); fprintf (stderr, "Error: PNG-file doesn't contain alpha channel\n"); exit (1); } /* row_bytes is the width x number of channels x (bit-depth / 8) */ row_bytes = png_get_rowbytes (png_ptr, info_ptr); if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); return FALSE; } if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) { png_destroy_read_struct (&png_ptr, &info_ptr, NULL); free (png_pixels); png_pixels = NULL; return FALSE; } /* set the individual row_pointers to point at the correct offsets */ for (i = 0; i < ((int) height); i++) row_pointers[i] = png_pixels + i * row_bytes; /* now we can go ahead and just read the whole image */ png_read_image (png_ptr, row_pointers); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end (png_ptr, info_ptr); /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL); /* write header of PNM file */ if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2"); fprintf (pnm_file, "%d %d\n", (int) width, (int) height); fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); } else if ((color_type == PNG_COLOR_TYPE_RGB) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) { fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3"); fprintf (pnm_file, "%d %d\n", (int) width, (int) height); fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); } /* write header of PGM file with alpha channel */ if ((alpha) && ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA))) { fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2"); fprintf (alpha_file, "%d %d\n", (int) width, (int) height); fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); } /* write data to PNM file */ pix_ptr = png_pixels; for (row = 0; row < (int) height; row++) { for (col = 0; col < (int) width; col++) { for (i = 0; i < (channels - alpha_present); i++) { if (raw) fputc ((int) *pix_ptr++ , pnm_file); else if (bit_depth == 16){ dep_16 = (long) *pix_ptr++; fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++)); } else fprintf (pnm_file, "%ld ", (long) *pix_ptr++); } if (alpha_present) { if (!alpha) { pix_ptr++; /* alpha */ if (bit_depth == 16) pix_ptr++; } else /* output alpha-channel as pgm file */ { if (raw) fputc ((int) *pix_ptr++ , alpha_file); else if (bit_depth == 16){ dep_16 = (long) *pix_ptr++; fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++); } else fprintf (alpha_file, "%ld ", (long) *pix_ptr++); } } /* if alpha_present */ if (!raw) if (col % 4 == 3) fprintf (pnm_file, "\n"); } /* end for col */ if (!raw) if (col % 4 != 0) fprintf (pnm_file, "\n"); } /* end for row */ if (row_pointers != (unsigned char**) NULL) free (row_pointers); if (png_pixels != (unsigned char*) NULL) free (png_pixels); return TRUE; } /* end of source */
FloatPixMapRef FPMCreateWithPNGCustom(png_voidp ioPtr, png_rw_ptr readDataFn, FPMGammaFactor desiredGamma, FPMPNGErrorHandler errorHandler) { png_structp png = NULL; png_infop pngInfo = NULL; png_infop pngEndInfo = NULL; FloatPixMapRef result = NULL; png_uint_32 i, width, height, rowBytes; int depth, colorType; png_bytepp rows = NULL; void *data = NULL; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, errorHandler, PNGError, PNGWarning); if (png == NULL) goto FAIL; pngInfo = png_create_info_struct(png); if (pngInfo == NULL) goto FAIL; pngEndInfo = png_create_info_struct(png); if (pngEndInfo == NULL) goto FAIL; if (setjmp(png_jmpbuf(png))) { // libpng will jump here on error. goto FAIL; } png_set_read_fn(png, ioPtr, readDataFn); png_read_info(png, pngInfo); if (!png_get_IHDR(png, pngInfo, &width, &height, &depth, &colorType, NULL, NULL, NULL)) goto FAIL; #if __LITTLE_ENDIAN__ if (depth == 16) png_set_swap(png); #endif if (depth <= 8 && !(colorType & PNG_COLOR_MASK_ALPHA)) { png_set_filler(png, 0xFF, PNG_FILLER_AFTER); } png_set_gray_to_rgb(png); if (depth < 8) { png_set_packing(png); png_set_expand(png); } png_read_update_info(png, pngInfo); rowBytes = png_get_rowbytes(png, pngInfo); rows = malloc(sizeof *rows * height); data = malloc(rowBytes * height); if (rows == NULL || data == NULL) goto FAIL; // Set up row pointers. for (i = 0; i < height; i++) { rows[i] = (png_bytep)data + i * rowBytes; } png_read_image(png, rows); png_read_end(png, pngEndInfo); free(rows); result = ConvertPNGData(data, width, height, rowBytes, pngInfo->bit_depth, pngInfo->color_type); if (result != NULL) { double invGamma = 1.0/kFPMGammaSRGB; png_get_gAMA(png, pngInfo, &invGamma); FPMApplyGamma(result, 1.0/invGamma, desiredGamma, pngInfo->bit_depth == 16 ? 65536 : 256); } png_destroy_read_struct(&png, &pngInfo, &pngEndInfo); free(data); return result; FAIL: FPMRelease(&result); if (png != NULL) png_destroy_read_struct(&png, &pngInfo, &pngEndInfo); free(rows); free(data); return NULL; }