static int pngdrv_open_memmap(const char *filename, int x_size, int y_size, BYTE *palette) { pngdrv_memmap_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (pngdrv_memmap_png_ptr == NULL) { return -1; } pngdrv_memmap_info_ptr = png_create_info_struct(pngdrv_memmap_png_ptr); if (pngdrv_memmap_info_ptr == NULL) { png_destroy_write_struct(&(pngdrv_memmap_png_ptr), (png_infopp)NULL); return -1; } /* pngdrv.c:232: warning: ‘jmpbuf‘ is deprecated (declared at /usr/include/libpng14/png.h:1096) */ /* if (setjmp(pngdrv_memmap_png_ptr->jmpbuf)) { */ if (setjmp(png_jmpbuf(pngdrv_memmap_png_ptr))) { png_destroy_write_struct(&(pngdrv_memmap_png_ptr), &(pngdrv_memmap_info_ptr)); return -1; } pngdrv_memmap_ext_filename = util_add_extension_const(filename, png_drv.default_extension); pngdrv_memmap_fd = fopen(pngdrv_memmap_ext_filename, MODE_WRITE); if (pngdrv_memmap_fd == NULL) { lib_free(pngdrv_memmap_ext_filename); return -1; } pngdrv_memmap_png_data = lib_malloc(x_size * 4); png_init_io(pngdrv_memmap_png_ptr, pngdrv_memmap_fd); png_set_compression_level(pngdrv_memmap_png_ptr, Z_BEST_COMPRESSION); /* pngdrv.c:251: warning: ‘width‘ is deprecated (declared at /usr/include/libpng14/png.h:639) pngdrv.c:252: warning: ‘height‘ is deprecated (declared at /usr/include/libpng14/png.h:640) pngdrv.c:253: warning: ‘bit_depth‘ is deprecated (declared at /usr/include/libpng14/png.h:651) pngdrv.c:254: warning: ‘color_type‘ is deprecated (declared at /usr/include/libpng14/png.h:653) */ /* pngdrv_memmap_info_ptr->width = x_size; pngdrv_memmap_info_ptr->height= y_size; pngdrv_memmap_info_ptr->bit_depth = 8; pngdrv_memmap_info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; */ png_set_IHDR(pngdrv_memmap_png_ptr, pngdrv_memmap_info_ptr, x_size, y_size, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(pngdrv_memmap_png_ptr, pngdrv_memmap_info_ptr); #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED png_set_invert_alpha(pngdrv_memmap_png_ptr); #endif return 0; }
void PngEncoder::encode() { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) throw "png_create_write_struct failed."; png_infop info_ptr = png_create_info_struct(png_ptr); if (!png_ptr) throw "png_create_info_struct failed."; int color_type; if (buf_type == BUF_RGB || buf_type == BUF_BGR) color_type = PNG_COLOR_TYPE_RGB; else color_type = PNG_COLOR_TYPE_RGB_ALPHA; png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_bytep *row_pointers = NULL; try { png_set_write_fn(png_ptr, (void *)this, png_chunk_producer, NULL); png_write_info(png_ptr, info_ptr); png_set_invert_alpha(png_ptr); if (buf_type == BUF_BGR || buf_type == BUF_BGRA) png_set_bgr(png_ptr); png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height); if (!row_pointers) throw "malloc failed in node-png (PngEncoder::encode)."; if (buf_type == BUF_RGB || buf_type == BUF_BGR) { for (int i=0; i<height; i++) row_pointers[i] = data+3*i*width; } else { for (int i=0; i<height; i++) row_pointers[i] = data+4*i*width; } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, NULL); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); } catch (const char *err) { png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); throw; } }
/* save screenshot in png format, return true if success, or false */ bool CScreenShot::SavePng() { png_bytep *row_pointers; png_structp png_ptr; png_infop info_ptr; TIMER_START(); if(!OpenFile()) return false; row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * yres); if (!row_pointers) { printf("CScreenShot::SavePng: malloc error\n"); fclose(fd); return false; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) { printf("CScreenShot::SavePng: %s save error\n", filename.c_str()); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); fclose(fd); return false; } png_init_io(png_ptr, fd); int y; for (y=0; y<yres; y++) { row_pointers[y] = pixel_data + (y*xres*4); } png_set_IHDR(png_ptr, info_ptr, xres, yres, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); //png_set_filter (png_ptr, 0, PNG_FILTER_NONE); png_set_compression_level(png_ptr, Z_BEST_SPEED); png_set_bgr(png_ptr); #ifdef BOXMODEL_APOLLO png_set_invert_alpha(png_ptr); #endif png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); fclose(fd); TIMER_STOP(filename.c_str()); return true; }
static int pngdrv_open(screenshot_t *screenshot, const char *filename) { gfxoutputdrv_data_t *sdata; sdata = lib_malloc(sizeof(gfxoutputdrv_data_t)); screenshot->gfxoutputdrv_data = sdata; sdata->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)NULL, NULL, NULL); if (sdata->png_ptr == NULL) { lib_free(sdata); return -1; } sdata->info_ptr = png_create_info_struct(sdata->png_ptr); if (sdata->info_ptr == NULL) { png_destroy_write_struct(&(sdata->png_ptr), (png_infopp)NULL); lib_free(sdata); return -1; } /* pngdrv.c:79: warning: ‘jmpbuf’ is deprecated (declared at /usr/include/libpng14/png.h:1096) */ /* if (setjmp(screenshot->gfxoutputdrv_data->png_ptr->jmpbuf)) { */ if (setjmp(png_jmpbuf(screenshot->gfxoutputdrv_data->png_ptr))) { png_destroy_write_struct(&(screenshot->gfxoutputdrv_data->png_ptr), &(screenshot->gfxoutputdrv_data->info_ptr)); lib_free(sdata); return -1; } sdata->ext_filename = util_add_extension_const(filename, png_drv.default_extension); sdata->fd = fopen(sdata->ext_filename, MODE_WRITE); if (sdata->fd == NULL) { lib_free(sdata->ext_filename); lib_free(sdata); return -1; } sdata->data = lib_malloc(screenshot->width * 4); png_init_io(sdata->png_ptr, sdata->fd); png_set_compression_level(sdata->png_ptr, Z_BEST_COMPRESSION); /* pngdrv.c:102: warning: ‘width’ is deprecated (declared at /usr/include/libpng14/png.h:639) pngdrv.c:103: warning: ‘height’ is deprecated (declared at /usr/include/libpng14/png.h:640) pngdrv.c:104: warning: ‘bit_depth’ is deprecated (declared at /usr/include/libpng14/png.h:651) pngdrv.c:105: warning: ‘color_type’ is deprecated (declared at /usr/include/libpng14/png.h:653) */ /* sdata->info_ptr->width = screenshot->width; sdata->info_ptr->height= screenshot->height; sdata->info_ptr->bit_depth = 8; sdata->info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; */ png_set_IHDR(sdata->png_ptr, sdata->info_ptr, screenshot->width, screenshot->height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(sdata->png_ptr, sdata->info_ptr); #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED png_set_invert_alpha(sdata->png_ptr); #endif return 0; }
void read_png(void) { static jmp_buf jbuf; static png_struct *png_ptr; static png_info *info_ptr; FILE *input; int x, y; unsigned int *p; png_bytep line; png_uint_32 i_width, i_height; int depth, color_type; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, &jbuf, NULL, NULL); if (!png_ptr) G_fatal_error("PNG: couldn't allocate PNG structure"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) G_fatal_error("PNG: couldn't allocate PNG structure"); if (setjmp(png_jmpbuf(png_ptr))) G_fatal_error("error reading PNG file"); input = fopen(png.file_name, "rb"); if (!input) G_fatal_error("PNG: couldn't open output file %s", png.file_name); png_init_io(png_ptr, input); png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &i_width, &i_height, &depth, &color_type, NULL, NULL, NULL); if (depth != 8) G_fatal_error("PNG: input file is not 8-bit"); if (i_width != png.width || i_height != png.height) G_fatal_error ("PNG: input file has incorrect dimensions: expected: %dx%d got: %lux%lu", png.width, png.height, (unsigned long) i_width, (unsigned long) i_height); if (png.true_color) { if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) G_fatal_error("PNG: input file is not RGBA"); } else { if (color_type != PNG_COLOR_TYPE_PALETTE) G_fatal_error("PNG: input file is not indexed color"); } if (!png.true_color && png.has_alpha) { png_bytep trans; int num_trans; png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); if (num_trans != 1 || trans[0] != 0) G_fatal_error("PNG: input file has invalid palette"); } if (png.true_color) png_set_invert_alpha(png_ptr); else { png_colorp png_pal; int num_palette; int i; png_get_PLTE(png_ptr, info_ptr, &png_pal, &num_palette); if (num_palette > 256) num_palette = 256; for (i = 0; i < num_palette; i++) { png.palette[i][0] = png_pal[i].red; png.palette[i][1] = png_pal[i].green; png.palette[i][2] = png_pal[i].blue; } } line = G_malloc(png.width * 4); for (y = 0, p = png.grid; y < png.height; y++) { png_bytep q = line; png_read_row(png_ptr, q, NULL); if (png.true_color) for (x = 0; x < png.width; x++, p++) { int r = *q++; int g = *q++; int b = *q++; int a = *q++; unsigned int c = png_get_color(r, g, b, a); *p = c; } else for (x = 0; x < png.width; x++, p++, q++) *p = (png_byte) * q; } G_free(line); png_read_end(png_ptr, NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); fclose(input); }
/* This routine is used for all formats. */ static int png_print_page(gx_device_printer * pdev, FILE * file) { gs_memory_t *mem = pdev->memory; int raster = gdev_prn_raster(pdev); /* PNG structures */ byte *row = gs_alloc_bytes(mem, raster, "png raster buffer"); png_struct *png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_info *info_ptr = png_create_info_struct(png_ptr); int height = pdev->height; int depth = pdev->color_info.depth; int y; int code; /* return code */ char software_key[80]; char software_text[256]; png_text text_png; if (row == 0 || png_ptr == 0 || info_ptr == 0) { code = gs_note_error(gs_error_VMerror); goto done; } /* set error handling */ if (setjmp(png_ptr->jmpbuf)) { /* If we get here, we had a problem reading the file */ code = gs_note_error(gs_error_VMerror); goto done; } code = 0; /* for normal path */ /* set up the output control */ png_init_io(png_ptr, file); /* set the file information here */ info_ptr->width = pdev->width; info_ptr->height = pdev->height; /* resolution is in pixels per meter vs. dpi */ info_ptr->x_pixels_per_unit = (png_uint_32) (pdev->HWResolution[0] * (100.0 / 2.54)); info_ptr->y_pixels_per_unit = (png_uint_32) (pdev->HWResolution[1] * (100.0 / 2.54)); info_ptr->phys_unit_type = PNG_RESOLUTION_METER; info_ptr->valid |= PNG_INFO_pHYs; switch (depth) { case 32: info_ptr->bit_depth = 8; info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; png_set_invert_alpha(png_ptr); { gx_device_pngalpha *ppdev = (gx_device_pngalpha *)pdev; png_color_16 background; background.index = 0; background.red = (ppdev->background >> 16) & 0xff; background.green = (ppdev->background >> 8) & 0xff; background.blue = (ppdev->background) & 0xff; background.gray = 0; png_set_bKGD(png_ptr, info_ptr, &background); } break; case 48: info_ptr->bit_depth = 16; info_ptr->color_type = PNG_COLOR_TYPE_RGB; #if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN) png_set_swap(png_ptr); #endif break; case 24: info_ptr->bit_depth = 8; info_ptr->color_type = PNG_COLOR_TYPE_RGB; break; case 8: info_ptr->bit_depth = 8; if (gx_device_has_color(pdev)) info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; else info_ptr->color_type = PNG_COLOR_TYPE_GRAY; break; case 4: info_ptr->bit_depth = 4; info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; break; case 1: info_ptr->bit_depth = 1; info_ptr->color_type = PNG_COLOR_TYPE_GRAY; /* invert monocrome pixels */ png_set_invert_mono(png_ptr); break; } /* set the palette if there is one */ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { int i; int num_colors = 1 << depth; gx_color_value rgb[3]; info_ptr->palette = (void *)gs_alloc_bytes(mem, 256 * sizeof(png_color), "png palette"); if (info_ptr->palette == 0) { code = gs_note_error(gs_error_VMerror); goto done; } info_ptr->num_palette = num_colors; info_ptr->valid |= PNG_INFO_PLTE; for (i = 0; i < num_colors; i++) { (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev, (gx_color_index) i, rgb); info_ptr->palette[i].red = gx_color_value_to_byte(rgb[0]); info_ptr->palette[i].green = gx_color_value_to_byte(rgb[1]); info_ptr->palette[i].blue = gx_color_value_to_byte(rgb[2]); } } /* add comment */ strncpy(software_key, "Software", sizeof(software_key)); sprintf(software_text, "%s %d.%02d", gs_product, (int)(gs_revision / 100), (int)(gs_revision % 100)); text_png.compression = -1; /* uncompressed */ text_png.key = software_key; text_png.text = software_text; text_png.text_length = strlen(software_text); info_ptr->text = &text_png; info_ptr->num_text = 1; /* write the file information */ png_write_info(png_ptr, info_ptr); /* don't write the comments twice */ info_ptr->num_text = 0; info_ptr->text = NULL; /* Write the contents of the image. */ for (y = 0; y < height; y++) { gdev_prn_copy_scan_lines(pdev, y, row, raster); png_write_rows(png_ptr, &row, 1); } /* write the rest of the file */ png_write_end(png_ptr, info_ptr); /* if you alloced the palette, free it here */ gs_free_object(mem, info_ptr->palette, "png palette"); done: /* free the structures */ png_destroy_write_struct(&png_ptr, &info_ptr); gs_free_object(mem, row, "png raster buffer"); return code; }
int write_PNG(char *filename, int interlace, char borfb) { //hardcore theft from fbgrab.c /* * fbgrab - takes screenshots using the framebuffer. * * (C) Gunnar Monell <*****@*****.**> 2002 * * This program is free Software, see the COPYING file * and is based on Stephan Beyer's <*****@*****.**> FBShot * (C) 2000. * * For features and differences, read the manual page. * * This program has been checked with "splint +posixlib" without * warnings. Splint is available from http://www.splint.org/ . * Patches and enhancements of fbgrab have to fulfill this too. */ png_uint_32 i; int bit_depth=0, color_type; png_uint_32 uheight, uwidth; uheight = (png_uint_32)height; uwidth = (png_uint_32)width; png_bytep row_pointers[uheight]; png_structp png_ptr; png_infop info_ptr; FILE *outfile = fopen(filename, "wb"); interlace = PNG_INTERLACE_NONE; //printf ("%d, %d\n", uheight, uwidth); //well, either from the buffer or the framebuffer... //yih, gotta clean this one up, reallyyyyy // if (borfb == 0) for (i=0; i<uheight; i++) row_pointers[i] = (unsigned char *)(fbp + (BPP*Ox) + (Oy + i) * 1 * (finfo.line_length/*uwidth+10*/)); if (borfb == 1) for (i=0; i<uheight; i++) row_pointers[i] = (unsigned char *)(tmp_buf + (BPP*Ox) + (Oy + i) * 1 * (finfo.line_length/*uwidth+10*/)); if (!outfile){ fprintf (stderr, "Error: Couldn't fopen %s.\n", filename); return -1; } png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL); if (!png_ptr){ fprintf(stderr,"Error: Couldn't create PNG write struct."); return -1; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp) NULL); fprintf(stderr, "Error: Couldn't create PNG info struct."); return -1; } if (setjmp(png_jmpbuf(png_ptr))){ fclose(outfile); png_destroy_write_struct(&png_ptr, &info_ptr); return -2; } png_init_io(png_ptr, outfile); //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); bit_depth = 8; color_type = PNG_COLOR_TYPE_RGB_ALPHA; png_set_IHDR(png_ptr, info_ptr, uwidth, uheight, bit_depth, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); //png_set_packing(png_ptr); png_set_invert_alpha(png_ptr); // //png_set function must be after set_IHDR //according to libpng-manual png_set_filter(png_ptr, 0, PNG_FILTER_NONE); png_set_filler(png_ptr, 0 , PNG_FILLER_BEFORE); png_set_bgr(png_ptr); png_write_info(png_ptr, info_ptr); //printf ("Now writing PNG file\n"); png_write_image(png_ptr, row_pointers); //png_write_rows(png_ptr, row_pointers, uheight); png_write_end(png_ptr, info_ptr); //puh, done, now freeing memory... png_destroy_write_struct(&png_ptr, &info_ptr); if (outfile != NULL) (void) fclose(outfile); //printf("Done writing...\n"); return 0; }
static FIBITMAP * DLL_CALLCONV Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) { png_structp png_ptr = NULL; png_infop info_ptr; png_uint_32 width, height; png_colorp png_palette = NULL; int color_type, palette_entries = 0; int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels FIBITMAP *dib = NULL; RGBQUAD *palette = NULL; // pointer to dib palette png_bytepp row_pointers = NULL; int i; fi_ioStructure fio; fio.s_handle = handle; fio.s_io = io; if (handle) { BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS; try { // check to see if the file is in fact a PNG file BYTE png_check[PNG_BYTES_TO_CHECK]; io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle); if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0) { return NULL; // Bad signature } // create the chunk manage structure png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler); if (!png_ptr) { return NULL; } // create the info structure info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } // init the IO png_set_read_fn(png_ptr, &fio, _ReadProc); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } // because we have already read the signature... png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); // read the IHDR chunk png_read_info(png_ptr, info_ptr); png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); pixel_depth = png_get_bit_depth(png_ptr, info_ptr) * png_get_channels(png_ptr, info_ptr); // get image data type (assume standard image type) FREE_IMAGE_TYPE image_type = FIT_BITMAP; if (bit_depth == 16) { if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) { image_type = FIT_UINT16; } else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) { image_type = FIT_RGB16; } else if ((pixel_depth == 64) && (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) { image_type = FIT_RGBA16; } else { // tell libpng to strip 16 bit/color files down to 8 bits/color png_set_strip_16(png_ptr); bit_depth = 8; } } #ifndef FREEIMAGE_BIGENDIAN if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) { // turn on 16 bit byte swapping png_set_swap(png_ptr); } #endif // set some additional flags switch(color_type) { case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB_ALPHA: #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR // flip the RGB pixels to BGR (or RGBA to BGRA) if(image_type == FIT_BITMAP) { png_set_bgr(png_ptr); } #endif break; case PNG_COLOR_TYPE_PALETTE: // expand palette images to the full 8 bits from 2 bits/pixel if (pixel_depth == 2) { png_set_packing(png_ptr); pixel_depth = 8; } break; case PNG_COLOR_TYPE_GRAY: // expand grayscale images to the full 8 bits from 2 bits/pixel // but *do not* expand fully transparent palette entries to a full alpha channel if (pixel_depth == 2) { png_set_expand_gray_1_2_4_to_8(png_ptr); pixel_depth = 8; } break; case PNG_COLOR_TYPE_GRAY_ALPHA: // expand 8-bit greyscale + 8-bit alpha to 32-bit png_set_gray_to_rgb(png_ptr); #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR // flip the RGBA pixels to BGRA png_set_bgr(png_ptr); #endif pixel_depth = 32; break; default: throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // unlike the example in the libpng documentation, we have *no* idea where // this file may have come from--so if it doesn't have a file gamma, don't // do any correction ("do no harm") if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { double gamma = 0; double screen_gamma = 2.2; if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA) { png_set_gamma(png_ptr, screen_gamma, gamma); } } // all transformations have been registered; now update info_ptr data png_read_update_info(png_ptr, info_ptr); // color type may have changed, due to our transformations color_type = png_get_color_type(png_ptr,info_ptr); // create a DIB and write the bitmap header // set up the DIB palette, if needed switch (color_type) { case PNG_COLOR_TYPE_RGB: png_set_invert_alpha(png_ptr); if(image_type == FIT_BITMAP) { dib = FreeImage_AllocateHeader(header_only, width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } else { dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); } break; case PNG_COLOR_TYPE_RGB_ALPHA: if(image_type == FIT_BITMAP) { dib = FreeImage_AllocateHeader(header_only, width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); } else { dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); } break; case PNG_COLOR_TYPE_PALETTE: dib = FreeImage_AllocateHeader(header_only, width, height, pixel_depth); png_get_PLTE(png_ptr,info_ptr, &png_palette, &palette_entries); palette_entries = MIN((unsigned)palette_entries, FreeImage_GetColorsUsed(dib)); palette = FreeImage_GetPalette(dib); // store the palette for (i = 0; i < palette_entries; i++) { palette[i].rgbRed = png_palette[i].red; palette[i].rgbGreen = png_palette[i].green; palette[i].rgbBlue = png_palette[i].blue; } break; case PNG_COLOR_TYPE_GRAY: dib = FreeImage_AllocateHeaderT(header_only, image_type, width, height, pixel_depth); if(pixel_depth <= 8) { palette = FreeImage_GetPalette(dib); palette_entries = 1 << pixel_depth; for (i = 0; i < palette_entries; i++) { palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = (BYTE)((i * 255) / (palette_entries - 1)); } } break; default: throw FI_MSG_ERROR_UNSUPPORTED_FORMAT; } // store the transparency table if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { // array of alpha (transparency) entries for palette png_bytep trans_alpha = NULL; // number of transparent entries int num_trans = 0; // graylevel or color sample values of the single transparent color for non-paletted images png_color_16p trans_color = NULL; png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color); if((color_type == PNG_COLOR_TYPE_GRAY) && trans_color) { // single transparent color if (trans_color->gray < palette_entries) { BYTE table[256]; memset(table, 0xFF, palette_entries); table[trans_color->gray] = 0; FreeImage_SetTransparencyTable(dib, table, palette_entries); } } else if((color_type == PNG_COLOR_TYPE_PALETTE) && trans_alpha) { // transparency table FreeImage_SetTransparencyTable(dib, (BYTE *)trans_alpha, num_trans); } } // store the background color if (png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) { // Get the background color to draw transparent and alpha images over. // Note that even if the PNG file supplies a background, you are not required to // use it - you should use the (solid) application background if it has one. png_color_16p image_background = NULL; RGBQUAD rgbBkColor; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) { rgbBkColor.rgbRed = (BYTE)image_background->red; rgbBkColor.rgbGreen = (BYTE)image_background->green; rgbBkColor.rgbBlue = (BYTE)image_background->blue; rgbBkColor.rgbReserved = 0; FreeImage_SetBackgroundColor(dib, &rgbBkColor); } } // get physical resolution if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) { png_uint_32 res_x, res_y; // we'll overload this var and use 0 to mean no phys data, // since if it's not in meters we can't use it anyway int res_unit_type = PNG_RESOLUTION_UNKNOWN; png_get_pHYs(png_ptr,info_ptr, &res_x, &res_y, &res_unit_type); if (res_unit_type == PNG_RESOLUTION_METER) { FreeImage_SetDotsPerMeterX(dib, res_x); FreeImage_SetDotsPerMeterY(dib, res_y); } } // get possible ICC profile if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) { png_charp profile_name = NULL; png_bytep profile_data = NULL; png_uint_32 profile_length = 0; int compression_type; png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length); // copy ICC profile data (must be done after FreeImage_AllocateHeader) FreeImage_CreateICCProfile(dib, profile_data, profile_length); } // --- header only mode => clean-up and return if (header_only) { // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } // set the individual row_pointers to point at the correct offsets row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep)); if (!row_pointers) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); FreeImage_Unload(dib); return NULL; } // read in the bitmap bits via the pointer table // allow loading of PNG with minor errors (such as images with several IDAT chunks) for (png_uint_32 k = 0; k < height; k++) { row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k); } png_set_benign_errors(png_ptr, 1); png_read_image(png_ptr, row_pointers); // check if the bitmap contains transparency, if so enable it in the header if (FreeImage_GetBPP(dib) == 32) { if (FreeImage_GetColorType(dib) == FIC_RGBALPHA) { FreeImage_SetTransparent(dib, TRUE); } else { FreeImage_SetTransparent(dib, FALSE); } } // cleanup if (row_pointers) { free(row_pointers); row_pointers = NULL; } // read the rest of the file, getting any additional chunks in info_ptr png_read_end(png_ptr, info_ptr); // get possible metadata (it can be located both before and after the image data) ReadMetadata(png_ptr, info_ptr, dib); if (png_ptr) { // clean up after the read, and free any memory allocated - REQUIRED png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } return dib; } catch (const char *text) { if (png_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); } if (row_pointers) { free(row_pointers); } if (dib) { FreeImage_Unload(dib); } FreeImage_OutputMessageProc(s_format_id, text); return NULL; } } return NULL; }
void set_invert_alpha() const { TRACE_IO_TRANSFORM("png_set_invert_alpha\n"); png_set_invert_alpha(m_png); }
void write_png(void) { static jmp_buf jbuf; static png_struct *png_ptr; static png_info *info_ptr; FILE *output; int x, y; unsigned int *p; png_bytep line; const char *str; int compress; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &jbuf, NULL, NULL); if (!png_ptr) G_fatal_error("PNG: couldn't allocate PNG structure"); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) G_fatal_error("PNG: couldn't allocate PNG structure"); if (setjmp(png_jmpbuf(png_ptr))) G_fatal_error("error writing PNG file"); output = fopen(png.file_name, "wb"); if (!output) G_fatal_error("PNG: couldn't open output file %s", png.file_name); png_set_write_fn(png_ptr, output, write_data, output_flush); png_set_IHDR(png_ptr, info_ptr, png.width, png.height, 8, png.true_color ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (png.true_color) png_set_invert_alpha(png_ptr); else { png_color png_pal[256]; int i; for (i = 0; i < 256; i++) { png_pal[i].red = png.palette[i][0]; png_pal[i].green = png.palette[i][1]; png_pal[i].blue = png.palette[i][2]; } png_set_PLTE(png_ptr, info_ptr, png_pal, 256); if (png.has_alpha) { png_byte trans = (png_byte) 0; png_set_tRNS(png_ptr, info_ptr, &trans, 1, NULL); } } str = getenv("GRASS_PNG_COMPRESSION"); if (str && sscanf(str, "%d", &compress) == 1) png_set_compression_level(png_ptr, compress); png_write_info(png_ptr, info_ptr); line = G_malloc(png.width * 4); for (y = 0, p = png.grid; y < png.height; y++) { png_bytep q = line; if (png.true_color) for (x = 0; x < png.width; x++, p++) { unsigned int c = *p; int r, g, b, a; png_get_pixel(c, &r, &g, &b, &a); *q++ = (png_byte) r; *q++ = (png_byte) g; *q++ = (png_byte) b; *q++ = (png_byte) a; } else for (x = 0; x < png.width; x++, p++, q++) *q = (png_byte) * p; png_write_row(png_ptr, line); } G_free(line); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); fclose(output); }
pointer PNG_READ_IMAGE(register context *ctx, int n, register pointer *argv) { char *file_name; pointer ret, image_ptr; ckarg(1); if (isstring(argv[0])) file_name = argv[0]->c.str.chars; else error(E_NOSTRING); FILE *fp = fopen(file_name, "rb"); if (!fp) { error(E_OPENFILE); return(NIL); } png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); info_ptr = png_create_info_struct(png_ptr); if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); error(E_EOF); return(NIL); } png_init_io(png_ptr, fp); png_read_info(png_ptr, info_ptr); int width = png_get_image_width(png_ptr, info_ptr); int height = png_get_image_height(png_ptr, info_ptr); int bit_depth = png_get_bit_depth(png_ptr, info_ptr); int channels = png_get_channels(png_ptr, info_ptr); int color_type = png_get_color_type(png_ptr, info_ptr); //fprintf(stderr, "bit_depth = %d, channels %d, color_type =%d (pal:%d,gray:%d,rgb:%d,rgba:%d)\n", bit_depth, channels, color_type, PNG_COLOR_TYPE_PALETTE,PNG_COLOR_TYPE_GRAY,PNG_COLOR_TYPE_RGB,PNG_COLOR_TYPE_RGB_ALPHA); switch (color_type) { case PNG_COLOR_TYPE_PALETTE: png_set_palette_to_rgb(png_ptr); break; case PNG_COLOR_TYPE_GRAY: #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED if ( bit_depth < 8) png_set_gray_to_rgb(png_ptr); #else if ( bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr); #endif break; case PNG_COLOR_TYPE_RGB: //png_set_bgr(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); // 16bit -> 8bit break; case PNG_COLOR_TYPE_RGB_ALPHA: if (bit_depth == 16) png_set_strip_16(png_ptr); // 16bit -> 8bit png_set_invert_alpha(png_ptr); //png_set_bgr(png_ptr); //png_set_strip_alpha(png_ptr); // RGBA -> rgb , GA -> g png_color_16 my_background = {0xff, 0xff, 0xff, 0xff, 0xff}; png_set_background(png_ptr, &my_background, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); break; } png_read_update_info(png_ptr, info_ptr); width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr);; bit_depth = png_get_bit_depth(png_ptr, info_ptr); channels = png_get_channels(png_ptr, info_ptr); color_type = png_get_color_type(png_ptr, info_ptr); png_bytep * row_pointers = (png_bytep *)malloc(height*sizeof(png_bytep)); int y, byte_per_scanline = png_get_rowbytes(png_ptr, info_ptr); image_ptr = makebuffer(height*byte_per_scanline); for(y=0;y<height;y++){ row_pointers[y] = image_ptr->c.str.chars+y*byte_per_scanline; } png_read_image(png_ptr, row_pointers); free(row_pointers); png_read_end(png_ptr,info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); ret=cons(ctx,image_ptr,NIL); ret=cons(ctx,makeint(channels),ret); ret=cons(ctx,makeint(height),ret); ret=cons(ctx,makeint(width),ret); return (ret); }
void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { int row; if(png_ptr == NULL) return; #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif png_read_info(png_ptr, info_ptr); if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error(png_ptr,"Image is too high to process with png_read_png()"); #if defined(PNG_READ_16_TO_8_SUPPORTED) if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); #endif #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) if (transforms & PNG_TRANSFORM_STRIP_ALPHA) png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) if (transforms & PNG_TRANSFORM_PACKSWAP) png_set_packswap(png_ptr); #endif #if defined(PNG_READ_EXPAND_SUPPORTED) if (transforms & PNG_TRANSFORM_EXPAND) if ((png_ptr->bit_depth < 8) || (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_expand(png_ptr); #endif #if defined(PNG_READ_INVERT_SUPPORTED) if (transforms & PNG_TRANSFORM_INVERT_MONO) png_set_invert_mono(png_ptr); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) if ((transforms & PNG_TRANSFORM_SHIFT) && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); } #endif #if defined(PNG_READ_BGR_SUPPORTED) if (transforms & PNG_TRANSFORM_BGR) png_set_bgr(png_ptr); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) if (transforms & PNG_TRANSFORM_SWAP_ALPHA) png_set_swap_alpha(png_ptr); #endif #if defined(PNG_READ_SWAP_SUPPORTED) if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif png_read_update_info(png_ptr, info_ptr); #ifdef PNG_FREE_ME_SUPPORTED png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); #endif if(info_ptr->row_pointers == NULL) { info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); #ifdef PNG_FREE_ME_SUPPORTED info_ptr->free_me |= PNG_FREE_ROWS; #endif for (row = 0; row < (int)info_ptr->height; row++) { info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); } } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; png_read_end(png_ptr, info_ptr); transforms = transforms; params = params; }
static int Write_PNG(struct picture * pict, char *filename, int interlace, int gray){ png_bytep *row_pointers; png_structp png_ptr; png_infop info_ptr; png_text txt_ptr[4]; int i; int bit_depth=0, color_type; FILE *OUTfd = fopen(filename, "wb"); #ifdef DEBUG i=open("pict.bin",O_CREAT|O_WRONLY|O_TRUNC); fprintf(stdout, "%i\n",write(i,(void*)pict->buffer,(pict->xres)*(pict->yres))); perror("dupa"); fprintf(stdout, "Writing to %s %ix%i %i\n", filename,(pict->xres),(pict->yres),(pict->xres)*(pict->yres)); fprintf(stdout, "start: %i, size: %i\n", pict->colormap->start,pict->colormap->len); fflush(stdout); close(i); #endif if (!OUTfd) FatalError("couldn't open output file"); png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL); if (!png_ptr) FatalError("couldn't create PNG write struct."); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr){ png_destroy_write_struct(&png_ptr, (png_infopp)NULL); FatalError("couldn't create PNG info struct."); } /* host_info=(struct utsname*)malloc(sizeof(struct utsname)); uname(host_info);*/ unsigned char pdate[21]; time_t ptime=time(NULL); struct tm *ltime=localtime(&ptime); sprintf(pdate,"%04d/%02d/%02d %02d:%02d:%02d",ltime->tm_year+1900,ltime->tm_mon+1,ltime->tm_mday,ltime->tm_hour,ltime->tm_min,ltime->tm_sec); txt_ptr[0].key="Name"; txt_ptr[0].text="LC-Display screenshot"; txt_ptr[0].compression=PNG_TEXT_COMPRESSION_NONE; txt_ptr[1].key="Date"; txt_ptr[1].text=pdate; txt_ptr[1].compression=PNG_TEXT_COMPRESSION_NONE; txt_ptr[2].key="Hostname"; txt_ptr[2].text="DBox2"; txt_ptr[2].compression=PNG_TEXT_COMPRESSION_NONE; txt_ptr[3].key="Program"; txt_ptr[3].text=PACKAGE" v."VERSION" by "MAINTAINER_NAME; txt_ptr[3].compression=PNG_TEXT_COMPRESSION_NONE; png_set_text(png_ptr, info_ptr, txt_ptr, 4); png_init_io(png_ptr, OUTfd); png_set_compression_level(png_ptr, (compression)?Z_BEST_COMPRESSION:Z_NO_COMPRESSION); row_pointers=(png_bytep*)malloc(sizeof(png_bytep)*pict->yres); bit_depth=8; color_type=(gray)?PNG_COLOR_TYPE_GRAY:PNG_COLOR_TYPE_RGB; for (i=0; i<(pict->yres); i++) row_pointers[i]=pict->buffer+i*((gray)?1:3)*(pict->xres); png_set_invert_alpha(png_ptr); png_set_IHDR(png_ptr, info_ptr, pict->xres, pict->yres, bit_depth, color_type, interlace, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, info_ptr); /* puh, done, now freeing memory... */ png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); fclose(OUTfd); return 0; }
int loadPNG(ePtr<gPixmap> &result, const char *filename) { __u8 header[8]; FILE *fp=fopen(filename, "rb"); if (!fp) { // eDebug("couldn't open %s", filename ); return 0; } if (!fread(header, 8, 1, fp)) { eDebug("couldn't read"); fclose(fp); return 0; } if (png_sig_cmp(header, 0, 8)) { fclose(fp); return 0; } png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!png_ptr) { eDebug("no pngptr"); fclose(fp); return 0; } png_infop info_ptr=png_create_info_struct(png_ptr); if (!info_ptr) { eDebug("no info ptr"); png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0); fclose(fp); return 0; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { eDebug("no end"); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(fp); return 0; } if (setjmp(png_ptr->jmpbuf)) { eDebug("das war wohl nix"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); result = 0; return 0; } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); png_set_invert_alpha(png_ptr); png_read_info(png_ptr, info_ptr); png_uint_32 width, height; int bit_depth; int color_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); if (color_type == PNG_COLOR_TYPE_GRAY || color_type & PNG_COLOR_MASK_PALETTE) { result=new gPixmap(eSize(width, height), bit_depth); gSurface *surface = result->surface; png_bytep *rowptr=new png_bytep[height]; for (unsigned int i=0; i<height; i++) rowptr[i]=((png_byte*)(surface->data))+i*surface->stride; png_read_rows(png_ptr, rowptr, 0, height); delete [] rowptr; if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_color *palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); if (num_palette) surface->clut.data=new gRGB[num_palette]; else surface->clut.data=0; surface->clut.colors=num_palette; for (int i=0; i<num_palette; i++) { surface->clut.data[i].a=0; surface->clut.data[i].r=palette[i].red; surface->clut.data[i].g=palette[i].green; surface->clut.data[i].b=palette[i].blue; } if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { png_byte *trans; png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0); for (int i=0; i<num_palette; i++) surface->clut.data[i].a=255-trans[i]; } } else { surface->clut.data=0; surface->clut.colors=0; } surface->clut.start=0; png_read_end(png_ptr, end_info); #ifndef BUILD_VUPLUS } else { result=0; eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type); } #else //csh Support for 32bit png file. }else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA && bit_depth == 8){
int convertToPNG(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, const char* png) { AbstractFile* imageFile; FILE *fp = fopen(png, "wb"); if(!fp) return -1; if(key != NULL) { imageFile = openAbstractFile2(imageWrapper, key, iv); } else { imageFile = openAbstractFile(imageWrapper); } InfoIBootIM* info = (InfoIBootIM*) (imageFile->data); png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn); if (!png_ptr) { return -1; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return -1; } png_init_io(png_ptr, fp); int color_type; int bytes_per_pixel; if(info->header.format == IBOOTIM_ARGB) { XLOG(3, "ARGB"); color_type = PNG_COLOR_TYPE_RGB_ALPHA; bytes_per_pixel = 4; } else if(info->header.format == IBOOTIM_GREY) { XLOG(3, "Grayscale"); color_type = PNG_COLOR_TYPE_GRAY_ALPHA; bytes_per_pixel = 2; } else { XLOG(3, "Unknown color type!"); } png_set_IHDR(png_ptr, info_ptr, info->header.width, info->header.height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_bgr(png_ptr); png_set_invert_alpha(png_ptr); png_write_info(png_ptr, info_ptr); void* imageBuffer = malloc(imageFile->getLength(imageFile)); imageFile->read(imageFile, imageBuffer, imageFile->getLength(imageFile)); png_bytepp row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info->header.height); int i; for(i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) { row_pointers[i] = imageBuffer + (info->header.width * bytes_per_pixel * i); } png_write_image(png_ptr, row_pointers); png_write_end(png_ptr, NULL); free(imageBuffer); return 0; }
int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); setvbuf(stdout, (char*)NULL, _IONBF, 0); if(argc != 4) { fprintf(stderr, MSG[I_HELP1], argv[0]); fputs(MSG[I_HELP2], stderr); return EXIT_FAILURE; } char *inname = argv[1], *outname = argv[2], *valarg = argv[3]; /* Quelldatei oeffnen und auf PNG-Signatur ueberpruefen **********************/ puts(MSG[I_OPEN]); FILE *f; f = fopen(inname, "rb"); if (f == NULL) { fputs(inname, stderr); fputs(MSG[E_OPEN], stderr); fputc('\n', stderr); return EXIT_FAILURE; } unsigned char sig[SIG_BYTES]; fread(sig, 1, SIG_BYTES, f); if (png_sig_cmp(sig, 0, SIG_BYTES)) { fputs(inname, stderr); fputs(MSG[E_CORRUPTED], stderr); fputc('\n', stderr); fclose(f); return EXIT_FAILURE; } /* PNG-Lesevorgang initialisieren *****************************************/ png_struct *png_ptr; png_info *info_ptr, *end_info; png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); if (png_ptr == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); fclose(f); return EXIT_FAILURE; } info_ptr = png_create_info_struct(png_ptr); end_info = png_create_info_struct(png_ptr); try_png_read( (info_ptr == NULL) || (end_info == NULL), &png_ptr, &info_ptr, &end_info, f, (char*)NULL ); try_png_read( setjmp(png_jmpbuf(png_ptr)), &png_ptr, &info_ptr, &end_info, f, MSG[E_READ] ); png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, SIG_BYTES); /* Bildinfo lesen: Bilddimensionen und ggf. Farbpalette. * Palette ggf. konvertieren. *********************************************/ long int width, height, pwidth, pheight; // png_uint_32 width, height, pwidth, pheight; comp_t *image, **row, *rwp; png_read_info(png_ptr, info_ptr); width = info_ptr->width; height = info_ptr->height; const long int original_width = info_ptr->width; const int bit_depth = info_ptr->bit_depth, color_type = info_ptr->color_type; const bool image_is_pal = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE); const bool image_is_gray = ( (color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ); const bool alpha = ( (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (color_type == PNG_COLOR_TYPE_RGB_ALPHA) ); int num_palette = 0; png_color *png_pal_got = NULL; if (image_is_pal) try_png_read( !png_get_PLTE(png_ptr, info_ptr, &png_pal_got, &num_palette), &png_ptr, &info_ptr, &end_info, f, MSG[E_READPAL] ); png_color png_pal[num_palette]; comp_t comp_pal[num_palette]; if (image_is_pal) for (int i = 0; i < num_palette; i++) { png_pal[i] = png_pal_got[i]; comp_t c; c = png_pal[i].red; c <<= CHAR_BIT; c |= png_pal[i].green; c <<= CHAR_BIT; c |= png_pal[i].blue; comp_pal[i] = c; } png_color_16 *img_bkgd; png_color_16 background; if (png_get_bKGD(png_ptr, info_ptr, &img_bkgd)) background = *img_bkgd; /* Parameter fuer Groessenaenderung auswerten: * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher), * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ******************/ long int diff; bool vert; bool aspp = false, asp2 = false, enlg = false, sign = true; switch (tolower(*valarg++)) { case 'h': vert = false; break; case 'v': vert = true; break; case '%': aspp = true; break; case '@': asp2 = true; break; default : try_png_read(true, &png_ptr, &info_ptr, &end_info, f, MSG[E_DIM]); } switch (*valarg) { case '+': enlg = true; break; case '-': enlg = false; break; default: sign = false; break; } diff = atol(valarg); bool valargok = !!diff; if (aspp || asp2) { try_png_read(!sign, &png_ptr, &info_ptr, &end_info, f, MSG[E_SIGN]); const float fheight = (float)height, fwidth = (float)width, casp = fheight / fwidth; float nasp; if (asp2) { const char *aspsw = strtok(valarg, ":"), *aspsh = strtok((char*)NULL, ":"); valargok = ((aspsw != NULL) && (aspsh != NULL)); const float aspw = valargok? atol(aspsw): 0, asph = valargok? atol(aspsh): 0; nasp = valargok? fabs(asph / aspw): 0; } else nasp = ((float)labs(diff) / 100.0f); vert = ((nasp < casp) ^ enlg); diff = valargok? labs(vert? (height - (fwidth * nasp)): (width - (fheight / nasp)) ): 0; if (!enlg) diff = -diff; } if (!diff) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); if (valargok) { puts(MSG[I_NOTHINGTODO]); // const char copycmd[] = "copy /b /y"; const char copycmd[] = "cp"; char copycmdln[ strlen(copycmd) + strlen(argv[1]) + strlen(argv[2]) + 7 ]; sprintf( copycmdln, "%s \"%s\" \"%s\"", copycmd, argv[1], argv[2] ); return system(copycmdln); } try_png_read(!valargok, &png_ptr, &info_ptr, &end_info, f, MSG[E_PAR]); } if (!(aspp || asp2 || sign)) diff -= vert? height: width; try_png_read( labs(diff) > (vert? height: width), &png_ptr, &info_ptr, &end_info, f, MSG[E_SIZE] ); /* Bild- sowie Zeilenzeigerspeicher anfordern und Zeiger setzen. **********/ image = malloc(width * height * sizeof(comp_t)); try_png_read(image == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL); row = malloc(height * sizeof(comp_t*)); try_png_read(row == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL); rwp = image; for (int i = 0; i < height; i++) { row[i] = rwp; rwp += width; } /* Bild laden. * Falls Alphakanal vorhanden, Alpha invertieren: hoher Wert => hohe Deckung. * Falls Nicht-Palettenbild ohne Alphakanal (24 bpp) oder Graubild * (8 oder 16 bpp), mit "png_set_filler" die Bilddaten auf 32 bzw. 16 bpp * ausweiten. 32 Bit ist die * comp_t-Breite. ****************************/ puts(MSG[I_LOAD]); if (alpha) png_set_invert_alpha(png_ptr); else if (!image_is_pal) png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); png_read_image(png_ptr, (void*)row); /* Falls 8 oder 16 bpp, Bilddaten auf "Pixel = comp_t-Element" ausweiten. */ // trw: Temporaere Zeile. void *trw = malloc(image_is_gray? (width * 2): width); try_png_read(trw == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL); // Zunaechst Bildzeile nach Temporaerzeile kopieren, dann Elemente einzeln zurueck. if (image_is_pal) { for (int i = 0; i < height; i++) { uint8_t *trwp = trw; rwp = row[i]; memcpy(trw, row[i], width * sizeof *trwp); for (int j = 0; j < width; j++) *rwp++ = *trwp++; } } if (image_is_gray) { for (int i = 0; i < height; i++) { uint16_t *trwp = trw; rwp = row[i]; memcpy(trw, row[i], width * sizeof *trwp); for (int j = 0; j < width; j++) *rwp++ = *trwp++; } } /* Lesevorgang beenden und Quelldatei schliessen. ************************/ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); printf( "%s: %d*%d > %d*%d: %s %+d\n", MSG[I_MEASURES], width, height, vert? width: width + diff, vert? height + diff: height, vert? MSG[I_VERT]: MSG[I_HORI], diff ); /* Hier kommt Fugenschnitzer zum Einsatz. * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher), * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ****************/ sc_init(); sc_load(image, &width, &height, 0); const int prep = sc_prepare( vert, diff, // Bild ggf. erweitern false, alpha? MARK_ALPHA: MARK_KEEP, // Ggf. Alpha-Markierung (mark_t*)NULL, // keine Markierung sonst &width, &height, &pwidth, &pheight ); if (prep < 0) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); free(image); free(row); return EXIT_FAILURE; } if (prep & 2) puts(MSG[E_ALPHA]); // Bildspeicher erweitern, falls das Bild vergroessert wurde: if (prep & 1) { image = realloc(image, (size_t)width * (size_t)height * sizeof(comp_t)); if (image == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); return EXIT_FAILURE; } if (vert) { row = realloc(row, (size_t)height * sizeof(comp_t*)); if (row == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); free(image); return EXIT_FAILURE; } } } pthread_t seam_th; pthread_create(&seam_th, NULL, seam_progress, (void*)(&diff)); // sc_seam(diff); seam_paral(diff); pthread_join(seam_th, NULL); putchar('\n'); printf(MSG[I_RESIZING]); // sc_carve(diff, &width, &height, &pwidth, &pheight); carve_paral(diff, &width, &height, &pwidth, &pheight); sc_fix( false, // Nicht wiederherstellen &width, &height, &pwidth, &pheight ); sc_eject(image); sc_close(); /* Das war's mit Fugenschnitzer. -- Zeilenzeiger neu setzen. **************/ rwp = image; for (int i = 0; i < height; i++) { row[i] = rwp; rwp += width; } /* Zieldatei oeffnen und Schreibvorgang initialisieren. ********************/ putchar('\n'); printf(MSG[I_SAVE]); f = fopen(outname, "wb"); if (f == NULL) { fputs(outname, stderr); fputs(MSG[E_SAVE], stderr); fputc('\n', stderr); return EXIT_FAILURE; } png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL ); if (png_ptr == NULL) { fputs(MSG[E_GENERIC], stderr); fputc('\n', stderr); fclose(f); return EXIT_FAILURE; } info_ptr = png_create_info_struct(png_ptr); try_png_write(info_ptr == NULL, &png_ptr, &info_ptr, f, (char*)NULL); try_png_write( setjmp(png_jmpbuf(png_ptr)), &png_ptr, &info_ptr, f, MSG[E_WRITE] ); png_init_io(png_ptr, f); /* Bildparameter setzen. **************************************************/ png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT ); if (image_is_pal) png_set_PLTE(png_ptr, info_ptr, png_pal, num_palette); if (alpha) png_set_bKGD(png_ptr, info_ptr, &background); png_write_info(png_ptr, info_ptr); /* Falls 8 oder 16 bpp, Bilddaten wieder zusammenschieben. ****************/ trw = realloc(trw, image_is_gray? (width * 2): width); try_png_write(trw == NULL, &png_ptr, &info_ptr, f, (char*)NULL); if (image_is_pal) { for (int i = 0; i < height; i++) { uint8_t *trwp = trw; rwp = row[i]; for (int j = 0; j < width; j++) *trwp++ = *rwp++; memcpy(row[i], trw, width * sizeof *trwp); } } if (image_is_gray) { for (int i = 0; i < height; i++) { uint16_t *trwp = trw; rwp = row[i]; for (int j = 0; j < width; j++) *trwp++ = *rwp++; memcpy(row[i], trw, width * sizeof *trwp); } } /* Bild speichern. Wieder Alpha invertieren (hoher Wert => hohe Transparenz) * sowie mit "png_set_filler" 32/16 bpp => 24/8 bpp setzen. ***************/ if (alpha) png_set_invert_alpha(png_ptr); else png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); png_write_image(png_ptr, (void*)row); png_write_end(png_ptr, (png_info*)NULL); puts(MSG[I_FINISHED]); /* Schreibvorgang beenden, Datei schliessen, Speicher freigeben, fertig. ***/ png_destroy_write_struct(&png_ptr, &info_ptr); fclose(f); free(trw); free(image); free(row); puts(MSG[I_COMPLETED]); return EXIT_SUCCESS; }
void* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) { AbstractFile* imageFile; unsigned char header[8]; InfoIBootIM* info; png_uint_32 i; png_bytepp row_pointers; uint8_t* imageBuffer; void* buffer; png->read(png, header, 8); if(png_sig_cmp(header, 0, 8) != 0) { XLOG(0, "error: not a valid png file\n"); return NULL; } png->seek(png, 0); png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn); if (!png_ptr) { return NULL; } png_infop info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); return NULL; } png_infop end_info = png_create_info_struct(png_ptr); if (!end_info) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { XLOG(0, "error reading png\n"); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); free(buffer); return NULL; } png_set_read_fn(png_ptr, png, pngRead); png_read_info(png_ptr, info_ptr); if(png_get_bit_depth(png_ptr, info_ptr) > 8) { XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", png_get_bit_depth(png_ptr, info_ptr)); } if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY || png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) { XLOG(0, "notice: attempting to add dummy transparency channel\n"); } if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "notice: attempting to expand palette into full rgb\n"); } png_set_expand(png_ptr); png_set_strip_16(png_ptr); png_set_bgr(png_ptr); png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER); png_set_invert_alpha(png_ptr); png_read_update_info(png_ptr, info_ptr); if(png_get_image_width(png_ptr, info_ptr) > 320 || png_get_image_height(png_ptr, info_ptr) > 480) { XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", png_get_image_width(png_ptr, info_ptr), png_get_image_height(png_ptr, info_ptr)); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(png_get_bit_depth(png_ptr, info_ptr) != 8) { XLOG(0, "error: bit depth per channel must be 8 not %d!\n", png_get_bit_depth(png_ptr, info_ptr)); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } if(png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_GRAY_ALPHA && png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB_ALPHA) { XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n"); if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY || png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) { XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n"); } if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) { XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n"); } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); return NULL; } row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * png_get_image_height(png_ptr, info_ptr)); imageBuffer = malloc(png_get_image_height(png_ptr, info_ptr) * png_get_rowbytes(png_ptr, info_ptr)); for(i = 0; i < png_get_image_height(png_ptr, info_ptr); i++) { row_pointers[i] = imageBuffer + (png_get_rowbytes(png_ptr, info_ptr) * i); } png_read_image(png_ptr, row_pointers); png_read_end(png_ptr, end_info); buffer = malloc(1); *fileSize = 0; if(key != NULL) { imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL); } else { imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize)); } info = (InfoIBootIM*) (imageFile->data); info->header.width = (uint16_t) png_get_image_width(png_ptr, info_ptr); info->header.height = (uint16_t) png_get_image_height(png_ptr, info_ptr); if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA) { info->header.format = IBOOTIM_GREY; } else { info->header.format = IBOOTIM_ARGB; } imageFile->write(imageFile, imageBuffer, png_get_image_height(png_ptr, info_ptr) * png_get_rowbytes(png_ptr, info_ptr)); imageFile->close(imageFile); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); png->close(png); free(row_pointers); free(imageBuffer); return buffer; }
void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { int row; if (png_ptr == NULL) return; /* png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error(png_ptr, "Image is too high to process with png_read_png()"); /* -------------- image transformations start here ------------------- */ #ifdef PNG_READ_16_TO_8_SUPPORTED /* Tell libpng to strip 16 bit/color files down to 8 bits per color. */ if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); #endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED /* Strip alpha bytes from the input data without combining with * the background (not recommended). */ if (transforms & PNG_TRANSFORM_STRIP_ALPHA) png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif #ifdef PNG_READ_PACKSWAP_SUPPORTED /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ if (transforms & PNG_TRANSFORM_PACKSWAP) png_set_packswap(png_ptr); #endif #ifdef PNG_READ_EXPAND_SUPPORTED /* Expand paletted colors into true RGB triplets * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel * Expand paletted or RGB images with transparency to full alpha * channels so the data will be available as RGBA quartets. */ if (transforms & PNG_TRANSFORM_EXPAND) if ((png_ptr->bit_depth < 8) || (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_expand(png_ptr); #endif /* We don't handle background color or gamma transformation or quantizing. */ #ifdef PNG_READ_INVERT_SUPPORTED /* Invert monochrome files to have 0 as white and 1 as black */ if (transforms & PNG_TRANSFORM_INVERT_MONO) png_set_invert_mono(png_ptr); #endif #ifdef PNG_READ_SHIFT_SUPPORTED /* If you want to shift the pixel values from the range [0,255] or * [0,65535] to the original [0,7] or [0,31], or whatever range the * colors were originally in: */ if ((transforms & PNG_TRANSFORM_SHIFT) && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); } #endif #ifdef PNG_READ_BGR_SUPPORTED /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ if (transforms & PNG_TRANSFORM_BGR) png_set_bgr(png_ptr); #endif #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) png_set_swap_alpha(png_ptr); #endif #ifdef PNG_READ_SWAP_SUPPORTED /* Swap bytes of 16 bit files to least significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif /* Added at libpng-1.2.41 */ #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED /* Invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif /* Added at libpng-1.2.41 */ #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* Expand grayscale image to RGB */ if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) png_set_gray_to_rgb(png_ptr); #endif /* We don't handle adding filler bytes */ /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (i.e., you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); /* -------------- image transformations end here ------------------- */ png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); if (info_ptr->row_pointers == NULL) { png_uint_32 iptr; info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); for (iptr=0; iptr<info_ptr->height; iptr++) info_ptr->row_pointers[iptr] = NULL; info_ptr->free_me |= PNG_FREE_ROWS; for (row = 0; row < (int)info_ptr->height; row++) info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); transforms = transforms; /* Quiet compiler warnings */ params = params; }
void ZLEwlImageManager::convertImageDirectPng(const std::string &stringData, ZLImageData &data) const { struct s_my_png my_png; my_png.p = (char*)stringData.data(); my_png.size = stringData.length(); png_structp png_ptr = NULL; png_infop info_ptr = NULL; unsigned int *row = NULL; png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)&my_png, mypng_error_func, mypng_warning_func); if ( !png_ptr ) return; if (setjmp( png_ptr->jmpbuf )) { data.init(0, 0); if (png_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); } if ( row ) delete row; return; } info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) mypng_error_func(png_ptr, "cannot create png info struct"); png_set_read_fn(png_ptr, (voidp)&my_png, mypng_read_func); png_read_info( png_ptr, info_ptr ); png_uint_32 width, height; int bit_depth, color_type, interlace_type; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL); data.init(width, height); row = new unsigned int[ width ]; // SET TRANSFORMS if (color_type & PNG_COLOR_MASK_PALETTE) png_set_palette_to_rgb(png_ptr); 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 (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_invert_alpha(png_ptr); } else { png_color_16 bg = {0, 0xffff, 0xffff, 0xffff, 0xffff}; png_set_background(png_ptr, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 0.0); png_set_strip_alpha(png_ptr); } if (bit_depth < 8) png_set_packing(png_ptr); //if (color_type == PNG_COLOR_TYPE_RGB) //png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); //if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) // png_set_swap_alpha(png_ptr); if (! (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) png_set_rgb_to_gray(png_ptr, 1, -1, -1); int number_passes = png_set_interlace_handling(png_ptr); //if (color_type == PNG_COLOR_TYPE_RGB_ALPHA || // color_type == PNG_COLOR_TYPE_GRAY_ALPHA) //if (color_type == PNG_COLOR_TYPE_RGB || // color_type == PNG_COLOR_TYPE_RGB_ALPHA) png_set_bgr(png_ptr); ZLIntegerOption myDitherAlgo(ZLCategoryKey::LOOK_AND_FEEL, "Options", "DitherAlgo", 0); register int dalgo = myDitherAlgo.value(); char *c; for(int pass = 0; pass < number_passes; pass++) { for(unsigned int y = 0; y < height; y++) { png_read_rows(png_ptr, (unsigned char **)&row, png_bytepp_NULL, 1); c = ((ZLEwlImageData&)data).getImageData() + width * y; if ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { unsigned char *s = (unsigned char*)row; if(dalgo == 1) for(unsigned int i = 0; i < width; i++) *c++ = Dither2BitColor(*(++s)++, i, y); else for(unsigned int i = 0; i < width; i++) *c++ = *(++s)++; } else if(dalgo == 1) { unsigned char *s = (unsigned char*)row; for(unsigned int i = 0; i < width; i++) *c++ = Dither2BitColor(*s++, i, y); } else memcpy(c, (char*)row, width); } } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); }