dbf-halloween2015
diff libs/imago/imago2.c @ 1:c3f5c32cb210
barfed all the libraries in the source tree to make porting easier
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 01 Nov 2015 00:36:56 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/imago/imago2.c Sun Nov 01 00:36:56 2015 +0200 1.3 @@ -0,0 +1,449 @@ 1.4 +/* 1.5 +libimago - a multi-format image file input/output library. 1.6 +Copyright (C) 2010 John Tsiombikas <nuclear@member.fsf.org> 1.7 + 1.8 +This program is free software: you can redistribute it and/or modify 1.9 +it under the terms of the GNU Lesser General Public License as published 1.10 +by the Free Software Foundation, either version 3 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU Lesser General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU Lesser General Public License 1.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 1.20 +*/ 1.21 + 1.22 +#include <stdio.h> 1.23 +#include <stdlib.h> 1.24 +#include <string.h> 1.25 +#include "imago2.h" 1.26 +#include "ftype_module.h" 1.27 + 1.28 +static int pixel_size(enum img_fmt fmt); 1.29 +static size_t def_read(void *buf, size_t bytes, void *uptr); 1.30 +static size_t def_write(void *buf, size_t bytes, void *uptr); 1.31 +static long def_seek(long offset, int whence, void *uptr); 1.32 + 1.33 + 1.34 +void img_init(struct img_pixmap *img) 1.35 +{ 1.36 + img->pixels = 0; 1.37 + img->width = img->height = 0; 1.38 + img->fmt = IMG_FMT_RGBA32; 1.39 + img->pixelsz = pixel_size(img->fmt); 1.40 + img->name = 0; 1.41 +} 1.42 + 1.43 + 1.44 +void img_destroy(struct img_pixmap *img) 1.45 +{ 1.46 + free(img->pixels); 1.47 + img->pixels = 0; /* just in case... */ 1.48 + img->width = img->height = 0xbadbeef; 1.49 + free(img->name); 1.50 +} 1.51 + 1.52 +struct img_pixmap *img_create(void) 1.53 +{ 1.54 + struct img_pixmap *p; 1.55 + 1.56 + if(!(p = malloc(sizeof *p))) { 1.57 + return 0; 1.58 + } 1.59 + img_init(p); 1.60 + return p; 1.61 +} 1.62 + 1.63 +void img_free(struct img_pixmap *img) 1.64 +{ 1.65 + img_destroy(img); 1.66 + free(img); 1.67 +} 1.68 + 1.69 +int img_set_name(struct img_pixmap *img, const char *name) 1.70 +{ 1.71 + char *tmp; 1.72 + 1.73 + if(!(tmp = malloc(strlen(name) + 1))) { 1.74 + return -1; 1.75 + } 1.76 + strcpy(tmp, name); 1.77 + img->name = tmp; 1.78 + return 0; 1.79 +} 1.80 + 1.81 +int img_set_format(struct img_pixmap *img, enum img_fmt fmt) 1.82 +{ 1.83 + if(img->pixels) { 1.84 + return img_convert(img, fmt); 1.85 + } 1.86 + img->fmt = fmt; 1.87 + return 0; 1.88 +} 1.89 + 1.90 +int img_copy(struct img_pixmap *dest, struct img_pixmap *src) 1.91 +{ 1.92 + return img_set_pixels(dest, src->width, src->height, src->fmt, src->pixels); 1.93 +} 1.94 + 1.95 +int img_set_pixels(struct img_pixmap *img, int w, int h, enum img_fmt fmt, void *pix) 1.96 +{ 1.97 + void *newpix; 1.98 + int pixsz = pixel_size(fmt); 1.99 + 1.100 + if(!(newpix = malloc(w * h * pixsz))) { 1.101 + return -1; 1.102 + } 1.103 + 1.104 + if(pix) { 1.105 + memcpy(newpix, pix, w * h * pixsz); 1.106 + } else { 1.107 + memset(newpix, 0, w * h * pixsz); 1.108 + } 1.109 + 1.110 + free(img->pixels); 1.111 + img->pixels = newpix; 1.112 + img->width = w; 1.113 + img->height = h; 1.114 + img->pixelsz = pixsz; 1.115 + img->fmt = fmt; 1.116 + return 0; 1.117 +} 1.118 + 1.119 +void *img_load_pixels(const char *fname, int *xsz, int *ysz, enum img_fmt fmt) 1.120 +{ 1.121 + struct img_pixmap img; 1.122 + 1.123 + img_init(&img); 1.124 + 1.125 + if(img_load(&img, fname) == -1) { 1.126 + return 0; 1.127 + } 1.128 + if(img.fmt != fmt) { 1.129 + if(img_convert(&img, fmt) == -1) { 1.130 + img_destroy(&img); 1.131 + return 0; 1.132 + } 1.133 + } 1.134 + 1.135 + *xsz = img.width; 1.136 + *ysz = img.height; 1.137 + return img.pixels; 1.138 +} 1.139 + 1.140 +int img_save_pixels(const char *fname, void *pix, int xsz, int ysz, enum img_fmt fmt) 1.141 +{ 1.142 + struct img_pixmap img; 1.143 + 1.144 + img_init(&img); 1.145 + img.fmt = fmt; 1.146 + img.name = (char*)fname; 1.147 + img.width = xsz; 1.148 + img.height = ysz; 1.149 + img.pixels = pix; 1.150 + 1.151 + return img_save(&img, fname); 1.152 +} 1.153 + 1.154 +void img_free_pixels(void *pix) 1.155 +{ 1.156 + free(pix); 1.157 +} 1.158 + 1.159 +int img_load(struct img_pixmap *img, const char *fname) 1.160 +{ 1.161 + int res; 1.162 + FILE *fp; 1.163 + 1.164 + if(!(fp = fopen(fname, "rb"))) { 1.165 + return -1; 1.166 + } 1.167 + res = img_read_file(img, fp); 1.168 + fclose(fp); 1.169 + return res; 1.170 +} 1.171 + 1.172 +/* TODO implement filetype selection */ 1.173 +int img_save(struct img_pixmap *img, const char *fname) 1.174 +{ 1.175 + int res; 1.176 + FILE *fp; 1.177 + 1.178 + img_set_name(img, fname); 1.179 + 1.180 + if(!(fp = fopen(fname, "wb"))) { 1.181 + return -1; 1.182 + } 1.183 + res = img_write_file(img, fp); 1.184 + fclose(fp); 1.185 + return res; 1.186 +} 1.187 + 1.188 +int img_read_file(struct img_pixmap *img, FILE *fp) 1.189 +{ 1.190 + struct img_io io = {0, def_read, def_write, def_seek}; 1.191 + 1.192 + io.uptr = fp; 1.193 + return img_read(img, &io); 1.194 +} 1.195 + 1.196 +int img_write_file(struct img_pixmap *img, FILE *fp) 1.197 +{ 1.198 + struct img_io io = {0, def_read, def_write, def_seek}; 1.199 + 1.200 + io.uptr = fp; 1.201 + return img_write(img, &io); 1.202 +} 1.203 + 1.204 +int img_read(struct img_pixmap *img, struct img_io *io) 1.205 +{ 1.206 + struct ftype_module *mod; 1.207 + 1.208 + if((mod = img_find_format_module(io))) { 1.209 + return mod->read(img, io); 1.210 + } 1.211 + return -1; 1.212 +} 1.213 + 1.214 +int img_write(struct img_pixmap *img, struct img_io *io) 1.215 +{ 1.216 + struct ftype_module *mod; 1.217 + 1.218 + if(!img->name || !(mod = img_guess_format(img->name))) { 1.219 + /* TODO throw some sort of warning? */ 1.220 + /* TODO implement some sort of module priority or let the user specify? */ 1.221 + if(!(mod = img_get_module(0))) { 1.222 + return -1; 1.223 + } 1.224 + } 1.225 + 1.226 + return mod->write(img, io); 1.227 +} 1.228 + 1.229 +int img_to_float(struct img_pixmap *img) 1.230 +{ 1.231 + enum img_fmt targ_fmt; 1.232 + 1.233 + switch(img->fmt) { 1.234 + case IMG_FMT_GREY8: 1.235 + targ_fmt = IMG_FMT_GREYF; 1.236 + break; 1.237 + 1.238 + case IMG_FMT_RGB24: 1.239 + targ_fmt = IMG_FMT_RGBF; 1.240 + break; 1.241 + 1.242 + case IMG_FMT_RGBA32: 1.243 + targ_fmt = IMG_FMT_RGBAF; 1.244 + break; 1.245 + 1.246 + default: 1.247 + return 0; /* already float */ 1.248 + } 1.249 + 1.250 + return img_convert(img, targ_fmt); 1.251 +} 1.252 + 1.253 +int img_to_integer(struct img_pixmap *img) 1.254 +{ 1.255 + enum img_fmt targ_fmt; 1.256 + 1.257 + switch(img->fmt) { 1.258 + case IMG_FMT_GREYF: 1.259 + targ_fmt = IMG_FMT_GREY8; 1.260 + break; 1.261 + 1.262 + case IMG_FMT_RGBF: 1.263 + targ_fmt = IMG_FMT_RGB24; 1.264 + break; 1.265 + 1.266 + case IMG_FMT_RGBAF: 1.267 + targ_fmt = IMG_FMT_RGBA32; 1.268 + break; 1.269 + 1.270 + default: 1.271 + return 0; /* already integer */ 1.272 + } 1.273 + 1.274 + return img_convert(img, targ_fmt); 1.275 +} 1.276 + 1.277 +int img_is_float(struct img_pixmap *img) 1.278 +{ 1.279 + return img->fmt >= IMG_FMT_GREYF && img->fmt <= IMG_FMT_RGBAF; 1.280 +} 1.281 + 1.282 +int img_has_alpha(struct img_pixmap *img) 1.283 +{ 1.284 + if(img->fmt == IMG_FMT_RGBA32 || img->fmt == IMG_FMT_RGBAF) { 1.285 + return 1; 1.286 + } 1.287 + return 0; 1.288 +} 1.289 + 1.290 + 1.291 +void img_setpixel(struct img_pixmap *img, int x, int y, void *pixel) 1.292 +{ 1.293 + char *dest = (char*)img->pixels + (y * img->width + x) * img->pixelsz; 1.294 + memcpy(dest, pixel, img->pixelsz); 1.295 +} 1.296 + 1.297 +void img_getpixel(struct img_pixmap *img, int x, int y, void *pixel) 1.298 +{ 1.299 + char *dest = (char*)img->pixels + (y * img->width + x) * img->pixelsz; 1.300 + memcpy(pixel, dest, img->pixelsz); 1.301 +} 1.302 + 1.303 +void img_setpixel1i(struct img_pixmap *img, int x, int y, int pix) 1.304 +{ 1.305 + img_setpixel4i(img, x, y, pix, pix, pix, pix); 1.306 +} 1.307 + 1.308 +void img_setpixel1f(struct img_pixmap *img, int x, int y, float pix) 1.309 +{ 1.310 + img_setpixel4f(img, x, y, pix, pix, pix, pix); 1.311 +} 1.312 + 1.313 +void img_setpixel4i(struct img_pixmap *img, int x, int y, int r, int g, int b, int a) 1.314 +{ 1.315 + if(img_is_float(img)) { 1.316 + img_setpixel4f(img, x, y, r / 255.0, g / 255.0, b / 255.0, a / 255.0); 1.317 + } else { 1.318 + unsigned char pixel[4]; 1.319 + pixel[0] = r; 1.320 + pixel[1] = g; 1.321 + pixel[2] = b; 1.322 + pixel[3] = a; 1.323 + 1.324 + img_setpixel(img, x, y, pixel); 1.325 + } 1.326 +} 1.327 + 1.328 +void img_setpixel4f(struct img_pixmap *img, int x, int y, float r, float g, float b, float a) 1.329 +{ 1.330 + if(img_is_float(img)) { 1.331 + float pixel[4]; 1.332 + pixel[0] = r; 1.333 + pixel[1] = g; 1.334 + pixel[2] = b; 1.335 + pixel[3] = a; 1.336 + 1.337 + img_setpixel(img, x, y, pixel); 1.338 + } else { 1.339 + img_setpixel4i(img, x, y, (int)(r * 255.0), (int)(g * 255.0), (int)(b * 255.0), (int)(a * 255.0)); 1.340 + } 1.341 +} 1.342 + 1.343 +void img_getpixel1i(struct img_pixmap *img, int x, int y, int *pix) 1.344 +{ 1.345 + int junk[3]; 1.346 + img_getpixel4i(img, x, y, pix, junk, junk + 1, junk + 2); 1.347 +} 1.348 + 1.349 +void img_getpixel1f(struct img_pixmap *img, int x, int y, float *pix) 1.350 +{ 1.351 + float junk[3]; 1.352 + img_getpixel4f(img, x, y, pix, junk, junk + 1, junk + 2); 1.353 +} 1.354 + 1.355 +void img_getpixel4i(struct img_pixmap *img, int x, int y, int *r, int *g, int *b, int *a) 1.356 +{ 1.357 + if(img_is_float(img)) { 1.358 + float pixel[4] = {0, 0, 0, 0}; 1.359 + img_getpixel(img, x, y, pixel); 1.360 + *r = pixel[0] * 255.0; 1.361 + *g = pixel[1] * 255.0; 1.362 + *b = pixel[2] * 255.0; 1.363 + *a = pixel[3] * 255.0; 1.364 + } else { 1.365 + unsigned char pixel[4]; 1.366 + img_getpixel(img, x, y, pixel); 1.367 + *r = pixel[0]; 1.368 + *g = pixel[1]; 1.369 + *b = pixel[2]; 1.370 + *a = pixel[3]; 1.371 + } 1.372 +} 1.373 + 1.374 +void img_getpixel4f(struct img_pixmap *img, int x, int y, float *r, float *g, float *b, float *a) 1.375 +{ 1.376 + if(img_is_float(img)) { 1.377 + float pixel[4] = {0, 0, 0, 0}; 1.378 + img_getpixel(img, x, y, pixel); 1.379 + *r = pixel[0]; 1.380 + *g = pixel[1]; 1.381 + *b = pixel[2]; 1.382 + *a = pixel[3]; 1.383 + } else { 1.384 + unsigned char pixel[4]; 1.385 + img_getpixel(img, x, y, pixel); 1.386 + *r = pixel[0] / 255.0; 1.387 + *g = pixel[1] / 255.0; 1.388 + *b = pixel[2] / 255.0; 1.389 + *a = pixel[3] / 255.0; 1.390 + } 1.391 +} 1.392 + 1.393 +void img_io_set_user_data(struct img_io *io, void *uptr) 1.394 +{ 1.395 + io->uptr = uptr; 1.396 +} 1.397 + 1.398 +void img_io_set_read_func(struct img_io *io, size_t (*read)(void*, size_t, void*)) 1.399 +{ 1.400 + io->read = read; 1.401 +} 1.402 + 1.403 +void img_io_set_write_func(struct img_io *io, size_t (*write)(void*, size_t, void*)) 1.404 +{ 1.405 + io->write = write; 1.406 +} 1.407 + 1.408 +void img_io_set_seek_func(struct img_io *io, long (*seek)(long, int, void*)) 1.409 +{ 1.410 + io->seek = seek; 1.411 +} 1.412 + 1.413 + 1.414 +static int pixel_size(enum img_fmt fmt) 1.415 +{ 1.416 + switch(fmt) { 1.417 + case IMG_FMT_GREY8: 1.418 + return 1; 1.419 + case IMG_FMT_RGB24: 1.420 + return 3; 1.421 + case IMG_FMT_RGBA32: 1.422 + return 4; 1.423 + case IMG_FMT_GREYF: 1.424 + return sizeof(float); 1.425 + case IMG_FMT_RGBF: 1.426 + return 3 * sizeof(float); 1.427 + case IMG_FMT_RGBAF: 1.428 + return 4 * sizeof(float); 1.429 + default: 1.430 + break; 1.431 + } 1.432 + return 0; 1.433 +} 1.434 + 1.435 +static size_t def_read(void *buf, size_t bytes, void *uptr) 1.436 +{ 1.437 + return uptr ? fread(buf, 1, bytes, uptr) : 0; 1.438 +} 1.439 + 1.440 +static size_t def_write(void *buf, size_t bytes, void *uptr) 1.441 +{ 1.442 + return uptr ? fwrite(buf, 1, bytes, uptr) : 0; 1.443 +} 1.444 + 1.445 +static long def_seek(long offset, int whence, void *uptr) 1.446 +{ 1.447 + if(!uptr || fseek(uptr, offset, whence) == -1) { 1.448 + return -1; 1.449 + } 1.450 + return ftell(uptr); 1.451 +} 1.452 +