/** The constructor loads the named PNG image from the given png filename. <P>The destructor free all memory and server resources that are used by the image. */ void LoadPNG(const char *png) // I - File to read { int i; // Looping var FILE *fp; // File pointer int channels; // Number of color channels png_structp pp; // PNG read pointer png_infop info; // PNG info pointers png_bytep *rows; // PNG row pointers // Open the PNG file... if ((fp = fopen(png, "rb")) == NULL) return; // Setup the PNG data structures... pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info = png_create_info_struct(pp); if (setjmp(pp->jmpbuf)) { int debug = 1; return; } // Initialize the PNG read "engine"... png_init_io(pp, fp); // Get the image dimensions and convert to grayscale or RGB... png_read_info(pp, info); if (info->color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(pp); if (info->color_type & PNG_COLOR_MASK_COLOR) channels = 3; else channels = 1; if ((info->color_type & PNG_COLOR_MASK_ALPHA) || info->num_trans) channels ++; int w = (int)(info->width); int h = (int)(info->height); int d = channels; pictureWidth = w; pictureHeight = h; if (info->bit_depth < 8) { png_set_packing(pp); png_set_expand(pp); } else if (info->bit_depth == 16) png_set_strip_16(pp); # if defined(HAVE_PNG_GET_VALID) && defined(HAVE_PNG_SET_TRNS_TO_ALPHA) // Handle transparency... if (png_get_valid(pp, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(pp); # endif // HAVE_PNG_GET_VALID && HAVE_PNG_SET_TRNS_TO_ALPHA unsigned char *array = (unsigned char *)pictureS; // Allocate pointers... rows = new png_bytep[h]; for (i = 0; i < h; i ++) rows[i] = (png_bytep)(array + i * w * d); // we flip it // Read the image, handling interlacing as needed... for (i = png_set_interlace_handling(pp); i > 0; i --) png_read_rows(pp, rows, NULL, h); #ifdef WIN32 // Some Windows graphics drivers don't honor transparency when RGB == white if (channels == 4) { // Convert RGB to 0 when alpha == 0... unsigned char *ptr = (unsigned char *)array; for (i = w * h; i > 0; i --, ptr += 4) if (!ptr[3]) ptr[0] = ptr[1] = ptr[2] = 0; } #endif // WIN32 if (channels == 3) { unsigned char *array2 = new unsigned char[pictureWidth * pictureHeight * 4]; for (int i = w * h - 1; i >= 0; --i) { array2[i*4+0] = array[i*3+0]; array2[i*4+1] = array[i*3+1]; array2[i*4+2] = array[i*3+2]; array2[i*4+3] = 255; } memcpy(array, array2, w * h * 4); delete[] array2; } // Free memory and return... delete[] rows; png_read_end(pp, info); png_destroy_read_struct(&pp, &info, NULL); fclose(fp); }
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 Read ( byte **data, int *width, int *height ) { // Setup the pointers *data = NULL; *width = 0; *height = 0; // Make sure we're actually reading PNG data. const int SIGNATURE_LEN = 8; byte ident[SIGNATURE_LEN]; memcpy (ident, buf, SIGNATURE_LEN); if ( !png_check_sig (ident, SIGNATURE_LEN) ) { ri->Printf (PRINT_ERROR, "PNG signature not found in given image."); return 0; } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, png_print_error, png_print_warning); if ( png_ptr == NULL ) { ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image."); return 0; } info_ptr = png_create_info_struct (png_ptr); if ( setjmp (png_jmpbuf (png_ptr)) ) { return 0; } // We've read the signature offset += SIGNATURE_LEN; // Setup reading information, and read header png_set_read_fn (png_ptr, (png_voidp)this, &user_read_data); #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED // This generic "ignore all, except required chunks" requires 1.6.0 or newer" png_set_keep_unknown_chunks (png_ptr, PNG_HANDLE_CHUNK_NEVER, NULL, -1); #endif png_set_sig_bytes (png_ptr, SIGNATURE_LEN); png_read_info (png_ptr, info_ptr); png_uint_32 width_; png_uint_32 height_; int depth; int colortype; png_get_IHDR (png_ptr, info_ptr, &width_, &height_, &depth, &colortype, NULL, NULL, NULL); // While modern OpenGL can handle non-PoT textures, it's faster to handle only PoT // so that the graphics driver doesn't have to fiddle about with the texture when uploading. if ( !IsPowerOfTwo (width_) || !IsPowerOfTwo (height_) ) { ri->Printf (PRINT_ERROR, "Width or height is not a power-of-two.\n"); return 0; } // This function is equivalent to using what used to be LoadPNG32. LoadPNG8 also existed, // but this only seemed to be used by the RMG system which does not work in JKA. If this // does need to be re-implemented, then colortype should be PNG_COLOR_TYPE_PALETTE or // PNG_COLOR_TYPE_GRAY. if ( colortype != PNG_COLOR_TYPE_RGB && colortype != PNG_COLOR_TYPE_RGBA ) { ri->Printf (PRINT_ERROR, "Image is not 24-bit or 32-bit."); return 0; } // Read the png data if ( colortype == PNG_COLOR_TYPE_RGB ) { // Expand RGB -> RGBA png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER); } png_read_update_info (png_ptr, info_ptr); // We always assume there are 4 channels. RGB channels are expanded to RGBA when read. byte *tempData = (byte *)ri->Z_Malloc (width_ * height_ * 4, TAG_TEMP_PNG, qfalse, 4); if ( !tempData ) { ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image."); return 0; } // Dynamic array of row pointers, with 'height' elements, initialized to NULL. byte **row_pointers = (byte **)ri->Hunk_AllocateTempMemory (sizeof (byte *) * height_); if ( !row_pointers ) { ri->Printf (PRINT_ERROR, "Could not allocate enough memory to load the image."); ri->Z_Free (tempData); return 0; } // Re-set the jmp so that these new memory allocations can be reclaimed if ( setjmp (png_jmpbuf (png_ptr)) ) { ri->Hunk_FreeTempMemory (row_pointers); ri->Z_Free (tempData); return 0; } for ( unsigned int i = 0, j = 0; i < height_; i++, j += 4 ) { row_pointers[i] = tempData + j * width_; } png_read_image (png_ptr, row_pointers); // Finish reading png_read_end (png_ptr, NULL); ri->Hunk_FreeTempMemory (row_pointers); // Finally assign all the parameters *data = tempData; *width = width_; *height = height_; return 1; }
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src) { SDL_Surface *volatile surface; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; Uint32 Rmask; Uint32 Gmask; Uint32 Bmask; Uint32 Amask; SDL_Palette *palette; png_bytep *volatile row_pointers; int row, i; volatile int ckey = -1; png_color_16 *transv; /* Initialize the data we will clean up when we're done */ png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL; /* Check to make sure we have something to do */ if ( ! src ) { goto done; } /* Create the PNG loading context structure */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (png_ptr == NULL){ IMG_SetError("Couldn't allocate memory for PNG file"); goto done; } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { IMG_SetError("Couldn't create image information for PNG file"); goto done; } /* Set error handling if you are using setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in png_create_read_struct() earlier. */ if ( setjmp(png_ptr->jmpbuf) ) { IMG_SetError("Error reading the PNG file."); goto done; } /* Set up the input control */ png_set_read_fn(png_ptr, src, png_read_data); /* Read PNG header info */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* tell libpng to strip 16 bit/color files down to 8 bits/color */ png_set_strip_16(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); /* scale greyscale values to the range 0..255 */ if(color_type == PNG_COLOR_TYPE_GRAY) png_set_expand(png_ptr); /* For images with a single "transparent colour", set colour key; if more than one index has transparency, or if partially transparent entries exist, use full alpha channel */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { int num_trans; Uint8 *trans; png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &transv); if(color_type == PNG_COLOR_TYPE_PALETTE) { /* Check if all tRNS entries are opaque except one */ int i, t = -1; for(i = 0; i < num_trans; i++) if(trans[i] == 0) { if(t >= 0) break; t = i; } else if(trans[i] != 255) break; if(i == num_trans) { /* exactly one transparent index */ ckey = t; } else { /* more than one transparent index, or translucency */ png_set_expand(png_ptr); } } else ckey = 0; /* actual value will be set later */ } if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb(png_ptr); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* Allocate the SDL surface to hold the image */ Rmask = Gmask = Bmask = Amask = 0 ; if ( color_type != PNG_COLOR_TYPE_PALETTE ) { if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { Rmask = 0x000000FF; Gmask = 0x0000FF00; Bmask = 0x00FF0000; Amask = (info_ptr->channels == 4) ? 0xFF000000 : 0; } else { int s = (info_ptr->channels == 4) ? 0 : 8; Rmask = 0xFF000000 >> s; Gmask = 0x00FF0000 >> s; Bmask = 0x0000FF00 >> s; Amask = 0x000000FF >> s; } } surface = SDL_AllocSurface(SDL_SWSURFACE, width, height, bit_depth*info_ptr->channels, Rmask,Gmask,Bmask,Amask); if ( surface == NULL ) { IMG_SetError("Out of memory"); goto done; } if(ckey != -1) { if(color_type != PNG_COLOR_TYPE_PALETTE) /* FIXME: Should these be truncated or shifted down? */ ckey = SDL_MapRGB(surface->format, (Uint8)transv->red, (Uint8)transv->green, (Uint8)transv->blue); SDL_SetColorKey(surface, SDL_SRCCOLORKEY, ckey); } /* Create the array of pointers to image data */ row_pointers = (png_bytep*) malloc(sizeof(png_bytep)*height); if ( (row_pointers == NULL) ) { IMG_SetError("Out of memory"); SDL_FreeSurface(surface); surface = NULL; goto done; } for (row = 0; row < (int)height; row++) { row_pointers[row] = (png_bytep) (Uint8 *)surface->pixels + row*surface->pitch; } /* Read the entire image in one go */ png_read_image(png_ptr, row_pointers); /* read rest of file, get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* Load the palette, if any */ palette = surface->format->palette; if ( palette ) { if(color_type == PNG_COLOR_TYPE_GRAY) { palette->ncolors = 256; for(i = 0; i < 256; i++) { palette->colors[i].r = i; palette->colors[i].g = i; palette->colors[i].b = i; } } else if (info_ptr->num_palette > 0 ) { palette->ncolors = info_ptr->num_palette; for( i=0; i<info_ptr->num_palette; ++i ) { palette->colors[i].b = info_ptr->palette[i].blue; palette->colors[i].g = info_ptr->palette[i].green; palette->colors[i].r = info_ptr->palette[i].red; } } } done: /* Clean up and return */ png_destroy_read_struct(&png_ptr, info_ptr ? &info_ptr : (png_infopp)0, (png_infopp)0); if ( row_pointers ) { free(row_pointers); } return(surface); }
static gint gegl_buffer_import_png (GeglBuffer *gegl_buffer, GInputStream *stream, gint dest_x, gint dest_y, gint *ret_width, gint *ret_height, const Babl *format, // can be NULL GError **err) { gint width; gint bit_depth; gint bpp; gint number_of_passes=1; png_uint_32 w; png_uint_32 h; png_structp load_png_ptr; png_infop load_info_ptr; guchar *pixels; /*png_bytep *rows;*/ unsigned int i; png_bytep *row_p = NULL; g_return_val_if_fail(stream, -1); if (!check_valid_png_header(stream, err)) { return -1; } load_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, error_fn, NULL); if (!load_png_ptr) { return -1; } load_info_ptr = png_create_info_struct (load_png_ptr); if (!load_info_ptr) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return -1; } if (setjmp (png_jmpbuf (load_png_ptr))) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); g_free (row_p); return -1; } png_set_read_fn(load_png_ptr, stream, read_fn); png_set_sig_bytes (load_png_ptr, 8); // we already read header png_read_info (load_png_ptr, load_info_ptr); { int color_type; int interlace_type; png_get_IHDR (load_png_ptr, load_info_ptr, &w, &h, &bit_depth, &color_type, &interlace_type, NULL, NULL); width = w; if (ret_width) *ret_width = w; if (ret_height) *ret_height = h; if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_expand (load_png_ptr); bit_depth = 8; } if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha (load_png_ptr); color_type |= PNG_COLOR_MASK_ALPHA; } switch (color_type) { case PNG_COLOR_TYPE_GRAY: bpp = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: bpp = 2; break; case PNG_COLOR_TYPE_RGB: bpp = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: bpp = 4; break; case (PNG_COLOR_TYPE_PALETTE | PNG_COLOR_MASK_ALPHA): bpp = 4; break; case PNG_COLOR_TYPE_PALETTE: bpp = 3; break; default: g_warning ("color type mismatch"); png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return -1; } if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (load_png_ptr); if (bit_depth == 16) bpp = bpp << 1; if (!format) format = get_babl_format(bit_depth, color_type); #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth == 16) png_set_swap (load_png_ptr); #endif if (interlace_type == PNG_INTERLACE_ADAM7) number_of_passes = png_set_interlace_handling (load_png_ptr); if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_gAMA)) { gdouble gamma; png_get_gAMA (load_png_ptr, load_info_ptr, &gamma); png_set_gamma (load_png_ptr, 2.2, gamma); } else { png_set_gamma (load_png_ptr, 2.2, 0.45455); } png_read_update_info (load_png_ptr, load_info_ptr); } pixels = g_malloc0 (width*bpp); { gint pass; GeglRectangle rect; for (pass=0; pass<number_of_passes; pass++) { for(i=0; i<h; i++) { gegl_rectangle_set (&rect, 0, i, width, 1); if (pass != 0) gegl_buffer_get (gegl_buffer, &rect, 1.0, format, pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); png_read_rows (load_png_ptr, &pixels, NULL, 1); gegl_buffer_set (gegl_buffer, &rect, 0, format, pixels, GEGL_AUTO_ROWSTRIDE); } } } png_read_end (load_png_ptr, NULL); png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); g_free (pixels); return 0; }
bool initSludge (char * filename) { int a = 0; mouseCursorAnim = makeNullAnim (); FILE * fp = openAndVerify (filename, 'G', 'E', ERROR_BAD_HEADER, gameVersion); if (! fp) return false; if (fgetc (fp)) { numBIFNames = get2bytes (fp); allBIFNames = new char * [numBIFNames]; if (! checkNew (allBIFNames)) return false; for (int fn = 0; fn < numBIFNames; fn ++) { allBIFNames[fn] = readString (fp); } numUserFunc = get2bytes (fp); allUserFunc = new char * [numUserFunc]; if (! checkNew (allUserFunc)) return false; for (int fn = 0; fn < numUserFunc; fn ++) { allUserFunc[fn] = readString (fp); } if (gameVersion >= VERSION(1,3)) { numResourceNames = get2bytes (fp); allResourceNames = new char * [numResourceNames]; if (! checkNew (allResourceNames)) return false; for (int fn = 0; fn < numResourceNames; fn ++) { allResourceNames[fn] = readString (fp); } } } winWidth = get2bytes (fp); winHeight = get2bytes (fp); specialSettings = fgetc (fp); desiredfps = 1000/fgetc (fp); delete[] readString (fp); // Unused - was used for registration purposes. size_t bytes_read = fread (& fileTime, sizeof (FILETIME), 1, fp); if (bytes_read != sizeof (FILETIME) && ferror (fp)) { debugOut("Reading error in initSludge.\n"); } char * dataFol = (gameVersion >= VERSION(1,3)) ? readString(fp) : joinStrings ("", ""); gameSettings.numLanguages = (gameVersion >= VERSION(1,3)) ? (fgetc (fp)) : 0; makeLanguageTable (fp); if (gameVersion >= VERSION(1,6)) { fgetc(fp); // aaLoad fgetc (fp); getFloat (fp); getFloat (fp); } char * checker = readString (fp); if (strcmp (checker, "okSoFar")) return fatal (ERROR_BAD_HEADER, filename); delete checker; checker = NULL; unsigned char customIconLogo = fgetc (fp); if (customIconLogo & 1) { // There is an icon - read it! int n; long file_pointer = ftell (fp); png_structp png_ptr; png_infop info_ptr, end_info; int fileIsPNG = true; // Is this a PNG file? char tmp[10]; bytes_read = fread(tmp, 1, 8, fp); if (bytes_read != 8 && ferror (fp)) { debugOut("Reading error in initSludge.\n"); } if (png_sig_cmp((png_byte *) tmp, 0, 8)) { // No, it's old-school HSI fileIsPNG = false; fseek(fp, file_pointer, SEEK_SET); iconW = get2bytes (fp); iconH = get2bytes (fp); } else { // Read the PNG header png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return false; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); return false; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return false; } png_init_io(png_ptr, fp); // Tell libpng which file to read png_set_sig_bytes(png_ptr, 8); // 8 bytes already read png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); iconW = width; iconH = height; if (bit_depth < 8) png_set_packing(png_ptr); png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); } gameIcon = new unsigned char [iconW*iconH*4]; if (! gameIcon) return fatal ("Can't reserve memory for game icon."); int32_t transCol = 63519; Uint8 *p = (Uint8 *) gameIcon; if (fileIsPNG) { unsigned char * row_pointers[iconH]; for (int i = 0; i<iconH; i++) row_pointers[i] = p + 4*i*iconW; png_read_image(png_ptr, (png_byte **) row_pointers); png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); } else { for (int t2 = 0; t2 < iconH; t2 ++) { int t1 = 0; while (t1 < iconW) { unsigned short c = (unsigned short) get2bytes (fp); if (c & 32) { n = fgetc (fp) + 1; c -= 32; } else { n = 1; } while (n --) { *p++ = (Uint8) redValue(c); *p++ = (Uint8) greenValue(c); *p++ = (Uint8) blueValue(c); *p++ = (Uint8) (c == transCol) ? 0 : 255; t1++; } } } } } if (customIconLogo & 2) { // There is an logo - read it! int n; long file_pointer = ftell (fp); png_structp png_ptr; png_infop info_ptr, end_info; int fileIsPNG = true; // Is this a PNG file? char tmp[10]; bytes_read = fread(tmp, 1, 8, fp); if (bytes_read != 8 && ferror (fp)) { debugOut("Reading error in initSludge.\n"); } if (png_sig_cmp((png_byte *) tmp, 0, 8)) { // No, it's old-school HSI fileIsPNG = false; fseek(fp, file_pointer, SEEK_SET); logoW = get2bytes (fp); logoH = get2bytes (fp); } else { // Read the PNG header png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { return false; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL); return false; } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return false; } png_init_io(png_ptr, fp); // Tell libpng which file to read png_set_sig_bytes(png_ptr, 8); // 8 bytes already read png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth, color_type, interlace_type, compression_type, filter_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); logoW = width; logoH = height; if (bit_depth < 8) png_set_packing(png_ptr); png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); #ifdef WIN32 // Windows wants a BGR bitmap if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); #endif png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_method); } if ((logoW != 310) || (logoH != 88)) return fatal ("Game logo have wrong dimensions. (Should be 310x88)"); gameLogo = new unsigned char [logoW*logoH*4]; if (! gameLogo) return fatal ("Can't reserve memory for game logo."); // int32_t transCol = 63519; Uint8 *p = (Uint8 *) gameLogo; if (fileIsPNG) { unsigned char * row_pointers[logoH]; for (int i = 0; i<logoH; i++) row_pointers[i] = p + 4*i*logoW; png_read_image(png_ptr, (png_byte **) row_pointers); png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); } else { for (int t2 = 0; t2 < logoH; t2 ++) { int t1 = 0; while (t1 < logoW) { unsigned short c = (unsigned short) get2bytes (fp); if (c & 32) { n = fgetc (fp) + 1; c -= 32; } else { n = 1; } while (n --) { #ifdef WIN32 // Windows wants a BGR bitmap *p++ = (Uint8) blueValue(c); *p++ = (Uint8) greenValue(c); *p++ = (Uint8) redValue(c); #else *p++ = (Uint8) redValue(c); *p++ = (Uint8) greenValue(c); *p++ = (Uint8) blueValue(c); #endif *p++ = (Uint8) /*(c == transCol) ? 0 :*/ 255; t1++; } } } } } numGlobals = get2bytes (fp); globalVars = new variable[numGlobals]; if (! checkNew (globalVars)) return false; for (a = 0; a < numGlobals; a ++) initVarNew (globalVars[a]); // Get the original (untranslated) name of the game and convert it to Unicode. // We use this to find saved preferences and saved games. setFileIndices (fp, gameSettings.numLanguages, 0); char * gameNameOrig = getNumberedString(1); char * gameName = encodeFilename (gameNameOrig); delete gameNameOrig; changeToUserDir (); #ifdef _WIN32 mkdir (gameName); #else mkdir (gameName, 0000777); #endif if (chdir (gameName)) return fatal ("This game's preference folder is inaccessible!\nI can't access the following directory (maybe there's a file with the same name, or maybe it's read-protected):", gameName); delete [] gameName; // Get user settings readIniFile (filename); // There's no startup window on Linux and respecting this // option from the ini file would disable commandline options. #if defined __unix__ && !(defined __APPLE__) if (! showSetupWindow()) return 0; saveIniFile (filename); #else if (! gameSettings.noStartWindow) { if (! showSetupWindow()) return 0; saveIniFile (filename); } #endif // Now set file indices properly to the chosen language. languageNum = getLanguageForFileB (); if (languageNum < 0) return fatal ("Can't find the translation data specified!"); setFileIndices (NULL, gameSettings.numLanguages, languageNum); if (dataFol[0]) { char *dataFolder = encodeFilename(dataFol); #ifdef _WIN32 mkdir (dataFolder); #else mkdir (dataFolder, 0000777); #endif if (chdir (dataFolder)) return fatal ("This game's data folder is inaccessible!\nI can't access the following directory (maybe there's a file with the same name, or maybe it's read-protected):", dataFolder); delete dataFolder; } positionStatus (10, winHeight - 15); return true; }
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; printf("62"); if ((fp = fopen(filename, "rb")) == NULL) { printf("64"); 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; }
bool SkPNGImageDecoderMy::onDecode(SkStream* sk_stream, SkBitmap* decodedBitmap, Mode mode) { png_structp png_ptr; png_infop info_ptr; if (onDecodeInit(sk_stream, &png_ptr, &info_ptr) == false) { return false; } if (setjmp(png_jmpbuf(png_ptr))) { return false; } PNGAutoClean autoClean(png_ptr, info_ptr); png_uint_32 origWidth, origHeight; int bit_depth, color_type, interlace_type; png_get_IHDR(png_ptr, info_ptr, &origWidth, &origHeight, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); SkBitmap::Config config; bool hasAlpha = false; bool doDither = this->getDitherImage(); SkPMColor theTranspColor = 0; // 0 tells us not to try to match if (getBitmapConfig(png_ptr, info_ptr, &config, &hasAlpha, &doDither, &theTranspColor) == false) { return false; } const int sampleSize = this->getSampleSize(); SkScaledBitmapSampler sampler(origWidth, origHeight, sampleSize); decodedBitmap->setConfig(config, sampler.scaledWidth(), sampler.scaledHeight(), 0); if (SkImageDecoder::kDecodeBounds_Mode == mode) { return true; } // from here down we are concerned with colortables and pixels // we track if we actually see a non-opaque pixels, since sometimes a PNG sets its colortype // to |= PNG_COLOR_MASK_ALPHA, but all of its pixels are in fact opaque. We care, since we // draw lots faster if we can flag the bitmap has being opaque bool reallyHasAlpha = false; SkColorTable* colorTable = NULL; if (color_type == PNG_COLOR_TYPE_PALETTE) { decodePalette(png_ptr, info_ptr, &hasAlpha, &reallyHasAlpha, &colorTable); } SkAutoUnref aur(colorTable); if (!this->allocPixelRef(decodedBitmap, SkBitmap::kIndex8_Config == config ? colorTable : NULL)) { return false; } SkAutoLockPixels alp(*decodedBitmap); /* Add filler (or alpha) byte (before/after each RGB triplet) */ if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY) { png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); } /* Turn on interlace handling. REQUIRED if you are not using * png_read_image(). To see how to handle interlacing passes, * see the png_read_row() method below: */ const int number_passes = interlace_type != PNG_INTERLACE_NONE ? png_set_interlace_handling(png_ptr) : 1; /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (ie you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); if (SkBitmap::kIndex8_Config == config && 1 == sampleSize) { for (int i = 0; i < number_passes; i++) { for (png_uint_32 y = 0; y < origHeight; y++) { uint8_t* bmRow = decodedBitmap->getAddr8(0, y); png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); } } } else { SkScaledBitmapSampler::SrcConfig sc; int srcBytesPerPixel = 4; if (colorTable != NULL) { sc = SkScaledBitmapSampler::kIndex; srcBytesPerPixel = 1; } else if (hasAlpha) { sc = SkScaledBitmapSampler::kRGBA; } else { sc = SkScaledBitmapSampler::kRGBX; } /* We have to pass the colortable explicitly, since we may have one even if our decodedBitmap doesn't, due to the request that we upscale png's palette to a direct model */ SkAutoLockColors ctLock(colorTable); if (!sampler.begin(decodedBitmap, sc, doDither, ctLock.colors())) { return false; } const int height = decodedBitmap->height(); if (number_passes > 1) { SkAutoMalloc storage(origWidth * origHeight * srcBytesPerPixel); uint8_t* base = (uint8_t*)storage.get(); size_t rb = origWidth * srcBytesPerPixel; for (int i = 0; i < number_passes; i++) { uint8_t* row = base; for (png_uint_32 y = 0; y < origHeight; y++) { uint8_t* bmRow = row; png_read_rows(png_ptr, &bmRow, png_bytepp_NULL, 1); row += rb; } } // now sample it base += sampler.srcY0() * rb; for (int y = 0; y < height; y++) { reallyHasAlpha |= sampler.next(base); base += sampler.srcDY() * rb; } } else { SkAutoMalloc storage(origWidth * srcBytesPerPixel); uint8_t* srcRow = (uint8_t*)storage.get(); skip_src_rows(png_ptr, srcRow, sampler.srcY0()); for (int y = 0; y < height; y++) { uint8_t* tmp = srcRow; png_read_rows(png_ptr, &tmp, png_bytepp_NULL, 1); reallyHasAlpha |= sampler.next(srcRow); if (y < height - 1) { skip_src_rows(png_ptr, srcRow, sampler.srcDY() - 1); } } // skip the rest of the rows (if any) png_uint_32 read = (height - 1) * sampler.srcDY() + sampler.srcY0() + 1; SkASSERT(read <= origHeight); skip_src_rows(png_ptr, srcRow, origHeight - read); } } /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); if (0 != theTranspColor) { reallyHasAlpha |= substituteTranspColor(decodedBitmap, theTranspColor); } decodedBitmap->setIsOpaque(!reallyHasAlpha); return true; }
int main(int argc, char *argv[]) { char filename1[MAXNAMELENGTH], filename2[MAXNAMELENGTH]; int idx, k, j; FILE *fd, *lut=NULL; byte *imgarr; int userfill=-1; int colorstyle=GRAYSCALE; int red, green, blue, alpha; int redarr[256], greenarr[256], bluearr[256], alphaarr[256]; unsigned char lutname[MAXNAMELENGTH]; unsigned char verbose=FALSE; png_structp png_ptr; png_infop info_ptr; png_colorp png_palette; png_colorp dest_pal; unsigned char *png_trans; png_structp in_png_ptr; png_infop in_info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE *fp; png_uint_32 i, rowbytes; byte *image_data = NULL; png_bytepp row_pointers = NULL; int bytesperpixel; int found; int num_not_found=0; int rednotfound[MAX_NOT_FOUND], greennotfound[MAX_NOT_FOUND], bluenotfound[MAX_NOT_FOUND]; int return_code=0; filename1[0] = '\0'; filename2[0] = '\0'; lutname[0] = '\0'; if (argc < 2) { fprintf(stderr, "Usage: RGBApng2Palpng [-v] -lut=<ColorMap file (must contain RGBA)> -fill=<LUT index value> -of=<output palette PNG file> <input RGBA PNG file>\n"); exit(-1); } for (j=1; j<argc; j++) if ( strcmp(argv[j], "-v") == 0 ) { fprintf(stderr, "Verbose mode requested.\n"); verbose = TRUE; } for (j=1; j<argc; j++) { if (strstr(argv[j], "-of=") == argv[j] ) { if ( sscanf(argv[j], "-of=%s", filename2) != 1 ) { fprintf(stderr, "Cannot read output file\n"); exit(-1); } if (verbose) fprintf(stderr, "Output file: %s\n", filename2); } else if (strstr(argv[j], "-lut=") == argv[j] ) { if ( sscanf(argv[j], "-lut=%s", lutname) != 1 ) { fprintf(stderr, "Cannot parse LUT name\n"); exit(-1); } if (verbose) fprintf(stderr, "Color LUT: %s\n", lutname); colorstyle = COLOR; } else if (strstr(argv[j], "-fill=") == argv[j] ) { if (sscanf(argv[j], "-fill=%d", &userfill) != 1) { fprintf(stderr, "Cannot read user fill value\n"); exit(-1); } if ( userfill < 0 || userfill > 255 ) { fprintf(stderr, "User fill value must be between 0 and 255\n"); exit(-1); } if (verbose) fprintf(stderr, "User fill value: %d\n", userfill); } else if ( strlen(filename2) == 0 && strcmp(argv[j], "-") == 0 ) { strcpy(filename2, "stdout"); if (verbose) fprintf(stderr, "Output file: %s\n", filename2); } else if ( strcmp(argv[j], "-v") != 0 ) { strcpy(filename1, argv[j]); if (verbose) fprintf(stderr, "Input file: %s\n", filename1); } } if ( strlen(filename1) == 0 || strlen(filename2) == 0 || strlen(lutname) == 0 || userfill < 0 ) { fprintf(stderr, "Unable to get all arguments\n"); exit(-1); } if ((fp = fopen(filename1, "rb")) == NULL) { fprintf(stderr, "Unable to open input file: %s\n", filename1); exit(-1); } in_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (in_png_ptr == NULL) { fclose(fp); fprintf(stderr, "Could not allocate PNG read struct\n"); return (-1); } in_info_ptr = png_create_info_struct(in_png_ptr); if (in_info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&in_png_ptr, png_infopp_NULL, png_infopp_NULL); fprintf(stderr, "Could not allocate input PNG info struct\n"); return (-1); } if (setjmp(png_jmpbuf(in_png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&in_png_ptr, &in_info_ptr, png_infopp_NULL); fclose(fp); /* If we get here, we had a problem reading the file */ return (-1); } /* Set up the input control if you are using standard C streams */ png_init_io(in_png_ptr, fp); png_read_info(in_png_ptr, in_info_ptr); png_get_IHDR(in_png_ptr, in_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL); if (verbose) { fprintf(stderr, "Width: %d\n", width); fprintf(stderr, "Height: %d\n", height); fprintf(stderr, "Bit Depth: %d\n", bit_depth); switch(color_type) { case 0: fprintf(stderr, "Color Type: Gray (0)\n"); break; case 3: fprintf(stderr, "Color Type: Palette (3)\n"); break; case 2: fprintf(stderr, "Color Type: RGB (2)\n"); break; case 6: fprintf(stderr, "Color Type: RGB Alpha (6)\n"); break; case 4: fprintf(stderr, "Color Type: Gray Alpha (4)\n"); break; default: fprintf(stderr, "Unknown Color Type: %d\n", color_type); } switch(interlace_type) { case 0: fprintf(stderr, "Interlace Type: None (0)\n"); break; case 1: fprintf(stderr, "Interlace Type: Adam7 (1)\n"); break; default: fprintf(stderr, "Unknown Interlace Type: %d\n", interlace_type); } } rowbytes = png_get_rowbytes(in_png_ptr, in_info_ptr); if ( verbose ) fprintf(stderr, "Number of bytes per row: %d\n", rowbytes); if ((image_data = (byte *)malloc(rowbytes*height)) == NULL) { png_destroy_read_struct(&in_png_ptr, &in_info_ptr, NULL); exit(-1); } if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { png_destroy_read_struct(&in_png_ptr, &in_info_ptr, NULL); free(image_data); image_data = NULL; exit(-1); } for (i = 0; i < height; ++i) row_pointers[i] = image_data + i*rowbytes; /* now we can go ahead and just read the whole image */ png_read_image(in_png_ptr, row_pointers); imgarr = (byte *) malloc(height * width * sizeof(byte)); png_palette = (png_colorp)malloc( 256 * sizeof( png_color) ); dest_pal = png_palette; if (colorstyle == GRAYSCALE) for (j=0; j<256; j++) { dest_pal->red = dest_pal->green = dest_pal->blue = j; dest_pal++; redarr[j] = greenarr[j] = bluearr[j] = j; alphaarr[j] = 255; } else { if ( (lut = fopen(lutname, "r")) != NULL ) { if (strlen(lutname) > 4 && ((!strcmp(lutname + strlen(lutname) - 4, ".xml")))) { fprintf(stderr, "Opening colormap file %s\n", lutname); if (lut) { int size = 1024, pos; int c; int j = 0; char *buffer = (char *)malloc(size); const char *entry_key = "ColorMapEntry"; const char *rgb_key = "rgb="; const char *transparent_key = "transparent="; const char *true_str = "\"true\""; do { // read all lines in file pos = 0; do { // read one line c = fgetc(lut); if(c != EOF) buffer[pos++] = (char)c; if(pos >= size - 1) { // increase buffer length - leave room for 0 size *=2; buffer = (char*)realloc(buffer, size); } } while(c != EOF && c != '\n'); buffer[pos] = 0; char *entry = strstr(buffer,entry_key); char *rgb = strstr(buffer,rgb_key); char *transparent = strstr(buffer,transparent_key); // GIBS colormap RGB values if (rgb != NULL && entry != NULL) { char rgb_string[11]; int rgb_length = strlen(rgb); int rgb_pos = pos - rgb_length; memcpy(rgb_string, &buffer[rgb_pos+5], 11); rgb_string[11] = '\0'; // break rgb string into int values int rgb_array[3]; int i = 0; char *rgb_values = strtok(rgb_string, ","); while (rgb_values != NULL) { rgb_array[i++] = strtol(rgb_values,NULL,10); rgb_values = strtok(NULL, ","); } red = rgb_array[0]; green = rgb_array[1]; blue = rgb_array[2]; dest_pal->red = red; dest_pal->green = green; dest_pal->blue = blue; alpha = strstr(transparent, true_str) != NULL ? 0 : 255; dest_pal++; redarr[j] = red; greenarr[j] = green; bluearr[j] = blue; alphaarr[j] = alpha; if ( verbose ) fprintf(stderr, "RGBA: %d %d %d %d \n", redarr[j], greenarr[j] , bluearr[j], alphaarr[j]); j++; } } while(c != EOF);; fclose(lut); free(buffer); } } else { for (j=0; j<256; j++) if ( fscanf(lut, "%d %d %d %d", &red, &green, &blue, &alpha) != 4 ) { fprintf(stderr, "Cannot read color index %d in LUT file\n", j); exit(-1); } else { dest_pal->red = red; dest_pal->green = green; dest_pal->blue = blue; dest_pal++; redarr[j] = red; greenarr[j] = green; bluearr[j] = blue; alphaarr[j] = alpha; } fclose(lut); } } else { fprintf(stderr, "Cannot open LUT file %s.\n", lutname); exit(-1); } } png_trans = (unsigned char *)malloc(256 * sizeof(unsigned char)); for (j=0; j<256; j++) { png_trans[j] = alphaarr[j]; } switch(color_type) { case(PNG_COLOR_TYPE_GRAY): bytesperpixel = 1; break; case(PNG_COLOR_TYPE_PALETTE): bytesperpixel = 1; break; case(PNG_COLOR_TYPE_RGB): bytesperpixel = 3; break; case(PNG_COLOR_TYPE_RGB_ALPHA): bytesperpixel = 4; break; case(PNG_COLOR_TYPE_GRAY_ALPHA): bytesperpixel = 2; break; default: fprintf(stderr, "Unknown Color Type: %d\n", color_type); exit(-1); } if ( color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA ) { fprintf(stderr, "Color Type must be RGB or RGBA.\n"); exit(-1); } if ( verbose ) fprintf(stderr, "Bytes per Pixel: %d\n", bytesperpixel); for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { idx = i*width+j; red = image_data[i*width*bytesperpixel+j*bytesperpixel]; green = image_data[i*width*bytesperpixel+j*bytesperpixel+1]; blue = image_data[i*width*bytesperpixel+j*bytesperpixel+2]; found = FALSE; for (k = 0; k < 256; k++) { if ( red == redarr[k] && green == greenarr[k] && blue == bluearr[k] ) { imgarr[idx] = (unsigned char) k; found = TRUE; break; } } if ( !found ) { imgarr[idx] = (unsigned char) userfill; found = FALSE; if ( num_not_found < MAX_NOT_FOUND ) { for (k = 0; k < num_not_found; k++) { if ( red == rednotfound[k] && green == greennotfound[k] && blue == bluenotfound[k] ) { found = TRUE; break; } } if ( !found ) { rednotfound[num_not_found] = red; greennotfound[num_not_found] = green; bluenotfound[num_not_found] = blue; num_not_found++; } } } } } if ( num_not_found > 0 ) { return_code = num_not_found; fprintf(stderr, "%d Colors in image not found in color table\n", num_not_found); for (k = 0; k < num_not_found; k++) { fprintf(stderr, "%3d %3d %3d\n", rednotfound[k], greennotfound[k], bluenotfound[k]); } } // Done with the read, clean up free(row_pointers); row_pointers = NULL; png_read_end(in_png_ptr, NULL); free(image_data); image_data = NULL; fclose(fp); // Start the write if (strcmp(filename2, "stdout") == 0) fd = stdout; else if ( (fd = fopen(filename2, "wb")) == NULL ) { fprintf(stderr, "Cannot open file %s.\n", filename2); exit(-1); } // Initialize write structure png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fprintf(stderr, "Could not allocate PNG write struct\n"); exit(-1); } // Initialize info structure info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fprintf(stderr, "Could not allocate PNG info struct\n"); exit(-1); } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG init_io\n"); exit(-1); } png_init_io(png_ptr, fd); if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG set header\n"); exit(-1); } // Write header (8 bit colour depth) png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG set pallette\n"); exit(-1); } png_set_PLTE(png_ptr, info_ptr, png_palette, 256); if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG set transparency\n"); exit(-1); } png_set_tRNS(png_ptr, info_ptr, png_trans, 256, NULL); if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG write info\n"); exit(-1); } png_write_info(png_ptr, info_ptr); if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG write row\n"); exit(-1); } for (k=0; k<height; k++) { idx = k * width; png_write_row(png_ptr, &imgarr[idx]); } if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "Error during PNG write end\n"); exit(-1); } // End write png_write_end(png_ptr, NULL); fclose(fd); free(imgarr); free(png_palette); free(png_trans); if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return return_code; }
int fh_png_load(const char *name, unsigned char *buffer, int x, int y) { static const png_color_16 my_background = {0, 0, 0, 0, 0}; png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; unsigned int i; int bit_depth, color_type, interlace_type; int number_passes, pass; png_byte * fbptr; FILE * fh; if (!(fh = fopen(name, "rb"))) return(FH_ERROR_FILE); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) return(FH_ERROR_FORMAT); 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(fh); return(FH_ERROR_FORMAT); } if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_FORMAT); } png_init_io(png_ptr, fh); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* other possibility for png_set_background: use png_get_bKGD */ } if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); png_set_background(png_ptr, (png_color_16 *)&my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); } if (color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); /* on Intel PC ?: if (bit_depth == 16) png_set_swap(png_ptr); */ number_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); if (width * 3 != png_get_rowbytes(png_ptr, info_ptr)) { printf("[png.cpp]: Error processing %s - please report (including image).\n", name); return(FH_ERROR_FORMAT); } for(pass = 0; pass < number_passes; pass++) { fbptr = (png_byte *)buffer; for (i = 0; i < height; i++, fbptr += width * 3) { png_read_row(png_ptr, fbptr, NULL); } } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fh); return(FH_ERROR_OK); }
void t_RenderClass::loadTexture(int target, const char *filename) { FILE *theFile = fopen(filename,"rb"); if (!theFile) { LOGI("Fopen failed"); exit(1); } char header[8]; fread(header,1,8,theFile); if (ferror(theFile)) { LOGI("Fread failed"); exit(1); } if (png_sig_cmp((png_byte *) header,0,8)) { LOGI("The file is not a png\n"); exit(1); } png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL,NULL,NULL ); if (!png_ptr) { printf("Failed initialization of png_ptr\n"); exit(1); } 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); printf("Info ptr creation failed\n"); exit(1); } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); printf("Info ptr creation failed\n"); exit(1); } png_init_io(png_ptr,theFile); 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_width(png_ptr,info_ptr); int depth = png_get_bit_depth(png_ptr,info_ptr); int rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_byte* image_data = new png_byte[rowbytes * height]; png_bytep *row_pointers = new png_bytep [height]; for (int i = 0; i < height; ++i) { row_pointers[i] = image_data + i * rowbytes; } LOGI("I have read the image with width %d, height %d, depth %d, rowbytes %d\n",width,height,depth,rowbytes); png_read_image(png_ptr,row_pointers); png_read_end(png_ptr,NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,image_data); checkGlError("glClear"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); checkGlError("glClear"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); checkGlError("glClear"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); checkGlError("glClear"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); checkGlError("glClear"); }
uint8_t* ImageDecoder::decodePNGImpl(png_structp pngPtr, uint32_t* width, uint32_t* height) { png_bytep* rowPtrs = NULL; uint8_t* outData = NULL; png_infop infoPtr = png_create_info_struct(pngPtr); if (!infoPtr) { LOG(LOG_ERROR,"Couldn't initialize png info struct"); png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0); return NULL; } if (setjmp(png_jmpbuf(pngPtr))) { png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); if (rowPtrs != NULL) delete [] rowPtrs; if (outData != NULL) delete [] outData; LOG(LOG_ERROR,"error during reading of the png file"); return NULL; } png_read_info(pngPtr, infoPtr); *width = png_get_image_width(pngPtr, infoPtr); *height = png_get_image_height(pngPtr, infoPtr); //bits per CHANNEL! note: not per pixel! png_uint_32 bitdepth = png_get_bit_depth(pngPtr, infoPtr); //Number of channels png_uint_32 channels = png_get_channels(pngPtr, infoPtr); //Color type. (RGB, RGBA, Luminance, luminance alpha... palette... etc) png_uint_32 color_type = png_get_color_type(pngPtr, infoPtr); // Transform everything into 24 bit RGB switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(pngPtr); // png_set_palette_to_rgb wil convert into 32 // bit, but we don't want the alpha png_set_strip_alpha(pngPtr); break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) png_set_gray_to_rgb(pngPtr); break; } if (bitdepth == 16) { png_set_strip_16(pngPtr); } if (channels > 3) { LOG(LOG_NOT_IMPLEMENTED, "Alpha channel not supported in PNG"); png_set_strip_alpha(pngPtr); } // Update the infoPtr to reflect the transformations set // above. Read new values by calling png_get_* again. png_read_update_info(pngPtr, infoPtr); //bitdepth = png_get_bit_depth(pngPtr, infoPtr); //color_type = png_get_color_type(pngPtr, infoPtr); channels = png_get_channels(pngPtr, infoPtr); if (channels != 3) { // Should never get here because of the // transformations LOG(LOG_NOT_IMPLEMENTED, "Unexpected number of channels in PNG!"); png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); return NULL; } const unsigned int stride = png_get_rowbytes(pngPtr, infoPtr); outData = new uint8_t[(*height) * stride]; rowPtrs = new png_bytep[(*height)]; for (size_t i = 0; i < (*height); i++) { rowPtrs[i] = (png_bytep)outData + i* stride; } png_read_image(pngPtr, rowPtrs); png_read_end(pngPtr, NULL); png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0); delete[] (png_bytep)rowPtrs; return outData; }
unsigned char *read_png_file(const char* file_name, int *width, int *height, int *stride) { png_byte color_type; png_byte bit_depth; png_structp png_ptr; png_infop info_ptr; int number_of_passes; png_bytep* row_pointers; int y; unsigned char header[8]; // 8 is the maximum size that can be checked unsigned char *buf; FILE *fp; /* open file and test for it being a png */ fp = fopen(file_name, "rb"); if (!fp) return NULL; fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { roadmap_log (ROADMAP_ERROR, "[read_png_file] File %s is not recognized as a PNG file", file_name); fclose(fp); return NULL; } /* initialize stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { roadmap_log (ROADMAP_ERROR, "[read_png_file] png_create_read_struct failed"); fclose(fp); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { roadmap_log (ROADMAP_ERROR, "[read_png_file] png_create_info_struct failed"); fclose(fp); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { roadmap_log (ROADMAP_ERROR, "[read_png_file] Error during init_io"); fclose(fp); return NULL; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); *width = info_ptr->width; *height = info_ptr->height; *stride = info_ptr->rowbytes; color_type = info_ptr->color_type; bit_depth = info_ptr->bit_depth; number_of_passes = png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); /* read file */ if (setjmp(png_jmpbuf(png_ptr))) { roadmap_log (ROADMAP_ERROR, "[read_png_file] Error during read_image"); fclose(fp); return NULL; } row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * *height); buf = malloc (*height * info_ptr->rowbytes); for (y=0; y<*height; y++) { row_pointers[y] = (png_byte*) (buf + y * info_ptr->rowbytes); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, NULL); png_destroy_read_struct (&png_ptr, &info_ptr, NULL); free (row_pointers); fclose(fp); return buf; }
unsigned char *readpng_get_image( png_store* pngdata) { double gamma; png_uint_32 i, rowbytes; png_bytepp row_pointers = NULL; png_structp png_ptr = pngdata->png_ptr; png_infop info_ptr = pngdata->info_ptr; int color_type = pngdata->colortype; int bit_depth = pngdata->bitdepth; int height = pngdata->height; double display_exponent = DISPLAY_EXPONENT; int *pChannels = &(pngdata->channels); unsigned long *pRowbytes = &(pngdata->rowbytes); unsigned char * image_data; /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, * transparency chunks to full alpha channel; strip 16-bit-per-sample * images to 8 bits per sample; and convert grayscale to RGB[A] */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); /* unlike the example in the libpng documentation, we have *no* idea where * this file may have come from--so if it doesn't have a file gamma, don't * do any correction ("do no harm") */ if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, display_exponent, gamma); /* 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); *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); *pChannels = (int)png_get_channels(png_ptr, info_ptr); if ((image_data = (unsigned char *)malloc(rowbytes*height)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(image_data); image_data = NULL; return NULL; } /* set the individual row_pointers to point at the correct offsets */ for (i = 0; i < height; ++i) row_pointers[i] = image_data + i*rowbytes; /* now we can go ahead and just read the whole image */ png_read_image(png_ptr, row_pointers); /* and we're done! (png_read_end() can be omitted if no processing of * post-IDAT text/time/etc. is desired) */ // free(row_pointers); // row_pointers = NULL; png_read_end(png_ptr, NULL); pngdata->image_data = image_data; pngdata->row_pointers = row_pointers; return image_data; }
void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { int row; if (png_ptr == NULL) return; #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) /* invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif /* png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error(png_ptr, "Image is too high to process with png_read_png()"); /* -------------- image transformations start here ------------------- */ #if defined(PNG_READ_16_TO_8_SUPPORTED) /* tell libpng to strip 16 bit/color files down to 8 bits per color */ if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); #endif #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) /* Strip alpha bytes from the input data without combining with * the background (not recommended). */ if (transforms & PNG_TRANSFORM_STRIP_ALPHA) png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ if (transforms & PNG_TRANSFORM_PACKSWAP) png_set_packswap(png_ptr); #endif #if defined(PNG_READ_EXPAND_SUPPORTED) /* Expand paletted colors into true RGB triplets * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel * Expand paletted or RGB images with transparency to full alpha * channels so the data will be available as RGBA quartets. */ if (transforms & PNG_TRANSFORM_EXPAND) if ((png_ptr->bit_depth < 8) || (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_expand(png_ptr); #endif /* We don't handle background color or gamma transformation or dithering. */ #if defined(PNG_READ_INVERT_SUPPORTED) /* invert monochrome files to have 0 as white and 1 as black */ if (transforms & PNG_TRANSFORM_INVERT_MONO) png_set_invert_mono(png_ptr); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) /* 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 ((transforms & PNG_TRANSFORM_SHIFT) && 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); } #endif #if defined(PNG_READ_BGR_SUPPORTED) /* flip the RGB pixels to BGR (or RGBA to BGRA) */ if (transforms & PNG_TRANSFORM_BGR) png_set_bgr(png_ptr); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) png_set_swap_alpha(png_ptr); #endif #if defined(PNG_READ_SWAP_SUPPORTED) /* swap bytes of 16 bit files to least significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif /* We don't handle adding filler bytes */ /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (i.e., you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); /* -------------- image transformations end here ------------------- */ #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); #endif if (info_ptr->row_pointers == NULL) { info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ROWS; #endif png_memset(info_ptr->row_pointers, 0, info_ptr->height * png_sizeof(png_bytep)); for (row = 0; row < (int)info_ptr->height; row++) info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); transforms = transforms; /* quiet compiler warnings */ params = params; }
int png_include_image (pdf_ximage *ximage, FILE *png_file) { pdf_obj *stream; pdf_obj *stream_dict; pdf_obj *colorspace, *mask, *intent; png_bytep stream_data_ptr; int trans_type; ximage_info info; /* Libpng stuff */ png_structp png_ptr; png_infop png_info_ptr; png_byte bpc, color_type; png_uint_32 width, height, rowbytes; pdf_ximage_init_image_info(&info); stream = NULL; stream_dict = NULL; colorspace = mask = intent = NULL; rewind (png_file); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn); if (png_ptr == NULL || (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) { WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR); if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); return -1; } #if PNG_LIBPNG_VER >= 10603 /* ignore possibly incorrect CMF bytes */ png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON); #endif /* Inititializing file IO. */ png_init_io (png_ptr, png_file); /* Read PNG info-header and get some info. */ png_read_info(png_ptr, png_info_ptr); color_type = png_get_color_type (png_ptr, png_info_ptr); width = png_get_image_width (png_ptr, png_info_ptr); height = png_get_image_height(png_ptr, png_info_ptr); bpc = png_get_bit_depth (png_ptr, png_info_ptr); /* We do not need 16-bpc color. Ask libpng to convert down to 8-bpc. */ if (bpc > 8) { png_set_strip_16(png_ptr); bpc = 8; } /* Ask libpng to gamma-correct. * It is wrong to assume screen gamma value 2.2 but... * We do gamma correction here only when uncalibrated color space is used. */ if (!png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP) && !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) && !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_cHRM) && !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) && png_get_valid(png_ptr, png_info_ptr, PNG_INFO_gAMA)) { double G = 1.0; png_get_gAMA (png_ptr, png_info_ptr, &G); png_set_gamma(png_ptr, 2.2, G); } trans_type = check_transparency(png_ptr, png_info_ptr); /* check_transparency() does not do updata_info() */ png_read_update_info(png_ptr, png_info_ptr); rowbytes = png_get_rowbytes(png_ptr, png_info_ptr); /* Values listed below will not be modified in the remaining process. */ info.width = width; info.height = height; info.bits_per_component = bpc; if (compat_mode) info.xdensity = info.ydensity = 72.0 / 100.0; else { png_uint_32 xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr); png_uint_32 yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr); if (xppm > 0) info.xdensity = 72.0 / 0.0254 / xppm; if (yppm > 0) info.ydensity = 72.0 / 0.0254 / yppm; } stream = pdf_new_stream (STREAM_COMPRESS); stream_dict = pdf_stream_dict(stream); stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte); read_image_data(png_ptr, stream_data_ptr, height, rowbytes); /* Non-NULL intent means there is valid sRGB chunk. */ intent = get_rendering_intent(png_ptr, png_info_ptr); if (intent) pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: colorspace = create_cspace_Indexed(png_ptr, png_info_ptr); switch (trans_type) { case PDF_TRANS_TYPE_BINARY: /* Color-key masking */ mask = create_ckey_mask(png_ptr, png_info_ptr); break; case PDF_TRANS_TYPE_ALPHA: /* Soft mask */ mask = create_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, width, height); break; default: /* Nothing to be done here. * No tRNS chunk or image already composited with background color. */ break; } break; case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr); else if (intent) { colorspace = create_cspace_sRGB(png_ptr, png_info_ptr); } else { colorspace = create_cspace_CalRGB(png_ptr, png_info_ptr); } if (!colorspace) colorspace = pdf_new_name("DeviceRGB"); switch (trans_type) { case PDF_TRANS_TYPE_BINARY: mask = create_ckey_mask(png_ptr, png_info_ptr); break; /* rowbytes changes 4 to 3 at here */ case PDF_TRANS_TYPE_ALPHA: mask = strip_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, &rowbytes, width, height); break; default: mask = NULL; } info.num_components = 3; break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP)) colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr); else if (intent) { colorspace = create_cspace_sRGB(png_ptr, png_info_ptr); } else { colorspace = create_cspace_CalGray(png_ptr, png_info_ptr); } if (!colorspace) colorspace = pdf_new_name("DeviceGray"); switch (trans_type) { case PDF_TRANS_TYPE_BINARY: mask = create_ckey_mask(png_ptr, png_info_ptr); break; case PDF_TRANS_TYPE_ALPHA: mask = strip_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, &rowbytes, width, height); break; default: mask = NULL; } info.num_components = 1; break; default: WARN("%s: Unknown PNG colortype %d.", PNG_DEBUG_STR, color_type); } pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace); pdf_add_stream(stream, stream_data_ptr, rowbytes*height); RELEASE(stream_data_ptr); if (mask) { if (trans_type == PDF_TRANS_TYPE_BINARY) pdf_add_dict(stream_dict, pdf_new_name("Mask"), mask); else if (trans_type == PDF_TRANS_TYPE_ALPHA) { pdf_add_dict(stream_dict, pdf_new_name("SMask"), pdf_ref_obj(mask)); pdf_release_obj(mask); } else { WARN("%s: Unknown transparency type...???", PNG_DEBUG_STR); pdf_release_obj(mask); } } /* Finally read XMP Metadata * See, XMP Specification Part 3, Storage in Files * http://www.adobe.com/jp/devnet/xmp.html * * We require libpng version >= 1.6.14 since prior versions * of libpng had a bug that incorrectly treat the compression * flag of iTxt chunks. */ #if PNG_LIBPNG_VER >= 10614 if (pdf_get_version() >= 4) { png_textp text_ptr; pdf_obj *XMP_stream, *XMP_stream_dict; int i, num_text; int have_XMP = 0; num_text = png_get_text(png_ptr, png_info_ptr, &text_ptr, NULL); for (i = 0; i < num_text; i++) { if (!memcmp(text_ptr[i].key, "XML:com.adobe.xmp", 17)) { /* XMP found */ if (text_ptr[i].compression != PNG_ITXT_COMPRESSION_NONE || text_ptr[i].itxt_length == 0) WARN("%s: Invalid value(s) in iTXt chunk for XMP Metadata.", PNG_DEBUG_STR); else if (have_XMP) WARN("%s: Multiple XMP Metadata. Don't know how to treat it.", PNG_DEBUG_STR); else { /* We compress XMP metadata for included images here. * It is not recommended to compress XMP metadata for PDF documents but * we compress XMP metadata for included images here to avoid confusing * application programs that only want PDF document global XMP metadata * and scan for that. */ XMP_stream = pdf_new_stream(STREAM_COMPRESS); XMP_stream_dict = pdf_stream_dict(XMP_stream); pdf_add_dict(XMP_stream_dict, pdf_new_name("Type"), pdf_new_name("Metadata")); pdf_add_dict(XMP_stream_dict, pdf_new_name("Subtype"), pdf_new_name("XML")); pdf_add_stream(XMP_stream, text_ptr[i].text, text_ptr[i].itxt_length); pdf_add_dict(stream_dict, pdf_new_name("Metadata"), pdf_ref_obj(XMP_stream)); pdf_release_obj(XMP_stream); have_XMP = 1; } } } } #endif /* PNG_LIBPNG_VER */ png_read_end(png_ptr, NULL); /* Cleanup */ if (png_info_ptr) png_destroy_info_struct(png_ptr, &png_info_ptr); if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL); pdf_ximage_set_image(ximage, &info, stream); return 0; }
//Called in the gl thread static void gst_gl_bumper_init_resources (GstGLFilter * filter) { GstGLBumper *bumper = GST_GL_BUMPER (filter); GstGLDisplay *display = filter->display; png_structp png_ptr; png_infop info_ptr; guint sig_read = 0; png_uint_32 width = 0; png_uint_32 height = 0; gint bit_depth = 0; gint color_type = 0; gint interlace_type = 0; png_FILE_p fp = NULL; guint y = 0; guchar *raw_data = NULL; guchar **rows = NULL; png_byte magic[8]; gint n_read; if (!filter->display) return; /* BEGIN load png image file */ if ((fp = fopen (bumper->location, "rb")) == NULL) LOAD_ERROR ("file not found"); /* Read magic number */ n_read = fread (magic, 1, sizeof (magic), fp); if (n_read != sizeof (magic)) { fclose (fp); LOAD_ERROR ("can't read PNG magic number"); } /* Check for valid magic number */ if (png_sig_cmp (magic, 0, sizeof (magic))) { fclose (fp); LOAD_ERROR ("not a valid PNG image"); } png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose (fp); LOAD_ERROR ("failed to initialize the png_struct"); } png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn); info_ptr = png_create_info_struct (png_ptr); if (info_ptr == NULL) { fclose (fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL); LOAD_ERROR ("failed to initialize the memory for image information"); } png_init_io (png_ptr, fp); png_set_sig_bytes (png_ptr, sig_read); 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); if (color_type != PNG_COLOR_TYPE_RGB) { fclose (fp); png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL); LOAD_ERROR ("color type is not rgb"); } raw_data = (guchar *) malloc (sizeof (guchar) * width * height * 3); rows = (guchar **) malloc (sizeof (guchar *) * height); for (y = 0; y < height; ++y) rows[y] = (guchar *) (raw_data + y * width * 3); png_read_image (png_ptr, rows); free (rows); png_read_end (png_ptr, info_ptr); png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL); fclose (fp); /* END load png image file */ bumper->bumpmap_width = width; bumper->bumpmap_height = height; glGenTextures (1, &bumper->bumpmap); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, bumper->bumpmap); glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, bumper->bumpmap_width, bumper->bumpmap_height, 0, GL_RGB, GL_UNSIGNED_BYTE, raw_data); free (raw_data); }
bool PngDecoder::readData( Mat& img ) { volatile bool result = false; AutoBuffer<uchar*> _buffer(m_height); uchar** buffer = _buffer; int color = img.channels() > 1; if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height ) { png_structp png_ptr = (png_structp)m_png_ptr; png_infop info_ptr = (png_infop)m_info_ptr; png_infop end_info = (png_infop)m_end_info; if( setjmp( png_jmpbuf ( png_ptr ) ) == 0 ) { int y; if( img.depth() == CV_8U && m_bit_depth == 16 ) png_set_strip_16( png_ptr ); else if( !isBigEndian() ) png_set_swap( png_ptr ); if(img.channels() < 4) { /* observation: png_read_image() writes 400 bytes beyond * end of data when reading a 400x118 color png * "mpplus_sand.png". OpenCV crashes even with demo * programs. Looking at the loaded image I'd say we get 4 * bytes per pixel instead of 3 bytes per pixel. Test * indicate that it is a good idea to always ask for * stripping alpha.. 18.11.2004 Axel Walthelm */ png_set_strip_alpha( png_ptr ); } if( m_color_type == PNG_COLOR_TYPE_PALETTE ) png_set_palette_to_rgb( png_ptr ); if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 ) #if (PNG_LIBPNG_VER_MAJOR*10000 + PNG_LIBPNG_VER_MINOR*100 + PNG_LIBPNG_VER_RELEASE >= 10209) || \ (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR == 0 && PNG_LIBPNG_VER_RELEASE >= 18) png_set_expand_gray_1_2_4_to_8( png_ptr ); #else png_set_gray_1_2_4_to_8( png_ptr ); #endif if( CV_MAT_CN(m_type) > 1 && color ) png_set_bgr( png_ptr ); // convert RGB to BGR else if( color ) png_set_gray_to_rgb( png_ptr ); // Gray->RGB else png_set_rgb_to_gray( png_ptr, 1, 0.299, 0.587 ); // RGB->Gray png_set_interlace_handling( png_ptr ); png_read_update_info( png_ptr, info_ptr ); for( y = 0; y < m_height; y++ ) buffer[y] = img.data + y*img.step; png_read_image( png_ptr, buffer ); png_read_end( png_ptr, end_info ); result = true; } } close(); return result; }
static int readpng( FILE *f, GrContext *grc, int use_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 color_type; int alpha_present; int i, x, y, r, g, b; int alpha = 0, ro, go, bo; int maxwidth, maxheight; GrColor *pColors = NULL; /* is it a PNG file? */ if( fread( buf,1,8,f ) != 8 ) return -1; if( ! png_check_sig( buf,8 ) ) return -1; png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if( !png_ptr ){ return -1; } info_ptr = png_create_info_struct( png_ptr ); if( !info_ptr ){ png_destroy_read_struct( &png_ptr,NULL,NULL ); return -1; } if( setjmp( png_jmpbuf(png_ptr) ) ){ png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); return -1; } png_init_io( png_ptr,f ); png_set_sig_bytes( png_ptr,8 ); png_read_info( png_ptr,info_ptr ); png_get_IHDR( png_ptr,info_ptr,&width,&height,&bit_depth, &color_type,NULL,NULL,NULL); /* tell libpng to strip 16 bit/color files down to 8 bits/color */ if( bit_depth == 16 ) png_set_strip_16( 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 ); /* transform grayscale images into rgb */ if( color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ) png_set_gray_to_rgb( png_ptr ); /* we don't do gamma correction by now */ png_read_update_info( png_ptr,info_ptr ); png_get_IHDR( png_ptr,info_ptr,&width,&height,&bit_depth, &color_type,NULL,NULL,NULL); if( color_type == PNG_COLOR_TYPE_RGB ) alpha_present = 0; else if( color_type == PNG_COLOR_TYPE_RGB_ALPHA ) alpha_present = 1; else{ png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); return -1; } row_bytes = png_get_rowbytes( png_ptr,info_ptr ); png_pixels = (png_byte *) malloc( row_bytes * height * sizeof(png_byte) ); if( png_pixels == NULL ){ png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); return -1; } row_pointers = (png_byte **) malloc( height * sizeof(png_bytep) ); if( row_pointers == NULL ){ png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); free( png_pixels ); png_pixels = NULL; return -1; } for( i=0; i<height; i++ ) row_pointers[i] = png_pixels + i * row_bytes; png_read_image (png_ptr, row_pointers); png_read_end (png_ptr, info_ptr); png_destroy_read_struct( &png_ptr,&info_ptr,NULL ); /* write data to context */ maxwidth = (width > GrSizeX()) ? GrSizeX() : width; maxheight = (height > GrSizeY()) ? GrSizeY() : height; pColors = malloc( maxwidth * sizeof(GrColor) ); if( pColors == NULL ){ free( row_pointers ); row_pointers = NULL; free( png_pixels ); png_pixels = NULL; return -1; } for( y=0; y<maxheight; y++ ){ pix_ptr = row_pointers[y]; if( alpha_present && use_alpha ){ memcpy( pColors,GrGetScanline( 0,maxwidth-1,y ), sizeof(GrColor)*maxwidth ); } for( x=0; x<width; x++ ){ r = *pix_ptr++; g = *pix_ptr++; b = *pix_ptr++; alpha = 0; if( alpha_present ) alpha = *pix_ptr++; if( x < maxwidth ){ if( alpha_present && use_alpha ){ if (alpha == 0) { GrQueryColor( pColors[x],&r,&g,&b ); } else if (alpha != 255) { // if a==255, rgb not modified float f1, f2; f1 = (alpha/255.0); f2 = ((255-alpha)/255.0); GrQueryColor( pColors[x],&ro,&go,&bo ); r = (r * f1) + (ro * f2); g = (g * f1) + (go * f2); b = (b * f1) + (bo * f2); } } pColors[x] = GrAllocColor( r,g,b ); } } GrPutScanline( 0,maxwidth-1,y,pColors,GrWRITE ); } if( pColors) free( pColors ); if( row_pointers ) free( row_pointers ); if( png_pixels ) free( png_pixels ); return 0; }
struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags) { struct ImBuf *ibuf = NULL; png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = NULL; png_bytepp row_pointers = NULL; png_uint_32 width, height; int bit_depth, color_type; PNGReadStruct ps; unsigned char *from, *to; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(NULL); png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { printf("Cannot png_create_read_struct\n"); return NULL; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); printf("Cannot png_create_info_struct\n"); return NULL; } ps.size = size; /* XXX, 4gig limit! */ ps.data = mem; ps.seek = 0; png_set_read_fn(png_ptr, (void *) &ps, ReadData); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); if (pixels) MEM_freeN(pixels); if (row_pointers) MEM_freeN(row_pointers); if (ibuf) IMB_freeImBuf(ibuf); return NULL; } // png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } bytesperpixel = png_get_channels(png_ptr, info_ptr); switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { bytesperpixel = 4; } else { bytesperpixel = 3; } break; case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY_ALPHA: if (bit_depth < 8) { png_set_expand(png_ptr); bit_depth = 8; } break; default: printf("PNG format not supported\n"); longjmp(png_jmpbuf(png_ptr), 1); } ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0); if (ibuf) { ibuf->ftype = PNG; ibuf->profile = IB_PROFILE_SRGB; if (png_get_valid (png_ptr, info_ptr, PNG_INFO_pHYs)) { int unit_type; png_uint_32 xres, yres; if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) if (unit_type == PNG_RESOLUTION_METER) { ibuf->ppm[0]= xres; ibuf->ppm[1]= yres; } } } else { printf("Couldn't allocate memory for PNG image\n"); } if (ibuf && ((flags & IB_test) == 0)) { imb_addrectImBuf(ibuf); pixels = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(unsigned char), "pixels"); if (pixels == NULL) { printf("Cannot allocate pixels array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // allocate memory for an array of row-pointers row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers"); if (row_pointers == NULL) { printf("Cannot allocate row-pointers array\n"); longjmp(png_jmpbuf(png_ptr), 1); } // set the individual row-pointers to point at the correct offsets for (i = 0; i < ibuf->y; i++) { row_pointers[ibuf->y-1-i] = (png_bytep) ((unsigned char *)pixels + (i * ibuf->x) * bytesperpixel * sizeof(unsigned char)); } png_read_image(png_ptr, row_pointers); // copy image data to = (unsigned char *) ibuf->rect; from = pixels; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = from[3]; to += 4; from += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = from[0]; to[1] = from[1]; to[2] = from[2]; to[3] = 0xff; to += 4; from += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = from[1]; to += 4; from += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to[0] = to[1] = to[2] = from[0]; to[3] = 0xff; to += 4; from++; } break; } if (flags & IB_metadata) { png_text* text_chunks; int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL); for (i = 0; i < count; i++) { IMB_metadata_add_field(ibuf, text_chunks[i].key, text_chunks[i].text); ibuf->flags |= IB_metadata; } } png_read_end(png_ptr, info_ptr); } // clean up MEM_freeN(pixels); MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; png_colorp png_palette; int color_type, palette_entries; int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels FIBITMAP *dib = NULL; RGBQUAD *palette = NULL; // pointer to dib palette png_bytepp row_pointers = NULL; int i; fi_ioStructure fio; fio.s_handle = handle; fio.s_io = io; if (handle) { try { // check to see if the file is in fact a PNG file unsigned char png_check[PNG_BYTES_TO_CHECK]; io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle); if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) return NULL; // Bad signature // create the chunk manage structure png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); if (!png_ptr) return NULL; // create the info structure 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; } // init the IO png_set_read_fn(png_ptr, &fio, _ReadProc); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } // because we have already read the signature... png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); // read the IHDR chunk png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); pixel_depth = info_ptr->pixel_depth; // get image data type (assume standard image type) FREE_IMAGE_TYPE image_type = FIT_BITMAP; if (bit_depth == 16) { if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) { image_type = FIT_UINT16; #ifndef FREEIMAGE_BIGENDIAN // turn on 16 bit byte swapping png_set_swap(png_ptr); #endif } else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) { image_type = FIT_RGB16; #ifndef FREEIMAGE_BIGENDIAN // turn on 16 bit byte swapping png_set_swap(png_ptr); #endif } else { // tell libpng to strip 16 bit/color files down to 8 bits/color png_set_strip_16(png_ptr); bit_depth = 8; } } // set some additional flags switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: #ifndef FREEIMAGE_BIGENDIAN // flip the RGB pixels to BGR (or RGBA to BGRA) if(image_type == FIT_BITMAP) png_set_bgr(png_ptr); #endif break; case PNG_COLOR_TYPE_PALETTE: // expand palette images to the full 8 bits from 2 bits/pixel if (pixel_depth == 2) { png_set_packing(png_ptr); pixel_depth = 8; } break; case PNG_COLOR_TYPE_GRAY: // expand grayscale images to the full 8 bits from 2 bits/pixel if (pixel_depth == 2) { png_set_expand(png_ptr); pixel_depth = 8; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: // expand 8-bit greyscale + 8-bit alpha to 32-bit png_set_gray_to_rgb(png_ptr); #ifndef FREEIMAGE_BIGENDIAN // flip the RGBA pixels to BGRA png_set_bgr(png_ptr); #endif pixel_depth = 32; break; default: throw "PNG format not supported"; } // Get the background color to draw transparent and alpha images over. // 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_16p image_background = NULL; RGBQUAD rgbBkColor; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { rgbBkColor.rgbRed = (BYTE)image_background->red; rgbBkColor.rgbGreen = (BYTE)image_background->green; rgbBkColor.rgbBlue = (BYTE)image_background->blue; rgbBkColor.rgbReserved = 0; } // if this image has transparency, store the trns values png_bytep trans = NULL; int num_trans = 0; png_color_16p trans_values = NULL; png_uint_32 transparent_value = png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values); // unlike the example in the libpng documentation, we have *no* idea where // this file may have come from--so if it doesn't have a file gamma, don't // do any correction ("do no harm") double gamma = 0; double screen_gamma = 2.2; if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA) png_set_gamma(png_ptr, screen_gamma, gamma); // all transformations have been registered; now update info_ptr data png_read_update_info(png_ptr, info_ptr); // color type may have changed, due to our transformations color_type = png_get_color_type(png_ptr,info_ptr); // create a DIB and write the bitmap header // set up the DIB palette, if needed switch (color_type) { case PNG_COLOR_TYPE_RGB: png_set_invert_alpha(png_ptr); if(image_type == FIT_BITMAP) { dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } else { dib = FreeImage_AllocateT(image_type, width, height, pixel_depth); } break; case PNG_COLOR_TYPE_RGB_ALPHA : dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); break; case PNG_COLOR_TYPE_PALETTE : dib = FreeImage_Allocate(width, height, pixel_depth); png_get_PLTE(png_ptr,info_ptr, &png_palette,&palette_entries); palette = FreeImage_GetPalette(dib); // store the palette for (i = 0; i < palette_entries; i++) { palette[i].rgbRed = png_palette[i].red; palette[i].rgbGreen = png_palette[i].green; palette[i].rgbBlue = png_palette[i].blue; } // store the transparency table if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) FreeImage_SetTransparencyTable(dib, (BYTE *)trans, num_trans); break; case PNG_COLOR_TYPE_GRAY: dib = FreeImage_AllocateT(image_type, width, height, pixel_depth); if(pixel_depth <= 8) { palette = FreeImage_GetPalette(dib); palette_entries = 1 << pixel_depth; for (i = 0; i < palette_entries; i++) { palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = (i * 255) / (palette_entries - 1); } } // store the transparency table if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) FreeImage_SetTransparencyTable(dib, (BYTE *)trans, num_trans); break; default: throw "PNG format not supported"; } // store the background color if(image_background) { FreeImage_SetBackgroundColor(dib, &rgbBkColor); } // get physical resolution if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { png_uint_32 res_x, res_y; // we'll overload this var and use 0 to mean no phys data, // since if it's not in meters we can't use it anyway int res_unit_type = 0; png_get_pHYs(png_ptr,info_ptr,&res_x,&res_y,&res_unit_type); if (res_unit_type == 1) { BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(dib); bih->biXPelsPerMeter = res_x; bih->biYPelsPerMeter = res_y; } } // get possible ICC profile if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_charp profile_name = NULL; png_charp profile_data = NULL; png_uint_32 profile_length = 0; int compression_type; png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length); // copy ICC profile data (must be done after FreeImage_Allocate) FreeImage_CreateICCProfile(dib, profile_data, profile_length); } // set the individual row_pointers to point at the correct offsets row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); if (!row_pointers) { if (palette) png_free(png_ptr, palette); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); FreeImage_Unload(dib); return NULL; } // read in the bitmap bits via the pointer table for (png_uint_32 k = 0; k < height; k++) row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); png_read_image(png_ptr, row_pointers); // check if the bitmap contains transparency, if so enable it in the header if (FreeImage_GetBPP(dib) == 32) if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) FreeImage_SetTransparent(dib, TRUE); else FreeImage_SetTransparent(dib, FALSE); // cleanup if (row_pointers) { free(row_pointers); row_pointers = NULL; } // read the rest of the file, getting any additional chunks in info_ptr png_read_end(png_ptr, info_ptr); // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } catch (const char *text) { if (png_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); if (row_pointers) free(row_pointers); if (dib) FreeImage_Unload(dib); FreeImage_OutputMessageProc(s_format_id, text); return NULL; } } return NULL; }
uint8 *readpng_get_image(uint32 *pChannels, uint32 *pRowbytes, uint32 *pWidth, uint32 *pHeight) { png_uint_32 width, height; int bit_depth, color_type; uint8 *image_data = NULL; png_uint_32 i, rowbytes; png_bytepp row_pointers = NULL; /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); *pWidth = width; *pHeight = height; /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, * transparency chunks to full alpha channel; strip 16-bit-per-sample * images to 8 bits per sample; and convert grayscale to RGB[A] */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); /* 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); *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); *pChannels = (int)png_get_channels(png_ptr, info_ptr); if ((image_data = (uint8 *)malloc(rowbytes*height)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(image_data); image_data = NULL; return NULL; } Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); /* set the individual row_pointers to point at the correct offsets */ for (i = 0; i < height; ++i) row_pointers[i] = image_data + i*rowbytes; /* now we can go ahead and just read the whole image */ png_read_image(png_ptr, row_pointers); free(row_pointers); row_pointers = NULL; png_read_end(png_ptr, NULL); return image_data; }
static e_texture_t* e_loadpng(e_device_t* device,int mipmaps,fs_handle_t file) { unsigned int width,height; unsigned int rowbytes; unsigned char* data; unsigned char** rows; unsigned int i; int bpp,type; int format; png_structp png; png_infop info; e_texture_t* texture; if(!e_checkpng(file)) return 0; png=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,(png_error_ptr)0,(png_error_ptr)0); if(!png) return 0; info=png_create_info_struct(png); if(!info) { png_destroy_read_struct(&png,0,0); return 0; } //Needed by libpng if(setjmp(png_jmpbuf(png))) { png_destroy_read_struct(&png,&info,0); if(rows) sys_free(rows); if(data) sys_free(data); return 0; } //Read up to image data png_set_read_fn(png,(png_voidp)file,e_readpng); png_set_sig_bytes(png,8); png_read_info(png,info); png_get_IHDR(png,info,&width,&height,&bpp,&type,0,0,0); if(width!=e_pow2(width)|| height!=e_pow2(height)) longjmp(png_jmpbuf(png),1); //Convert this image to fit the required format if(type==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if(type==PNG_COLOR_TYPE_GRAY|| type==PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if(type==PNG_COLOR_TYPE_GRAY||bpp<8) png_set_expand(png); if(png_get_valid(png,info,PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png); png_read_update_info(png,info); rowbytes=png_get_rowbytes(png,info); //Allocate memory to store the image data=(unsigned char*)sys_alloc(rowbytes*height); if(!data) longjmp(png_jmpbuf(png),1); rows=(unsigned char**)sys_alloc(sizeof(unsigned char*)*height); if(!rows) longjmp(png_jmpbuf(png),1); for(i=0;i<height;i++) rows[i]=data+(height-(i+1))*rowbytes; //Read png png_read_image(png,rows); png_read_end(png,0); sys_free(rows); texture=(e_texture_t*)sys_alloc(sizeof(e_texture_t)); texture->width=width; texture->height=height; glGenTextures(1,&texture->id); glBindTexture(GL_TEXTURE_2D,texture->id); texture->bpp=(type&PNG_COLOR_MASK_ALPHA)?32:24; format=(type&PNG_COLOR_MASK_ALPHA)?GL_RGBA:GL_RGB; glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); if(mipmaps) gluBuild2DMipmaps(GL_TEXTURE_2D,(type&PNG_COLOR_MASK_ALPHA)?4:3,texture->width,texture->height,format,GL_UNSIGNED_BYTE,data); else glTexImage2D(GL_TEXTURE_2D,0,format,texture->width,texture->height,0,format,GL_UNSIGNED_BYTE,data); sys_free(data); return texture; }
int svlImageCodecPNG::Read(svlSampleImage &image, const unsigned int videoch, const unsigned char *buffer, const size_t buffersize, bool noresize) { if (videoch >= image.GetVideoChannels()) return SVL_FAIL; if (!buffer || buffersize < static_cast<unsigned int>(PNG_SIG_SIZE)) return SVL_FAIL; // check file for signature if (png_sig_cmp(const_cast<unsigned char*>(buffer), 0, PNG_SIG_SIZE) != 0) return SVL_FAIL; // create read structure png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png_ptr == 0) return SVL_FAIL; // create info structure png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == 0) { png_destroy_read_struct(&png_ptr, reinterpret_cast<png_infopp>(0), reinterpret_cast<png_infopp>(0)); return SVL_FAIL; } // setup error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, reinterpret_cast<png_infopp>(0)); return SVL_FAIL; } _PNG_source_memory source; source.buffer = const_cast<unsigned char*>(buffer + PNG_SIG_SIZE); source.buffersize = static_cast<unsigned int>(buffersize - PNG_SIG_SIZE); source.error = false; png_set_read_fn(png_ptr, &source, PNG_read_data_memory); png_set_sig_bytes(png_ptr, PNG_SIG_SIZE); png_read_info(png_ptr, info_ptr); // check file header const unsigned int width = static_cast<unsigned int>(png_get_image_width(png_ptr, info_ptr)); const unsigned int height = static_cast<unsigned int>(png_get_image_height(png_ptr, info_ptr)); const unsigned int row_stride = width * 3; if (width < 1 || height < 1) return SVL_FAIL; // Allocate image buffer if not done yet if (static_cast<unsigned int>(width) != image.GetWidth(videoch) || static_cast<unsigned int>(height) != image.GetHeight(videoch)) { if (noresize) return SVL_FAIL; image.SetSize(videoch, static_cast<unsigned int>(width), static_cast<unsigned int>(height)); } // allocate row buffer if not done yet if (!pngRows) { pngRows = new unsigned char*[height]; pngRowsSize = height; } else if (pngRows && pngRowsSize < static_cast<unsigned int>(height)) { delete [] pngRows; pngRows = new unsigned char*[height]; pngRowsSize = height; } // generate row pointer array unsigned char *dest = image.GetUCharPointer(videoch); for (unsigned int i = 0; i < height; i ++) { pngRows[i] = dest; dest += row_stride; } const unsigned int bitdepth = static_cast<unsigned int>(png_get_bit_depth(png_ptr, info_ptr)); const unsigned int color_type = static_cast<unsigned int>(png_get_color_type(png_ptr, info_ptr)); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_GRAY: if (bitdepth < 8) { #if PNG_LIBPNG_VER >= 10300 png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif } break; } 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); } png_set_bgr(png_ptr); // read image png_read_image(png_ptr, pngRows); // read ending png_read_end(png_ptr, info_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) { // Gray8toRGB24 can do in-place conversion svlConverter::Gray8toRGB24(dest, dest, width * height); } // clean up png_destroy_read_struct(&png_ptr, &info_ptr,reinterpret_cast<png_infopp>(0)); return SVL_OK; }
ImageNode *LoadPNGImage(const char *fileName) { static ImageNode *result; static FILE *fd; static unsigned char **rows; static png_structp pngData; static png_infop pngInfo; static png_infop pngEndInfo; unsigned char header[8]; unsigned long rowBytes; int bitDepth, colorType; unsigned int x, y; png_uint_32 width; png_uint_32 height; Assert(fileName); result = NULL; fd = NULL; rows = NULL; pngData = NULL; pngInfo = NULL; pngEndInfo = NULL; fd = fopen(fileName, "rb"); if(!fd) { return NULL; } x = fread(header, 1, sizeof(header), fd); if(x != sizeof(header) || png_sig_cmp(header, 0, sizeof(header))) { fclose(fd); return NULL; } pngData = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if(JUNLIKELY(!pngData)) { fclose(fd); Warning(_("could not create read struct for PNG image: %s"), fileName); return NULL; } if(JUNLIKELY(setjmp(png_jmpbuf(pngData)))) { png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo); if(fd) { fclose(fd); } if(rows) { ReleaseStack(rows); } DestroyImage(result); Warning(_("error reading PNG image: %s"), fileName); return NULL; } pngInfo = png_create_info_struct(pngData); if(JUNLIKELY(!pngInfo)) { png_destroy_read_struct(&pngData, NULL, NULL); fclose(fd); Warning(_("could not create info struct for PNG image: %s"), fileName); return NULL; } pngEndInfo = png_create_info_struct(pngData); if(JUNLIKELY(!pngEndInfo)) { png_destroy_read_struct(&pngData, &pngInfo, NULL); fclose(fd); Warning("could not create end info struct for PNG image: %s", fileName); return NULL; } png_init_io(pngData, fd); png_set_sig_bytes(pngData, sizeof(header)); png_read_info(pngData, pngInfo); png_get_IHDR(pngData, pngInfo, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); result = CreateImage(width, height, 0); png_set_expand(pngData); if(bitDepth == 16) { png_set_strip_16(pngData); } else if(bitDepth < 8) { png_set_packing(pngData); } png_set_swap_alpha(pngData); png_set_filler(pngData, 0xFF, PNG_FILLER_BEFORE); if(colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(pngData); } png_read_update_info(pngData, pngInfo); rowBytes = png_get_rowbytes(pngData, pngInfo); rows = AllocateStack(result->height * sizeof(result->data)); y = 0; for(x = 0; x < result->height; x++) { rows[x] = &result->data[y]; y += rowBytes; } png_read_image(pngData, rows); png_read_end(pngData, pngInfo); png_destroy_read_struct(&pngData, &pngInfo, &pngEndInfo); fclose(fd); ReleaseStack(rows); rows = NULL; return result; }
Reference<Bitmap> StreamerPNG::loadBitmap(std::istream & input) { char header[8]; input.read(header, 8); const int is_png = !png_sig_cmp(reinterpret_cast<png_byte *>(header), 0, 8); if(!is_png) { WARN("File is not a valid PNG image."); return nullptr; } // Set up the necessary structures for libpng. png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if(!png_ptr) { return nullptr; } png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_read_struct(&png_ptr, static_cast<png_infopp>(nullptr), static_cast<png_infopp>(nullptr)); return nullptr; } if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, static_cast<png_infopp>(nullptr)); return nullptr; } struct PNGFunctions { static void readData(png_structp read_ptr, png_bytep data, png_size_t length) { std::istream * in = reinterpret_cast<std::istream *>(png_get_io_ptr(read_ptr)); if(in == nullptr || !in->good()) { png_error(read_ptr, "Error in input stream."); } in->read(reinterpret_cast<char *>(data), static_cast<std::streamsize>(length)); if(in->gcount() != static_cast<std::streamsize>(length)) { png_error(read_ptr, "Requested amount of data could not be extracted from input stream"); } } }; png_set_read_fn(png_ptr, reinterpret_cast<png_voidp>(&input), PNGFunctions::readData); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, nullptr, nullptr, nullptr); PixelFormat pixelFormat = PixelFormat::RGB; switch(color_type) { case PNG_COLOR_TYPE_GRAY: // Convert bpp less than 8 to 8 bits. if(bit_depth < 8) { png_set_expand_gray_1_2_4_to_8(png_ptr); } pixelFormat = PixelFormat::MONO; break; case PNG_COLOR_TYPE_GRAY_ALPHA: // Convert grayscale with alpha to RGBA. png_set_expand(png_ptr); png_set_gray_to_rgb(png_ptr); pixelFormat = PixelFormat::RGBA; break; case PNG_COLOR_TYPE_PALETTE: // Convert color palette to RGB(A). png_set_expand(png_ptr); // Check if the color palette contains transparent colors. #if PNG_LIBPNG_VER >= 10300 if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)){ pixelFormat = PixelFormat::RGBA; } #else if(info_ptr->valid & PNG_INFO_tRNS) { pixelFormat = PixelFormat::RGBA; } #endif break; case PNG_COLOR_TYPE_RGB_ALPHA: pixelFormat = PixelFormat::RGBA; break; default: // Already set to RGB above. break; } // Convert 16 bpp to 8 bits. if (bit_depth == 16) { png_set_strip_16(png_ptr); } // Create the bitmap to store the data. Reference<Bitmap> bitmap = new Bitmap(width, height, pixelFormat); auto row_pointers = new png_bytep[height]; const uint8_t bytes = pixelFormat.getBytesPerPixel(); for (uint_fast32_t row = 0; row < height; ++row) { // Take over rows in the same order. row_pointers[row] = reinterpret_cast<png_bytep>(bitmap->data() + row * width * bytes); } // This function automatically handles interlacing. png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, nullptr); png_destroy_read_struct(&png_ptr, &info_ptr, static_cast<png_infopp>(nullptr)); png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); delete [] row_pointers; return bitmap; }
static int lload(lua_State *L) { int top = lua_gettop(L); FILE *fp; struct png_source source; if (top == 1) { const char *filename = luaL_checkstring(L,1); fp = fopen(filename, "rb"); if (fp == NULL) { return luaL_error(L, strerror(errno)); } unsigned char header[PNGSIGSIZE]; if (fread(header, 1, PNGSIGSIZE, fp) != PNGSIGSIZE) { return luaL_error(L, "png invalid"); } if (png_sig_cmp(header, 0, PNGSIGSIZE)) { return luaL_error(L, "png sig invalid"); } fseek(fp, 0, SEEK_SET); } else if (top == 2) { luaL_checktype(L,1,LUA_TLIGHTUSERDATA); void *data = lua_touserdata(L,1); size_t size = luaL_checkinteger(L,2); if (size < PNGSIGSIZE) { return luaL_error(L, "png invalid"); } if (png_sig_cmp(data, 0, PNGSIGSIZE)) { return luaL_error(L, "png sig invalid"); } source.data = data; source.size = size; source.offset = 0; } else { return luaL_error(L, "invalid argument number"); } png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; int step;//, type; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { return 0; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 0; } if (top == 1) png_init_io(png_ptr, fp); else png_set_read_fn(png_ptr, (void *)&source, png_read_cb); //png_set_sig_bytes(png_ptr, PNGSIGSIZE); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { bit_depth = 8; png_set_expand_gray_1_2_4_to_8(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) png_set_tRNS_to_alpha(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (bit_depth < 8) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); switch (color_type) { case PNG_COLOR_TYPE_GRAY: // type = TEXTURE_DEPTH; step = 1; break; case PNG_COLOR_TYPE_RGB: //type = TEXTURE_RGB; step = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: //type = TEXTURE_RGBA; step = 4; break; default: return luaL_error(L, "png color type %d not support", color_type); } png_bytep *row_pointers = (png_bytep *)malloc(height * sizeof(png_bytep)); png_size_t rowbytes = png_get_rowbytes(png_ptr,info_ptr); size_t bytes = rowbytes * height; uint8_t *buffer = (uint8_t *)malloc(bytes); int i; for (i=0; i<height; ++i) { row_pointers[i] = buffer + i*rowbytes; } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(row_pointers); switch (color_type) { case PNG_COLOR_TYPE_GRAY: lua_pushliteral(L,"GRAY"); break; case PNG_COLOR_TYPE_RGB: lua_pushliteral(L,"RGB8"); break; case PNG_COLOR_TYPE_RGBA: lua_pushliteral(L,"RGBA8"); break; } lua_pushinteger(L,width); lua_pushinteger(L,height); int n = width * height * step; lua_createtable(L,n,0); for (i=0; i<n; ++i) { lua_pushinteger(L, buffer[i]); lua_rawseti(L, -2, i+1); } free(buffer); return 4; }
void LoadPNG (char *filename, byte **pic, int *width, int *height) { png_structp png; png_infop pnginfo; byte ioBuffer[8192]; int len; byte *raw; *pic=0; len = ri.FS_LoadFile (filename, (void **)&raw); if (!raw) { ri.Con_Printf (PRINT_DEVELOPER, "Bad png file %s\n", filename); return; } if( png_sig_cmp(raw,0,4)) return; png = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); if(!png) return; pnginfo = png_create_info_struct( png ); if(!pnginfo) { png_destroy_read_struct(&png,&pnginfo,0); return; } png_set_sig_bytes(png,0/*sizeof( sig )*/); mypng_struct_create(); // creates the my_png struct my_png->tmpBuf = raw; //buf = whole file content my_png->tmpi=0; png_set_read_fn(png,ioBuffer,fReadData ); png_read_info( png, pnginfo ); png_get_IHDR(png, pnginfo, &my_png->Width, &my_png->Height,&my_png->BitDepth, &my_png->ColorType, &my_png->Interlace, &my_png->Compression, &my_png->Filter ); // ...removed bgColor code here... if (my_png->ColorType == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png); if (my_png->ColorType == PNG_COLOR_TYPE_GRAY && my_png->BitDepth < 8) png_set_gray_1_2_4_to_8(png); // Add alpha channel if present if(png_get_valid( png, pnginfo, PNG_INFO_tRNS )) png_set_tRNS_to_alpha(png); // hax: expand 24bit to 32bit if (my_png->BitDepth == 8 && my_png->ColorType == PNG_COLOR_TYPE_RGB) png_set_filler(png,255, PNG_FILLER_AFTER); if (( my_png->ColorType == PNG_COLOR_TYPE_GRAY) || (my_png->ColorType == PNG_COLOR_TYPE_GRAY_ALPHA )) png_set_gray_to_rgb( png ); if (my_png->BitDepth < 8) png_set_expand (png); // update the info structure png_read_update_info( png, pnginfo ); my_png->FRowBytes = png_get_rowbytes( png, pnginfo ); my_png->BytesPerPixel = png_get_channels( png, pnginfo ); // DL Added 30/08/2000 InitializeDemData(); if((my_png->Data)&&(my_png->FRowPtrs)) png_read_image(png, (png_bytepp)my_png->FRowPtrs); png_read_end(png, pnginfo); // read last information chunks png_destroy_read_struct(&png, &pnginfo, 0); //only load 32 bit by now... if (my_png->BitDepth == 8) { *pic= my_png->Data; *width = my_png->Width; *height = my_png->Height; } else { ri.Con_Printf (PRINT_DEVELOPER, "Bad png color depth: %s\n", filename); *pic = NULL; free(my_png->Data); } mypng_struct_destroy(true); ri.FS_FreeFile ((void *)raw); }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; int color_type; int bit_depth; int pixel_depth = 0; // pixel_depth = bit_depth * channels FIBITMAP *dib = NULL; png_bytepp row_pointers = NULL; fi_ioStructure fio; fio.s_handle = handle; fio.s_io = io; if (handle) { BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; try { // check to see if the file is in fact a PNG file BYTE png_check[PNG_BYTES_TO_CHECK]; io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle); if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) { return NULL; // Bad signature } // create the chunk manage structure png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); if (!png_ptr) { return NULL; } // create the info structure 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; } // init the IO png_set_read_fn(png_ptr, &fio, _ReadProc); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } // because we have already read the signature... png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); // read the IHDR chunk png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); // configure the decoder FREE_IMAGE_TYPE image_type = FIT_BITMAP; if(!ConfigureDecoder(png_ptr, info_ptr, flags, &image_type)) { throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // update image info color_type = png_get_color_type(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); pixel_depth = bit_depth * png_get_channels(png_ptr, info_ptr); // create a dib and write the bitmap header // set up the dib palette, if needed switch (color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); break; case PNG_COLOR_TYPE_PALETTE: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); if(dib) { png_colorp png_palette = NULL; int palette_entries = 0; png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries); palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib)); // store the palette RGBQUAD *palette = FreeImage_GetPalette(dib); for(int i = 0; i < palette_entries; i++) { palette[i].rgbRed = png_palette[i].red; palette[i].rgbGreen = png_palette[i].green; palette[i].rgbBlue = png_palette[i].blue; } } break; case PNG_COLOR_TYPE_GRAY: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); if(dib && (pixel_depth <= 8)) { RGBQUAD *palette = FreeImage_GetPalette(dib); const int palette_entries = 1 << pixel_depth; for(int i = 0; i < palette_entries; i++) { palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = (BYTE)((i * 255) / (palette_entries - 1)); } } break; default: throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } if(!dib) { throw FI_MSG_ERROR_DIB_MEMORY; } // store the transparency table if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // array of alpha (transparency) entries for palette png_bytep trans_alpha = NULL; // number of transparent entries int num_trans = 0; // graylevel or color sample values of the single transparent color for non-paletted images png_color_16p trans_color = NULL; png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color); if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) { // single transparent color if (trans_color->gray < 256) { BYTE table[256]; memset(table, 0xFF, 256); table[trans_color->gray] = 0; FreeImage_SetTransparencyTable(dib, table, 256); } // check for a full transparency table, too else if ((trans_alpha) && (pixel_depth <= 8)) { FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); } } else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) { // transparency table FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); } } // store the background color (only supported for FIT_BITMAP types) if ((image_type == FIT_BITMAP) && png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) { // Get the background color to draw transparent and alpha images over. // 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_16p image_background = NULL; RGBQUAD rgbBkColor; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { rgbBkColor.rgbRed = (BYTE)image_background->red; rgbBkColor.rgbGreen = (BYTE)image_background->green; rgbBkColor.rgbBlue = (BYTE)image_background->blue; rgbBkColor.rgbReserved = 0; FreeImage_SetBackgroundColor(dib, &rgbBkColor); } } // get physical resolution if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { png_uint_32 res_x, res_y; // we'll overload this var and use 0 to mean no phys data, // since if it's not in meters we can't use it anyway int res_unit_type = PNG_RESOLUTION_UNKNOWN; png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type); if (res_unit_type == PNG_RESOLUTION_METER) { FreeImage_SetDotsPerMeterX(dib, res_x); FreeImage_SetDotsPerMeterY(dib, res_y); } } // get possible ICC profile if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_charp profile_name = NULL; png_bytep profile_data = NULL; png_uint_32 profile_length = 0; int compression_type; png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length); // copy ICC profile data (must be done after FreeImage_AllocateHeader) FreeImage_CreateICCProfile(dib, profile_data, profile_length); } // --- header only mode => clean-up and return if (header_only) { // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } // set the individual row_pointers to point at the correct offsets row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); if (!row_pointers) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); FreeImage_Unload(dib); return NULL; } // read in the bitmap bits via the pointer table // allow loading of PNG with minor errors (such as images with several IDAT chunks) for (png_uint_32 k = 0; k < height; k++) { row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); } png_set_benign_errors(png_ptr, 1); png_read_image(png_ptr, row_pointers); // check if the bitmap contains transparency, if so enable it in the header if (FreeImage_GetBPP(dib) == 32) { if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) { FreeImage_SetTransparent(dib, TRUE); } else { FreeImage_SetTransparent(dib, FALSE); } } // cleanup if (row_pointers) { free(row_pointers); row_pointers = NULL; } // read the rest of the file, getting any additional chunks in info_ptr png_read_end(png_ptr, info_ptr); // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } catch (const char *text) { if (png_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } if (row_pointers) { free(row_pointers); } if (dib) { FreeImage_Unload(dib); } FreeImage_OutputMessageProc(s_format_id, text); return NULL; } } return NULL; }
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load) { png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; double gamma; struct rtgui_image_png *png; png = (struct rtgui_image_png *) rtgui_malloc(sizeof(struct rtgui_image_png)); png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png->png_ptr == RT_NULL) { rtgui_free(png); return RT_FALSE; } png->info_ptr = png_create_info_struct(png->png_ptr); if (png->info_ptr == RT_NULL) { png_destroy_read_struct(&png->png_ptr, NULL, NULL); rtgui_free(png); return RT_FALSE; } png->filerw = file; png_set_read_fn(png->png_ptr, png->filerw, rtgui_image_png_read_data); png_read_info(png->png_ptr, png->info_ptr); png_get_IHDR(png->png_ptr, png->info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); /* set image information */ image->w = width; image->h = height; image->engine = &rtgui_image_png_engine; image->data = png; if (bit_depth == 16) png_set_strip_16(png->png_ptr); if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand(png->png_ptr); if (bit_depth < 8) png_set_expand(png->png_ptr); if (png_get_valid(png->png_ptr, png->info_ptr, PNG_INFO_tRNS)) png_set_expand(png->png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png->png_ptr); /* Ignore background color */ /* set gamma conversion */ if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma)) png_set_gamma(png->png_ptr, (double)2.2, gamma); png_read_update_info(png->png_ptr, png->info_ptr); if (load == RT_TRUE) { /* load all pixels */ png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t)); if (png->pixels == RT_NULL) { png_read_end(png->png_ptr, RT_NULL); /* destroy png struct */ png_destroy_info_struct(png->png_ptr, &png->info_ptr); png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL); /* release data */ rtgui_free(png); return RT_FALSE; } rtgui_image_png_process(png->png_ptr, png->info_ptr, png); } else { png->pixels = RT_NULL; } return RT_TRUE; }