Crossfire Client, Branch
R11627
|
00001 const char * const rcsid_gtk2_png_c = 00002 "$Id: png.c 9193 2008-06-01 14:26:32Z anmaster $"; 00003 /* 00004 Crossfire client, a client program for the crossfire program. 00005 00006 Copyright (C) 2005 Mark Wedel & Crossfire Development Team 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 00022 The author can be reached via e-mail to crossfire@metalforge.org 00023 */ 00024 00030 #include <config.h> 00031 #include <stdlib.h> 00032 #include <sys/stat.h> 00033 #ifndef WIN32 00034 #include <unistd.h> 00035 #endif 00036 #include <png.h> 00037 #include <client-types.h> 00038 #include <client.h> 00039 00040 /* Pick up the gtk headers we need */ 00041 #include <gtk/gtk.h> 00042 #ifndef WIN32 00043 #include <gdk/gdkx.h> 00044 #else 00045 #include <gdk/gdkwin32.h> 00046 #endif 00047 #include <gdk/gdkkeysyms.h> 00048 00049 00050 /* Defines for PNG return values */ 00051 /* These should be in a header file, but currently our calling functions 00052 * routines just check for nonzero return status and don't really care 00053 * why the load failed. 00054 */ 00055 #define PNGX_NOFILE 1 00056 #define PNGX_OUTOFMEM 2 00057 #define PNGX_DATA 3 00058 00059 static uint8 *data_cp; 00060 static int data_len, data_start; 00061 00068 static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { 00069 memcpy(data, data_cp + data_start, length); 00070 data_start += length; 00071 } 00072 00080 uint8 *png_to_data(uint8 *data, int len, uint32 *width, uint32 *height) 00081 { 00082 uint8 *pixels=NULL; 00083 static png_bytepp rows=NULL; 00084 static int rows_byte=0; 00085 00086 png_structp png_ptr; 00087 png_infop info_ptr; 00088 int bit_depth, color_type, interlace_type, compression_type, y; 00089 00090 data_len=len; 00091 data_cp = data; 00092 data_start=0; 00093 00094 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 00095 NULL, NULL, NULL); 00096 00097 if (!png_ptr) { 00098 return NULL; 00099 } 00100 info_ptr = png_create_info_struct (png_ptr); 00101 00102 if (!info_ptr) { 00103 png_destroy_read_struct (&png_ptr, NULL, NULL); 00104 return NULL; 00105 } 00106 00107 00108 if (setjmp (png_jmpbuf(png_ptr))) { 00109 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00110 return NULL; 00111 } 00112 00113 00114 png_set_read_fn(png_ptr, NULL, user_read_data); 00115 png_read_info (png_ptr, info_ptr); 00116 00117 /* 00118 * This seems to bug on at least one system (other than mine) 00119 * http://www.metalforge.net/cfmb/viewtopic.php?t=1085 00120 * 00121 * I think its actually a bug in libpng. This function dies with an 00122 * error based on image width. However I've produced a work around 00123 * using the indivial functions. Repeated below. 00124 * 00125 png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)width, (png_unit_32*)height, &bit_depth, 00126 &color_type, &interlace_type, &compression_type, &filter_type); 00127 */ 00128 *width = png_get_image_width(png_ptr, info_ptr); 00129 *height = png_get_image_height(png_ptr, info_ptr); 00130 bit_depth = png_get_bit_depth(png_ptr, info_ptr); 00131 color_type = png_get_color_type(png_ptr, info_ptr); 00132 interlace_type = png_get_interlace_type(png_ptr, info_ptr); 00133 compression_type = png_get_compression_type(png_ptr, info_ptr); 00134 00135 if (color_type == PNG_COLOR_TYPE_PALETTE && 00136 bit_depth <= 8) { 00137 00138 /* Convert indexed images to RGB */ 00139 png_set_expand (png_ptr); 00140 00141 } else if (color_type == PNG_COLOR_TYPE_GRAY && 00142 bit_depth < 8) { 00143 00144 /* Convert grayscale to RGB */ 00145 png_set_expand (png_ptr); 00146 00147 } else if (png_get_valid (png_ptr, 00148 info_ptr, PNG_INFO_tRNS)) { 00149 00150 /* If we have transparency header, convert it to alpha 00151 channel */ 00152 png_set_expand(png_ptr); 00153 00154 } else if (bit_depth < 8) { 00155 00156 /* If we have < 8 scale it up to 8 */ 00157 png_set_expand(png_ptr); 00158 00159 00160 /* Conceivably, png_set_packing() is a better idea; 00161 * God only knows how libpng works 00162 */ 00163 } 00164 /* If we are 16-bit, convert to 8-bit */ 00165 if (bit_depth == 16) { 00166 png_set_strip_16(png_ptr); 00167 } 00168 00169 /* If gray scale, convert to RGB */ 00170 if (color_type == PNG_COLOR_TYPE_GRAY || 00171 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { 00172 png_set_gray_to_rgb(png_ptr); 00173 } 00174 00175 /* If interlaced, handle that */ 00176 if (interlace_type != PNG_INTERLACE_NONE) { 00177 png_set_interlace_handling(png_ptr); 00178 } 00179 00180 /* pad it to 4 bytes to make processing easier */ 00181 if (!(color_type & PNG_COLOR_MASK_ALPHA)) 00182 png_set_filler(png_ptr, 255, PNG_FILLER_AFTER); 00183 00184 /* Update the info the reflect our transformations */ 00185 png_read_update_info(png_ptr, info_ptr); 00186 /* re-read due to transformations just made */ 00187 /* 00188 * See above for error description 00189 png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)width, (png_uint_32*)height, &bit_depth, 00190 &color_type, &interlace_type, &compression_type, &filter_type); 00191 */ 00192 *width = png_get_image_width(png_ptr, info_ptr); 00193 *height = png_get_image_height(png_ptr, info_ptr); 00194 bit_depth = png_get_bit_depth(png_ptr, info_ptr); 00195 color_type = png_get_color_type(png_ptr, info_ptr); 00196 interlace_type = png_get_interlace_type(png_ptr, info_ptr); 00197 compression_type = png_get_compression_type(png_ptr, info_ptr); 00198 00199 00200 pixels = (uint8*)malloc(*width * *height * 4); 00201 00202 if (!pixels) { 00203 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00204 LOG(LOG_CRITICAL,"gtk::png_to_data","Out of memory - exiting"); 00205 exit(1); 00206 } 00207 00208 /* the png library needs the rows, but we will just return the raw data */ 00209 if (rows_byte == 0) { 00210 rows =(png_bytepp) malloc(sizeof(char*) * *height); 00211 rows_byte=*height; 00212 } else if (*height > rows_byte) { 00213 rows =(png_bytepp) realloc(rows, sizeof(char*) * *height); 00214 rows_byte=*height; 00215 } 00216 if (!rows) { 00217 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00218 return NULL; 00219 } 00220 00221 for (y=0; y<*height; y++) 00222 rows[y] = pixels + y * *width * 4; 00223 00224 png_read_image(png_ptr, rows); 00225 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00226 00227 return pixels; 00228 } 00229 00230 /* RATIO is used to know what units scale is - in this case, a percentage, so 00231 * it is set to 100 00232 */ 00233 #define RATIO 100 00234 00235 #define MAX_IMAGE_WIDTH 1024 00236 #define MAX_IMAGE_HEIGHT 1024 00237 #define BPP 4 00238 00267 uint8 *rescale_rgba_data(uint8 *data, int *width, int *height, int scale) 00268 { 00269 static int xrow[BPP * MAX_IMAGE_WIDTH], yrow[BPP*MAX_IMAGE_HEIGHT]; 00270 static uint8 *nrows[MAX_IMAGE_HEIGHT]; 00271 00272 /* Figure out new height/width */ 00273 int new_width = *width * scale / RATIO, new_height = *height * scale / RATIO; 00274 00275 int sourcerow=0, ytoleft, ytofill, xtoleft, xtofill, dest_column=0, source_column=0, needcol, 00276 destrow=0; 00277 int x,y; 00278 uint8 *ndata; 00279 uint8 r,g,b,a; 00280 00281 if (*width > MAX_IMAGE_WIDTH || new_width > MAX_IMAGE_WIDTH 00282 || *height > MAX_IMAGE_HEIGHT || new_height > MAX_IMAGE_HEIGHT) 00283 { 00284 LOG(LOG_CRITICAL,"gtk::rescale_rgba_data","Image too big"); 00285 exit(0); 00286 } 00287 00288 /* clear old values these may have */ 00289 memset(yrow, 0, sizeof(int) * *height * BPP); 00290 00291 ndata = (uint8*)malloc(new_width * new_height * BPP); 00292 00293 for (y=0; y<new_height; y++) 00294 nrows[y] = (png_bytep) (ndata + y * new_width * BPP); 00295 00296 ytoleft = scale; 00297 ytofill = RATIO; 00298 00299 for (y=0,sourcerow=0; y < new_height; y++) { 00300 memset(xrow, 0, sizeof(int) * *width * BPP); 00301 while (ytoleft < ytofill) { 00302 for (x=0; x< *width; ++x) { 00303 /* Only want to copy the data if this is not a transperent pixel. 00304 * If it is transparent, the color information is has is probably 00305 * bogus, and blending that makes the results look worse. 00306 */ 00307 if (data[(sourcerow * *width + x)*BPP+3] > 0 ) { 00308 yrow[x*BPP] += ytoleft * data[(sourcerow * *width + x)*BPP]/RATIO; 00309 yrow[x*BPP+1] += ytoleft * data[(sourcerow * *width + x)*BPP+1]/RATIO; 00310 yrow[x*BPP+2] += ytoleft * data[(sourcerow * *width + x)*BPP+2]/RATIO; 00311 } 00312 /* Alpha is a bit special - we don't want to blend it - 00313 * we want to take whatever is the more opaque value. 00314 */ 00315 if (data[(sourcerow * *width + x)*BPP+3] > yrow[x*BPP+3]) 00316 yrow[x*BPP+3] = data[(sourcerow * *width + x)*BPP+3]; 00317 } 00318 ytofill -= ytoleft; 00319 ytoleft = scale; 00320 if (sourcerow < *height) 00321 sourcerow++; 00322 } 00323 00324 for (x=0; x < *width; ++x) { 00325 if (data[(sourcerow * *width + x)*BPP+3] > 0 ) { 00326 xrow[x*BPP] = yrow[x*BPP] + ytofill * data[(sourcerow * *width + x)*BPP] / RATIO; 00327 xrow[x*BPP+1] = yrow[x*BPP+1] + ytofill * data[(sourcerow * *width + x)*BPP+1] / RATIO; 00328 xrow[x*BPP+2] = yrow[x*BPP+2] + ytofill * data[(sourcerow * *width + x)*BPP+2] / RATIO; 00329 } 00330 if (data[(sourcerow * *width + x)*BPP+3] > xrow[x*BPP+3]) 00331 xrow[x*BPP+3] = data[(sourcerow * *width + x)*BPP+3]; 00332 yrow[x*BPP]=0; yrow[x*BPP+1]=0; yrow[x*BPP+2]=0; yrow[x*BPP+3]=0; 00333 } 00334 00335 ytoleft -= ytofill; 00336 if (ytoleft <= 0) { 00337 ytoleft = scale; 00338 if (sourcerow < *height) 00339 sourcerow++; 00340 } 00341 00342 ytofill = RATIO; 00343 xtofill = RATIO; 00344 dest_column = 0; 00345 source_column=0; 00346 needcol=0; 00347 r=0; g=0; b=0; a=0; 00348 00349 for (x=0; x< *width; x++) { 00350 xtoleft = scale; 00351 00352 while (xtoleft >= xtofill) { 00353 if (needcol) { 00354 dest_column++; 00355 r=0; g=0; b=0; a=0; 00356 } 00357 00358 if (xrow[source_column*BPP+3] > 0) { 00359 r += xtofill * xrow[source_column*BPP] / RATIO; 00360 g += xtofill * xrow[1+source_column*BPP] / RATIO; 00361 b += xtofill * xrow[2+source_column*BPP] / RATIO; 00362 } 00363 if (xrow[3+source_column*BPP] > a) 00364 a = xrow[3+source_column*BPP]; 00365 00366 nrows[destrow][dest_column * BPP] = r; 00367 nrows[destrow][1+dest_column * BPP] = g; 00368 nrows[destrow][2+dest_column * BPP] = b; 00369 nrows[destrow][3+dest_column * BPP] = a; 00370 xtoleft -= xtofill; 00371 xtofill = RATIO; 00372 needcol=1; 00373 } 00374 00375 if (xtoleft > 0 ){ 00376 if (needcol) { 00377 dest_column++; 00378 r=0; g=0; b=0; a=0; 00379 needcol=0; 00380 } 00381 00382 if (xrow[3+source_column*BPP] > 0) { 00383 r += xtoleft * xrow[source_column*BPP] / RATIO; 00384 g += xtoleft * xrow[1+source_column*BPP] / RATIO; 00385 b += xtoleft * xrow[2+source_column*BPP] / RATIO; 00386 } 00387 if (xrow[3+source_column*BPP] > a) 00388 a = xrow[3+source_column*BPP]; 00389 00390 xtofill -= xtoleft; 00391 } 00392 source_column++; 00393 } 00394 00395 if (xtofill > 0 ) { 00396 source_column--; 00397 if (xrow[3+source_column*BPP] > 0) { 00398 r += xtofill * xrow[source_column*BPP] / RATIO; 00399 g += xtofill * xrow[1+source_column*BPP] / RATIO; 00400 b += xtofill * xrow[2+source_column*BPP] / RATIO; 00401 } 00402 if (xrow[3+source_column*BPP] > a) 00403 a = xrow[3+source_column*BPP]; 00404 } 00405 00406 /* Not positve, but without the bound checking for dest_column, 00407 * we were overrunning the buffer. My guess is this only really 00408 * showed up if when the images are being scaled - there is probably 00409 * something like half a pixel left over. 00410 */ 00411 if (!needcol && (dest_column < new_width)) { 00412 nrows[destrow][dest_column * BPP] = r; 00413 nrows[destrow][1+dest_column * BPP] = g; 00414 nrows[destrow][2+dest_column * BPP] = b; 00415 nrows[destrow][3+dest_column * BPP] = a; 00416 } 00417 destrow++; 00418 } 00419 *width = new_width; 00420 *height = new_height; 00421 return ndata; 00422 } 00423 00424 00425 guchar rgb[512*512*3]; 00441 int rgba_to_gdkpixmap(GdkWindow *window, uint8 *data,int width, int height, 00442 GdkPixmap **pix, GdkBitmap **mask, GdkColormap *colormap) 00443 { 00444 GdkGC *gc, *gc_alpha; 00445 int has_alpha=0, alpha; 00446 GdkColor scolor; 00447 int x,y; 00448 00449 *pix = gdk_pixmap_new(window, width, height, -1); 00450 00451 gc=gdk_gc_new(*pix); 00452 gdk_gc_set_function(gc, GDK_COPY); 00453 00454 *mask=gdk_pixmap_new(window, width, height,1); 00455 gc_alpha=gdk_gc_new(*mask); 00456 00457 scolor.pixel=1; 00458 gdk_gc_set_foreground(gc_alpha, &scolor); 00459 gdk_draw_rectangle(*mask, gc_alpha, 1, 0, 0, width, height); 00460 00461 scolor.pixel=0; 00462 gdk_gc_set_foreground(gc_alpha, &scolor); 00463 00464 /* we need to draw the alpha channel. The image may not in fact 00465 * have alpha, but no way to know at this point other than to try 00466 * and draw it. 00467 */ 00468 for (y=0; y<height; y++) { 00469 for (x=0; x<width; x++) { 00470 alpha = data[(y * width + x) * 4 +3]; 00471 /* Transparent bit */ 00472 if (alpha==0) { 00473 gdk_draw_point(*mask, gc_alpha, x, y); 00474 has_alpha=1; 00475 } 00476 } 00477 } 00478 00479 gdk_draw_rgb_32_image(*pix, gc, 0, 0, width, height, GDK_RGB_DITHER_NONE, data, width*4); 00480 if (!has_alpha) { 00481 gdk_pixmap_unref(*mask); 00482 *mask = NULL; 00483 } 00484 00485 gdk_gc_destroy(gc_alpha); 00486 gdk_gc_destroy(gc); 00487 return 0; 00488 } 00489 00500 int rgba_to_gdkpixbuf(uint8 *data,int width, int height,GdkPixbuf **pix) 00501 { 00502 int rowstride; 00503 guchar *pixels, *p; 00504 int x,y; 00505 00506 #if 0 00507 /* I'm not sure why this doesn't work, since it seems 00508 * the data should be in the right format, but it doesn't. 00509 */ 00510 *pix = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, 00511 TRUE, 8, width, height, width * 4, NULL, NULL); 00512 return 0; 00513 00514 #else 00515 *pix = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); 00516 00517 rowstride = gdk_pixbuf_get_rowstride(*pix); 00518 pixels = gdk_pixbuf_get_pixels(*pix); 00519 00520 for (y=0; y<height; y++) { 00521 for (x=0; x<width; x++) { 00522 p = pixels + y * rowstride + x * 4; 00523 p[0] = data[4*(x + y * width)]; 00524 p[1] = data[4*(x + y * width) + 1 ]; 00525 p[2] = data[4*(x + y * width) + 2 ]; 00526 p[3] = data[4*(x + y * width) + 3 ]; 00527 00528 } 00529 } 00530 00531 return 0; 00532 #endif 00533 } 00534 00544 int png_to_gdkpixmap(GdkWindow *window, uint8 *data, int len, 00545 GdkPixmap **pix, GdkBitmap **mask, GdkColormap *colormap) 00546 { 00547 static uint8 *pixels=NULL; 00548 static int pixels_byte=0, rows_byte=0; 00549 static png_bytepp rows=NULL; 00550 unsigned long width, height; 00551 png_structp png_ptr; 00552 png_infop info_ptr; 00553 int bit_depth, color_type, interlace_type, compression_type, filter_type, 00554 bpp, x,y,has_alpha,i,alpha; 00555 GdkColor scolor; 00556 GdkGC *gc, *gc_alpha; 00557 00558 data_len=len; 00559 data_cp = data; 00560 data_start=0; 00561 00562 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 00563 NULL, NULL, NULL); 00564 00565 if (!png_ptr) { 00566 return PNGX_OUTOFMEM; 00567 } 00568 info_ptr = png_create_info_struct (png_ptr); 00569 00570 if (!info_ptr) { 00571 png_destroy_read_struct (&png_ptr, NULL, NULL); 00572 return PNGX_OUTOFMEM; 00573 } 00574 if (setjmp (png_ptr->jmpbuf)) { 00575 png_destroy_read_struct (&png_ptr, &info_ptr,NULL); 00576 return PNGX_DATA; 00577 } 00578 has_alpha=0; 00579 png_set_read_fn(png_ptr, NULL, user_read_data); 00580 png_read_info (png_ptr, info_ptr); 00581 00582 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 00583 &color_type, &interlace_type, &compression_type, &filter_type); 00584 00585 if (color_type == PNG_COLOR_TYPE_PALETTE && 00586 bit_depth <= 8) { 00587 00588 /* Convert indexed images to RGB */ 00589 png_set_expand (png_ptr); 00590 00591 } else if (color_type == PNG_COLOR_TYPE_GRAY && 00592 bit_depth < 8) { 00593 00594 /* Convert grayscale to RGB */ 00595 png_set_expand (png_ptr); 00596 00597 } else if (png_get_valid (png_ptr, 00598 info_ptr, PNG_INFO_tRNS)) { 00599 00600 /* If we have transparency header, convert it to alpha 00601 channel */ 00602 png_set_expand(png_ptr); 00603 00604 } else if (bit_depth < 8) { 00605 00606 /* If we have < 8 scale it up to 8 */ 00607 png_set_expand(png_ptr); 00608 00609 00610 /* Conceivably, png_set_packing() is a better idea; 00611 * God only knows how libpng works 00612 */ 00613 } 00614 /* If we are 16-bit, convert to 8-bit */ 00615 if (bit_depth == 16) { 00616 png_set_strip_16(png_ptr); 00617 } 00618 00619 /* If gray scale, convert to RGB */ 00620 if (color_type == PNG_COLOR_TYPE_GRAY || 00621 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { 00622 png_set_gray_to_rgb(png_ptr); 00623 } 00624 00625 /* If interlaced, handle that */ 00626 if (interlace_type != PNG_INTERLACE_NONE) { 00627 png_set_interlace_handling(png_ptr); 00628 } 00629 00630 /* Update the info the reflect our transformations */ 00631 png_read_update_info(png_ptr, info_ptr); 00632 /* re-read due to transformations just made */ 00633 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 00634 &color_type, &interlace_type, &compression_type, &filter_type); 00635 if (color_type & PNG_COLOR_MASK_ALPHA) 00636 bpp = 4; 00637 else 00638 bpp = 3; 00639 00640 /* Allocate the memory we need once, and increase it if necessary. 00641 * This is more efficient the allocating this block of memory every time. 00642 */ 00643 if (pixels_byte==0) { 00644 pixels_byte = width * height * bpp; 00645 pixels = (uint8*)malloc(pixels_byte); 00646 } else if ((width * height * bpp) > pixels_byte) { 00647 pixels_byte =width * height * bpp; 00648 /* Doing a free/malloc is probably more efficient - 00649 * we don't care about the old data in this 00650 * buffer. 00651 */ 00652 free(pixels); 00653 pixels= (uint8*)malloc(pixels_byte); 00654 } 00655 00656 if (!pixels) { 00657 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00658 pixels_byte=0; 00659 return PNGX_OUTOFMEM; 00660 } 00661 if (rows_byte == 0) { 00662 rows =(png_bytepp) malloc(sizeof(char*) * height); 00663 rows_byte=height; 00664 } else if (height > rows_byte) { 00665 rows =(png_bytepp) realloc(rows, sizeof(char*) * height); 00666 rows_byte=height; 00667 } 00668 if (!rows) { 00669 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00670 pixels_byte=0; 00671 return PNGX_OUTOFMEM; 00672 } 00673 00674 for (y=0; y<height; y++) 00675 rows[y] = pixels + y * width * bpp; 00676 00677 png_read_image(png_ptr, rows); 00678 #if 0 00679 fprintf(stderr,"image is %d X %d, bpp=%d, color_type=%d\n", 00680 width, height, bpp, color_type); 00681 #endif 00682 00683 *pix = gdk_pixmap_new(window, width, height, -1); 00684 00685 00686 gc=gdk_gc_new(*pix); 00687 gdk_gc_set_function(gc, GDK_COPY); 00688 00689 if (color_type & PNG_COLOR_MASK_ALPHA) { 00690 *mask=gdk_pixmap_new(window, width, height,1); 00691 gc_alpha=gdk_gc_new(*mask); 00692 gdk_gc_set_function(gc_alpha, GDK_COPY); 00693 00694 scolor.pixel=1; 00695 gdk_gc_set_foreground(gc_alpha, &scolor); 00696 gdk_draw_rectangle(*mask, gc_alpha, 1, 0, 0, width, height); 00697 00698 scolor.pixel=0; 00699 gdk_gc_set_foreground(gc_alpha, &scolor); 00700 has_alpha=1; 00701 } 00702 else { 00703 *mask = NULL; 00704 gc_alpha = NULL; /* Prevent compile warnings */ 00705 } 00706 i=0; 00707 for (y=0; y<height; y++) { 00708 for (x=0; x<width; x++) { 00709 rgb[i++]=rows[y][x*bpp]; /* red */ 00710 rgb[i++]=rows[y][x*bpp+1]; /* green */ 00711 rgb[i++]=rows[y][x*bpp+2]; /* blue */ 00712 if (has_alpha) { 00713 alpha = rows[y][x*bpp+3]; 00714 /* Transparent bit */ 00715 if (alpha==0) { 00716 gdk_draw_point(*mask, gc_alpha, x, y); 00717 } 00718 } 00719 } 00720 } 00721 gdk_draw_rgb_image(*pix, gc, 0, 0, 32, 32, GDK_RGB_DITHER_NONE, rgb, 32*3); 00722 png_destroy_read_struct (&png_ptr, &info_ptr, NULL); 00723 if (has_alpha) 00724 gdk_gc_destroy(gc_alpha); 00725 gdk_gc_destroy(gc); 00726 return 0; 00727 }