Back to index

lightning-sunbird  0.9+nobinonly
read_png.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2003 USC, Information Sciences Institute
00003  *
00004  * Permission to use, copy, modify, distribute, and sell this software
00005  * and its documentation for any purpose is hereby granted without
00006  * fee, provided that the above copyright notice appear in all copies
00007  * and that both that copyright notice and this permission notice
00008  * appear in supporting documentation, and that the name of the
00009  * University of Southern California not be used in advertising or
00010  * publicity pertaining to distribution of the software without
00011  * specific, written prior permission. The University of Southern
00012  * California makes no representations about the suitability of this
00013  * software for any purpose.  It is provided "as is" without express
00014  * or implied warranty.
00015  *
00016  * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH
00017  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
00018  * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF
00019  * SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00020  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00021  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
00022  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
00023  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00024  *
00025  * Author: Carl D. Worth <cworth@isi.edu>
00026  */
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <png.h>
00031 
00032 #include "read_png.h"
00033 #include "xmalloc.h"
00034 
00035 static void
00036 premultiply_data (png_structp   png,
00037                   png_row_infop row_info,
00038                   png_bytep     data)
00039 {
00040     int i;
00041 
00042     for (i = 0; i < row_info->rowbytes; i += 4) {
00043        unsigned char  *base = &data[i];
00044        unsigned char  blue = base[0];
00045        unsigned char  green = base[1];
00046        unsigned char  red = base[2];
00047        unsigned char  alpha = base[3];
00048        unsigned long p;
00049 
00050        red = ((unsigned) red * (unsigned) alpha + 127) / 255;
00051        green = ((unsigned) green * (unsigned) alpha + 127) / 255;
00052        blue = ((unsigned) blue * (unsigned) alpha + 127) / 255;
00053        p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
00054        memcpy (base, &p, sizeof (unsigned long));
00055     }
00056 }
00057 
00058 read_png_status_t
00059 read_png_argb32 (const char         *filename,
00060                unsigned char      **data,
00061                unsigned int       *width,
00062                unsigned int       *height,
00063                unsigned int     *stride)
00064 {
00065     int i;
00066     FILE *file;
00067     static const int PNG_SIG_SIZE = 8;
00068     unsigned char png_sig[PNG_SIG_SIZE];
00069     int sig_bytes;
00070     png_struct *png;
00071     png_info *info;
00072     png_uint_32 png_width, png_height;
00073     int depth, color_type, interlace;
00074     unsigned int pixel_size;
00075     png_byte **row_pointers;
00076 
00077     file = fopen (filename, "rb");
00078     if (file == NULL) {
00079        return READ_PNG_FILE_NOT_FOUND;
00080     }
00081 
00082     sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file);
00083     if (png_check_sig (png_sig, sig_bytes) == 0) {
00084         fclose (file);
00085        return READ_PNG_FILE_NOT_PNG;
00086     }
00087 
00088     /* XXX: Perhaps we'll want some other error handlers? */
00089     png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
00090                                   NULL,
00091                                   NULL,
00092                                   NULL);
00093     if (png == NULL) {
00094         fclose (file);
00095        return READ_PNG_NO_MEMORY;
00096     }
00097 
00098     info = png_create_info_struct (png);
00099     if (info == NULL) {
00100         fclose (file);
00101         png_destroy_read_struct (&png, NULL, NULL);
00102        return READ_PNG_NO_MEMORY;
00103     }
00104 
00105     png_init_io (png, file);
00106     png_set_sig_bytes (png, sig_bytes);
00107 
00108     png_read_info (png, info);
00109 
00110     png_get_IHDR (png, info,
00111                   &png_width, &png_height, &depth,
00112                   &color_type, &interlace, NULL, NULL);
00113     *width = png_width;
00114     *height = png_height;
00115     *stride = 4 * png_width;
00116 
00117 
00118     /* convert palette/gray image to rgb */
00119     if (color_type == PNG_COLOR_TYPE_PALETTE)
00120         png_set_palette_to_rgb (png);
00121 
00122     /* expand gray bit depth if needed */
00123     if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
00124         png_set_gray_1_2_4_to_8 (png);
00125     /* transform transparency to alpha */
00126     if (png_get_valid(png, info, PNG_INFO_tRNS))
00127         png_set_tRNS_to_alpha (png);
00128 
00129     if (depth == 16)
00130         png_set_strip_16 (png);
00131 
00132     if (depth < 8)
00133         png_set_packing (png);
00134 
00135     /* convert grayscale to RGB */
00136     if (color_type == PNG_COLOR_TYPE_GRAY
00137         || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00138         png_set_gray_to_rgb (png);
00139 
00140     if (interlace != PNG_INTERLACE_NONE)
00141         png_set_interlace_handling (png);
00142 
00143     png_set_bgr (png);
00144     png_set_filler (png, 0xff, PNG_FILLER_AFTER);
00145 
00146     png_set_read_user_transform_fn (png, premultiply_data);
00147 
00148     png_read_update_info (png, info);
00149 
00150     pixel_size = 4;
00151     *data = xmalloc (png_width * png_height * pixel_size);
00152 
00153     row_pointers = malloc (png_height * sizeof(char *));
00154     for (i=0; i < png_height; i++)
00155         row_pointers[i] = (png_byte *) (*data + i * png_width * pixel_size);
00156 
00157     png_read_image (png, row_pointers);
00158     png_read_end (png, info);
00159 
00160     free (row_pointers);
00161     fclose (file);
00162 
00163     png_destroy_read_struct (&png, &info, NULL);
00164 
00165     return READ_PNG_SUCCESS;
00166 }