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

Last change on this file since 2636 was 2636, checked in by Sam Hocevar, 14 years ago
  • pixels.c: fix a typo in the dithering method that could cause crashes.
File size: 7.1 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        case PIPI_PIXELS_Y_F:
66            bytes = img->w * img->h * sizeof(float);
67            break;
68        default:
69            return NULL;
70        }
71
72        img->p[type].pixels = malloc(bytes);
73    }
74
75    /* Convert pixels */
76    if(img->last_modified == PIPI_PIXELS_RGBA32
77                  && type == PIPI_PIXELS_RGBA_F)
78    {
79        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_RGBA32].pixels;
80        float *dest = (float *)img->p[type].pixels;
81
82        init_tables();
83
84        for(y = 0; y < img->h; y++)
85            for(x = 0; x < img->w; x++)
86                for(i = 0; i < 4; i++)
87                    dest[4 * (y * img->w + x) + i]
88                        = u8tof32(src[4 * (y * img->w + x) + i]);
89    }
90    else if(img->last_modified == PIPI_PIXELS_BGR24
91                       && type == PIPI_PIXELS_RGBA_F)
92    {
93        uint8_t *src = (uint8_t *)img->p[PIPI_PIXELS_BGR24].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            {
101                dest[4 * (y * img->w + x)]
102                    = u8tof32(src[3 * (y * img->w + x) + 2]);
103                dest[4 * (y * img->w + x) + 1]
104                    = u8tof32(src[3 * (y * img->w + x) + 1]);
105                dest[4 * (y * img->w + x) + 2]
106                    = u8tof32(src[3 * (y * img->w + x)]);
107                dest[4 * (y * img->w + x) + 3] = 1.0;
108            }
109    }
110    else if(img->last_modified == PIPI_PIXELS_RGBA_F
111                       && type == PIPI_PIXELS_RGBA32)
112    {
113        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
114        uint8_t *dest = (uint8_t *)img->p[type].pixels;
115
116        init_tables();
117
118        for(y = 0; y < img->h; y++)
119            for(x = 0; x < img->w; x++)
120                for(i = 0; i < 4; i++)
121                {
122                    double p, e;
123                    uint8_t d;
124
125                    p = src[4 * (y * img->w + x) + i];
126
127                    if(p < 0.) d = 0.;
128                    else if(p > 1.) d = 255;
129                    else d = (int)(255.999 * pow(p, 1. / GAMMA));
130
131                    dest[4 * (y * img->w + x) + i] = d;
132
133                    e = p - u8tof32(d);
134                    if(x < img->w - 1)
135                        src[4 * (y * img->w + x + 1) + i] += e * .4375;
136                    if(y < img->h - 1)
137                    {
138                        if(x > 0)
139                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875;
140                        src[4 * ((y + 1) * img->w + x) + i] += e * .3125;
141                        if(x < img->w - 1)
142                            src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625;
143                    }
144                }
145    }
146    else if(img->last_modified == PIPI_PIXELS_RGBA_F
147                       && type == PIPI_PIXELS_BGR24)
148    {
149        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
150        uint8_t *dest = (uint8_t *)img->p[type].pixels;
151
152        init_tables();
153
154        for(y = 0; y < img->h; y++)
155            for(x = 0; x < img->w; x++)
156                for(i = 0; i < 3; i++)
157                {
158                    double p, e;
159                    uint8_t d;
160
161                    p = src[4 * (y * img->w + x) + i];
162
163                    if(p < 0.) d = 0.;
164                    else if(p > 1.) d = 255;
165                    else d = (int)(255.999 * pow(p, 1. / GAMMA));
166
167                    dest[3 * (y * img->w + x) + i] = d;
168
169                    e = p - u8tof32(d);
170                    if(x < img->w - 1)
171                        src[4 * (y * img->w + x + 1) + i] += e * .4375;
172                    if(y < img->h - 1)
173                    {
174                        if(x > 0)
175                            src[4 * ((y + 1) * img->w + x - 1) + i] += e * .1875;
176                        src[4 * ((y + 1) * img->w + x) + i] += e * .3125;
177                        if(x < img->w - 1)
178                            src[4 * ((y + 1) * img->w + x + 1) + i] += e * .0625;
179                    }
180                }
181    }
182    else if(img->last_modified == PIPI_PIXELS_Y_F
183                       && type == PIPI_PIXELS_RGBA_F)
184    {
185        float *src = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
186        float *dest = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
187
188        init_tables();
189
190        for(y = 0; y < img->h; y++)
191            for(x = 0; x < img->w; x++)
192            {
193                float p = src[y * img->w + x];
194                dest[4 * (y * img->w + x)] = p;
195                dest[4 * (y * img->w + x) + 1] = p;
196                dest[4 * (y * img->w + x) + 2] = p;
197                dest[4 * (y * img->w + x) + 3] = 1.0;
198            }
199    }
200    else if(img->last_modified == PIPI_PIXELS_RGBA_F
201                       && type == PIPI_PIXELS_Y_F)
202    {
203        float *src = (float *)img->p[PIPI_PIXELS_RGBA_F].pixels;
204        float *dest = (float *)img->p[PIPI_PIXELS_Y_F].pixels;
205
206        init_tables();
207
208        for(y = 0; y < img->h; y++)
209            for(x = 0; x < img->w; x++)
210            {
211                float p = 0.;
212                p += 0.299 * src[4 * (y * img->w + x)];
213                p += 0.587 * src[4 * (y * img->w + x) + 1];
214                p += 0.114 * src[4 * (y * img->w + x) + 2];
215                dest[y * img->w + x] = p;
216            }
217    }
218    else
219    {
220        memset(img->p[type].pixels, 0, bytes);
221    }
222
223    img->last_modified = type;
224
225    return &img->p[type];
226}
227
228
229static void init_tables(void)
230{
231    static int done = 0;
232    int i;
233
234    if(done)
235        return;
236
237    for(i = 0; i < 256; i++)
238        u8tof32_table[i] = pow((double)i / 255., GAMMA);
239
240    done = 1;
241}
242
Note: See TracBrowser for help on using the repository browser.