istereo2
view libs/imago2/imago2.c @ 8:661bf09db398
- replaced Quartz timer with cross-platform timer code
- protected goatkit builtin theme function from being optimized out
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 24 Sep 2015 07:09:37 +0300 |
parents | |
children |
line source
1 /*
2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "imago2.h"
23 #include "ftype_module.h"
25 static int pixel_size(enum img_fmt fmt);
26 static size_t def_read(void *buf, size_t bytes, void *uptr);
27 static size_t def_write(void *buf, size_t bytes, void *uptr);
28 static long def_seek(long offset, int whence, void *uptr);
31 void img_init(struct img_pixmap *img)
32 {
33 img->pixels = 0;
34 img->width = img->height = 0;
35 img->fmt = IMG_FMT_RGBA32;
36 img->pixelsz = pixel_size(img->fmt);
37 img->name = 0;
38 }
41 void img_destroy(struct img_pixmap *img)
42 {
43 free(img->pixels);
44 img->pixels = 0; /* just in case... */
45 img->width = img->height = 0xbadbeef;
46 free(img->name);
47 }
49 struct img_pixmap *img_create(void)
50 {
51 struct img_pixmap *p;
53 if(!(p = malloc(sizeof *p))) {
54 return 0;
55 }
56 img_init(p);
57 return p;
58 }
60 void img_free(struct img_pixmap *img)
61 {
62 img_destroy(img);
63 free(img);
64 }
66 int img_set_name(struct img_pixmap *img, const char *name)
67 {
68 char *tmp;
70 if(!(tmp = malloc(strlen(name) + 1))) {
71 return -1;
72 }
73 strcpy(tmp, name);
74 img->name = tmp;
75 return 0;
76 }
78 int img_set_format(struct img_pixmap *img, enum img_fmt fmt)
79 {
80 if(img->pixels) {
81 return img_convert(img, fmt);
82 }
83 img->fmt = fmt;
84 return 0;
85 }
87 int img_copy(struct img_pixmap *dest, struct img_pixmap *src)
88 {
89 return img_set_pixels(dest, src->width, src->height, src->fmt, src->pixels);
90 }
92 int img_set_pixels(struct img_pixmap *img, int w, int h, enum img_fmt fmt, void *pix)
93 {
94 void *newpix;
95 int pixsz = pixel_size(fmt);
97 if(!(newpix = malloc(w * h * pixsz))) {
98 return -1;
99 }
101 if(pix) {
102 memcpy(newpix, pix, w * h * pixsz);
103 } else {
104 memset(newpix, 0, w * h * pixsz);
105 }
107 free(img->pixels);
108 img->pixels = newpix;
109 img->width = w;
110 img->height = h;
111 img->pixelsz = pixsz;
112 img->fmt = fmt;
113 return 0;
114 }
116 void *img_load_pixels(const char *fname, int *xsz, int *ysz, enum img_fmt fmt)
117 {
118 struct img_pixmap img;
120 img_init(&img);
122 if(img_load(&img, fname) == -1) {
123 return 0;
124 }
125 if(img.fmt != fmt) {
126 if(img_convert(&img, fmt) == -1) {
127 img_destroy(&img);
128 return 0;
129 }
130 }
132 *xsz = img.width;
133 *ysz = img.height;
134 return img.pixels;
135 }
137 int img_save_pixels(const char *fname, void *pix, int xsz, int ysz, enum img_fmt fmt)
138 {
139 struct img_pixmap img;
141 img_init(&img);
142 img.fmt = fmt;
143 img.name = (char*)fname;
144 img.width = xsz;
145 img.height = ysz;
146 img.pixels = pix;
148 return img_save(&img, fname);
149 }
151 void img_free_pixels(void *pix)
152 {
153 free(pix);
154 }
156 int img_load(struct img_pixmap *img, const char *fname)
157 {
158 int res;
159 FILE *fp;
161 if(!(fp = fopen(fname, "rb"))) {
162 return -1;
163 }
164 res = img_read_file(img, fp);
165 fclose(fp);
166 return res;
167 }
169 /* TODO implement filetype selection */
170 int img_save(struct img_pixmap *img, const char *fname)
171 {
172 int res;
173 FILE *fp;
175 img_set_name(img, fname);
177 if(!(fp = fopen(fname, "wb"))) {
178 return -1;
179 }
180 res = img_write_file(img, fp);
181 fclose(fp);
182 return res;
183 }
185 int img_read_file(struct img_pixmap *img, FILE *fp)
186 {
187 struct img_io io = {0, def_read, def_write, def_seek};
189 io.uptr = fp;
190 return img_read(img, &io);
191 }
193 int img_write_file(struct img_pixmap *img, FILE *fp)
194 {
195 struct img_io io = {0, def_read, def_write, def_seek};
197 io.uptr = fp;
198 return img_write(img, &io);
199 }
201 int img_read(struct img_pixmap *img, struct img_io *io)
202 {
203 struct ftype_module *mod;
205 if((mod = img_find_format_module(io))) {
206 return mod->read(img, io);
207 }
208 return -1;
209 }
211 int img_write(struct img_pixmap *img, struct img_io *io)
212 {
213 struct ftype_module *mod;
215 if(!img->name || !(mod = img_guess_format(img->name))) {
216 /* TODO throw some sort of warning? */
217 /* TODO implement some sort of module priority or let the user specify? */
218 if(!(mod = img_get_module(0))) {
219 return -1;
220 }
221 }
223 return mod->write(img, io);
224 }
226 int img_to_float(struct img_pixmap *img)
227 {
228 enum img_fmt targ_fmt;
230 switch(img->fmt) {
231 case IMG_FMT_GREY8:
232 targ_fmt = IMG_FMT_GREYF;
233 break;
235 case IMG_FMT_RGB24:
236 targ_fmt = IMG_FMT_RGBF;
237 break;
239 case IMG_FMT_RGBA32:
240 targ_fmt = IMG_FMT_RGBAF;
241 break;
243 default:
244 return 0; /* already float */
245 }
247 return img_convert(img, targ_fmt);
248 }
250 int img_to_integer(struct img_pixmap *img)
251 {
252 enum img_fmt targ_fmt;
254 switch(img->fmt) {
255 case IMG_FMT_GREYF:
256 targ_fmt = IMG_FMT_GREY8;
257 break;
259 case IMG_FMT_RGBF:
260 targ_fmt = IMG_FMT_RGB24;
261 break;
263 case IMG_FMT_RGBAF:
264 targ_fmt = IMG_FMT_RGBA32;
265 break;
267 default:
268 return 0; /* already integer */
269 }
271 return img_convert(img, targ_fmt);
272 }
274 int img_is_float(struct img_pixmap *img)
275 {
276 return img->fmt >= IMG_FMT_GREYF && img->fmt <= IMG_FMT_RGBAF;
277 }
279 int img_has_alpha(struct img_pixmap *img)
280 {
281 return img->fmt >= IMG_FMT_GREY8 && img->fmt <= IMG_FMT_RGBA32;
282 }
284 void img_io_set_user_data(struct img_io *io, void *uptr)
285 {
286 io->uptr = uptr;
287 }
289 void img_io_set_read_func(struct img_io *io, size_t (*read)(void*, size_t, void*))
290 {
291 io->read = read;
292 }
294 void img_io_set_write_func(struct img_io *io, size_t (*write)(void*, size_t, void*))
295 {
296 io->write = write;
297 }
299 void img_io_set_seek_func(struct img_io *io, long (*seek)(long, int, void*))
300 {
301 io->seek = seek;
302 }
305 static int pixel_size(enum img_fmt fmt)
306 {
307 switch(fmt) {
308 case IMG_FMT_GREY8:
309 return 1;
310 case IMG_FMT_RGB24:
311 return 3;
312 case IMG_FMT_RGBA32:
313 return 4;
314 case IMG_FMT_GREYF:
315 return sizeof(float);
316 case IMG_FMT_RGBF:
317 return 3 * sizeof(float);
318 case IMG_FMT_RGBAF:
319 return 4 * sizeof(float);
320 default:
321 break;
322 }
323 return 0;
324 }
326 static size_t def_read(void *buf, size_t bytes, void *uptr)
327 {
328 return uptr ? fread(buf, 1, bytes, uptr) : 0;
329 }
331 static size_t def_write(void *buf, size_t bytes, void *uptr)
332 {
333 return uptr ? fwrite(buf, 1, bytes, uptr) : 0;
334 }
336 static long def_seek(long offset, int whence, void *uptr)
337 {
338 if(!uptr || fseek(uptr, offset, whence) == -1) {
339 return -1;
340 }
341 return ftell(uptr);
342 }