dbf-halloween2015

annotate libs/imago/imago2.c @ 3:c37fe5d8a4ed

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