2 * art_rgba.c: Functions for manipulating RGBA pixel data.
4 * Libart_LGPL - library of basic graphic primitives
5 * Copyright (C) 2000 Raph Levien
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.
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.
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.
27 #define ART_OPTIMIZE_SPACE
29 #ifndef ART_OPTIMIZE_SPACE
30 #include "art_rgba_table.c"
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.
39 * Composites the RGBA pixels in @dst over the @src buffer.
42 art_rgba_rgba_composite (art_u8 *dst, const art_u8 *src, int n)
45 #ifdef WORDS_BIGENDIAN
46 art_u32 src_rgba, dst_rgba;
48 art_u32 src_abgr, dst_abgr;
50 art_u8 src_alpha, dst_alpha;
52 for (i = 0; i < n; i++)
54 #ifdef WORDS_BIGENDIAN
55 src_rgba = ((art_u32 *)src)[i];
56 src_alpha = src_rgba & 0xff;
58 src_abgr = ((art_u32 *)src)[i];
59 src_alpha = (src_abgr >> 24) & 0xff;
63 if (src_alpha == 0xff ||
65 #ifdef WORDS_BIGENDIAN
66 dst_rgba = ((art_u32 *)dst)[i],
67 dst_alpha = dst_rgba & 0xff,
69 dst_abgr = ((art_u32 *)dst)[i],
70 dst_alpha = (dst_abgr >> 24),
73 #ifdef WORDS_BIGENDIAN
74 ((art_u32 *)dst)[i] = src_rgba;
76 ((art_u32 *)dst)[i] = src_abgr;
81 int src_r, src_g, src_b;
82 int dst_r, dst_g, dst_b;
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;
91 tmp = art_rgba_composite_table[(src_alpha << 8) + dst_alpha];
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;
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;
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;
116 ((art_u32 *)dst)[i] = (a << 24) | (b << 16) | (g << 8) | r;
121 /* it's not clear to me this optimization really wins */
124 /* skip over run of transparent pixels */
125 for (; i < n - 1; i++)
127 #ifdef WORDS_BIGENDIAN
128 src_rgba = ((art_u32 *)src)[i + 1];
132 src_abgr = ((art_u32 *)src)[i + 1];
133 if (src_abgr & 0xff000000)
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.
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.
155 art_rgba_fill_run (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int n)
158 #ifdef WORDS_BIGENDIAN
164 #ifdef WORDS_BIGENDIAN
165 src_rgba = (r << 24) | (g << 16) | (b << 8) | 255;
167 src_abgr = (255 << 24) | (b << 16) | (g << 8) | r;
169 for (i = 0; i < n; i++)
171 #ifdef WORDS_BIGENDIAN
172 ((art_u32 *)buf)[i] = src_rgba;
174 ((art_u32 *)buf)[i] = src_abgr;
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.
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.
193 art_rgba_run_alpha (art_u8 *buf, art_u8 r, art_u8 g, art_u8 b, int alpha, int n)
196 #ifdef WORDS_BIGENDIAN
197 art_u32 src_rgba, dst_rgba;
199 art_u32 src_abgr, dst_abgr;
203 int dst_r, dst_g, dst_b;
207 #ifdef WORDS_BIGENDIAN
208 src_rgba = (r << 24) | (g << 16) | (b << 8) | alpha;
210 src_abgr = (alpha << 24) | (b << 16) | (g << 8) | r;
212 for (i = 0; i < n; i++)
214 #ifdef WORDS_BIGENDIAN
215 dst_rgba = ((art_u32 *)buf)[i];
216 dst_alpha = dst_rgba & 0xff;
218 dst_abgr = ((art_u32 *)buf)[i];
219 dst_alpha = (dst_abgr >> 24) & 0xff;
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;
228 tmp = art_rgba_composite_table[(alpha << 8) + dst_alpha];
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;
237 dst_r = dst_abgr & 0xff;
238 dst_g = (dst_abgr >> 8) & 0xff;
239 dst_b = (dst_abgr >> 16) & 0xff;
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;
247 ((art_u32 *)buf)[i] = (a << 24) | (dst_b << 16) | (dst_g << 8) | dst_r;
252 #ifdef WORDS_BIGENDIAN
253 ((art_u32 *)buf)[i] = src_rgba;
255 ((art_u32 *)buf)[i] = src_abgr;