source: libpipi/trunk/pipi/pixels.c @ 2902

Last change on this file since 2902 was 2902, checked in by Sam Hocevar, 11 years ago

Support C99 types on Win32 through the same hacks as in libcaca.

File size: 8.2 KB
Line 
1/*
2 *  libpipi       Pathetic image processing interface library
3 *  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 * pixels.c: pixel-level image manipulation
17 */
18
19#include "config.h"
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <math.h>
26
27#include "pipi.h"
28#include "pipi_internals.h"
29
30static void init_tables(void);
31
32static double global_gamma = 2.2;
33static int done = 0;
34
35static float u8tof32_table[256];
36static inline float u8tof32(uint8_t p) { return u8tof32_table[(int)p]; }
37
38/* Return a direct pointer to an image's pixels. */
39pipi_pixels_t *pipi_getpixels(pipi_image_t *img, pipi_format_t type)
40{
41    size_t bytes = 0;
42    int x, y, i, bpp = 0;
43
44    if(type < 0 || type >= PIPI_PIXELS_MAX)
45        return NULL;
46
47    if(img->last_modified == type)
48        return &img->p[type];
49
50    /* Handle special cases */
51    if(type == PIPI_PIXELS_MASK_C)
52        return &img->p[type];
53
54    /* Preliminary conversions */
55    if(img->last_modified == PIPI_PIXELS_RGBA_C
56                  && type == PIPI_PIXELS_Y_F)
57        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
58    else if(img->last_modified == PIPI_PIXELS_BGR_C
59                       && type == PIPI_PIXELS_Y_F)
60        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
61    else if(img->last_modified == PIPI_PIXELS_Y_F
62                       && type == PIPI_PIXELS_RGBA_C)
63        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
64    else if(img->last_modified == PIPI_PIXELS_Y_F
65                       && type == PIPI_PIXELS_BGR_C)
66        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
67
68    /* Allocate pixels if necessary */
69    if(!img->p[type].pixels)
70    {
71        switch(type)
72        {
73        case PIPI_PIXELS_RGBA_C:
74            bytes = img->w * img->h * 4 * sizeof(uint8_t);
75            bpp = 4 * sizeof(uint8_t);
76            break;
77        case PIPI_PIXELS_BGR_C:
78            bytes = img->w * img->h * 3 * sizeof(uint8_t);
79            bpp = 3 * sizeof(uint8_t);
80            break;
81        case PIPI_PIXELS_RGBA_F:
82            bytes = img->w * img->h * 4 * sizeof(float);
83            bpp = 4 * sizeof(float);
84            break;
85        case PIPI_PIXELS_Y_F:
86            bytes = img->w * img->h * sizeof(float);
87            bpp = sizeof(float);
88            break;
89        default:
90            return NULL;
91        }
92
93        img->p[type].pixels = malloc(bytes);
94        img->p[type].bytes = bytes;
95        img->p[type].bpp = bpp;
96        img->p[type].w = img->w;
97        img->p[type].h = img->h;
98    }
99
100    /* Convert pixels */
101    if(img->last_modified == PIPI_PIXELS_RGBA_C
102                  && type == PIPI_PIXELS_RGBA_F)
103    {
104        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA_C].pixels;
105        float *dest = (float *)img->p[type].pixels;
106
107        init_tables();
108
109        for(y = 0; y < img->h; y++)
110            for(x = 0; x < img->w; x++)
111                for(i = 0; i < 4; i++)
112                    dest[4 * (y * img->w + x) + i]
113                        = u8tof32(src[4 * (y * img->w + x) + i]);
114    }
115    else if(img->last_modified == PIPI_PIXELS_BGR_C
116                       && type == PIPI_PIXELS_RGBA_F)
117    {
118        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_BGR_C].pixels;
119        float *dest = (float *)img->p[type].pixels;
120
121        init_tables();
122
123        for(y = 0; y < img->h; y++)
124            for(x = 0; x < img->w; x++)
125            {
126                dest[4 * (y * img->w + x)]
127                    = u8tof32(src[3 * (y * img->w + x) + 2]);
128                dest[4 * (y * img->w + x) + 1]
129                    = u8tof32(src[3 * (y * img->w + x) + 1]);
130                dest[4 * (y * img->w + x) + 2]
131                    = u8tof32(src[3 * (y * img->w + x)]);
132                dest[4 * (y * img->w + x) + 3] = 1.0;
133            }
134    }
135    else if(img->last_modified == PIPI_PIXELS_RGBA_F
136                       && type == PIPI_PIXELS_RGBA_C)
137    {
138        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
139        uint8_t *dest = (uint8_t *)img->p[type].pixels;
140
141        init_tables();
142
143        for(y = 0; y < img->h; y++)
144            for(x = 0; x < img->w; x++)
145                for(i = 0; i < 4; i++)
146                {
147                    double p, e;
148                    uint8_t d;
149
150                    p = src[4 * (y * img->w + x) + i];
151
152                    if(p < 0.) d = 0.;
153                    else if(p > 1.) d = 255;
154                    else d = (int)(255.999 * pow(p, 1. / global_gamma));
155
156                    dest[4 * (y * img->w + x) + i] = d;
157
158                    e = (p - u8tof32(d)) / 16;
159                    if(x < img->w - 1)
160                        src[4 * (y * img->w + x + 1) + i] += e * 7;
161                    if(y < img->h - 1)
162                    {
163                        if(x > 0)
164                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * 3;
165                        src[4 * ((y + 1) * img->w + x) + i] += e * 5;
166                        if(x < img->w - 1)
167                            src[4 * ((y + 1) * img->w + x + 1) + i] += e;
168                    }
169                }
170    }
171    else if(img->last_modified == PIPI_PIXELS_RGBA_F
172                       && type == PIPI_PIXELS_BGR_C)
173    {
174        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
175        uint8_t *dest = (uint8_t *)img->p[type].pixels;
176
177        init_tables();
178
179        for(y = 0; y < img->h; y++)
180            for(x = 0; x < img->w; x++)
181                for(i = 0; i < 3; i++)
182                {
183                    double p, e;
184                    uint8_t d;
185
186                    p = src[4 * (y * img->w + x) + i];
187
188                    if(p < 0.) d = 0.;
189                    else if(p > 1.) d = 255;
190                    else d = (int)(255.999 * pow(p, 1. / global_gamma));
191
192                    dest[3 * (y * img->w + x) + i] = d;
193
194                    e = (p - u8tof32(d)) / 16;
195                    if(x < img->w - 1)
196                        src[4 * (y * img->w + x + 1) + i] += e * 7;
197                    if(y < img->h - 1)
198                    {
199                        if(x > 0)
200                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * 3;
201                        src[4 * ((y + 1) * img->w + x) + i] += e * 5;
202                        if(x < img->w - 1)
203                            src[4 * ((y + 1) * img->w + x + 1) + i] += e;
204                    }
205                }
206    }
207    else if(img->last_modified == PIPI_PIXELS_Y_F
208                       && type == PIPI_PIXELS_RGBA_F)
209    {
210        float *src = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
211        float *dest = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
212
213        init_tables();
214
215        for(y = 0; y < img->h; y++)
216            for(x = 0; x < img->w; x++)
217            {
218                float p = src[y * img->w + x];
219                dest[4 * (y * img->w + x)] = p;
220                dest[4 * (y * img->w + x) + 1] = p;
221                dest[4 * (y * img->w + x) + 2] = p;
222                dest[4 * (y * img->w + x) + 3] = 1.0;
223            }
224    }
225    else if(img->last_modified == PIPI_PIXELS_RGBA_F
226                       && type == PIPI_PIXELS_Y_F)
227    {
228        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
229        float *dest = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
230
231        init_tables();
232
233        for(y = 0; y < img->h; y++)
234            for(x = 0; x < img->w; x++)
235            {
236                float p = 0.;
237                p += 0.299 * src[4 * (y * img->w + x)];
238                p += 0.587 * src[4 * (y * img->w + x) + 1];
239                p += 0.114 * src[4 * (y * img->w + x) + 2];
240                dest[y * img->w + x] = p;
241            }
242    }
243    else
244    {
245        memset(img->p[type].pixels, 0, bytes);
246    }
247
248    img->last_modified = type;
249
250    return &img->p[type];
251}
252
253void pipi_set_gamma(double g)
254{
255    if(g > 0.)
256    {
257        global_gamma = g;
258        done = 0;
259    }
260}
261
262static void init_tables(void)
263{
264    int i;
265
266    if(done)
267        return;
268
269    for(i = 0; i < 256; i++)
270        u8tof32_table[i] = pow((double)i / 255., global_gamma);
271
272    done = 1;
273}
274
Note: See TracBrowser for help on using the repository browser.