This patch split the png image creation in two steps: 1. The first step reads the image file, check the image size (width and height) and create the RImage struct for it. For this step, the RContext argument is not needed (is X11 independent). The image file is loaded "as-is" in the srcdata RImage field. Of course, srcdata is the file image, no the image ready to see.
2. The second step reads the image stored in the srcdata and process it. The final image is stored in the RImage struct. Now the image is ready for the user. The image file is not used here. Signed-off-by: Rodolfo García Peñas (kix) <[email protected]> --- wrlib/png.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 43 deletions(-) diff --git a/wrlib/png.c b/wrlib/png.c index daae324..c4be981 100644 --- a/wrlib/png.c +++ b/wrlib/png.c @@ -33,38 +33,91 @@ #include "wraster.h" #include "imgformat.h" +RImage *RDrawPNG(RContext *context, RImage *image); + +/* + * png_structp png: Pointer on struct which contains pointer on our data + * png_byte buffer: Where you have to copy the source data for libpng computing + * png_size_t count: Length of datas to copy + */ +static void read_xpm_from_buffer(png_structp png, png_byte *buffer, png_size_t count) +{ + /* Pointer on our struct */ + char *pnginfo = (char *) png_get_io_ptr(png); + + /* copy data from image buffer */ + memcpy (buffer, pnginfo, count); + pnginfo += count; + png->io_ptr = pnginfo; +} + RImage *RLoadPNG(RContext *context, const char *file) { - char *tmp; - RImage *image = NULL; FILE *f; + unsigned char *rawimage; + long bufsize, newlen; + /* Local tmp vars */ png_structp png; png_infop pinfo, einfo; - png_color_16p bkcolor; - int alpha; - int x, y, i; - double gamma, sgamma; png_uint_32 width, height; - int depth, junk, color_type; - png_bytep *png_rows; - unsigned char *ptr; + int junk, color_type, alpha; + RImage *image = NULL; f = fopen(file, "rb"); if (!f) { RErrorCode = RERR_OPEN; return NULL; } + + /* Go to the end of file */ + if (fseek(f, 0L, SEEK_END) != 0) { + fclose(f); + return NULL; + } + + /* We can set a max buffer size check here */ + bufsize = ftell(f); + if (bufsize == -1) { + fclose(f); + return NULL; + } + + rawimage = malloc(sizeof(char) * (bufsize + 1)); + if (rawimage == NULL) { + fclose(f); + return NULL; + } + + /* Return to the start of the file */ + if (fseek(f, 0L, SEEK_SET) != 0) { + free(rawimage); + fclose(f); + return NULL; + } + + /* Read the entire file */ + newlen = fread(rawimage, sizeof(char), bufsize, f); + if (newlen == 0) { + free(rawimage); + fclose(f); + return NULL; + } + + rawimage[newlen] = '\0'; + fclose(f); + + /* We need read the width, height and alpha to create the RImage */ png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr) NULL, (png_error_ptr) NULL); if (!png) { RErrorCode = RERR_NOMEMORY; - fclose(f); + free(rawimage); return NULL; } pinfo = png_create_info_struct(png); if (!pinfo) { RErrorCode = RERR_NOMEMORY; - fclose(f); + free(rawimage); png_destroy_read_struct(&png, NULL, NULL); return NULL; } @@ -72,7 +125,7 @@ RImage *RLoadPNG(RContext *context, const char *file) einfo = png_create_info_struct(png); if (!einfo) { RErrorCode = RERR_NOMEMORY; - fclose(f); + free(rawimage); png_destroy_read_struct(&png, &pinfo, NULL); return NULL; } @@ -83,24 +136,20 @@ RImage *RLoadPNG(RContext *context, const char *file) #else if (setjmp(png_jmpbuf(png))) { #endif - fclose(f); png_destroy_read_struct(&png, &pinfo, &einfo); - if (image) - RReleaseImage(image); + free(rawimage); return NULL; } - png_init_io(png, f); - + png_set_read_fn(png, rawimage, read_xpm_from_buffer); png_read_info(png, pinfo); - - png_get_IHDR(png, pinfo, &width, &height, &depth, &color_type, &junk, &junk, &junk); + png_get_IHDR(png, pinfo, &width, &height, &junk, &color_type, &junk, &junk, &junk); /* sanity check */ if (width < 1 || height < 1) { - fclose(f); png_destroy_read_struct(&png, &pinfo, &einfo); RErrorCode = RERR_BADIMAGEFILE; + free(rawimage); return NULL; } @@ -113,11 +162,77 @@ RImage *RLoadPNG(RContext *context, const char *file) /* allocate RImage */ image = RCreateImage(width, height, alpha); if (!image) { - fclose(f); png_destroy_read_struct(&png, &pinfo, &einfo); + free(rawimage); + return NULL; + } + + png_destroy_read_struct(&png, &pinfo, &einfo); + + /* Set the srcdata with the buffer */ + image->srcformat = IM_PNG; + image->srcdata = rawimage; + image->srcdatalen = newlen; + + image = RDrawPNG(context, image); + return image; +} + +RImage *RDrawPNG(RContext *context, RImage *image) +{ + char *tmp; + png_structp png; + png_infop pinfo, einfo; + png_color_16p bkcolor; + int alpha, x, y, i; + double gamma, sgamma; + png_uint_32 junk32; + int depth, junk, color_type; + png_bytep *png_rows; + unsigned char *ptr; + char *rawimage; + + if ((context == NULL) || (image == NULL)) { + if (image) + RReleaseImage(image); + + return NULL; + } + + rawimage = (char *) image->srcdata; + + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr) NULL, (png_error_ptr) NULL); + if (!png) { + RErrorCode = RERR_NOMEMORY; + return NULL; + } + + pinfo = png_create_info_struct(png); + if (!pinfo) { + RErrorCode = RERR_NOMEMORY; + png_destroy_read_struct(&png, NULL, NULL); + return NULL; + } + + einfo = png_create_info_struct(png); + if (!einfo) { + RErrorCode = RERR_NOMEMORY; + png_destroy_read_struct(&png, &pinfo, NULL); return NULL; } + RErrorCode = RERR_INTERNAL; + + png_set_read_fn(png, rawimage, read_xpm_from_buffer); + png_read_info(png, pinfo); + png_get_IHDR(png, pinfo, &junk32, &junk32, &depth, &color_type, &junk, &junk, &junk); + + /* check for an alpha channel */ + if (png_get_valid(png, pinfo, PNG_INFO_tRNS)) + alpha = True; + else + alpha = (color_type & PNG_COLOR_MASK_ALPHA); + /* normalize to 8bpp with alpha channel */ if (color_type == PNG_COLOR_TYPE_PALETTE && depth <= 8) png_set_expand(png); @@ -162,19 +277,17 @@ RImage *RLoadPNG(RContext *context, const char *file) image->background.blue = bkcolor->blue >> 8; } - png_rows = calloc(height, sizeof(char *)); + png_rows = calloc(image->height, sizeof(char *)); if (!png_rows) { RErrorCode = RERR_NOMEMORY; - fclose(f); RReleaseImage(image); png_destroy_read_struct(&png, &pinfo, &einfo); return NULL; } - for (y = 0; y < height; y++) { + for (y = 0; y < image->height; y++) { png_rows[y] = malloc(png_get_rowbytes(png, pinfo)); if (!png_rows[y]) { RErrorCode = RERR_NOMEMORY; - fclose(f); RReleaseImage(image); png_destroy_read_struct(&png, &pinfo, &einfo); while (y-- > 0) @@ -184,37 +297,29 @@ RImage *RLoadPNG(RContext *context, const char *file) return NULL; } } + /* read data */ png_read_image(png, png_rows); - png_read_end(png, einfo); - png_destroy_read_struct(&png, &pinfo, &einfo); - - fclose(f); - ptr = image->data; /* convert to RImage */ - if (alpha) { - for (y = 0; y < height; y++) { - for (x = 0, i = width * 4; x < i; x++, ptr++) { + if (alpha) + for (y = 0; y < image->height; y++) + for (x = 0, i = image->width * 4; x < i; x++, ptr++) *ptr = *(png_rows[y] + x); - } - } - } else { - for (y = 0; y < height; y++) { - for (x = 0, i = width * 3; x < i; x++, ptr++) { + else + for (y = 0; y < image->height; y++) + for (x = 0, i = image->width * 3; x < i; x++, ptr++) *ptr = *(png_rows[y] + x); - } - } - } - for (y = 0; y < height; y++) + + for (y = 0; y < image->height; y++) if (png_rows[y]) free(png_rows[y]); + free(png_rows); - image->srcformat = IM_PNG; return image; } -- 1.8.4.rc3 -- To unsubscribe, send mail to [email protected].
