long PngReadFileToPixmap (Display* display, Window window, GC gc, char* filename, Pixmap* pixmap, long* w, long* h) { int red_mask, green_mask, blue_mask; int red_shift, green_shift, blue_shift; int start_shift, msb_flag; unsigned int start_mask, udat; XWindowAttributes win_attr; FILE* ifile; long display_depth; png_byte sig[8]; png_infop info_ptr; png_structp png_ptr; png_uint_32 png_width; png_uint_32 png_height; int png_depth; int png_color_type; png_uint_32 png_row_bytes; png_uint_32 png_channels; long rwidth; long rheight; long components; unsigned char* buf; png_byte** png_row_ptrs; long vwidth; long vheight; long stretched; XImage* image; Visual* visual; Pixmap pix; int i; char* data1; unsigned char r,g,b; long ptr = 0; long ptr2 = 0; long j; red_mask = green_mask = blue_mask = 0; red_shift = green_shift = blue_shift = 0; ifile = fopen(filename,"r"); if (ifile == NULL){ return -1; } display_depth = XDefaultDepth(display,XDefaultScreen(display)); fread(sig, 1, 8, ifile); if (png_sig_cmp(sig, 0, 8)){ fclose(ifile); return -1; } png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); if (png_ptr == NULL){ fclose(ifile); return -1; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL){ png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(ifile); return -1; } png_init_io(png_ptr, ifile); png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &png_depth, &png_color_type, NULL, NULL, NULL); if (png_depth == 16){ png_set_strip_16(png_ptr); } png_row_bytes = png_get_rowbytes(png_ptr, info_ptr); png_channels = png_get_channels(png_ptr, info_ptr); if (png_depth < 8){ if (png_color_type == PNG_COLOR_TYPE_GRAY ){ png_set_expand_gray_1_2_4_to_8(png_ptr); png_row_bytes = png_width; }else{ png_set_expand(png_ptr); png_row_bytes = png_width; png_row_bytes = png_width * 3; png_channels = 3; } } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)){ png_set_expand(png_ptr); png_row_bytes = png_width; } if (png_color_type == PNG_COLOR_TYPE_GRAY || png_color_type == PNG_COLOR_TYPE_GRAY_ALPHA){ png_set_gray_to_rgb(png_ptr); png_row_bytes = png_width; } if (png_color_type == PNG_COLOR_TYPE_PALETTE){ png_set_palette_to_rgb(png_ptr); png_row_bytes = png_width * 3; png_channels = 3; } rwidth = png_width; rheight = png_height; components = png_channels; /* possible integer overflow? */ assert ((int) png_row_bytes > 0); assert ((int) png_height > 0); assert (((int)png_row_bytes) * ((int)png_height) * sizeof(png_byte) > 0); buf = rxvt_malloc(png_row_bytes * png_height * sizeof(png_byte)); if (buf == NULL){ rxvt_msg (DBG_ERROR, DBG_IMAGES, "png read error: out of memory..\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(ifile); return -1; } /* possible integer overflow? */ assert ((int) png_height > 0); assert (sizeof(png_bytep) * ((int)png_height) > 0); png_row_ptrs = rxvt_malloc (sizeof(png_bytep)*png_height); if (png_row_ptrs == NULL){ rxvt_msg (DBG_ERROR, DBG_IMAGES, "png read error: out of memory..\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(ifile); return -1; } for(i = 0; i < (int)png_height; i++){ png_row_ptrs[i] = (png_byte*)(buf + i * png_row_bytes); } png_read_image(png_ptr, png_row_ptrs); png_read_end(png_ptr,NULL); rxvt_free(png_row_ptrs); vwidth = *w; vheight = *h; stretched =0; if (*w == 0 || *h == 0){ *w = rwidth; *h = rheight; }else{ if ((long)((double)rwidth * vheight/vwidth) < rheight){ *w = (long)((double)vheight * rwidth/rheight); }else{ *h = (long)((double)vwidth * rheight/rwidth); } stretched = 1; } vwidth = *w; vheight = *h; image = 0; visual = XDefaultVisual(display,XDefaultScreen(display)); if (display_depth >16){ image = XCreateImage(display,visual, display_depth, ZPixmap,0,0,vwidth,vheight,32,0); }else if (display_depth >8){ image = XCreateImage(display,visual, display_depth, ZPixmap,0,0,vwidth,vheight,16,0); }else{ image = XCreateImage(display,visual, display_depth, ZPixmap,0,0,vwidth,vheight,8,0); } msb_flag = (ImageByteOrder(display) == MSBFirst)?1:0; if (XGetWindowAttributes(display, RootWindow(display, DefaultScreen(display)), &win_attr) == 0) { fclose(ifile); return -1; } if ((win_attr.depth == 24) || (win_attr.depth == 16)) { unsigned int n; if (win_attr.depth == 24) { start_shift = 24; start_mask = 0x80000000; }else{ start_shift = 8; start_mask = 0x8000; } red_mask = win_attr.visual->red_mask; red_shift = start_shift; n = start_mask; while (!(n & red_mask)) { n >>= 1; red_shift--; } green_mask = win_attr.visual->green_mask; green_shift = start_shift; n = start_mask; while (!(n & green_mask)) { n >>= 1; green_shift--; } blue_mask = win_attr.visual->blue_mask; blue_shift = start_shift; n = start_mask; while (!(n & blue_mask)) { n >>= 1; blue_shift--; } }
unsigned char *sdlgl_load_png_file(const char *filename, int *image_w, int *image_h) { /* -AJA- all these volatiles here may seem strange. They are needed * because the ANSI C standard (which GCC adheres to) says that when * setjmp/longjmp is being used, only volatile local variables are * guaranteed to keep their state if longjmp() gets called. */ FILE * volatile fp = NULL; unsigned char * volatile image_dat = NULL; png_bytep * volatile row_pointers = NULL; /* we take the address of these two, so we shouldn't need the * volatile. (GCC complains about discarding qualifiers if the * volatile is there). */ png_structp /*volatile*/ png_ptr = NULL; png_infop /*volatile*/ info_ptr = NULL; char sig_buf[CHECK_PNG_BYTES]; png_uint_32 width, height; int bit_depth, color_type, interlace_type; int row, stride; /* open the prospective PNG file */ #ifdef FILE_AREAS fp = fopen_datafile_area(FILE_AREA_SHARE, filename, RDBMODE, FALSE); #else fp = fopen_datafile(filename, RDBMODE, FALSE); #endif if (!fp) { sdlgl_warning("Failed to open file: %s\n", filename); return NULL; } /* read in some of the signature bytes */ if (fread(sig_buf, 1, CHECK_PNG_BYTES, fp) != CHECK_PNG_BYTES) { sdlgl_warning("Failed to read from file: %s\n", filename); goto failed; } /* compare the first CHECK_PNG_BYTES bytes of the signature */ if (png_sig_cmp(sig_buf, (png_size_t)0, CHECK_PNG_BYTES) != 0) { sdlgl_warning("File is not a PNG file: %s\n", filename); goto failed; } /* pass NULLs for the error functions -- thus use the setjump stuff */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { sdlgl_warning("Problem within LibPNG (no memory ?)\n"); goto failed; } /* allocate/initialize the memory for image information */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { sdlgl_warning("Out of memory with LibPNG\n"); goto failed; } /* set error handling since we are using the setjmp/longjmp method * (this is the normal method of doing things with libpng). */ if (setjmp(png_ptr->jmpbuf)) { sdlgl_warning("Problem within LibPNG (unknown)\n"); goto failed; } /* set up the input control since we're using standard C streams */ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, CHECK_PNG_BYTES); /* the call to 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); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); *image_w = (int)width; *image_h = (int)height; /* tell libpng to strip 16 bit/color down to 8 bits/color */ png_set_strip_16(png_ptr); /* expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE || color_type == PNG_COLOR_TYPE_GRAY || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); } /* set alpha position and filler value */ png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); /* let all the above calls take effect */ png_read_update_info(png_ptr, info_ptr); /* allocate the memory for the image */ stride = png_get_rowbytes(png_ptr, info_ptr); image_dat = (unsigned char *) alloc(height * stride); row_pointers = (png_bytep *) alloc(height * sizeof(png_bytep)); for (row=0; row < height; row++) { row_pointers[row] = image_dat + row * stride; } /* now read in the image. Yeah baby ! */ png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, info_ptr); /* free stuff & close the file */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); free(row_pointers); fclose(fp); return image_dat; /* -AJA- Normally I don't like gotos. In this situation where there * are lots of points of possible failure and a growing set of * things to be undone, it makes for nicer code. */ failed: if (image_dat) free(image_dat); if (png_ptr) { /* assume NULLs not allowed (png docs don't say, bad bad) */ if (info_ptr) png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); else png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); } if (row_pointers) free(row_pointers); if (fp) fclose(fp); return NULL; }
//int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) { int pngLoadRaw(const char* filename, pngRawInfo *pinfo, vsxf* filesystem) { unsigned char header[8]; png_structp png; png_infop info; png_infop endinfo; png_bytep data; png_bytep *row_p; double fileGamma; vsxf_info i_filesystem; png_uint_32 width, height; int depth, color; png_uint_32 i; if (pinfo == NULL) { printf("error in png loader: pinfo is NULL %d\n",__LINE__); return 0; } i_filesystem.filesystem = filesystem; i_filesystem.fp = filesystem->f_open(filename,"rb"); if (!i_filesystem.fp) { printf("error in png loader: i_filesystem.fp not valid on line %d\n",__LINE__); return 0; } filesystem->f_read(header, 8, i_filesystem.fp); if (!png_check_sig(header, 8)) { printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } info = png_create_info_struct(png); if (!info) { png_destroy_read_struct(&png,(png_infopp)NULL,(png_infopp)NULL); printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } endinfo = png_create_info_struct(png); if (!endinfo) { png_destroy_read_struct(&png, &info, (png_infopp)NULL); printf("error in %s on line %d\n",__FILE__,__LINE__); return 0; } if (setjmp(png_jmpbuf(png))) { printf("error in png_jmpbuf %s on line %d\n",__FILE__,__LINE__); png_destroy_read_struct(&png, &info,&endinfo); filesystem->f_close(i_filesystem.fp); return 0; } png_set_read_fn(png, (png_bytep)(&i_filesystem), png_vsxf_read_data); png_set_sig_bytes(png, 8); png_read_info(png, info); png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); pinfo->Width = width; pinfo->Height = height; pinfo->Depth = depth; if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png); if (color == PNG_COLOR_TYPE_PALETTE) png_set_expand(png); /*--GAMMA--*/ checkForGammaEnv(); if (png_get_gAMA(png, info, &fileGamma)) png_set_gamma(png, screenGamma, fileGamma); else png_set_gamma(png, screenGamma, 1.0/2.2); png_read_update_info(png, info); data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); for (i = 0; i < height; i++) { if (StandardOrientation) row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; else row_p[i] = &data[png_get_rowbytes(png, info)*i]; } png_read_image(png, row_p); free(row_p); if (color == PNG_COLOR_TYPE_PALETTE) { int cols; png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols); } else { pinfo->Palette = NULL; } if (color&PNG_COLOR_MASK_ALPHA) { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA) pinfo->Components = 2; else pinfo->Components = 4; pinfo->Alpha = 8; } else { if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY) pinfo->Components = 1; else pinfo->Components = 3; pinfo->Alpha = 0; } pinfo->Data = data; png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); filesystem->f_close(i_filesystem.fp); return 1; }
bool PNGDecoder::LoadFile(const std::string &filename, DecodedFrames &frames) { png_byte header[8]; RGBAImage *ret = NULL; CFile fp; if (!fp.Open(filename)) { perror(filename.c_str()); return false; } // read the header fp.Read(header, 8); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", filename.c_str()); return false; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); return false; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); return false; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return false; } // init png reading png_init_io(png_ptr, fp.getFP()); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); } //set it to 32bit pixeldepth png_color_8 sig_bit; sig_bit.red = 32; sig_bit.green = 32; sig_bit.blue = 32; // if the image has an alpha channel then sig_bit.alpha = 32; png_set_sBIT(png_ptr, info_ptr, &sig_bit); /* Add filler (or alpha) byte (before/after each RGB triplet) */ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ //png_set_swap_alpha(png_ptr); // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned // rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; image_data = (png_byte*)new png_byte[rowbytes * temp_height * sizeof(png_byte)+15]; if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return false; } // row_pointers is for pointing to image_data for reading the png with libpng png_bytep * row_pointers = (png_bytep*) new png_bytep[temp_height * sizeof(png_bytep)]; if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] image_data; return false; } // set the individual row_pointers to point at the correct offsets of image_data for (unsigned int i = 0; i < temp_height; i++) { row_pointers[i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); frames.user = NULL; DecodedFrame frame; frame.rgbaImage.pixels = (char *)image_data; frame.rgbaImage.height = temp_height; frame.rgbaImage.width = temp_width; frame.rgbaImage.bbp = 32; frame.rgbaImage.pitch = 4 * temp_width; frames.frameList.push_back(frame); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] row_pointers; return true; }
ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) { struct ImBuf *ibuf = NULL; png_structp png_ptr; png_infop info_ptr; unsigned char *pixels = NULL; unsigned short *pixels16 = NULL; png_bytepp row_pointers = NULL; png_uint_32 width, height; int bit_depth, color_type; PNGReadStruct ps; unsigned char *from, *to; unsigned short *from16; float *to_float; int i, bytesperpixel; if (imb_is_a_png(mem) == 0) return(NULL); /* both 8 and 16 bit PNGs are default to standard byte colorspace */ colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); 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; } png_set_error_fn(png_ptr, NULL, imb_png_error, imb_png_warning); 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 (pixels16) MEM_freeN(pixels16); 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); 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); break; } ibuf = IMB_allocImBuf(width, height, 8 * bytesperpixel, 0); if (ibuf) { ibuf->ftype = PNG; if (bit_depth == 16) ibuf->ftype |= PNG_16BIT; 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)) { if (bit_depth == 16) { imb_addrectfloatImBuf(ibuf); png_set_swap(png_ptr); pixels16 = MEM_mallocN(ibuf->x * ibuf->y * bytesperpixel * sizeof(png_uint_16), "pixels"); if (pixels16 == 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_uint_16p), "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) ((png_uint_16 *)pixels16 + (i * ibuf->x) * bytesperpixel); } png_read_image(png_ptr, row_pointers); /* copy image data */ to_float = ibuf->rect_float; from16 = pixels16; switch (bytesperpixel) { case 4: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = from16[0] / 65535.0; to_float[1] = from16[1] / 65535.0; to_float[2] = from16[2] / 65535.0; to_float[3] = from16[3] / 65535.0; to_float += 4; from16 += 4; } break; case 3: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = from16[0] / 65535.0; to_float[1] = from16[1] / 65535.0; to_float[2] = from16[2] / 65535.0; to_float[3] = 1.0; to_float += 4; from16 += 3; } break; case 2: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; to_float[3] = from16[1] / 65535.0; to_float += 4; from16 += 2; } break; case 1: for (i = ibuf->x * ibuf->y; i > 0; i--) { to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0; to_float[3] = 1.0; to_float += 4; from16++; } break; } } else { 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 */ if (pixels) MEM_freeN(pixels); if (pixels16) MEM_freeN(pixels16); if (row_pointers) MEM_freeN(row_pointers); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return(ibuf); }
/** * @brief Reads a PNG image into a surface. * * @param npng PNG image to load. * @return Surface with data from the PNG image. */ SDL_Surface *npng_readSurface( npng_t *npng, int pad_pot, int vflip ) { png_bytep *row_pointers; png_uint_32 width, height, row, rheight; SDL_Surface *surface; int channels; Uint32 Rmask, Gmask, Bmask, Amask; int bit_depth, color_type, interlace_type; /* Read information. */ channels = png_get_channels( npng->png_ptr, npng->info_ptr ); png_get_IHDR( npng->png_ptr, npng->info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL ); /* Pad POT if needed. */ rheight = height; if (pad_pot) { width = gl_pot( width ); height = gl_pot( height ); } /* Allocate the SDL surface to hold the image */ if (SDL_BYTEORDER == SDL_LIL_ENDIAN) { Rmask = 0x000000FF; Gmask = 0x0000FF00; Bmask = 0x00FF0000; Amask = (channels == 4) ? 0xFF000000 : 0; } else { int s = (channels == 4) ? 0 : 8; Rmask = 0xFF000000 >> s; Gmask = 0x00FF0000 >> s; Bmask = 0x0000FF00 >> s; Amask = 0x000000FF >> s; } surface = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, bit_depth*channels, Rmask, Gmask, Bmask, Amask ); if (surface == NULL) { ERR( "Out of Memory" ); return NULL; } /*if (bit_depth*channels < npng_pitch( npng )) DEBUG(" %d / %d ", bit_depth*channels, npng_pitch( npng ) );*/ /* Create the array of pointers to image data */ row_pointers = malloc( sizeof(png_bytep) * rheight ); if (row_pointers == NULL) { ERR( "Out of Memory" ); return NULL; } for (row=0; row<rheight; row++) { /* We only need to go to real height, not full height. */ row_pointers[ vflip ? rheight-row-1 : row ] = (png_bytep) (Uint8 *) surface->pixels + row * surface->pitch; } /* Load the data. */ npng_readInto( npng, row_pointers ); /* Free rows. */ free( row_pointers ); return surface; }
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; }
static void read_png(unsigned char** block, unsigned* width, unsigned* height, FILE* file, const int base_img_size) { png_structp png_ptr; png_infop info_ptr; png_bytep* row_pointers; unsigned row, x, y; int rowbytes; char* dst; //png_uint_32 is 64 bit on some architectures! png_uint_32 widthpu32,heightpu32; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); if (png_ptr == NULL) { printf("read_png: Could not create read struct.\n"); exit(1); } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { printf("read_png: Could not create info struct.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); exit(1); } if (setjmp(png_ptr->jmpbuf)) { printf("read_png: fatal error.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_info**)0); /* free pointers before returning, if necessary */ free(png_ptr); free(info_ptr); exit(1); } /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, file); /* 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, &widthpu32, &heightpu32, &bit_depth, &color_type, &interlace_type, NULL, NULL ); *width = widthpu32; *height = heightpu32; if (*height % base_img_size != 0 || *width % base_img_size != 0) { printf("read_png: Invalid image size.\n"); exit(1); } // printf("read_png: width=%d, height=%d, bit_depth=%d\n", width, height, bit_depth); // printf("read_png: color_type=%d, interlace_type=%d\n", color_type, interlace_type); /* 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); /* Expand paletted colors into true RGB triplets */ png_set_expand(png_ptr); png_start_read_image(png_ptr); /* The easiest way to read the image: */ rowbytes = png_get_rowbytes(png_ptr, info_ptr) * 3; row_pointers = malloc(*height * sizeof(*row_pointers)); row_pointers[0] = malloc(rowbytes * *height * 2); for (row = 1; row < *height; row++) { row_pointers[row] = row_pointers[row - 1] + rowbytes * 2; } /* Read the entire image in one go */ png_read_image(png_ptr, row_pointers); // we use fixed height here because block is of limited, fixed size // not fixed any more *block = realloc(*block, *height * *width * 6); // *block = malloc(*height * *width * 6); dst = *block; for (y = 0; y < *height; y++) { for (x = 0; x < *width * 3; x++) { *dst++ = row_pointers[y][x]; // *dst++ = 0; } } free(row_pointers[0]); free(row_pointers); /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); /* At this point you have read the entire image */ /* clean up after the read, and free any memory allocated - REQUIRED */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); }
bool R9_ImgReadPNG( F9FILE file, r9Img* img ) { if(file==NULL || img==NULL) return false; R9_ImgDestroy(img); // check png sig const int headersize = 8; byte header[headersize]; if(file->Read( header, headersize) != headersize) return false; BOOL ispng = png_check_sig(header, headersize) != 0; if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; } // create png structures png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, NULL, R9_ImgPNG_FatalError, R9_ImgPNG_Warning, NULL, R9_ImgPNG_Malloc, R9_ImgPNG_Free ); if(png_ptr==NULL) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } png_infop end_info = png_create_info_struct(png_ptr); if(end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return false; } // set global file r9_imgpng_file = file; png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData); // read off the info on the image png_set_sig_bytes(png_ptr, headersize); png_read_info(png_ptr, info_ptr); png_uint_32 pngwidth; png_uint_32 pngheight; int32 pngbits; int32 pngpf; png_get_IHDR(png_ptr, info_ptr, &pngwidth, &pngheight, &pngbits, &pngpf, NULL, // interlace NULL, // compression_type NULL); // filter_type BOOL alpha = FALSE; img->m_width = pngwidth; img->m_height = pngheight; img->m_pf = R9_PF_RGB; assert(img->m_width!=0 && img->m_height!=0); // Strip off any 16 bit info if(pngbits==16) png_set_strip_16(png_ptr); // Expand a transparency channel into a full alpha channel... if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); alpha = TRUE; } if( pngpf == PNG_COLOR_TYPE_RGB) { png_set_expand(png_ptr); img->m_pf = alpha ? R9_PF_ARGB : R9_PF_RGB; } else if( pngpf == PNG_COLOR_TYPE_RGB_ALPHA) { png_set_expand(png_ptr); img->m_pf = R9_PF_ARGB; } else { elog::rnd() << "png wrong color format" << std::endl; png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return false; } // Update the info pointer with the result of the transformations above... png_read_update_info(png_ptr, info_ptr); png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr); if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*3); else if(img->m_pf==R9_PF_RGB) assert(rowbytes==img->m_width*4); // create image R9_ImgCreate(img); // set up the row pointers... png_bytep* rowpointers = new png_bytep[img->m_height]; for(int i=0; i<img->m_height; i++) rowpointers[i] = img->m_data + (i*rowbytes); // read image png_read_image(png_ptr, rowpointers); // release png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete [] rowpointers; r9_imgpng_file = NULL; R9_ImgFlipRGB(img); // it was BGR, we want it RGB ! return true; }
static int read_png(FILE *fp, png_bytepp buffer, int32_t *bpp, int32_t *width, int32_t *height) { png_structp png_ptr; png_infop info; png_uint_32 w; png_uint_32 h; png_bytep *rows; int bit_depth; int32_t color_type; int row; int rowsize; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) return FALSE; info = png_create_info_struct(png_ptr); if (info == NULL) { png_destroy_read_struct(&png_ptr, NULL, NULL); return FALSE; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info, NULL); return FALSE; } png_init_io(png_ptr, fp); png_read_info(png_ptr, info); png_get_IHDR(png_ptr, info, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); switch (color_type) { case PNG_COLOR_TYPE_GRAY: #ifdef PNG2ICNS_EXPAND_GRAY png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } png_set_gray_to_rgb(png_ptr); png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_GRAY_ALPHA: #ifdef PNG2ICNS_EXPAND_GRAY png_set_expand_gray_1_2_4_to_8(png_ptr); #else png_set_gray_1_2_4_to_8(png_ptr); #endif if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); if (png_get_valid(png_ptr, info, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); else png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_RGB: if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_RGB_ALPHA: if (bit_depth == 16) { png_set_strip_16(png_ptr); bit_depth = 8; } break; } *width = w; *height = h; *bpp = bit_depth * 4; png_read_update_info(png_ptr, info); rowsize = png_get_rowbytes(png_ptr, info); rows = malloc (sizeof(png_bytep) * h); *buffer = malloc(rowsize * h + 8); rows[0] = *buffer; for (row = 1; row < h; row++) { rows[row] = rows[row-1] + rowsize; } png_read_image(png_ptr, rows); png_destroy_read_struct(&png_ptr, &info, NULL); free(rows); return TRUE; }
GLuint loadPNG(const char * file_name, GLuint tex) { png_byte header[8]; FILE *fp = fopen(file_name, "rb"); if (fp == 0) { perror(file_name); return 0; } // read the header fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { fprintf(stderr, "error: %s is not a PNG.\n", file_name); fclose(fp); return 0; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) { fprintf(stderr, "error: png_create_read_struct returned 0.\n"); fclose(fp); return 0; } // create png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(fp); return 0; } // create png info struct png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { fprintf(stderr, "error: png_create_info_struct returned 0.\n"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL); fclose(fp); return 0; } // the code in this if statement gets called if libpng encounters an error if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "error from libpng\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // init png reading png_init_io(png_ptr, fp); // let libpng know you already read the first 8 bytes png_set_sig_bytes(png_ptr, 8); // read all the info up to the image data png_read_info(png_ptr, info_ptr); // variables to pass to get info int bit_depth, color_type; png_uint_32 temp_width, temp_height; // get info about png png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type, NULL, NULL, NULL); GLint format; switch(color_type) { case PNG_COLOR_TYPE_RGB: format = GL_RGB; break; case PNG_COLOR_TYPE_RGB_ALPHA: format = GL_RGBA; break; case PNG_COLOR_TYPE_GRAY: //cout<<"color Type Grey"<<endl; format = GL_RGBA; png_set_gray_to_rgb(png_ptr); png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); break; case PNG_COLOR_TYPE_GRAY_ALPHA: //cout<<"color Type Grey Alpha"<<endl; format = GL_RGBA; png_set_gray_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_PALETTE: //cout<<"color Type Palette"<<endl; format = GL_RGBA; png_set_palette_to_rgb(png_ptr); png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); //return 0; break; default: fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type); return 0; } // Update the png info struct. png_read_update_info(png_ptr, info_ptr); // Row size in bytes. int rowbytes = png_get_rowbytes(png_ptr, info_ptr); // glTexImage2d requires rows to be 4-byte aligned rowbytes += 3 - ((rowbytes-1) % 4); // Allocate the image_data as a big block, to be given to opengl png_byte * image_data; //image_data = (png_byte*) malloc(rowbytes * temp_height * sizeof(png_byte)+15); image_data = new png_byte[rowbytes * temp_height]; if (image_data == NULL) { fprintf(stderr, "error: could not allocate memory for PNG image data\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return 0; } // row_pointers is for pointing to image_data for reading the png with libpng //png_bytep * row_pointers = (png_bytep*) malloc(temp_height * sizeof(png_bytep)); png_bytep * row_pointers = new png_bytep[temp_height]; if (row_pointers == NULL) { fprintf(stderr, "error: could not allocate memory for PNG row pointers\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(image_data); fclose(fp); return 0; } // set the individual row_pointers to point at the correct offsets of image_data int i; for (i = 0; i < temp_height; i++) { row_pointers[/*temp_height - 1 - */i] = image_data + i * rowbytes; } // read the png into image_data through row_pointers png_read_image(png_ptr, row_pointers); glBindTexture(GL_TEXTURE_2D, tex); glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // clean up png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); delete[] image_data; delete[] row_pointers; fclose(fp); return tex; }
bool wxPNGHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int WXUNUSED(index)) { // VZ: as this function uses setjmp() the only fool-proof error handling // method is to use goto (setjmp is not really C++ dtors friendly...) unsigned char **lines = NULL; png_infop info_ptr = (png_infop) NULL; wxPNGInfoStruct wxinfo; png_uint_32 i, width, height = 0; int bit_depth, color_type, interlace_type; wxinfo.verbose = verbose; wxinfo.stream.in = &stream; image->Destroy(); png_structp png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING, NULL, wx_PNG_error, wx_PNG_warning ); if (!png_ptr) goto error; // NB: please see the comment near wxPNGInfoStruct declaration for // explanation why this line is mandatory png_set_read_fn( png_ptr, &wxinfo, wx_PNG_stream_reader); info_ptr = png_create_info_struct( png_ptr ); if (!info_ptr) goto error; if (setjmp(wxinfo.jmpbuf)) goto error; 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_expand( png_ptr ); // Fix for Bug [ 439207 ] Monochrome PNG images come up black if (bit_depth < 8) png_set_expand( png_ptr ); png_set_strip_16( png_ptr ); png_set_packing( png_ptr ); if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr ); png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER ); image->Create((int)width, (int)height, (bool) false /* no need to init pixels */); if (!image->IsOk()) goto error; // initialize all line pointers to NULL to ensure that they can be safely // free()d if an error occurs before all of them could be allocated lines = (unsigned char **)calloc(height, sizeof(unsigned char *)); if ( !lines ) goto error; for (i = 0; i < height; i++) { if ((lines[i] = (unsigned char *)malloc( (size_t)(width * 4))) == NULL) goto error; } png_read_image( png_ptr, lines ); png_read_end( png_ptr, info_ptr ); #if wxUSE_PALETTE if (color_type == PNG_COLOR_TYPE_PALETTE) { png_colorp palette = NULL; int numPalette = 0; (void) png_get_PLTE(png_ptr, info_ptr, &palette, &numPalette); unsigned char* r = new unsigned char[numPalette]; unsigned char* g = new unsigned char[numPalette]; unsigned char* b = new unsigned char[numPalette]; for (int j = 0; j < numPalette; j++) { r[j] = palette[j].red; g[j] = palette[j].green; b[j] = palette[j].blue; } image->SetPalette(wxPalette(numPalette, r, g, b)); delete[] r; delete[] g; delete[] b; } #endif // wxUSE_PALETTE // set the image resolution if it's available png_uint_32 resX, resY; int unitType; if (png_get_pHYs(png_ptr, info_ptr, &resX, &resY, &unitType) == PNG_INFO_pHYs) { wxImageResolution res = wxIMAGE_RESOLUTION_CM; switch (unitType) { default: wxLogWarning(_("Unknown PNG resolution unit %d"), unitType); wxFALLTHROUGH; case PNG_RESOLUTION_UNKNOWN: image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, resX); image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, resY); res = wxIMAGE_RESOLUTION_NONE; break; case PNG_RESOLUTION_METER: /* Convert meters to centimeters. Use a string to not lose precision (converting to cm and then to inch would result in integer rounding error). If an app wants an int, GetOptionInt will convert and round down for them. */ image->SetOption(wxIMAGE_OPTION_RESOLUTIONX, wxString::FromCDouble((double) resX / 100.0, 2)); image->SetOption(wxIMAGE_OPTION_RESOLUTIONY, wxString::FromCDouble((double) resY / 100.0, 2)); break; } image->SetOption(wxIMAGE_OPTION_RESOLUTIONUNIT, res); } png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL ); // loaded successfully, now init wxImage with this data CopyDataFromPNG(image, lines, width, height, color_type); for ( i = 0; i < height; i++ ) free( lines[i] ); free( lines ); return true; error: if (verbose) { wxLogError(_("Couldn't load a PNG image - file is corrupted or not enough memory.")); } if ( image->IsOk() ) { image->Destroy(); } if ( lines ) { for ( unsigned int n = 0; n < height; n++ ) free( lines[n] ); free( lines ); } if ( png_ptr ) { if ( info_ptr ) { png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL ); free(info_ptr); } else png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL ); } return false; }
bool CCImage::_initWithPngData(void * pData, int nDatalen) { bool bRet = false; png_byte header[8] = {0}; png_structp png_ptr = 0; png_infop info_ptr = 0; unsigned char * pImateData = 0; do { // png header len is 8 bytes CC_BREAK_IF(nDatalen < 8); // check the data is png or not memcpy(header, pData, 8); CC_BREAK_IF(png_sig_cmp(header, 0, 8)); // init png_struct png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); CC_BREAK_IF(! png_ptr); // init png_info info_ptr = png_create_info_struct(png_ptr); CC_BREAK_IF(!info_ptr || setjmp(png_jmpbuf(png_ptr))); // set the read call back function tImageSource imageSource; imageSource.data = (unsigned char*)pData; imageSource.size = nDatalen; imageSource.offset = 0; png_set_read_fn(png_ptr, &imageSource, pngReadCallback); // read png // PNG_TRANSFORM_EXPAND: perform set_expand() // PNG_TRANSFORM_PACKING: expand 1, 2 and 4-bit samples to bytes // PNG_TRANSFORM_STRIP_16: strip 16-bit samples to 8 bits // PNG_TRANSFORM_GRAY_TO_RGB: expand grayscale samples to RGB (or GA to RGBA) png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_GRAY_TO_RGB, 0); int color_type = 0; png_uint_32 nWidth = 0; png_uint_32 nHeight = 0; int nBitsPerComponent = 0; png_get_IHDR(png_ptr, info_ptr, &nWidth, &nHeight, &nBitsPerComponent, &color_type, 0, 0, 0); // init image info m_bPreMulti = true; m_bHasAlpha = ( info_ptr->color_type & PNG_COLOR_MASK_ALPHA ) ? true : false; // allocate memory and read data int bytesPerComponent = 3; if (m_bHasAlpha) { bytesPerComponent = 4; } pImateData = new unsigned char[nHeight * nWidth * bytesPerComponent]; CC_BREAK_IF(! pImateData); png_bytep * rowPointers = png_get_rows(png_ptr, info_ptr); // copy data to image info int bytesPerRow = nWidth * bytesPerComponent; if(m_bHasAlpha) { unsigned int *tmp = (unsigned int *)pImateData; for(unsigned int i = 0; i < nHeight; i++) { for(int j = 0; j < bytesPerRow; j += 4) { *tmp++ = CC_RGB_PREMULTIPLY_APLHA( rowPointers[i][j], rowPointers[i][j + 1], rowPointers[i][j + 2], rowPointers[i][j + 3] ); } } } else { for (unsigned int j = 0; j < nHeight; ++j) { memcpy(pImateData + j * bytesPerRow, rowPointers[j], bytesPerRow); } } m_nBitsPerComponent = nBitsPerComponent; m_nHeight = (short)nHeight; m_nWidth = (short)nWidth; m_pData = pImateData; pImateData = 0; bRet = true; } while (0); CC_SAFE_DELETE_ARRAY(pImateData); if (png_ptr) { png_destroy_read_struct(&png_ptr, (info_ptr) ? &info_ptr : 0, 0); } return bRet; }
unsigned char * ReadPNG(FILE * fp, unsigned int & sizeX, unsigned int &sizeY, int &img_depth, int &img_color_type, unsigned char *** row_pointer_ptr) { png_structp png_ptr; png_bytepp row_pointers; png_infop info_ptr; int interlace_type; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); if (png_ptr == NULL) { exit(1); 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); fprintf(stderr,"VSImage ERROR : PNG info_ptr == NULL !!!\n"); exit(1); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); /* If we get here, we had a problem reading the file */ exit(1); return NULL; } png_init_io(png_ptr, fp); //png_set_sig_bytes(png_ptr, 8); png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)&sizeX, (png_uint_32 *)&sizeY, &img_depth, &img_color_type, &interlace_type, NULL, NULL); # if __BYTE_ORDER != __BIG_ENDIAN if (img_depth==16) png_set_swap (png_ptr); #endif if (img_depth==16)//for now png_set_strip_16(png_ptr); if (img_color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); if (img_color_type == PNG_COLOR_TYPE_GRAY && img_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); png_set_expand (png_ptr); png_read_update_info (png_ptr,info_ptr); png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)&sizeX, (png_uint_32 *)&sizeY, &img_depth, &img_color_type, &interlace_type, NULL, NULL); row_pointers = (unsigned char **)malloc (sizeof (unsigned char *) *sizeY); int numchan=1; if (img_color_type&PNG_COLOR_MASK_COLOR) numchan =3; if (img_color_type &PNG_COLOR_MASK_PALETTE) numchan =1; if (img_color_type&PNG_COLOR_MASK_ALPHA) numchan++; unsigned long stride = numchan*sizeof (unsigned char)*img_depth/8; unsigned char * image = (unsigned char *) malloc (stride*sizeX*sizeY); for (unsigned int i=0;i<sizeY;i++) { row_pointers[i] = &image[i*stride*sizeX]; } png_read_image (png_ptr,row_pointers); unsigned char * result; result = image; //free (row_pointers); *row_pointer_ptr=row_pointers; png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return result; }
/* ReadPNG - Reads the contents of a PNG file and stores the contents into BMGImageStruct Inputs: filename - the name of the file to be opened Outputs: img - the BMGImageStruct containing the image data Returns: BMGError - if the file could not be read or a resource error occurred BMG_OK - if the file was read and the data was stored in img Limitations: None. Comments: 2-bit images are converted to 4-bit images. 16-bit images are converted to 8-bit images. gray scale images with alpha components are converted to 32-bit images */ BMGError ReadPNG( const char *filename, struct BMGImageStruct * volatile img ) { jmp_buf err_jmp; int error; FILE * volatile file = NULL; int BitDepth; int ColorType; int InterlaceType; unsigned char signature[8]; png_structp volatile png_ptr = NULL; png_infop volatile info_ptr = NULL; png_infop volatile end_info = NULL; png_color_16 *ImageBackground = NULL; png_bytep trns = NULL; int NumTrans = 0; int i, k; png_color_16p TransColors = NULL; png_uint_32 Width, Height; unsigned char *bits; unsigned char** volatile rows = NULL; BMGError tmp; /* error handler */ error = setjmp( err_jmp ); if (error != 0) { if (end_info != NULL) png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info); else if (info_ptr != NULL) png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL); else if (png_ptr != NULL) png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL); if (rows) { if (rows[0]) free(rows[0]); free(rows); } if (img) FreeBMGImage(img); if (file) fclose(file); SetLastBMGError((BMGError) error); return (BMGError) error; } if ( img == NULL ) longjmp ( err_jmp, (int)errInvalidBMGImage ); file = fopen( filename, "rb" ); if ( !file || fread( signature, 1, 8, file ) != 8) longjmp ( err_jmp, (int)errFileOpen ); /* check the signature */ if ( png_sig_cmp( signature, 0, 8 ) != 0 ) longjmp( err_jmp, (int)errUnsupportedFileFormat ); /* create a pointer to the png read structure */ png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( !png_ptr ) longjmp( err_jmp, (int)errMemoryAllocation ); /* create a pointer to the png info structure */ info_ptr = png_create_info_struct( png_ptr ); if ( !info_ptr ) longjmp( err_jmp, (int)errMemoryAllocation ); /* create a pointer to the png end-info structure */ end_info = png_create_info_struct(png_ptr); if (!end_info) longjmp( err_jmp, (int)errMemoryAllocation ); /* bamboozle the PNG longjmp buffer */ /*generic PNG error handler*/ /* error will always == 1 which == errLib */ // error = png_setjmp(png_ptr); error = setjmp( png_jmpbuf( png_ptr ) ); if ( error > 0 ) longjmp( err_jmp, error ); /* set function pointers in the PNG library, for read callbacks */ png_set_read_fn(png_ptr, (png_voidp) file, user_read_data); /*let the read functions know that we have already read the 1st 8 bytes */ png_set_sig_bytes( png_ptr, 8 ); /* read all PNG data up to the image data */ png_read_info( png_ptr, info_ptr ); /* extract the data we need to form the HBITMAP from the PNG header */ png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType, &InterlaceType, NULL, NULL); img->width = (unsigned int) Width; img->height = (unsigned int) Height; img->bits_per_pixel = (unsigned char)32; img->scan_width = Width * 4; /* convert 16-bit images to 8-bit images */ if (BitDepth == 16) png_set_strip_16(png_ptr); /* These are not really required per Rice format spec, * but is done just in case someone uses them. */ /* convert palette color to rgb color */ if (ColorType == PNG_COLOR_TYPE_PALETTE) { png_set_palette_to_rgb(png_ptr); ColorType = PNG_COLOR_TYPE_RGB; } /* expand 1,2,4 bit gray scale to 8 bit gray scale */ if (ColorType == PNG_COLOR_TYPE_GRAY && BitDepth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); /* convert gray scale or gray scale + alpha to rgb color */ if (ColorType == PNG_COLOR_TYPE_GRAY || ColorType == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_gray_to_rgb(png_ptr); ColorType = PNG_COLOR_TYPE_RGB; } /* add alpha channel if any */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(png_ptr); ColorType = PNG_COLOR_TYPE_RGB_ALPHA; } /* convert rgb to rgba */ if (ColorType == PNG_COLOR_TYPE_RGB) { png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); ColorType = PNG_COLOR_TYPE_RGB_ALPHA; } png_set_bgr(png_ptr); /* set the background color if one is found */ if ( png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD) ) png_get_bKGD(png_ptr, info_ptr, &ImageBackground); /* get the transparent color if one is there */ if ( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) ) png_get_tRNS( png_ptr, info_ptr, &trns, &NumTrans, &TransColors ); img->palette_size = (unsigned short)0; img->bytes_per_palette_entry = 4U; tmp = AllocateBMGImage( img ); if ( tmp != BMG_OK ) longjmp( err_jmp, (int)tmp ); png_read_update_info( png_ptr, info_ptr ); /* create buffer to read data to */ rows = (unsigned char **)malloc(Height*sizeof(unsigned char *)); if ( !rows ) longjmp( err_jmp, (int)errMemoryAllocation ); k = png_get_rowbytes( png_ptr, info_ptr ); rows[0] = (unsigned char *)malloc( Height*k*sizeof(char)); if ( !rows[0] ) longjmp( err_jmp, (int)errMemoryAllocation ); for ( i = 1; i < (int)Height; i++ ) rows[i] = rows[i-1] + k; /* read the entire image into rows */ png_read_image( png_ptr, rows ); bits = img->bits + (Height - 1) * img->scan_width; for ( i = 0; i < (int)Height; i++ ) { memcpy(bits, rows[i], 4*Width); bits -= img->scan_width; } free( rows[0] ); free( rows ); png_read_end( png_ptr, info_ptr ); png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info); fclose( file ); return BMG_OK; }
bool R9_ImgReadHeaderPNG( F9FILE file, r9Img* img ) { if(file==NULL || img==NULL) return false; R9_ImgDestroy(img); // check png sig const int headersize = 8; byte header[headersize]; if(file->Read( header, headersize)!=headersize) return false; BOOL ispng = png_check_sig(header, headersize) != 0; if(!ispng) { elog::rnd() << "png sig failed" << std::endl; return false; } // create png structures png_structp png_ptr = png_create_read_struct_2( PNG_LIBPNG_VER_STRING, NULL, R9_ImgPNG_FatalError, R9_ImgPNG_Warning, NULL, R9_ImgPNG_Malloc, R9_ImgPNG_Free ); if(png_ptr==NULL) return false; png_infop info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return false; } png_infop end_info = png_create_info_struct(png_ptr); if(end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return false; } // set global file r9_imgpng_file = file; png_set_read_fn(png_ptr, NULL, R9_ImgPNG_ReadData); // read off the info on the image png_set_sig_bytes(png_ptr, headersize); png_read_info(png_ptr, info_ptr); png_uint_32 pngwidth; png_uint_32 pngheight; int32 pngbits; int32 pngpf; png_get_IHDR(png_ptr, info_ptr, &pngwidth, &pngheight, &pngbits, &pngpf, NULL, // interlace NULL, // compression_type NULL); // filter_type BOOL alpha = FALSE; img->m_width = pngwidth; img->m_height = pngheight; img->m_pf = R9_PF_RGB; // release png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); r9_imgpng_file = NULL; return true; }
unsigned char* LoadPNGJPGFromMemory(const unsigned char* buffer, int len, int* width, int* height) { const int number=8; // проверяем сигнатуру файла (первые number байт) if ( !png_check_sig((png_bytep)buffer, number) ) { // неизвестный формат return LoadJPGWithAlphaFromMemory(buffer, len, width, height); } // создаем внутреннюю структуру png для работы с файлом // последние параметры - структура, для функции обработки ошибок и варнинга (последн. 2 параметра) png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); // создаем структуру с информацией о файле png_infop info_ptr = png_create_info_struct(png_ptr); PNGBuffer pngBuffer; pngBuffer.data = (png_bytep)buffer; pngBuffer.position = 8; png_set_read_fn(png_ptr, (void*)&pngBuffer, PNGRead); // говорим библиотеке, что мы уже прочли number байт, когда проверяли сигнатуру png_set_sig_bytes(png_ptr, number); // читаем всю информацию о файле png_read_info(png_ptr, info_ptr); // Эта функция возвращает инфу из info_ptr png_uint_32 w = 0, h = 0; // размер картинки в пикселях int bit_depth = 0; // глубина цвета (одного из каналов, может быть 1, 2, 4, 8, 16) int color_type = 0; // описывает какие каналы присутствуют: // PNG_COLOR_TYPE_GRAY, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, // PNG_COLOR_TYPE_RGB, PNG_COLOR_TYPE_RGB_ALPHA... // последние 3 параметра могут быть нулями и обозначают: тип фильтра, тип компрессии и тип смещения png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0); // png формат может содержать 16 бит на канал, но нам нужно только 8, поэтому сужаем канал if (bit_depth == 16) png_set_strip_16(png_ptr); // преобразуем файл если он содержит палитру в нормальный RGB if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8) png_set_palette_to_rgb(png_ptr); // если в грэйскейле меньше бит на канал чем 8, то конвертим к нормальному 8-битному //if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); // и добавляем полный альфа-канал if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); double gamma = 0.0f; // если есть информация о гамме в файле, то устанавливаем на 2.2 if ( png_get_gAMA(png_ptr, info_ptr, &gamma) ) png_set_gamma(png_ptr, 2.2, gamma); // иначе ставим дефолтную гамму для файла в 0.45455 (good guess for GIF images on PCs) else png_set_gamma(png_ptr, 2.2, 0.45455); // после всех трансформаций, апдейтим информацию в библиотеке png_read_update_info(png_ptr, info_ptr); // опять получаем все размеры и параметры обновленной картинки png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type, 0, 0, 0); // определяем кол-во байт нужных для того чтобы вместить строку png_uint_32 row_bytes = png_get_rowbytes(png_ptr, info_ptr); // теперь, мы можем выделить память чтобы вместить картинку png_byte* data = new png_byte[row_bytes * h]; // выделяем память, для указателей на каждую строку png_byte **row_pointers = new png_byte * [h]; // сопоставляем массив указателей на строчки, с выделенными в памяти (res) // т.к. изображение перевернутое, то указатели идут снизу вверх for (unsigned int i = 0; i < h; i++) row_pointers[i] = data + i * row_bytes; // все, читаем картинку png_read_image(png_ptr, row_pointers); // освобождаем память от указателей на строки delete []row_pointers; // освобождаем память выделенную для библиотеки libpng png_destroy_read_struct(&png_ptr, &info_ptr, 0); *width=w; *height=h; return data; }
void LoadPNG( const char *name, byte **pic, int *width, int *height, int *numLayers, int *numMips, int *bits, byte alphaByte ) { int bit_depth; int color_type; png_uint_32 w; png_uint_32 h; unsigned int row; png_infop info; png_structp png; png_bytep *row_pointers; byte *data; byte *out; // load png ri.FS_ReadFile( name, ( void ** ) &data ); if ( !data ) { return; } png = png_create_read_struct( PNG_LIBPNG_VER_STRING, ( png_voidp ) nullptr, png_user_error_fn, png_user_warning_fn ); if ( !png ) { ri.Printf( PRINT_WARNING, "LoadPNG: png_create_write_struct() failed for (%s)\n", name ); ri.FS_FreeFile( data ); return; } // allocate/initialize the memory for image information. REQUIRED info = png_create_info_struct( png ); if ( !info ) { ri.Printf( PRINT_WARNING, "LoadPNG: png_create_info_struct() failed for (%s)\n", name ); ri.FS_FreeFile( data ); png_destroy_read_struct( &png, ( png_infopp ) nullptr, ( png_infopp ) nullptr ); return; } /* * Set error handling if you are using the setjmp/longjmp method (this is * the common method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ if ( setjmp( png_jmpbuf( png ) ) ) { // if we get here, we had a problem reading the file ri.Printf( PRINT_WARNING, "LoadPNG: first exception handler called for (%s)\n", name ); ri.FS_FreeFile( data ); png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) nullptr ); return; } png_set_read_fn( png, data, png_read_data ); png_set_sig_bytes( png, 0 ); // 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, info ); // get picture info png_get_IHDR( png, info, ( png_uint_32 * ) &w, ( png_uint_32 * ) &h, &bit_depth, &color_type, nullptr, nullptr, nullptr ); // tell libpng to strip 16 bit/color files down to 8 bits/color png_set_strip_16( png ); // expand paletted images to RGB triplets if ( color_type & PNG_COLOR_MASK_PALETTE ) { png_set_expand( png ); } // expand gray-scaled images to RGB triplets if ( !( color_type & PNG_COLOR_MASK_COLOR ) ) { png_set_gray_to_rgb( png ); } // expand grayscale images to the 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 ( png_get_valid( png, info, PNG_INFO_tRNS ) ) { png_set_tRNS_to_alpha( png ); } // if there is no alpha information, fill with alphaByte if ( !( color_type & PNG_COLOR_MASK_ALPHA ) ) { png_set_filler( png, alphaByte, PNG_FILLER_AFTER ); } // expand pictures with less than 8bpp to 8bpp if ( bit_depth < 8 ) { png_set_packing( png ); } png_set_interlace_handling( png ); // update structure with the above settings png_read_update_info( png, info ); // allocate the memory to hold the image *width = w; *height = h; *pic = out = ( byte * ) ri.Z_Malloc( w * h * 4 ); row_pointers = ( png_bytep * ) ri.Hunk_AllocateTempMemory( sizeof( png_bytep ) * h ); // set a new exception handler if ( setjmp( png_jmpbuf( png ) ) ) { ri.Printf( PRINT_WARNING, "LoadPNG: second exception handler called for (%s)\n", name ); ri.Hunk_FreeTempMemory( row_pointers ); ri.FS_FreeFile( data ); png_destroy_read_struct( &png, ( png_infopp ) & info, ( png_infopp ) nullptr ); return; } for ( row = 0; row < h; row++ ) { row_pointers[ row ] = ( png_bytep )( out + ( row * 4 * w ) ); } // read image data png_read_image( png, row_pointers ); // read rest of file, and get additional chunks in info png_read_end( png, info ); // clean up after the read, and free any memory allocated png_destroy_read_struct( &png, &info, ( png_infopp ) nullptr ); ri.Hunk_FreeTempMemory( row_pointers ); ri.FS_FreeFile( data ); }
/* Read a PNG file. You may want to return an error code if the read * fails (depending upon the failure). There are two "prototypes" given * here - one where we are given the filename, and we need to open the * file, and the other where we are given an open file (possibly with * some or all of the magic bytes read - see comments above). */ #ifdef open_file /* prototype 1 */ void read_png(char *file_name) /* We need to open the file */ { png_structp png_ptr; png_infop info_ptr; unsigned int sig_read = 0; png_uint_32 width, height; int bit_depth, color_type, interlace_type; FILE *fp; if ((fp = fopen(file_name, "rb")) == NULL) return (ERROR); #else no_open_file /* prototype 2 */ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ { png_structp png_ptr; png_infop info_ptr; png_uint_32 width, height; int bit_depth, color_type, interlace_type; #endif no_open_file /* Only use one prototype! */ /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also supply the * the compiler header file version, so that we know if the application * was compiled with a compatible version of the library. REQUIRED */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp user_error_ptr, user_error_fn, user_warning_fn); if (png_ptr == NULL) { fclose(fp); return (ERROR); } /* Allocate/initialize the memory for image information. REQUIRED. */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_read_struct(&png_ptr, NULL, NULL); return (ERROR); } /* Set error handling if you are using the setjmp/longjmp method (this is * the normal method of doing things with libpng). REQUIRED unless you * set up your own error handlers in the png_create_read_struct() earlier. */ if (setjmp(png_jmpbuf(png_ptr))) { /* Free all of the memory associated with the png_ptr and info_ptr */ png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(fp); /* If we get here, we had a problem reading the file */ return (ERROR); } /* One of the following I/O initialization methods is REQUIRED */ #ifdef streams /* PNG file I/O method 1 */ /* Set up the input control if you are using standard C streams */ png_init_io(png_ptr, fp); #else no_streams /* PNG file I/O method 2 */ /* If you are using replacement read functions, instead of calling * png_init_io() here you would call: */ png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); /* where user_io_ptr is a structure you want available to the callbacks */ #endif no_streams /* Use only one I/O method! */ /* If we have already read some of the signature */ png_set_sig_bytes(png_ptr, sig_read); #ifdef hilevel /* * If you have enough memory to read in the entire image at once, * and you need to specify only transforms that can be controlled * with one of the PNG_TRANSFORM_* bits (this presently excludes * quantizing, filling, setting background, and doing gamma * adjustment), then you can read the entire image (including * pixels) into the info structure with this call: */ png_read_png(png_ptr, info_ptr, png_transforms, NULL); #else /* OK, you're doing it the hard way, with the lower-level functions */ /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). REQUIRED */ png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); /* Set up the data transformations you want. Note that these are all * optional. Only call them if you want/need them. Many of the * transformations only work on specific types of images, and many * are mutually exclusive. */ /* Tell libpng to strip 16 bit/color files down to 8 bits/color. * Use accurate scaling if it's available, otherwise just chop off the * low byte. */ #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED png_set_scale_16(png_ptr); #else png_set_strip_16(png_ptr); #endif /* Strip alpha bytes from the input data without combining with the * background (not recommended). */ png_set_strip_alpha(png_ptr); /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ png_set_packing(png_ptr); /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ png_set_packswap(png_ptr); /* Expand paletted colors into true RGB triplets */ if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); /* Expand paletted or RGB images with transparency to full alpha channels * so the data will be available as RGBA quartets. */ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) png_set_tRNS_to_alpha(png_ptr); /* Set the background color to draw transparent and alpha images over. * It is possible to set the red, green, and blue components directly * for paletted images instead of supplying a palette index. Note that * even if the PNG file supplies a background, you are not required to * use it - you should use the (solid) application background if it has one. */ png_color_16 my_background, *image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background) != 0) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); else png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); /* Some suggestions as to how to get a screen gamma value * * Note that screen gamma is the display_exponent, which includes * the CRT_exponent and any correction for viewing conditions */ if (/* We have a user-defined screen gamma value */) { screen_gamma = user-defined screen_gamma; } /* This is one way that applications share the same screen gamma value */ else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
// load in the image data IImage* CImageLoaderPng::loadImage(irr::io::IReadFile* file) { #ifdef _IRR_COMPILE_WITH_LIBPNG_ if (!file) return 0; Image = 0; RowPointers = 0; png_byte buffer[8]; // Read the first few bytes of the PNG file if( file->read(buffer, 8) != 8 ) { os::Printer::log("LOAD PNG: can't read file\n", file->getFileName(), ELL_ERROR); return 0; } // Check if it really is a PNG file if( png_sig_cmp(buffer, 0, 8) ) { os::Printer::log("LOAD PNG: not really a png\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png read struct png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)png_cpexcept_error, NULL); if (!png_ptr) { os::Printer::log("LOAD PNG: Internal PNG create read struct failure\n", file->getFileName(), ELL_ERROR); return 0; } // Allocate the png info struct png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { os::Printer::log("LOAD PNG: Internal PNG create info struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (RowPointers) delete [] RowPointers; return 0; } // changed by zola so we don't need to have public FILE pointers png_set_read_fn(png_ptr, file, user_read_data_fcn); png_set_sig_bytes(png_ptr, 8); // Tell png that we read the signature png_read_info(png_ptr, info_ptr); // Read the info section of the png file // Extract info png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&Width, (png_uint_32*)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); // Convert palette color to true color if (ColorType==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); // Convert low bit colors to 8 bit colors if (BitDepth < 8) { if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_1_2_4_to_8(png_ptr); else png_set_packing(png_ptr); } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); // Convert high bit colors to 8 bit colors if (BitDepth == 16) png_set_strip_16(png_ptr); // Convert gray color to true color if (ColorType==PNG_COLOR_TYPE_GRAY || ColorType==PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); // Update the changes png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&Width, (png_uint_32*)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); // Convert RGBA to BGRA if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) { #ifdef __BIG_ENDIAN__ png_set_swap_alpha(png_ptr); #else png_set_bgr(png_ptr); #endif } // Update the changes png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&Width, (png_uint_32*)&Height, &BitDepth, &ColorType, NULL, NULL, NULL); // Create the image structure to be filled by png data if (ColorType==PNG_COLOR_TYPE_RGB_ALPHA) Image = new CImage(ECF_A8R8G8B8, core::dimension2d<s32>(Width, Height)); else Image = new CImage(ECF_R8G8B8, core::dimension2d<s32>(Width, Height)); if (!Image) { os::Printer::log("LOAD PNG: Internal PNG create image struct failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); return 0; } // Create array of pointers to rows in image data RowPointers = new png_bytep[Height]; if (!RowPointers) { os::Printer::log("LOAD PNG: Internal PNG create row pointers failure\n", file->getFileName(), ELL_ERROR); png_destroy_read_struct(&png_ptr, NULL, NULL); delete Image; return 0; } // Fill array of pointers to rows in image data unsigned char* data = (unsigned char*)Image->lock(); for (u32 i=0; i<Height; ++i) { RowPointers[i]=data; data += Image->getPitch(); } // for proper error handling if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); delete [] RowPointers; Image->unlock(); delete [] Image; return 0; } // Read data using the library function that handles all transformations including interlacing png_read_image(png_ptr, RowPointers); png_read_end(png_ptr, NULL); delete [] RowPointers; Image->unlock(); png_destroy_read_struct(&png_ptr,&info_ptr, 0); // Clean up memory return Image; #else return 0; #endif // _IRR_COMPILE_WITH_LIBPNG_ }
int loadPNG(ePtr<gPixmap> &result, const char *filename) { __u8 header[8]; FILE *fp=fopen(filename, "rb"); if (!fp) { // eDebug("couldn't open %s", filename ); return 0; } if (!fread(header, 8, 1, fp)) { eDebug("couldn't read"); fclose(fp); return 0; } if (png_sig_cmp(header, 0, 8)) { fclose(fp); return 0; } png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { eDebug("no pngptr"); fclose(fp); return 0; } png_infop info_ptr=png_create_info_struct(png_ptr); if (!info_ptr) { eDebug("no info ptr"); png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0); fclose(fp); return 0; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { eDebug("no end"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); return 0; } #if (PNG_LIBPNG_VER < 10500) if (setjmp(png_ptr->jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) #endif { eDebug("das war wohl nix"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); result = 0; return 0; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_set_invert_alpha(png_ptr); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth; int color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type == PNG_COLOR_TYPE_GRAY || color_type & PNG_COLOR_MASK_PALETTE) { result=new gPixmap(eSize(width, height), bit_depth); gSurface *surface = result->surface; png_bytep *rowptr=new png_bytep[height]; for (unsigned int i=0; i<height; i++) rowptr[i]=((png_byte*)(surface->data))+i*surface->stride; png_read_rows(png_ptr, rowptr, 0, height); delete [] rowptr; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_color *palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); if (num_palette) surface->clut.data=new gRGB[num_palette]; else surface->clut.data=0; surface->clut.colors=num_palette; for (int i=0; i<num_palette; i++) { surface->clut.data[i].a=0; surface->clut.data[i].r=palette[i].red; surface->clut.data[i].g=palette[i].green; surface->clut.data[i].b=palette[i].blue; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_byte *trans; png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0); for (int i=0; i<num_palette; i++) surface->clut.data[i].a=255-trans[i]; } } else { surface->clut.data=0; surface->clut.colors=0; } surface->clut.start=0; png_read_end(png_ptr, end_info); } else { result=0; eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type); } png_destroy_read_struct(&png_ptr, &info_ptr,&end_info); fclose(fp); return 0; }
static void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0) { if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { double file_gamma; png_get_gAMA(png_ptr, info_ptr, &file_gamma); png_set_gamma(png_ptr, screen_gamma, file_gamma); } png_uint_32 width; png_uint_32 height; int bit_depth; int color_type; png_bytep trans_alpha = 0; png_color_16p trans_color_p = 0; int num_trans; png_colorp palette = 0; int num_palette; int interlace_method; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method, 0, 0); png_set_interlace_handling(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY) { // Black & White or 8-bit grayscale if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { png_set_invert_mono(png_ptr); png_read_update_info(png_ptr, info_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) { image = QImage(width, height, QImage::Format_Mono); if (image.isNull()) return; } image.setColorCount(2); image.setColor(1, qRgb(0,0,0)); image.setColor(0, qRgb(255,255,255)); } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_gray_to_rgb(png_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) { image = QImage(width, height, QImage::Format_ARGB32); if (image.isNull()) return; } if (QSysInfo::ByteOrder == QSysInfo::BigEndian) png_set_swap_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); } else { if (bit_depth == 16) png_set_strip_16(png_ptr); else if (bit_depth < 8) png_set_packing(png_ptr); int ncols = bit_depth < 8 ? 1 << bit_depth : 256; png_read_update_info(png_ptr, info_ptr); if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) { image = QImage(width, height, QImage::Format_Indexed8); if (image.isNull()) return; } image.setColorCount(ncols); for (int i=0; i<ncols; i++) { int c = i*255/(ncols-1); image.setColor(i, qRgba(c,c,c,0xff)); } if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) { const int g = trans_color_p->gray; if (g < ncols) { image.setColor(g, 0); } } } } else if (color_type == PNG_COLOR_TYPE_PALETTE && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) && num_palette <= 256) { // 1-bit and 8-bit color if (bit_depth != 1) png_set_packing(png_ptr); png_read_update_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); QImage::Format format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8; if (image.size() != QSize(width, height) || image.format() != format) { image = QImage(width, height, format); if (image.isNull()) return; } png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); image.setColorCount(num_palette); int i = 0; if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) { while (i < num_trans) { image.setColor(i, qRgba( palette[i].red, palette[i].green, palette[i].blue, trans_alpha[i] ) ); i++; } } while (i < num_palette) { image.setColor(i, qRgba( palette[i].red, palette[i].green, palette[i].blue, 0xff ) ); i++; } } else { // 32-bit if (bit_depth == 16) png_set_strip_16(png_ptr); png_set_expand(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); QImage::Format format = QImage::Format_ARGB32; // Only add filler if no alpha, or we can get 5 channel data. if (!(color_type & PNG_COLOR_MASK_ALPHA) && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ? PNG_FILLER_BEFORE : PNG_FILLER_AFTER); // We want 4 bytes, but it isn't an alpha channel format = QImage::Format_RGB32; } QSize outSize(width,height); if (!scaledSize.isEmpty() && quint32(scaledSize.width()) <= width && quint32(scaledSize.height()) <= height && interlace_method == PNG_INTERLACE_NONE) { // Do inline downscaling outSize = scaledSize; if (doScaledRead) *doScaledRead = true; } if (image.size() != outSize || image.format() != format) { image = QImage(outSize, format); if (image.isNull()) return; } if (QSysInfo::ByteOrder == QSysInfo::BigEndian) png_set_swap_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); } // Qt==ARGB==Big(ARGB)==Little(BGRA) if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) { png_set_bgr(png_ptr); } }
void png_reader::init() { FILE *fp=fopen(fileName_.c_str(),"rb"); if (!fp) throw image_reader_exception("cannot open image file "+fileName_); png_byte header[8]; memset(header,0,8); if ( fread(header,1,8,fp) != 8) { fclose(fp); throw image_reader_exception("Could not read " + fileName_); } int is_png=!png_sig_cmp(header,0,8); if (!is_png) { fclose(fp); throw image_reader_exception(fileName_ + " is not a png file"); } png_structp png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,0,0,0); if (!png_ptr) { fclose(fp); throw image_reader_exception("failed to allocate png_ptr"); } // catch errors in a custom way to avoid the need for setjmp png_set_error_fn(png_ptr, png_get_error_ptr(png_ptr), user_error_fn, user_warning_fn); png_infop info_ptr; try { info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw image_reader_exception("failed to create info_ptr"); } } catch (std::exception const& ex) { png_destroy_read_struct(&png_ptr,0,0); fclose(fp); throw; } png_set_read_fn(png_ptr, (png_voidp)fp, png_read_data); png_set_sig_bytes(png_ptr,8); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth_, &color_type_,0,0,0); width_=width; height_=height; MAPNIK_LOG_DEBUG(png_reader) << "png_reader: bit_depth=" << bit_depth_ << ",color_type=" << color_type_; png_destroy_read_struct(&png_ptr,&info_ptr,0); fclose(fp); }
static void read_image_scaled(QImage *outImage, png_structp png_ptr, png_infop info_ptr, QPngHandlerPrivate::AllocatedMemoryPointers &, QSize scaledSize) { 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, 0, 0, 0); uchar *data = outImage->bits(); int bpl = outImage->bytesPerLine(); if (scaledSize.isEmpty() || !width || !height) return; const quint32 iysz = height; const quint32 ixsz = width; const quint32 oysz = scaledSize.height(); const quint32 oxsz = scaledSize.width(); const quint32 ibw = 4*width; amp.accRow = new quint32[ibw]; memset(amp.accRow, 0, ibw*sizeof(quint32)); amp.inRow = new png_byte[ibw]; memset(amp.inRow, 0, ibw*sizeof(png_byte)); amp.outRow = new uchar[ibw]; memset(amp.outRow, 0, ibw*sizeof(uchar)); qint32 rval = 0; for (quint32 oy=0; oy<oysz; oy++) { // Store the rest of the previous input row, if any for (quint32 i=0; i < ibw; i++) amp.accRow[i] = rval*amp.inRow[i]; // Accumulate the next input rows for (rval = iysz-rval; rval > 0; rval-=oysz) { png_read_row(png_ptr, amp.inRow, NULL); quint32 fact = qMin(oysz, quint32(rval)); for (quint32 i=0; i < ibw; i++) amp.accRow[i] += fact*amp.inRow[i]; } rval *= -1; // We have a full output row, store it for (quint32 i=0; i < ibw; i++) amp.outRow[i] = uchar(amp.accRow[i]/iysz); quint32 a[4] = {0, 0, 0, 0}; qint32 cval = oxsz; quint32 ix = 0; for (quint32 ox=0; ox<oxsz; ox++) { for (quint32 i=0; i < 4; i++) a[i] = cval * amp.outRow[ix+i]; for (cval = ixsz - cval; cval > 0; cval-=oxsz) { ix += 4; if (ix >= ibw) break; // Safety belt, should not happen quint32 fact = qMin(oxsz, quint32(cval)); for (quint32 i=0; i < 4; i++) a[i] += fact * amp.outRow[ix+i]; } cval *= -1; for (quint32 i=0; i < 4; i++) data[(4*ox)+i] = uchar(a[i]/ixsz); } data += bpl; } amp.deallocate(); outImage->setDotsPerMeterX((png_get_x_pixels_per_meter(png_ptr,info_ptr)*oxsz)/ixsz); outImage->setDotsPerMeterY((png_get_y_pixels_per_meter(png_ptr,info_ptr)*oysz)/iysz); }
/** Reads one PNG file. @param process Process the image data (0 for initial parameter determination) @returns -1 on failure, 1 on sucess */ int decode_png(const char *pngname, int process, parameters_t *param) { int num_pass = 1; int bit_depth, color_type; FILE *pngfile; //png_byte hdptr[8]; /* Now open this PNG file, and examine its header to retrieve the YUV4MPEG info that shall be written */ pngfile = fopen(pngname, "rb"); if (!pngfile) { perror("PNG file open failed:"); return -1; } //fread(hdptr, 1, 8, pngfile); #if 0 bool is_png = !png_sig_cmp(hdptr, 0, 8); if (!is_png) { mjpeg_error("%s is _no_ PNG file !\n"); return -1; } #endif png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) mjpeg_error_exit1("%s: Could not allocate PNG read struct !", pngname); png_init_io(png_ptr, pngfile); //png_set_sig_bytes(png_ptr, 8); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); mjpeg_error_exit1("%s: Could not allocate PNG info struct !", pngname); } end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); mjpeg_error_exit1("%s: Could not allocate PNG end info struct !", pngname); } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); mjpeg_error("%s: Corrupted PNG file !", pngname); return -1; } if (process) png_set_read_user_transform_fn(png_ptr, png_separation); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_STRIP_ALPHA, NULL); if (png_get_IHDR(png_ptr, info_ptr, ¶m->width, ¶m->height, &bit_depth, // &color_type, &interlace_type, &compression_type, &filter_type)) &color_type, NULL, NULL, NULL)) num_pass = png_set_interlace_handling(png_ptr); else mjpeg_error_exit1("PNG header reading failed !!\n"); #if 0 mjpeg_info("Reading info struct...\n"); png_read_info(png_ptr, info_ptr); mjpeg_info("Done...\n"); if (png_get_IHDR(png_ptr, info_ptr, ¶m->width, ¶m->height, &bit_depth, // &color_type, &interlace_type, &compression_type, &filter_type)) &color_type, NULL, NULL, NULL)) num_pass = png_set_interlace_handling(png_ptr); else mjpeg_error_exit1("PNG header reading failed !!\n"); if (process) { printf("%d passes needed\n\n", num_pass); if (bit_depth != 8 && bit_depth != 16) { mjpeg_error_exit1("Invalid bit_depth %d, only 8 and 16 bit allowed !!\n", bit_depth); } png_set_strip_16(png_ptr); // always has to strip the 16bit input, MPEG can't handle it png_set_strip_alpha(png_ptr); // Alpha can't be processed until Z/Alpha is integrated printf("\nAllocating row buffer..."); png_set_read_user_transform_fn(png_ptr, png_separation); png_bytep row_buf = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); for (int n=0; n < num_pass; n++) for (int y=0; y < sh_param->height; y++) { printf("Writing row data for pass %d\n", n); png_read_rows(png_ptr, (png_bytepp)&row_buf, NULL, 1); } png_free(png_ptr, row_buf); } png_read_end(png_ptr, info_ptr); #endif if (setjmp(png_ptr->jmpbuf)) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return 2; } fclose(pngfile); return 1; }
bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) { if (state == Error) return false; if (state == Ready && !readPngHeader()) { state = Error; return false; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; amp.deallocate(); state = Error; return false; } bool doScaledRead = false; setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma); if (outImage->isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; amp.deallocate(); state = Error; return false; } if (doScaledRead) { read_image_scaled(outImage, png_ptr, info_ptr, amp, scaledSize); } else { 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, 0, 0, 0); uchar *data = outImage->bits(); int bpl = outImage->bytesPerLine(); amp.row_pointers = new png_bytep[height]; for (uint y = 0; y < height; y++) amp.row_pointers[y] = data + y * bpl; png_read_image(png_ptr, amp.row_pointers); amp.deallocate(); outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr)); outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr)); // sanity check palette entries if (color_type == PNG_COLOR_TYPE_PALETTE && outImage->format() == QImage::Format_Indexed8) { int color_table_size = outImage->colorCount(); for (int y=0; y<(int)height; ++y) { uchar *p = FAST_SCAN_LINE(data, bpl, y); uchar *end = p + width; while (p < end) { if (*p >= color_table_size) *p = 0; ++p; } } } } state = ReadingEnd; png_read_end(png_ptr, end_info); readPngTexts(end_info); for (int i = 0; i < readTexts.size()-1; i+=2) outImage->setText(readTexts.at(i), readTexts.at(i+1)); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png_ptr = 0; amp.deallocate(); state = Ready; if (scaledSize.isValid() && outImage->size() != scaledSize) *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); return true; }
int fh_png_load(const char *name,unsigned char **buffer,int* /*xp*/,int* /*yp*/) { 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) { fclose(fh); 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); } /* this test does not trigger for 8bit-paletted PNGs with newer libpng (1.2.36 at least), but the data delivered is with alpha channel anyway, so always strip alpha for now */ #if PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR <= 2 && PNG_LIBPNG_VER_RELEASE < 36 if (color_type & PNG_COLOR_MASK_ALPHA) #endif 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); printf(" width: %lu rowbytes: %lu\n", width, png_get_rowbytes(png_ptr, info_ptr)); fclose(fh); 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); }
BMGError ReadPNGInfo( const char *filename, struct BMGImageStruct * volatile img ) { jmp_buf err_jmp; int error; FILE * volatile file = NULL; int BitDepth; int ColorType; int InterlaceType; unsigned char signature[8]; png_structp volatile png_ptr = NULL; png_infop volatile info_ptr = NULL; png_infop volatile end_info = NULL; png_uint_32 Width, Height; /* error handler */ error = setjmp( err_jmp ); if (error != 0) { if (end_info != NULL) png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info); else if (info_ptr != NULL) png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, NULL); else if (png_ptr != NULL) png_destroy_read_struct((png_structp *) &png_ptr, NULL, NULL); if (img) FreeBMGImage(img); if (file) fclose(file); SetLastBMGError((BMGError) error); return (BMGError) error; } if ( img == NULL ) longjmp ( err_jmp, (int)errInvalidBMGImage ); file = fopen( filename, "rb" ); if ( !file || fread( signature, 1, 8, file ) != 8) longjmp ( err_jmp, (int)errFileOpen ); /* check the signature */ if ( png_sig_cmp( signature, 0, 8 ) != 0 ) longjmp( err_jmp, (int)errUnsupportedFileFormat ); /* create a pointer to the png read structure */ png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL ); if ( !png_ptr ) longjmp( err_jmp, (int)errMemoryAllocation ); /* create a pointer to the png info structure */ info_ptr = png_create_info_struct( png_ptr ); if ( !info_ptr ) longjmp( err_jmp, (int)errMemoryAllocation ); /* create a pointer to the png end-info structure */ end_info = png_create_info_struct(png_ptr); if (!end_info) longjmp( err_jmp, (int)errMemoryAllocation ); /* bamboozle the PNG longjmp buffer */ /*generic PNG error handler*/ /* error will always == 1 which == errLib */ // error = png_setjmp(png_ptr); error = setjmp( png_jmpbuf( png_ptr ) ); if ( error > 0 ) longjmp( err_jmp, error ); /* set function pointers in the PNG library, for read callbacks */ png_set_read_fn(png_ptr, (png_voidp) file, user_read_data); /*let the read functions know that we have already read the 1st 8 bytes */ png_set_sig_bytes( png_ptr, 8 ); /* read all PNG data up to the image data */ png_read_info( png_ptr, info_ptr ); /* extract the data we need to form the HBITMAP from the PNG header */ png_get_IHDR( png_ptr, info_ptr, &Width, &Height, &BitDepth, &ColorType, &InterlaceType, NULL, NULL); img->width = (unsigned int) Width; img->height = (unsigned int) Height; img->bits_per_pixel = (unsigned char)32; img->scan_width = Width * 4; img->palette_size = (unsigned short)0; img->bytes_per_palette_entry = 4U; img->bits = NULL; png_destroy_read_struct((png_structp *) &png_ptr, (png_infop *) &info_ptr, (png_infop *) &end_info); fclose( file ); return BMG_OK; }
static int open_theme_png(const char* name, const char* themename, png_structp* png_ptr, png_infop* info_ptr, png_uint_32* width, png_uint_32* height, png_byte* channels) { char resPath[256] = {0}; unsigned char header[8] = {0}; int result = 0; if(*name != '/') { snprintf(resPath, sizeof(resPath), "/cache/cot/themes/%s/%s.png", themename, name); }else{ strlcpy(resPath,name,sizeof(resPath)); } FILE* fp = fopen(resPath, "rb"); if (fp == NULL) { result = -1; goto exit; } size_t bytesRead = fread(header, 1, sizeof(header), fp); if (bytesRead != sizeof(header)) { result = -2; goto exit; } if (png_sig_cmp(header, 0, sizeof(header))) { result = -3; goto exit; } *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!*png_ptr) { result = -4; goto exit; } *info_ptr = png_create_info_struct(*png_ptr); if (!*info_ptr) { result = -5; goto exit; } if (setjmp(png_jmpbuf(*png_ptr))) { result = -6; goto exit; } png_init_io(*png_ptr, fp); png_set_sig_bytes(*png_ptr, sizeof(header)); png_read_info(*png_ptr, *info_ptr); int color_type, bit_depth; png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth, &color_type, NULL, NULL, NULL); *channels = png_get_channels(*png_ptr, *info_ptr); if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) { // 8-bit RGB images: great, nothing to do. } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) { // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray. png_set_expand_gray_1_2_4_to_8(*png_ptr); } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE) { // paletted images: expand to 8-bit RGB. Note that we DON'T // currently expand the tRNS chunk (if any) to an alpha // channel, because minui doesn't support alpha channels in // general. png_set_palette_to_rgb(*png_ptr); } else { fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n", bit_depth, *channels, color_type); result = -7; goto exit; } if (png_get_valid(*png_ptr, *info_ptr, PNG_INFO_tRNS)) { fprintf(stdout,"Has PNG_INFO_tRNS!\n"); png_set_tRNS_to_alpha(png_ptr); } png_read_update_info(*png_ptr, *info_ptr); png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth, &color_type, NULL, NULL, NULL); *channels = png_get_channels(*png_ptr, *info_ptr); return result; exit: if (result < 0) { png_destroy_read_struct(png_ptr, info_ptr, NULL); } if (fp != NULL) { fclose(fp); } return result; }
uint8_t* GraphicsTexture::loadImage() { Pegas_log_info("GraphicsTexture::loadImage"); Resource::AutoDispose autoDispose(mResource); if (mResource.open() != STATUS_OK) { Pegas_log_error("mResource.open failed"); return NULL; } png_byte header[8]; if (mResource.read(header, sizeof(header)) != STATUS_OK) { Pegas_log_error("mResource.read failed"); return NULL; } if (png_sig_cmp(header, 0, 8) != 0) { Pegas_log_error("png_sig_cmp failed, header param: %s", header); return NULL; } png_structp pngMain = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!pngMain) { Pegas_log_error("png_create_read_struct failed"); return NULL; } png_infop pngInfo = png_create_info_struct(pngMain); if (!pngInfo) { Pegas_log_error("png_create_info_struct failed"); return NULL; } png_set_read_fn(pngMain, &mResource, callback_read); if (setjmp(png_jmpbuf(pngMain))) { Pegas_log_error("setjmp failed"); return NULL; } png_set_sig_bytes(pngMain, 8); png_read_info(pngMain, pngInfo); png_int_32 depth, colorType; png_uint_32 width, height; png_get_IHDR(pngMain, pngInfo, &width, &height, &depth, &colorType, NULL, NULL, NULL); mWidth = width; mHeight = height; bool transparency = false; // Creates a full alpha channel if transparency is encoded as // an array of palette entries or a single transparent color. if (png_get_valid(pngMain, pngInfo, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(pngMain); transparency = true; Pegas_log_error("png_get_valid failed"); return NULL; } // Expands PNG with less than 8bits per channel to 8bits. if (depth < 0) { png_set_packing(pngMain); // Shrinks PNG with 16bits per color channel down to 8bits. } else if (depth == 16) { png_set_strip_16(pngMain); } // Indicates that image needs conversion to RGBA if needed. switch (colorType) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(pngMain); mFormat = transparency ? GL_RGBA : GL_RGB; break; case PNG_COLOR_TYPE_RGB: mFormat = transparency ? GL_RGBA : GL_RGB; break; case PNG_COLOR_TYPE_RGBA: mFormat = GL_RGBA; break; case PNG_COLOR_TYPE_GRAY: png_set_expand_gray_1_2_4_to_8(pngMain); mFormat = transparency ? GL_LUMINANCE_ALPHA : GL_LUMINANCE; break; case PNG_COLOR_TYPE_GA: png_set_expand_gray_1_2_4_to_8(pngMain); mFormat = GL_LUMINANCE_ALPHA; break; } png_read_update_info(pngMain, pngInfo); png_int_32 rowSize = png_get_rowbytes(pngMain, pngInfo); if (rowSize <= 0) { Pegas_log_error("invalid png row size: %d", rowSize); return NULL; } png_byte* imageBuffer = new png_byte[rowSize * height]; if (!imageBuffer) { Pegas_log_error("can not allocate image buffer"); return NULL; } png_bytep* rowPtrs = new png_bytep[height]; if (!rowPtrs) { Pegas_log_error("can not allocate row pointers"); //TODO: use smart pointer for this delete[] imageBuffer; return NULL; } for (int32_t i = 0; i < height; ++i) { rowPtrs[height - (i + 1)] = imageBuffer + (i * rowSize); } png_read_image(pngMain, rowPtrs); png_destroy_read_struct(&pngMain, &pngInfo, NULL); delete[] rowPtrs; return imageBuffer; }