nuclear@14: /* nuclear@14: libimago - a multi-format image file input/output library. nuclear@14: Copyright (C) 2010 John Tsiombikas nuclear@14: nuclear@14: This program is free software: you can redistribute it and/or modify nuclear@14: it under the terms of the GNU Lesser General Public License as published nuclear@14: by the Free Software Foundation, either version 3 of the License, or nuclear@14: (at your option) any later version. nuclear@14: nuclear@14: This program is distributed in the hope that it will be useful, nuclear@14: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@14: GNU Lesser General Public License for more details. nuclear@14: nuclear@14: You should have received a copy of the GNU Lesser General Public License nuclear@14: along with this program. If not, see . nuclear@14: */ nuclear@14: #include nuclear@14: #include "imago2.h" nuclear@14: nuclear@14: /* pixel-format conversions are sub-optimal at the moment to avoid nuclear@14: * writing a lot of code. optimize at some point ? nuclear@14: */ nuclear@14: nuclear@14: #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x))) nuclear@14: nuclear@14: struct pixel { nuclear@14: float r, g, b, a; nuclear@14: }; nuclear@14: nuclear@14: static void unpack_grey8(struct pixel *unp, void *pptr, int count); nuclear@14: static void unpack_rgb24(struct pixel *unp, void *pptr, int count); nuclear@14: static void unpack_rgba32(struct pixel *unp, void *pptr, int count); nuclear@14: static void unpack_greyf(struct pixel *unp, void *pptr, int count); nuclear@14: static void unpack_rgbf(struct pixel *unp, void *pptr, int count); nuclear@14: static void unpack_rgbaf(struct pixel *unp, void *pptr, int count); nuclear@14: nuclear@14: static void pack_grey8(void *pptr, struct pixel *unp, int count); nuclear@14: static void pack_rgb24(void *pptr, struct pixel *unp, int count); nuclear@14: static void pack_rgba32(void *pptr, struct pixel *unp, int count); nuclear@14: static void pack_greyf(void *pptr, struct pixel *unp, int count); nuclear@14: static void pack_rgbf(void *pptr, struct pixel *unp, int count); nuclear@14: static void pack_rgbaf(void *pptr, struct pixel *unp, int count); nuclear@14: nuclear@14: /* XXX keep in sync with enum img_fmt at imago2.h */ nuclear@14: static void (*unpack[])(struct pixel*, void*, int) = { nuclear@14: unpack_grey8, nuclear@14: unpack_rgb24, nuclear@14: unpack_rgba32, nuclear@14: unpack_greyf, nuclear@14: unpack_rgbf, nuclear@14: unpack_rgbaf nuclear@14: }; nuclear@14: nuclear@14: /* XXX keep in sync with enum img_fmt at imago2.h */ nuclear@14: static void (*pack[])(void*, struct pixel*, int) = { nuclear@14: pack_grey8, nuclear@14: pack_rgb24, nuclear@14: pack_rgba32, nuclear@14: pack_greyf, nuclear@14: pack_rgbf, nuclear@14: pack_rgbaf nuclear@14: }; nuclear@14: nuclear@14: nuclear@14: int img_convert(struct img_pixmap *img, enum img_fmt tofmt) nuclear@14: { nuclear@14: struct pixel pbuf[8]; nuclear@14: int bufsz = (img->width & 7) == 0 ? 8 : ((img->width & 3) == 0 ? 4 : 1); nuclear@14: int i, num_pix = img->width * img->height; nuclear@14: int num_iter = num_pix / bufsz; nuclear@14: char *sptr, *dptr; nuclear@14: struct img_pixmap nimg; nuclear@14: nuclear@14: if(img->fmt == tofmt) { nuclear@14: return 0; /* nothing to do */ nuclear@14: } nuclear@14: nuclear@14: img_init(&nimg); nuclear@14: if(img_set_pixels(&nimg, img->width, img->height, tofmt, 0) == -1) { nuclear@14: img_destroy(&nimg); nuclear@14: return -1; nuclear@14: } nuclear@14: nuclear@14: sptr = img->pixels; nuclear@14: dptr = nimg.pixels; nuclear@14: nuclear@14: for(i=0; ifmt](pbuf, sptr, bufsz); nuclear@14: pack[tofmt](dptr, pbuf, bufsz); nuclear@14: nuclear@14: sptr += bufsz * img->pixelsz; nuclear@14: dptr += bufsz * nimg.pixelsz; nuclear@14: } nuclear@14: nuclear@14: img_copy(img, &nimg); nuclear@14: img_destroy(&nimg); nuclear@14: return 0; nuclear@14: } nuclear@14: nuclear@14: /* the following functions *could* benefit from SIMD */ nuclear@14: nuclear@14: static void unpack_grey8(struct pixel *unp, void *pptr, int count) nuclear@14: { nuclear@14: int i; nuclear@14: unsigned char *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir = unp->g = unp->b = (float)*pix++ / 255.0; nuclear@14: unp->a = 1.0; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void unpack_rgb24(struct pixel *unp, void *pptr, int count) nuclear@14: { nuclear@14: int i; nuclear@14: unsigned char *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir = (float)*pix++ / 255.0; nuclear@14: unp->g = (float)*pix++ / 255.0; nuclear@14: unp->b = (float)*pix++ / 255.0; nuclear@14: unp->a = 1.0; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void unpack_rgba32(struct pixel *unp, void *pptr, int count) nuclear@14: { nuclear@14: int i; nuclear@14: unsigned char *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir = (float)*pix++ / 255.0; nuclear@14: unp->g = (float)*pix++ / 255.0; nuclear@14: unp->b = (float)*pix++ / 255.0; nuclear@14: unp->a = (float)*pix++ / 255.0; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void unpack_greyf(struct pixel *unp, void *pptr, int count) nuclear@14: { nuclear@14: int i; nuclear@14: float *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir = unp->g = unp->b = *pix++; nuclear@14: unp->a = 1.0; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void unpack_rgbf(struct pixel *unp, void *pptr, int count) nuclear@14: { nuclear@14: int i; nuclear@14: float *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir = *pix++; nuclear@14: unp->g = *pix++; nuclear@14: unp->b = *pix++; nuclear@14: unp->a = 1.0; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void unpack_rgbaf(struct pixel *unp, void *pptr, int count) nuclear@14: { nuclear@14: int i; nuclear@14: float *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir = *pix++; nuclear@14: unp->g = *pix++; nuclear@14: unp->b = *pix++; nuclear@14: unp->a = *pix++; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: nuclear@14: static void pack_grey8(void *pptr, struct pixel *unp, int count) nuclear@14: { nuclear@14: int i; nuclear@14: unsigned char *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir + unp->g + unp->b) / 3.0); nuclear@14: *pix++ = CLAMP(lum, 0, 255); nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void pack_rgb24(void *pptr, struct pixel *unp, int count) nuclear@14: { nuclear@14: int i; nuclear@14: unsigned char *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir * 255.0); nuclear@14: int g = (int)(unp->g * 255.0); nuclear@14: int b = (int)(unp->b * 255.0); nuclear@14: nuclear@14: *pix++ = CLAMP(r, 0, 255); nuclear@14: *pix++ = CLAMP(g, 0, 255); nuclear@14: *pix++ = CLAMP(b, 0, 255); nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void pack_rgba32(void *pptr, struct pixel *unp, int count) nuclear@14: { nuclear@14: int i; nuclear@14: unsigned char *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir * 255.0); nuclear@14: int g = (int)(unp->g * 255.0); nuclear@14: int b = (int)(unp->b * 255.0); nuclear@14: int a = (int)(unp->a * 255.0); nuclear@14: nuclear@14: *pix++ = CLAMP(r, 0, 255); nuclear@14: *pix++ = CLAMP(g, 0, 255); nuclear@14: *pix++ = CLAMP(b, 0, 255); nuclear@14: *pix++ = CLAMP(a, 0, 255); nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void pack_greyf(void *pptr, struct pixel *unp, int count) nuclear@14: { nuclear@14: int i; nuclear@14: float *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir + unp->g + unp->b) / 3.0; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void pack_rgbf(void *pptr, struct pixel *unp, int count) nuclear@14: { nuclear@14: int i; nuclear@14: float *pix = pptr; nuclear@14: nuclear@14: for(i=0; ir; nuclear@14: *pix++ = unp->g; nuclear@14: *pix++ = unp->b; nuclear@14: unp++; nuclear@14: } nuclear@14: } nuclear@14: nuclear@14: static void pack_rgbaf(void *pptr, struct pixel *unp, int count) nuclear@14: { nuclear@14: memcpy(pptr, unp, count * sizeof *unp); nuclear@14: } nuclear@14: