divide negative window x-coordinates properly, fixing random crashes
[btb/d2x.git] / misc / pngfile.c
1 /* $Id: pngfile.c,v 1.1 2004-05-22 23:41:29 btb Exp $ */
2 #include <stdio.h>
3 #include <png.h>
4
5 #include "pngfile.h"
6 #include "u_mem.h"
7 #include "pstypes.h"
8
9 int read_png(char *filename, png_data *pdata)
10 {
11         ubyte header[8];
12         png_structp png_ptr = NULL;
13         png_infop info_ptr = NULL;
14         png_bytepp row_pointers = NULL;
15         png_uint_32 width, height;
16         int depth, color_type;
17         int i;
18         FILE *fp = NULL;
19
20         if (!filename || !pdata)
21                 return 0;
22
23         if ((fp = fopen(filename, "rb")) == NULL)
24                 return 0;
25
26         fread(header, 1, 8, fp);
27         if (!png_check_sig(header, 8))
28                 return 0;
29
30         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
31         info_ptr = png_create_info_struct(png_ptr);
32
33         pdata->data = pdata->palette = NULL;
34         pdata->num_palette = 0;
35         if (setjmp(png_ptr->jmpbuf))
36         {
37                 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
38                 if (pdata->data)
39                         free(pdata->data);
40                 if (pdata->palette)
41                         free(pdata->palette);
42                 if (row_pointers)
43                         free(row_pointers);
44                 fclose(fp);
45                 return 0;
46         }
47
48         png_init_io(png_ptr, fp);
49         png_set_sig_bytes(png_ptr, 8);
50         png_read_info(png_ptr, info_ptr);
51         png_get_IHDR(png_ptr, info_ptr, &width, &height, &depth, &color_type, NULL, NULL, NULL);
52
53         pdata->width = width;
54         pdata->height = height;
55         pdata->depth = depth;
56
57         pdata->data = (ubyte*)malloc(png_get_rowbytes(png_ptr, info_ptr) * height);
58         row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height);
59         for (i = 0; i < height; i++)
60                 row_pointers[i] = &pdata->data[png_get_rowbytes(png_ptr, info_ptr) * i];
61
62         png_read_image(png_ptr, row_pointers);
63         free(row_pointers);
64         row_pointers=NULL;
65         png_read_end(png_ptr, info_ptr);
66
67         if (color_type == PNG_COLOR_TYPE_PALETTE)
68         {
69                 png_colorp palette;
70
71                 if (png_get_PLTE(png_ptr, info_ptr, &palette, &pdata->num_palette))
72                 {
73                         pdata->palette = (ubyte*)malloc(pdata->num_palette * 3);
74                         memcpy(pdata->palette, palette, pdata->num_palette * 3);
75                 }
76         }
77
78         pdata->paletted = (color_type & PNG_COLOR_MASK_PALETTE) > 0;
79         pdata->color = (color_type & PNG_COLOR_MASK_COLOR) > 0;
80         pdata->alpha = (color_type & PNG_COLOR_MASK_ALPHA) > 0;
81         if (pdata->color && pdata->alpha)
82                 pdata->channels = 4;
83         else if (pdata->color && !pdata->alpha)
84                 pdata->channels = 3;
85         else if (!pdata->color && pdata->alpha)
86                 pdata->channels = 2;
87         else //if (!pdata->color && !pdata->alpha)
88                 pdata->channels = 1;
89
90         png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
91         fclose(fp);
92
93         return 1;
94 }