2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010-2020 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/>.
22 /* pixel-format conversions are sub-optimal at the moment to avoid
23 * writing a lot of code. optimize at some point ?
26 #define CLAMP(x, a, b) ((x) < (a) ? (a) : ((x) > (b) ? (b) : (x)))
32 static void unpack_grey8(struct pixel *unp, void *pptr, int count);
33 static void unpack_rgb24(struct pixel *unp, void *pptr, int count);
34 static void unpack_rgba32(struct pixel *unp, void *pptr, int count);
35 static void unpack_bgra32(struct pixel *unp, void *pptr, int count);
36 static void unpack_greyf(struct pixel *unp, void *pptr, int count);
37 static void unpack_rgbf(struct pixel *unp, void *pptr, int count);
38 static void unpack_rgbaf(struct pixel *unp, void *pptr, int count);
39 static void unpack_rgb565(struct pixel *unp, void *pptr, int count);
41 static void pack_grey8(void *pptr, struct pixel *unp, int count);
42 static void pack_rgb24(void *pptr, struct pixel *unp, int count);
43 static void pack_rgba32(void *pptr, struct pixel *unp, int count);
44 static void pack_bgra32(void *pptr, struct pixel *unp, int count);
45 static void pack_greyf(void *pptr, struct pixel *unp, int count);
46 static void pack_rgbf(void *pptr, struct pixel *unp, int count);
47 static void pack_rgbaf(void *pptr, struct pixel *unp, int count);
48 static void pack_rgb565(void *pptr, struct pixel *unp, int count);
50 /* XXX keep in sync with enum img_fmt at imago2.h */
51 static void (*unpack[])(struct pixel*, void*, int) = {
62 /* XXX keep in sync with enum img_fmt at imago2.h */
63 static void (*pack[])(void*, struct pixel*, int) = {
75 int img_convert(struct img_pixmap *img, enum img_fmt tofmt)
78 int bufsz = (img->width & 7) == 0 ? 8 : ((img->width & 3) == 0 ? 4 : 1);
79 int i, num_pix = img->width * img->height;
80 int num_iter = num_pix / bufsz;
82 struct img_pixmap nimg;
84 if(img->fmt == tofmt) {
85 return 0; /* nothing to do */
89 if(img_set_pixels(&nimg, img->width, img->height, tofmt, 0) == -1) {
97 for(i=0; i<num_iter; i++) {
98 unpack[img->fmt](pbuf, sptr, bufsz);
99 pack[tofmt](dptr, pbuf, bufsz);
101 sptr += bufsz * img->pixelsz;
102 dptr += bufsz * nimg.pixelsz;
105 img_copy(img, &nimg);
110 /* the following functions *could* benefit from SIMD */
112 static void unpack_grey8(struct pixel *unp, void *pptr, int count)
115 unsigned char *pix = pptr;
117 for(i=0; i<count; i++) {
118 unp->r = unp->g = unp->b = (float)*pix++ / 255.0;
124 static void unpack_rgb24(struct pixel *unp, void *pptr, int count)
127 unsigned char *pix = pptr;
129 for(i=0; i<count; i++) {
130 unp->r = (float)*pix++ / 255.0;
131 unp->g = (float)*pix++ / 255.0;
132 unp->b = (float)*pix++ / 255.0;
138 static void unpack_rgba32(struct pixel *unp, void *pptr, int count)
141 unsigned char *pix = pptr;
143 for(i=0; i<count; i++) {
144 unp->r = (float)*pix++ / 255.0;
145 unp->g = (float)*pix++ / 255.0;
146 unp->b = (float)*pix++ / 255.0;
147 unp->a = (float)*pix++ / 255.0;
152 static void unpack_bgra32(struct pixel *unp, void *pptr, int count)
155 unsigned char *pix = pptr;
157 for(i=0; i<count; i++) {
158 unp->b = (float)*pix++ / 255.0;
159 unp->g = (float)*pix++ / 255.0;
160 unp->r = (float)*pix++ / 255.0;
161 unp->a = (float)*pix++ / 255.0;
166 static void unpack_greyf(struct pixel *unp, void *pptr, int count)
171 for(i=0; i<count; i++) {
172 unp->r = unp->g = unp->b = *pix++;
178 static void unpack_rgbf(struct pixel *unp, void *pptr, int count)
183 for(i=0; i<count; i++) {
192 static void unpack_rgbaf(struct pixel *unp, void *pptr, int count)
197 for(i=0; i<count; i++) {
206 static void unpack_rgb565(struct pixel *unp, void *pptr, int count)
209 uint16_t *pix = pptr;
211 for(i=0; i<count; i++) {
212 uint16_t r, g, b, p = *pix++;
214 if(b & 8) b |= 7; /* fill LSbits with whatever bit 0 was */
216 if(g & 4) g |= 3; /* ditto */
218 if(r & 8) r |= 7; /* same */
220 unp->r = (float)r / 255.0f;
221 unp->g = (float)g / 255.0f;
222 unp->b = (float)b / 255.0f;
229 static void pack_grey8(void *pptr, struct pixel *unp, int count)
232 unsigned char *pix = pptr;
234 for(i=0; i<count; i++) {
235 int lum = (int)(255.0 * (unp->r + unp->g + unp->b) / 3.0);
236 *pix++ = CLAMP(lum, 0, 255);
241 static void pack_rgb24(void *pptr, struct pixel *unp, int count)
244 unsigned char *pix = pptr;
246 for(i=0; i<count; i++) {
247 int r = (int)(unp->r * 255.0);
248 int g = (int)(unp->g * 255.0);
249 int b = (int)(unp->b * 255.0);
251 *pix++ = CLAMP(r, 0, 255);
252 *pix++ = CLAMP(g, 0, 255);
253 *pix++ = CLAMP(b, 0, 255);
258 static void pack_rgba32(void *pptr, struct pixel *unp, int count)
261 unsigned char *pix = pptr;
263 for(i=0; i<count; i++) {
264 int r = (int)(unp->r * 255.0);
265 int g = (int)(unp->g * 255.0);
266 int b = (int)(unp->b * 255.0);
267 int a = (int)(unp->a * 255.0);
269 *pix++ = CLAMP(r, 0, 255);
270 *pix++ = CLAMP(g, 0, 255);
271 *pix++ = CLAMP(b, 0, 255);
272 *pix++ = CLAMP(a, 0, 255);
277 static void pack_bgra32(void *pptr, struct pixel *unp, int count)
280 unsigned char *pix = pptr;
282 for(i=0; i<count; i++) {
283 int r = (int)(unp->r * 255.0);
284 int g = (int)(unp->g * 255.0);
285 int b = (int)(unp->b * 255.0);
286 int a = (int)(unp->a * 255.0);
288 *pix++ = CLAMP(b, 0, 255);
289 *pix++ = CLAMP(g, 0, 255);
290 *pix++ = CLAMP(r, 0, 255);
291 *pix++ = CLAMP(a, 0, 255);
296 static void pack_greyf(void *pptr, struct pixel *unp, int count)
301 for(i=0; i<count; i++) {
302 *pix++ = (unp->r + unp->g + unp->b) / 3.0;
307 static void pack_rgbf(void *pptr, struct pixel *unp, int count)
312 for(i=0; i<count; i++) {
320 static void pack_rgbaf(void *pptr, struct pixel *unp, int count)
322 memcpy(pptr, unp, count * sizeof *unp);
326 static void pack_rgb565(void *pptr, struct pixel *unp, int count)
329 uint16_t *pix = pptr;
331 for(i=0; i<count; i++) {
332 uint16_t r = (uint16_t)(unp->r * 31.0f);
333 uint16_t g = (uint16_t)(unp->g * 63.0f);
334 uint16_t b = (uint16_t)(unp->b * 31.0f);
338 *pix++ = (r << 11) | (g << 5) | b;