2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /* pixel-format conversions are sub-optimal at the moment to avoid
22 * writing a lot of code. optimize at some point ?
25 #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
31 static void unpack_grey8(struct pixel *unp, void *pptr, int count);
32 static void unpack_rgb24(struct pixel *unp, void *pptr, int count);
33 static void unpack_rgba32(struct pixel *unp, void *pptr, int count);
34 static void unpack_greyf(struct pixel *unp, void *pptr, int count);
35 static void unpack_rgbf(struct pixel *unp, void *pptr, int count);
36 static void unpack_rgbaf(struct pixel *unp, void *pptr, int count);
38 static void pack_grey8(void *pptr, struct pixel *unp, int count);
39 static void pack_rgb24(void *pptr, struct pixel *unp, int count);
40 static void pack_rgba32(void *pptr, struct pixel *unp, int count);
41 static void pack_greyf(void *pptr, struct pixel *unp, int count);
42 static void pack_rgbf(void *pptr, struct pixel *unp, int count);
43 static void pack_rgbaf(void *pptr, struct pixel *unp, int count);
45 /* XXX keep in sync with enum img_fmt at imago2.h */
46 static void (*unpack[])(struct pixel*, void*, int) = {
55 /* XXX keep in sync with enum img_fmt at imago2.h */
56 static void (*pack[])(void*, struct pixel*, int) = {
66 int img_convert(struct img_pixmap *img, enum img_fmt tofmt)
69 int bufsz = (img->width & 7) == 0 ? 8 : ((img->width & 3) == 0 ? 4 : 1);
70 int i, num_pix = img->width * img->height;
71 int num_iter = num_pix / bufsz;
73 struct img_pixmap nimg;
75 if(img->fmt == tofmt) {
76 return 0; /* nothing to do */
80 if(img_set_pixels(&nimg, img->width, img->height, tofmt, 0) == -1) {
88 for(i=0; i<num_iter; i++) {
89 unpack[img->fmt](pbuf, sptr, bufsz);
90 pack[tofmt](dptr, pbuf, bufsz);
92 sptr += bufsz * img->pixelsz;
93 dptr += bufsz * nimg.pixelsz;
101 /* the following functions *could* benefit from SIMD */
103 static void unpack_grey8(struct pixel *unp, void *pptr, int count)
106 unsigned char *pix = pptr;
108 for(i=0; i<count; i++) {
109 unp->r = unp->g = unp->b = (float)*pix++ / 255.0;
115 static void unpack_rgb24(struct pixel *unp, void *pptr, int count)
118 unsigned char *pix = pptr;
120 for(i=0; i<count; i++) {
121 unp->r = (float)*pix++ / 255.0;
122 unp->g = (float)*pix++ / 255.0;
123 unp->b = (float)*pix++ / 255.0;
129 static void unpack_rgba32(struct pixel *unp, void *pptr, int count)
132 unsigned char *pix = pptr;
134 for(i=0; i<count; i++) {
135 unp->r = (float)*pix++ / 255.0;
136 unp->g = (float)*pix++ / 255.0;
137 unp->b = (float)*pix++ / 255.0;
138 unp->a = (float)*pix++ / 255.0;
143 static void unpack_greyf(struct pixel *unp, void *pptr, int count)
148 for(i=0; i<count; i++) {
149 unp->r = unp->g = unp->b = *pix++;
155 static void unpack_rgbf(struct pixel *unp, void *pptr, int count)
160 for(i=0; i<count; i++) {
169 static void unpack_rgbaf(struct pixel *unp, void *pptr, int count)
174 for(i=0; i<count; i++) {
184 static void pack_grey8(void *pptr, struct pixel *unp, int count)
187 unsigned char *pix = pptr;
189 for(i=0; i<count; i++) {
190 int lum = (int)(255.0 * (unp->r + unp->g + unp->b) / 3.0);
191 *pix++ = CLAMP(lum, 0, 255);
196 static void pack_rgb24(void *pptr, struct pixel *unp, int count)
199 unsigned char *pix = pptr;
201 for(i=0; i<count; i++) {
202 int r = (int)(unp->r * 255.0);
203 int g = (int)(unp->g * 255.0);
204 int b = (int)(unp->b * 255.0);
206 *pix++ = CLAMP(r, 0, 255);
207 *pix++ = CLAMP(g, 0, 255);
208 *pix++ = CLAMP(b, 0, 255);
213 static void pack_rgba32(void *pptr, struct pixel *unp, int count)
216 unsigned char *pix = pptr;
218 for(i=0; i<count; i++) {
219 int r = (int)(unp->r * 255.0);
220 int g = (int)(unp->g * 255.0);
221 int b = (int)(unp->b * 255.0);
222 int a = (int)(unp->a * 255.0);
224 *pix++ = CLAMP(r, 0, 255);
225 *pix++ = CLAMP(g, 0, 255);
226 *pix++ = CLAMP(b, 0, 255);
227 *pix++ = CLAMP(a, 0, 255);
232 static void pack_greyf(void *pptr, struct pixel *unp, int count)
237 for(i=0; i<count; i++) {
238 *pix++ = (unp->r + unp->g + unp->b) / 3.0;
243 static void pack_rgbf(void *pptr, struct pixel *unp, int count)
248 for(i=0; i<count; i++) {
256 static void pack_rgbaf(void *pptr, struct pixel *unp, int count)
258 memcpy(pptr, unp, count * sizeof *unp);