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

Last change on this file since 4690 was 3342, checked in by Sam Hocevar, 12 years ago

Change _C pixel format suffixes into _U8 for more clarity.

File size: 8.4 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_get_pixels(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_U8)
52        return &img->p[type];
53
54    /* Preliminary conversions */
55    if(img->last_modified == PIPI_PIXELS_RGBA_U8
56                  && type == PIPI_PIXELS_Y_F32)
57        pipi_get_pixels(img, PIPI_PIXELS_RGBA_F32);
58    else if(img->last_modified == PIPI_PIXELS_BGR_U8
59                       && type == PIPI_PIXELS_Y_F32)
60        pipi_get_pixels(img, PIPI_PIXELS_RGBA_F32);
61    else if(img->last_modified == PIPI_PIXELS_Y_F32
62                       && type == PIPI_PIXELS_RGBA_U8)
63        pipi_get_pixels(img, PIPI_PIXELS_RGBA_F32);
64    else if(img->last_modified == PIPI_PIXELS_Y_F32
65                       && type == PIPI_PIXELS_BGR_U8)
66        pipi_get_pixels(img, PIPI_PIXELS_RGBA_F32);
67
68    /* Allocate pixels if necessary */
69    if(!img->p[type].pixels)
70    {
71        switch(type)
72        {
73        case PIPI_PIXELS_RGBA_U8:
74            bytes = img->w * img->h * 4 * sizeof(uint8_t);
75            bpp = 4 * sizeof(uint8_t);
76            break;
77        case PIPI_PIXELS_BGR_U8:
78            bytes = img->w * img->h * 3 * sizeof(uint8_t);
79            bpp = 3 * sizeof(uint8_t);
80            break;
81        case PIPI_PIXELS_RGBA_F32:
82            bytes = img->w * img->h * 4 * sizeof(float);
83            bpp = 4 * sizeof(float);
84            break;
85        case PIPI_PIXELS_Y_F32:
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_U8
102                  && type == PIPI_PIXELS_RGBA_F32)
103    {
104        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA_U8].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_U8
116                       && type == PIPI_PIXELS_RGBA_F32)
117    {
118        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_BGR_U8].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_F32
136                       && type == PIPI_PIXELS_RGBA_U8)
137    {
138        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F32].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_F32
172                       && type == PIPI_PIXELS_BGR_U8)
173    {
174        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F32].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_F32
208                       && type == PIPI_PIXELS_RGBA_F32)
209    {
210        float *src = (float *)img->p[PIPI_PIXELS_Y_F32].pixels;
211        float *dest = (float *)img->p[PIPI_PIXELS_RGBA_F32].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_F32
226                       && type == PIPI_PIXELS_Y_F32)
227    {
228        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F32].pixels;
229        float *dest = (float *)img->p[PIPI_PIXELS_Y_F32].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_release_pixels(pipi_image_t *img, pipi_pixels_t *p)
254{
255    return;
256}
257
258void pipi_set_colorspace(pipi_image_t *img, pipi_format_t fmt)
259{
260    pipi_pixels_t *p = pipi_get_pixels(img, fmt);
261    pipi_release_pixels(img, p);
262}
263
264void pipi_set_gamma(double g)
265{
266    if(g > 0.)
267    {
268        global_gamma = g;
269        done = 0;
270    }
271}
272
273static void init_tables(void)
274{
275    int i;
276
277    if(done)
278        return;
279
280    for(i = 0; i < 256; i++)
281        u8tof32_table[i] = pow((double)i / 255., global_gamma);
282
283    done = 1;
284}
285
Note: See TracBrowser for help on using the repository browser.