istereo

annotate libs/imago2/imago2.c @ 33:33e9eedad390

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