The BIG graph update
[rrdtool.git] / libraries / libart_lgpl-2.3.7 / art_rgba.c
1 /*
2  * art_rgba.c: Functions for manipulating RGBA pixel data.
3  *
4  * Libart_LGPL - library of basic graphic primitives
5  * Copyright (C) 2000 Raph Levien
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <config.h>
24 #include "art_misc.h"
25 #include "art_rgba.h"
26
27 #define ART_OPTIMIZE_SPACE
28
29 #ifndef ART_OPTIMIZE_SPACE
30 #include "art_rgba_table.c"
31 #endif
32
33 /**
34  * art_rgba_rgba_composite: Composite RGBA image over RGBA buffer.
35  * @dst: Destination RGBA buffer.
36  * @src: Source RGBA buffer.
37  * @n: Number of RGBA pixels to composite.
38  *
39  * Composites the RGBA pixels in @dst over the @src buffer.
40  **/
41 void
42 art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n)
43 {
44   int i;
45 #ifdef WORDS_BIGENDIAN
46   art_u32 src_rgba, dst_rgba;
47 #else
48   art_u32 src_abgr, dst_abgr;
49 #endif
50   art_u8 src_alpha, dst_alpha;
51
52   for (i = 0; i < n; i++)
53     {
54 #ifdef WORDS_BIGENDIAN
55       src_rgba = ((art_u32 *)src)[i];
56       src_alpha = src_rgba & 0xff;
57 #else
58       src_abgr = ((art_u32 *)src)[i];
59       src_alpha = (src_abgr >> 24) & 0xff;
60 #endif
61       if (src_alpha)
62         {
63           if (src_alpha == 0xff ||
64               (
65 #ifdef WORDS_BIGENDIAN
66                dst_rgba = ((art_u32 *)dst)[i],
67                dst_alpha = dst_rgba & 0xff,
68 #else
69                dst_abgr = ((art_u32 *)dst)[i],
70                dst_alpha = (dst_abgr >> 24),
71 #endif
72                dst_alpha == 0))
73 #ifdef WORDS_BIGENDIAN
74             ((art_u32 *)dst)[i] = src_rgba;
75 #else
76             ((art_u32 *)dst)[i] = src_abgr;
77 #endif
78           else
79             {
80               int r, g, b, a;
81               int src_r, src_g, src_b;
82               int dst_r, dst_g, dst_b;
83               int tmp;
84               int c;
85
86 #ifdef ART_OPTIMIZE_SPACE
87               tmp = (255 - src_alpha) * (255 - dst_alpha) + 0x80;
88               a = 255 - ((tmp + (tmp >> 8)) >> 8);
89               c = ((src_alpha << 16) + (a >> 1)) / a;
90 #else
91               tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha];
92               c = tmp & 0x1ffff;
93               a = tmp >> 24;
94 #endif
95 #ifdef WORDS_BIGENDIAN
96               src_r = (src_rgba >> 24) & 0xff;
97               src_g = (src_rgba >> 16) & 0xff;
98               src_b = (src_rgba >> 8) & 0xff;
99               dst_r = (dst_rgba >> 24) & 0xff;
100               dst_g = (dst_rgba >> 16) & 0xff;
101               dst_b = (dst_rgba >> 8) & 0xff;
102 #else
103               src_r = src_abgr & 0xff;
104               src_g = (src_abgr >> 8) & 0xff;
105               src_b = (src_abgr >> 16) & 0xff;
106               dst_r = dst_abgr & 0xff;
107               dst_g = (dst_abgr >> 8) & 0xff;
108               dst_b = (dst_abgr >> 16) & 0xff;
109 #endif
110               r = dst_r + (((src_r - dst_r) * c + 0x8000) >> 16);
111               g = dst_g + (((src_g - dst_g) * c + 0x8000) >> 16);
112               b = dst_b + (((src_b - dst_b) * c + 0x8000) >> 16);
113 #ifdef WORDS_BIGENDIAN
114             ((art_u32 *)dst)[i] = (r << 24) | (g << 16) | (b << 8) | a;
115 #else
116             ((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r;
117 #endif        
118             }
119         }
120 #if 0
121       /* it's not clear to me this optimization really wins */
122       else
123         {
124           /* skip over run of transparent pixels */
125           for (; i < n - 1; i++)
126             {
127 #ifdef WORDS_BIGENDIAN
128               src_rgba = ((art_u32 *)src)[i + 1];
129               if (src_rgba & 0xff)
130                 break;
131 #else
132               src_abgr = ((art_u32 *)src)[i + 1];
133               if (src_abgr & 0xff000000)
134                 break;
135 #endif
136             }
137         }
138 #endif
139     }
140 }
141
142 /**
143  * art_rgba_fill_run: fill an RGBA buffer a solid RGB color.
144  * @buf: Buffer to fill.
145  * @r: Red, range 0..255.
146  * @g: Green, range 0..255.
147  * @b: Blue, range 0..255.
148  * @n: Number of RGB triples to fill.
149  *
150  * Fills a buffer with @n copies of the (@r, @g, @b) triple, solid
151  * alpha. Thus, locations @buf (inclusive) through @buf + 4 * @n
152  * (exclusive) are written.
153  **/
154 void
155 art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
156 {
157   int i;
158 #ifdef WORDS_BIGENDIAN
159   art_u32 src_rgba;
160 #else
161   art_u32 src_abgr;
162 #endif
163
164 #ifdef WORDS_BIGENDIAN
165   src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
166 #else
167   src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
168 #endif
169   for (i = 0; i < n; i++)
170     {
171 #ifdef WORDS_BIGENDIAN
172       ((art_u32 *)buf)[i] = src_rgba;
173 #else
174       ((art_u32 *)buf)[i] = src_abgr;
175 #endif
176     }    
177 }
178
179 /**
180  * art_rgba_run_alpha: Render semitransparent color over RGBA buffer.
181  * @buf: Buffer for rendering.
182  * @r: Red, range 0..255.
183  * @g: Green, range 0..255.
184  * @b: Blue, range 0..255.
185  * @alpha: Alpha, range 0..255.
186  * @n: Number of RGB triples to render.
187  *
188  * Renders a sequential run of solid (@r, @g, @b) color over @buf with
189  * opacity @alpha. Note that the range of @alpha is 0..255, in contrast
190  * to art_rgb_run_alpha, which has a range of 0..256.
191  **/
192 void
193 art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
194 {
195   int i;
196 #ifdef WORDS_BIGENDIAN
197   art_u32 src_rgba, dst_rgba;
198 #else
199   art_u32 src_abgr, dst_abgr;
200 #endif
201   art_u8 dst_alpha;
202   int a;
203   int dst_r, dst_g, dst_b;
204   int tmp;
205   int c;
206
207 #ifdef WORDS_BIGENDIAN
208   src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha;
209 #else
210   src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r;
211 #endif
212   for (i = 0; i < n; i++)
213     {
214 #ifdef WORDS_BIGENDIAN
215       dst_rgba = ((art_u32 *)buf)[i];
216       dst_alpha = dst_rgba & 0xff;
217 #else
218       dst_abgr = ((art_u32 *)buf)[i];
219       dst_alpha = (dst_abgr >> 24) & 0xff;
220 #endif
221       if (dst_alpha)
222         {
223 #ifdef ART_OPTIMIZE_SPACE
224           tmp = (255 - alpha) * (255 - dst_alpha) + 0x80;
225           a = 255 - ((tmp + (tmp >> 8)) >> 8);
226           c = ((alpha << 16) + (a >> 1)) / a;
227 #else
228           tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha];
229           c = tmp & 0x1ffff;
230           a = tmp >> 24;
231 #endif
232 #ifdef WORDS_BIGENDIAN
233           dst_r = (dst_rgba >> 24) & 0xff;
234           dst_g = (dst_rgba >> 16) & 0xff;
235           dst_b = (dst_rgba >> 8) & 0xff;
236 #else
237           dst_r = dst_abgr & 0xff;
238           dst_g = (dst_abgr >> 8) & 0xff;
239           dst_b = (dst_abgr >> 16) & 0xff;
240 #endif
241           dst_r += (((r - dst_r) * c + 0x8000) >> 16);
242           dst_g += (((g - dst_g) * c + 0x8000) >> 16);
243           dst_b += (((b - dst_b) * c + 0x8000) >> 16);
244 #ifdef WORDS_BIGENDIAN
245           ((art_u32 *)buf)[i] = (dst_r << 24) | (dst_g << 16) | (dst_b << 8) | a;
246 #else
247           ((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r;
248 #endif
249         }
250       else
251         {
252 #ifdef WORDS_BIGENDIAN
253           ((art_u32 *)buf)[i] = src_rgba;
254 #else
255           ((art_u32 *)buf)[i] = src_abgr;
256 #endif
257         }
258     }
259 }