static gint gegl_buffer_import_png (GeglBuffer *gegl_buffer, GInputStream *stream, gint dest_x, gint dest_y, gint *ret_width, gint *ret_height, const Babl *format, // can be NULL GError **err) { gint width; gint bit_depth; gint bpp; gint number_of_passes=1; png_uint_32 w; png_uint_32 h; png_structp load_png_ptr; png_infop load_info_ptr; guchar *pixels; /*png_bytep *rows;*/ unsigned int i; png_bytep *row_p = NULL; g_return_val_if_fail(stream, -1); if (!check_valid_png_header(stream, err)) { return -1; } load_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, error_fn, NULL); if (!load_png_ptr) { return -1; } load_info_ptr = png_create_info_struct (load_png_ptr); if (!load_info_ptr) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return -1; } if (setjmp (png_jmpbuf (load_png_ptr))) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); if (row_p) g_free (row_p); return -1; } png_set_read_fn(load_png_ptr, stream, read_fn); png_set_sig_bytes (load_png_ptr, 8); // we already read header png_read_info (load_png_ptr, load_info_ptr); { int color_type; int interlace_type; png_get_IHDR (load_png_ptr, load_info_ptr, &w, &h, &bit_depth, &color_type, &interlace_type, NULL, NULL); width = w; if (ret_width) *ret_width = w; if (ret_height) *ret_height = h; if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { png_set_expand (load_png_ptr); bit_depth = 8; } if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha (load_png_ptr); color_type |= PNG_COLOR_MASK_ALPHA; } switch (color_type) { case PNG_COLOR_TYPE_GRAY: bpp = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: bpp = 2; break; case PNG_COLOR_TYPE_RGB: bpp = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: bpp = 4; break; case (PNG_COLOR_TYPE_PALETTE | PNG_COLOR_MASK_ALPHA): bpp = 4; break; case PNG_COLOR_TYPE_PALETTE: bpp = 3; break; default: g_warning ("color type mismatch"); png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return -1; } if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb (load_png_ptr); if (bit_depth == 16) bpp = bpp << 1; if (!format) format = get_babl_format(bit_depth, color_type); #if BYTE_ORDER == LITTLE_ENDIAN if (bit_depth == 16) png_set_swap (load_png_ptr); #endif if (interlace_type == PNG_INTERLACE_ADAM7) number_of_passes = png_set_interlace_handling (load_png_ptr); if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_gAMA)) { gdouble gamma; png_get_gAMA (load_png_ptr, load_info_ptr, &gamma); png_set_gamma (load_png_ptr, 2.2, gamma); } else { png_set_gamma (load_png_ptr, 2.2, 0.45455); } png_read_update_info (load_png_ptr, load_info_ptr); } pixels = g_malloc0 (width*bpp); { gint pass; GeglRectangle rect; for (pass=0; pass<number_of_passes; pass++) { for(i=0; i<h; i++) { gegl_rectangle_set (&rect, 0, i, width, 1); if (pass != 0) gegl_buffer_get (gegl_buffer, &rect, 1.0, format, pixels, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); png_read_rows (load_png_ptr, &pixels, NULL, 1); gegl_buffer_set (gegl_buffer, &rect, 0, format, pixels, GEGL_AUTO_ROWSTRIDE); } } } png_read_end (load_png_ptr, NULL); png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); g_free (pixels); return 0; }
static gint query_png (GInputStream *stream, gint *width, gint *height, const Babl **format, GError **err) { png_uint_32 w; png_uint_32 h; png_structp load_png_ptr; png_infop load_info_ptr; png_bytep *row_p = NULL; g_return_val_if_fail(stream, -1); if (!check_valid_png_header(stream, err)) { return -1; } load_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, error_fn, NULL); if (!load_png_ptr) { return -1; } load_info_ptr = png_create_info_struct (load_png_ptr); if (!load_info_ptr) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return -1; } if (setjmp (png_jmpbuf (load_png_ptr))) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); g_free (row_p); return -1; } png_set_read_fn(load_png_ptr, stream, read_fn); png_set_sig_bytes (load_png_ptr, 8); // we already read header png_read_info (load_png_ptr, load_info_ptr); { int bit_depth; int color_type; const Babl *f; png_get_IHDR (load_png_ptr, load_info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); *width = w; *height = h; if (png_get_valid (load_png_ptr, load_info_ptr, PNG_INFO_tRNS)) color_type |= PNG_COLOR_MASK_ALPHA; f = get_babl_format(bit_depth, color_type); if (!f) { png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return -1; } *format = f; } png_destroy_read_struct (&load_png_ptr, &load_info_ptr, NULL); return 0; }