|
1 #include "image.h" |
|
2 |
|
3 static int pt_image_new (struct pt_image **img_ptr, struct pt_ctx *ctx, const char *png_path) |
|
4 { |
|
5 struct pt_image *img; |
|
6 |
|
7 // alloc |
|
8 if ((img = calloc(1, sizeof(*img))) == NULL) |
|
9 return -1; |
|
10 |
|
11 if ((img->png_path = strdup(png_path)) == NULL) |
|
12 goto error; |
|
13 |
|
14 // init |
|
15 img->ctx = ctx; |
|
16 |
|
17 // ok |
|
18 *img_ptr = img; |
|
19 |
|
20 return 0; |
|
21 |
|
22 error: |
|
23 pt_image_destroy(img); |
|
24 |
|
25 return -1; |
|
26 } |
|
27 |
|
28 /** |
|
29 * Open the image's FILE |
|
30 */ |
|
31 static int pt_image_open_file (struct pt_image *img, FILE **file_ptr) |
|
32 { |
|
33 FILE *fp; |
|
34 |
|
35 // open |
|
36 if (fopen(img->png_path, "rb") < 0) |
|
37 return -1; |
|
38 |
|
39 // ok |
|
40 *file_ptr = fp; |
|
41 |
|
42 return 0; |
|
43 } |
|
44 |
|
45 /** |
|
46 * Open the PNG image, setting up the I/O and returning the png_structp and png_infop |
|
47 */ |
|
48 static int pt_image_open_png (struct pt_image *img, png_structp *png_ptr, png_infop *info_ptr) |
|
49 { |
|
50 FILE *fp = NULL; |
|
51 png_structp png = NULL; |
|
52 png_infop info = NULL; |
|
53 |
|
54 // open I/O |
|
55 if (pt_image_open_file(img, &fp)) |
|
56 goto error; |
|
57 |
|
58 // create the struct |
|
59 if ((png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL) |
|
60 goto error; |
|
61 |
|
62 // create the info |
|
63 if ((info = png_create_info_struct(png)) == NULL) |
|
64 goto error; |
|
65 |
|
66 // setup error trap for the I/O |
|
67 if (setjmp(png_jmpbuf(png))) |
|
68 goto error; |
|
69 |
|
70 // setup I/O to FILE |
|
71 png_init_io(png, fp); |
|
72 |
|
73 // ok |
|
74 *png_ptr = png; |
|
75 *info_ptr = info; |
|
76 |
|
77 return 0; |
|
78 |
|
79 error: |
|
80 // cleanup file |
|
81 if (fp) fclose(fp); |
|
82 |
|
83 // cleanup PNG state |
|
84 png_destroy_read_struct(&png, &info, NULL); |
|
85 |
|
86 return -1; |
|
87 } |
|
88 |
|
89 /** |
|
90 * Open the PNG image, and write out to the cache |
|
91 */ |
|
92 static int pt_image_update_cache (struct pt_image *img) |
|
93 { |
|
94 png_structp png; |
|
95 png_infop info; |
|
96 |
|
97 // open .png |
|
98 if (pt_image_open_png(img, &png, &info)) |
|
99 return -1; |
|
100 |
|
101 // setup error trap |
|
102 if (setjmp(png_jmpbuf(png))) |
|
103 goto error; |
|
104 |
|
105 // read meta-info |
|
106 png_read_info(png, info); |
|
107 |
|
108 // pass to cache object |
|
109 if (pt_cache_update_png(img->cache, png, info)) |
|
110 goto error; |
|
111 |
|
112 // finish off, ignore trailing data |
|
113 png_read_end(png, NULL); |
|
114 |
|
115 // clean up |
|
116 png_destroy_read_struct(&png, &info); |
|
117 |
|
118 return 0; |
|
119 |
|
120 error: |
|
121 // clean up |
|
122 png_destroy_read_struct(&png, &info); |
|
123 |
|
124 return -1; |
|
125 } |
|
126 |
|
127 int pt_image_open (struct pt_image **img_ptr, struct pt_ctx *ctx, const char *png_path, int cache_mode) |
|
128 { |
|
129 struct pt_image *img; |
|
130 |
|
131 // XXX: verify that the png_path exists and looks like a PNG file |
|
132 |
|
133 // alloc |
|
134 if (pt_image_new(&img, ctx, png_path)) |
|
135 return -1; |
|
136 |
|
137 // open the cache object for this image |
|
138 if (pt_cache_open(&img->cache, img, mode)) |
|
139 goto error; |
|
140 |
|
141 // update if not fresh |
|
142 if (!pt_cache_fresh(img->cache)) |
|
143 pt_image_update_cache(img); |
|
144 |
|
145 // ok, ready for access |
|
146 *img_ptr = img; |
|
147 |
|
148 return 0; |
|
149 |
|
150 error: |
|
151 pt_image_destroy(img); |
|
152 } |