eqemu

annotate libs/libimago/src/imago2.c @ 10:819c7ebb1bec

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