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

Last change on this file since 2630 was 2630, checked in by Sam Hocevar, 14 years ago
  • pixels.c: add support for 24-bpp BGR format.
File size: 5.8 KB
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    /* Allocate pixels if necessary */
52    if(!img->p[type].pixels)
53    {
54        switch(type)
55        {
56        case PIPI_PIXELS_RGBA32:
57            bytes = img->w * img->h * 4 * sizeof(uint8_t);
58            break;
59        case PIPI_PIXELS_BGR24:
60            bytes = img->w * img->h * 3 * sizeof(uint8_t);
61            break;
62        case PIPI_PIXELS_RGBA_F:
63            bytes = img->w * img->h * 4 * sizeof(float);
64            break;
65        default:
66            return NULL;
67        }
68
69        img->p[type].pixels = malloc(bytes);
70    }
71
72    /* Convert pixels */
73    if(img->last_modified == PIPI_PIXELS_RGBA32
74                  && type == PIPI_PIXELS_RGBA_F)
75    {
76        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA32].pixels;
77        float *dest = (float *)img->p[type].pixels;
78
79        init_tables();
80
81        for(y = 0; y < img->h; y++)
82            for(x = 0; x < img->w; x++)
83                for(i = 0; i < 4; i++)
84                    dest[4 * (y * img->w + x) + i]
85                        = u8tof32(src[4 * (y * img->w + x) + i]);
86    }
87    else if(img->last_modified == PIPI_PIXELS_BGR24
88                       && type == PIPI_PIXELS_RGBA_F)
89    {
90        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_BGR24].pixels;
91        float *dest = (float *)img->p[type].pixels;
92
93        init_tables();
94
95        for(y = 0; y < img->h; y++)
96            for(x = 0; x < img->w; x++)
97            {
98                dest[4 * (y * img->w + x)]
99                    = u8tof32(src[3 * (y * img->w + x) + 2]);
100                dest[4 * (y * img->w + x) + 1]
101                    = u8tof32(src[3 * (y * img->w + x) + 1]);
102                dest[4 * (y * img->w + x) + 2]
103                    = u8tof32(src[3 * (y * img->w + x)]);
104                dest[4 * (y * img->w + x) + 3] = 1.0;
105            }
106    }
107    else if(img->last_modified == PIPI_PIXELS_RGBA_F
108                       && type == PIPI_PIXELS_RGBA32)
109    {
110        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
111        uint8_t *dest = (uint8_t *)img->p[type].pixels;
112
113        init_tables();
114
115        for(y = 0; y < img->h; y++)
116            for(x = 0; x < img->w; x++)
117                for(i = 0; i < 4; i++)
118                {
119                    double p, e;
120                    uint8_t d;
121
122                    p = src[4 * (y * img->w + x) + i];
123
124                    if(p < 0.) d = 0.;
125                    else if(p > 1.) d = 255;
126                    else d = (int)(255.999 * pow(p, 1. / GAMMA));
127
128                    dest[4 * (y * img->w + x) + i] = d;
129
130                    e = p - u8tof32(d);
131                    if(x < img->w - 1)
132                        src[4 * (y * img->w + x + 1) + i] += e * .4375;
133                    if(y < img->h - 1)
134                    {
135                        if(x < img->w - 1)
136                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875;
137                        src[4 * ((y + 1) * img->w + x) + i] += e * .3125;
138                        if(x < img->w - 1)
139                            src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625;
140                    }
141                }
142    }
143    else if(img->last_modified == PIPI_PIXELS_RGBA_F
144                       && type == PIPI_PIXELS_BGR24)
145    {
146        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
147        uint8_t *dest = (uint8_t *)img->p[type].pixels;
148
149        init_tables();
150
151        for(y = 0; y < img->h; y++)
152            for(x = 0; x < img->w; x++)
153                for(i = 0; i < 3; i++)
154                {
155                    double p, e;
156                    uint8_t d;
157
158                    p = src[4 * (y * img->w + x) + i];
159
160                    if(p < 0.) d = 0.;
161                    else if(p > 1.) d = 255;
162                    else d = (int)(255.999 * pow(p, 1. / GAMMA));
163
164                    dest[3 * (y * img->w + x) + i] = d;
165
166                    e = p - u8tof32(d);
167                    if(x < img->w - 1)
168                        src[4 * (y * img->w + x + 1) + i] += e * .4375;
169                    if(y < img->h - 1)
170                    {
171                        if(x < img->w - 1)
172                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875;
173                        src[4 * ((y + 1) * img->w + x) + i] += e * .3125;
174                        if(x < img->w - 1)
175                            src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625;
176                    }
177                }
178    }
179    else
180    {
181        memset(img->p[type].pixels, 0, bytes);
182    }
183
184    img->last_modified = type;
185
186    return &img->p[type];
187}
188
189
190static void init_tables(void)
191{
192    static int done = 0;
193    int i;
194
195    if(done)
196        return;
197
198    for(i = 0; i < 256; i++)
199        u8tof32_table[i] = pow((double)i / 255., GAMMA);
200
201    done = 1;
202}
203
Note: See TracBrowser for help on using the repository browser.