31 #define PNGX_OUTOFMEM 2
43 static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
50 guint8 *pixels = NULL;
51 static png_bytepp rows = NULL;
52 static guint32 rows_byte = 0;
56 int bit_depth, color_type, interlace_type;
62 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
67 info_ptr = png_create_info_struct(png_ptr);
69 png_destroy_read_struct(&png_ptr, NULL, NULL);
73 if (setjmp(png_jmpbuf(png_ptr))) {
74 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
79 png_read_info(png_ptr, info_ptr);
92 *
width = png_get_image_width(png_ptr, info_ptr);
93 *
height = png_get_image_height(png_ptr, info_ptr);
94 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
95 color_type = png_get_color_type(png_ptr, info_ptr);
96 interlace_type = png_get_interlace_type(png_ptr, info_ptr);
98 if (color_type == PNG_COLOR_TYPE_PALETTE &&
102 png_set_expand (png_ptr);
104 }
else if (color_type == PNG_COLOR_TYPE_GRAY &&
108 png_set_expand (png_ptr);
110 }
else if (png_get_valid (png_ptr,
111 info_ptr, PNG_INFO_tRNS)) {
115 png_set_expand(png_ptr);
117 }
else if (bit_depth < 8) {
120 png_set_expand(png_ptr);
128 if (bit_depth == 16) {
129 png_set_strip_16(png_ptr);
133 if (color_type == PNG_COLOR_TYPE_GRAY ||
134 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
135 png_set_gray_to_rgb(png_ptr);
139 if (interlace_type != PNG_INTERLACE_NONE) {
140 png_set_interlace_handling(png_ptr);
144 if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
145 png_set_filler(png_ptr, 255, PNG_FILLER_AFTER);
149 png_read_update_info(png_ptr, info_ptr);
156 *
width = png_get_image_width(png_ptr, info_ptr);
157 *
height = png_get_image_height(png_ptr, info_ptr);
162 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
168 if (rows_byte == 0) {
169 rows = (png_bytepp)g_malloc(
sizeof(png_byte *) **
height);
171 }
else if (*
height > rows_byte) {
172 rows = (png_bytepp)g_realloc(rows,
sizeof(png_byte *) **
height);
176 "Could not allocate memory: %s", strerror(errno));
183 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
188 for (guint32 y = 0; y < *
height; y++) {
189 rows[y] = pixels + y * *
width * 4;
192 png_read_image(png_ptr, rows);
193 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
203 #define MAX_IMAGE_WIDTH 1024
204 #define MAX_IMAGE_HEIGHT 1024
243 int sourcerow=0, ytoleft, ytofill, xtoleft, xtofill, dest_column=0, source_column=0, needcol,
256 memset(yrow, 0,
sizeof(
int) **
height *
BPP);
258 ndata = (guint8*)g_malloc(new_width * new_height *
BPP);
260 for (y=0; y<new_height; y++) {
261 nrows[y] = (png_bytep) (ndata + y * new_width *
BPP);
267 for (y=0,sourcerow=0; y < new_height; y++) {
268 memset(xrow, 0,
sizeof(
int) **
width *
BPP);
269 while (ytoleft < ytofill) {
270 for (x=0; x< *
width; ++x) {
275 if (data[(sourcerow **
width + x)*
BPP+3] > 0 ) {
283 if (data[(sourcerow **
width + x)*
BPP+3] > yrow[x*
BPP+3]) {
284 yrow[x*
BPP+3] = data[(sourcerow **
width + x)*
BPP+3];
289 if (sourcerow < *
height) {
294 for (x=0; x < *
width; ++x) {
295 if (data[(sourcerow **
width + x)*
BPP+3] > 0 ) {
300 if (data[(sourcerow **
width + x)*
BPP+3] > xrow[x*
BPP+3]) {
301 xrow[x*
BPP+3] = data[(sourcerow **
width + x)*
BPP+3];
312 if (sourcerow < *
height) {
327 for (x=0; x< *
width; x++) {
330 while (xtoleft >= xtofill) {
339 if (xrow[source_column*
BPP+3] > 0) {
340 r += xtofill * xrow[source_column*
BPP] /
RATIO;
341 g += xtofill * xrow[1+source_column*
BPP] /
RATIO;
342 b += xtofill * xrow[2+source_column*
BPP] /
RATIO;
344 if (xrow[3+source_column*
BPP] > a) {
345 a = xrow[3+source_column*
BPP];
348 nrows[destrow][dest_column *
BPP] = r;
349 nrows[destrow][1+dest_column *
BPP] = g;
350 nrows[destrow][2+dest_column *
BPP] = b;
351 nrows[destrow][3+dest_column *
BPP] = a;
367 if (xrow[3+source_column*
BPP] > 0) {
368 r += xtoleft * xrow[source_column*
BPP] /
RATIO;
369 g += xtoleft * xrow[1+source_column*
BPP] /
RATIO;
370 b += xtoleft * xrow[2+source_column*
BPP] /
RATIO;
372 if (xrow[3+source_column*
BPP] > a) {
373 a = xrow[3+source_column*
BPP];
383 if (xrow[3+source_column*
BPP] > 0) {
384 r += xtofill * xrow[source_column*
BPP] /
RATIO;
385 g += xtofill * xrow[1+source_column*
BPP] /
RATIO;
386 b += xtofill * xrow[2+source_column*
BPP] /
RATIO;
388 if (xrow[3+source_column*
BPP] > a) {
389 a = xrow[3+source_column*
BPP];
398 if (!needcol && (dest_column < new_width)) {
399 nrows[destrow][dest_column *
BPP] = r;
400 nrows[destrow][1+dest_column *
BPP] = g;
401 nrows[destrow][2+dest_column *
BPP] = b;
402 nrows[destrow][3+dest_column *
BPP] = a;
419 pix = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
width,
height);
421 int rowstride = gdk_pixbuf_get_rowstride(pix);
422 unsigned char *pixels = gdk_pixbuf_get_pixels(pix);
424 for (
int y = 0; y <
height; y++) {
425 for (
int x = 0; x <
width; x++) {
426 unsigned char *p = pixels + y * rowstride + x * 4;
427 p[0] = data[4*(x + y *
width)];
428 p[1] = data[4*(x + y *
width) + 1 ];
429 p[2] = data[4*(x + y *
width) + 2 ];
430 p[3] = data[4*(x + y *
width) + 3 ];
441 cairo_surface_t *surface;
442 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
width,
height);
443 cairo_surface_flush(surface);
445 unsigned char *pixels = cairo_image_surface_get_data(surface);
446 int stride = cairo_image_surface_get_stride(surface);
448 for (
int y = 0; y <
height; y++) {
449 for (
int x = 0; x <
width; x++) {
450 guint32 *p = (guint32 *)(pixels + y * stride + x * 4);
453 guint32 a = data[4 * (x + y *
width) + 3];
454 guint32 r = data[4 * (x + y *
width) + 0] * a / 255;
455 guint32 g = data[4 * (x + y *
width) + 1] * a / 255;
456 guint32 b = data[4 * (x + y *
width) + 2] * a / 255;
458 *p = a << (3 * 8) | r << (2 * 8) | g << (1 * 8) | b << (0 * 8);
462 cairo_surface_mark_dirty(surface);