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

Revision 2655, 7.7 KB checked in by sam, 5 years ago (diff)
  • pixels.c: support more conversion combinations.
Line 
1/*
2 *  libpipi       Proper image processing implementation 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#include "common.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <math.h>
27
28#include "pipi.h"
29#include "pipi_internals.h"
30
31#define GAMMA 2.2
32
33static void init_tables(void);
34
35static float u8tof32_table[256];
36static inline float u8tof32(uint8_t p) { return u8tof32_table[(int)p]; }
37
38
39/* Return a direct pointer to an image's pixels. */
40pipi_pixels_t *pipi_getpixels(pipi_image_t *img, pipi_format_t type)
41{
42    size_t bytes = 0;
43    int x, y, i;
44
45    if(type < 0 || type >= PIPI_PIXELS_MAX)
46        return NULL;
47
48    if(img->last_modified == type)
49        return &img->p[type];
50
51    /* Preliminary conversions */
52    if(img->last_modified == PIPI_PIXELS_RGBA32
53                  && type == PIPI_PIXELS_Y_F)
54        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
55    else if(img->last_modified == PIPI_PIXELS_BGR24
56                       && type == PIPI_PIXELS_Y_F)
57        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
58    else if(img->last_modified == PIPI_PIXELS_Y_F
59                       && type == PIPI_PIXELS_RGBA32)
60        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
61    else if(img->last_modified == PIPI_PIXELS_Y_F
62                       && type == PIPI_PIXELS_BGR24)
63        pipi_getpixels(img, PIPI_PIXELS_RGBA_F);
64
65    /* Allocate pixels if necessary */
66    if(!img->p[type].pixels)
67    {
68        switch(type)
69        {
70        case PIPI_PIXELS_RGBA32:
71            bytes = img->w * img->h * 4 * sizeof(uint8_t);
72            break;
73        case PIPI_PIXELS_BGR24:
74            bytes = img->w * img->h * 3 * sizeof(uint8_t);
75            break;
76        case PIPI_PIXELS_RGBA_F:
77            bytes = img->w * img->h * 4 * sizeof(float);
78            break;
79        case PIPI_PIXELS_Y_F:
80            bytes = img->w * img->h * sizeof(float);
81            break;
82        default:
83            return NULL;
84        }
85
86        img->p[type].pixels = malloc(bytes);
87    }
88
89    /* Convert pixels */
90    if(img->last_modified == PIPI_PIXELS_RGBA32
91                  && type == PIPI_PIXELS_RGBA_F)
92    {
93        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA32].pixels;
94        float *dest = (float *)img->p[type].pixels;
95
96        init_tables();
97
98        for(y = 0; y < img->h; y++)
99            for(x = 0; x < img->w; x++)
100                for(i = 0; i < 4; i++)
101                    dest[4 * (y * img->w + x) + i]
102                        = u8tof32(src[4 * (y * img->w + x) + i]);
103    }
104    else if(img->last_modified == PIPI_PIXELS_BGR24
105                       && type == PIPI_PIXELS_RGBA_F)
106    {
107        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_BGR24].pixels;
108        float *dest = (float *)img->p[type].pixels;
109
110        init_tables();
111
112        for(y = 0; y < img->h; y++)
113            for(x = 0; x < img->w; x++)
114            {
115                dest[4 * (y * img->w + x)]
116                    = u8tof32(src[3 * (y * img->w + x) + 2]);
117                dest[4 * (y * img->w + x) + 1]
118                    = u8tof32(src[3 * (y * img->w + x) + 1]);
119                dest[4 * (y * img->w + x) + 2]
120                    = u8tof32(src[3 * (y * img->w + x)]);
121                dest[4 * (y * img->w + x) + 3] = 1.0;
122            }
123    }
124    else if(img->last_modified == PIPI_PIXELS_RGBA_F
125                       && type == PIPI_PIXELS_RGBA32)
126    {
127        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
128        uint8_t *dest = (uint8_t *)img->p[type].pixels;
129
130        init_tables();
131
132        for(y = 0; y < img->h; y++)
133            for(x = 0; x < img->w; x++)
134                for(i = 0; i < 4; i++)
135                {
136                    double p, e;
137                    uint8_t d;
138
139                    p = src[4 * (y * img->w + x) + i];
140
141                    if(p < 0.) d = 0.;
142                    else if(p > 1.) d = 255;
143                    else d = (int)(255.999 * pow(p, 1. / GAMMA));
144
145                    dest[4 * (y * img->w + x) + i] = d;
146
147                    e = p - u8tof32(d);
148                    if(x < img->w - 1)
149                        src[4 * (y * img->w + x + 1) + i] += e * .4375;
150                    if(y < img->h - 1)
151                    {
152                        if(x > 0)
153                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875;
154                        src[4 * ((y + 1) * img->w + x) + i] += e * .3125;
155                        if(x < img->w - 1)
156                            src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625;
157                    }
158                }
159    }
160    else if(img->last_modified == PIPI_PIXELS_RGBA_F
161                       && type == PIPI_PIXELS_BGR24)
162    {
163        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
164        uint8_t *dest = (uint8_t *)img->p[type].pixels;
165
166        init_tables();
167
168        for(y = 0; y < img->h; y++)
169            for(x = 0; x < img->w; x++)
170                for(i = 0; i < 3; i++)
171                {
172                    double p, e;
173                    uint8_t d;
174
175                    p = src[4 * (y * img->w + x) + i];
176
177                    if(p < 0.) d = 0.;
178                    else if(p > 1.) d = 255;
179                    else d = (int)(255.999 * pow(p, 1. / GAMMA));
180
181                    dest[3 * (y * img->w + x) + i] = d;
182
183                    e = p - u8tof32(d);
184                    if(x < img->w - 1)
185                        src[4 * (y * img->w + x + 1) + i] += e * .4375;
186                    if(y < img->h - 1)
187                    {
188                        if(x > 0)
189                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875;
190                        src[4 * ((y + 1) * img->w + x) + i] += e * .3125;
191                        if(x < img->w - 1)
192                            src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625;
193                    }
194                }
195    }
196    else if(img->last_modified == PIPI_PIXELS_Y_F
197                       && type == PIPI_PIXELS_RGBA_F)
198    {
199        float *src = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
200        float *dest = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
201
202        init_tables();
203
204        for(y = 0; y < img->h; y++)
205            for(x = 0; x < img->w; x++)
206            {
207                float p = src[y * img->w + x];
208                dest[4 * (y * img->w + x)] = p;
209                dest[4 * (y * img->w + x) + 1] = p;
210                dest[4 * (y * img->w + x) + 2] = p;
211                dest[4 * (y * img->w + x) + 3] = 1.0;
212            }
213    }
214    else if(img->last_modified == PIPI_PIXELS_RGBA_F
215                       && type == PIPI_PIXELS_Y_F)
216    {
217        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
218        float *dest = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
219
220        init_tables();
221
222        for(y = 0; y < img->h; y++)
223            for(x = 0; x < img->w; x++)
224            {
225                float p = 0.;
226                p += 0.299 * src[4 * (y * img->w + x)];
227                p += 0.587 * src[4 * (y * img->w + x) + 1];
228                p += 0.114 * src[4 * (y * img->w + x) + 2];
229                dest[y * img->w + x] = p;
230            }
231    }
232    else
233    {
234        memset(img->p[type].pixels, 0, bytes);
235    }
236
237    img->last_modified = type;
238
239    return &img->p[type];
240}
241
242
243static void init_tables(void)
244{
245    static int done = 0;
246    int i;
247
248    if(done)
249        return;
250
251    for(i = 0; i < 256; i++)
252        u8tof32_table[i] = pow((double)i / 255., GAMMA);
253
254    done = 1;
255}
256
Note: See TracBrowser for help on using the repository browser.