The BIG graph update
[rrdtool.git] / libraries / libart_lgpl-2.3.7 / art_rgb_bitmap_affine.c
1 /* Libart_LGPL - library of basic graphic primitives
2  * Copyright (C) 1998 Raph Levien
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <math.h>
21 #include "art_misc.h"
22 #include "art_point.h"
23 #include "art_affine.h"
24 #include "art_rgb_affine_private.h"
25 #include "art_rgb_bitmap_affine.h"
26
27 /* This module handles compositing of affine-transformed bitmap images
28    over rgb pixel buffers. */
29
30 /* Composite the source image over the destination image, applying the
31    affine transform. Foreground color is given and assumed to be
32    opaque, background color is assumed to be fully transparent. */
33
34 static void
35 art_rgb_bitmap_affine_opaque (art_u8 *dst,
36                               int x0, int y0, int x1, int y1,
37                               int dst_rowstride,
38                               const art_u8 *src,
39                               int src_width, int src_height, int src_rowstride,
40                               art_u32 rgb,
41                               const double affine[6],
42                               ArtFilterLevel level,
43                               ArtAlphaGamma *alphagamma)
44 {
45   /* Note: this is a slow implementation, and is missing all filter
46      levels other than NEAREST. It is here for clarity of presentation
47      and to establish the interface. */
48   int x, y;
49   double inv[6];
50   art_u8 *dst_p, *dst_linestart;
51   const art_u8 *src_p;
52   ArtPoint pt, src_pt;
53   int src_x, src_y;
54   art_u8 r, g, b;
55   int run_x0, run_x1;
56
57   r = rgb >> 16;
58   g = (rgb >> 8) & 0xff;
59   b = rgb & 0xff;
60   dst_linestart = dst;
61   art_affine_invert (inv, affine);
62   for (y = y0; y < y1; y++)
63     {
64       pt.y = y + 0.5;
65       run_x0 = x0;
66       run_x1 = x1;
67       art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
68                           inv);
69       dst_p = dst_linestart + (run_x0 - x0) * 3;
70       for (x = run_x0; x < run_x1; x++)
71         {
72           pt.x = x + 0.5;
73           art_affine_point (&src_pt, &pt, inv);
74           src_x = floor (src_pt.x);
75           src_y = floor (src_pt.y);
76           src_p = src + (src_y * src_rowstride) + (src_x >> 3);
77           if (*src_p & (128 >> (src_x & 7)))
78             {
79               dst_p[0] = r;
80               dst_p[1] = g;
81               dst_p[2] = b;
82             }
83           dst_p += 3;
84         }
85       dst_linestart += dst_rowstride;
86     }
87 }
88 /* Composite the source image over the destination image, applying the
89    affine transform. Foreground color is given, background color is
90    assumed to be fully transparent. */
91
92 /**
93  * art_rgb_bitmap_affine: Affine transform source bitmap image and composite.
94  * @dst: Destination image RGB buffer.
95  * @x0: Left coordinate of destination rectangle.
96  * @y0: Top coordinate of destination rectangle.
97  * @x1: Right coordinate of destination rectangle.
98  * @y1: Bottom coordinate of destination rectangle.
99  * @dst_rowstride: Rowstride of @dst buffer.
100  * @src: Source image bitmap buffer.
101  * @src_width: Width of source image.
102  * @src_height: Height of source image.
103  * @src_rowstride: Rowstride of @src buffer.
104  * @rgba: RGBA foreground color, in 0xRRGGBBAA.
105  * @affine: Affine transform.
106  * @level: Filter level.
107  * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing.
108  *
109  * Affine transform the source image stored in @src, compositing over
110  * the area of destination image @dst specified by the rectangle
111  * (@x0, @y0) - (@x1, @y1).
112  *
113  * The source bitmap stored with MSB as the leftmost pixel. Source 1
114  * bits correspond to the semitransparent color @rgba, while source 0
115  * bits are transparent.
116  *
117  * See art_rgb_affine() for a description of additional parameters.
118  **/
119 void
120 art_rgb_bitmap_affine (art_u8 *dst,
121                        int x0, int y0, int x1, int y1, int dst_rowstride,
122                        const art_u8 *src,
123                        int src_width, int src_height, int src_rowstride,
124                        art_u32 rgba,
125                        const double affine[6],
126                        ArtFilterLevel level,
127                        ArtAlphaGamma *alphagamma)
128 {
129   /* Note: this is a slow implementation, and is missing all filter
130      levels other than NEAREST. It is here for clarity of presentation
131      and to establish the interface. */
132   int x, y;
133   double inv[6];
134   art_u8 *dst_p, *dst_linestart;
135   const art_u8 *src_p;
136   ArtPoint pt, src_pt;
137   int src_x, src_y;
138   int alpha;
139   art_u8 bg_r, bg_g, bg_b;
140   art_u8 fg_r, fg_g, fg_b;
141   art_u8 r, g, b;
142   int run_x0, run_x1;
143
144   alpha = rgba & 0xff;
145   if (alpha == 0xff)
146     {
147       art_rgb_bitmap_affine_opaque (dst, x0, y0, x1, y1, dst_rowstride,
148                                     src,
149                                     src_width, src_height, src_rowstride,
150                                     rgba >> 8,
151                                     affine,
152                                     level,
153                                     alphagamma);
154       return;
155     }
156   /* alpha = (65536 * alpha) / 255; */
157   alpha = (alpha << 8) + alpha + (alpha >> 7);
158   r = rgba >> 24;
159   g = (rgba >> 16) & 0xff;
160   b = (rgba >> 8) & 0xff;
161   dst_linestart = dst;
162   art_affine_invert (inv, affine);
163   for (y = y0; y < y1; y++)
164     {
165       pt.y = y + 0.5;
166       run_x0 = x0;
167       run_x1 = x1;
168       art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height,
169                           inv);
170       dst_p = dst_linestart + (run_x0 - x0) * 3;
171       for (x = run_x0; x < run_x1; x++)
172         {
173           pt.x = x + 0.5;
174           art_affine_point (&src_pt, &pt, inv);
175           src_x = floor (src_pt.x);
176           src_y = floor (src_pt.y);
177           src_p = src + (src_y * src_rowstride) + (src_x >> 3);
178           if (*src_p & (128 >> (src_x & 7)))
179             {
180               bg_r = dst_p[0];
181               bg_g = dst_p[1];
182               bg_b = dst_p[2];
183
184               fg_r = bg_r + (((r - bg_r) * alpha + 0x8000) >> 16);
185               fg_g = bg_g + (((g - bg_g) * alpha + 0x8000) >> 16);
186               fg_b = bg_b + (((b - bg_b) * alpha + 0x8000) >> 16);
187
188               dst_p[0] = fg_r;
189               dst_p[1] = fg_g;
190               dst_p[2] = fg_b;
191             }
192           dst_p += 3;
193         }
194       dst_linestart += dst_rowstride;
195     }
196 }