]> Dogcows Code - chaz/openbox/blob - render/image.c
update copyright step 1
[chaz/openbox] / render / image.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3 image.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 See the COPYING file for a copy of the GNU General Public License.
17 */
18
19 #include "geom.h"
20 #include "image.h"
21 #include "color.h"
22
23 #include <glib.h>
24
25 #define FRACTION 12
26 #define FLOOR(i) ((i) & (~0UL << FRACTION))
27 #define AVERAGE(a, b) (((((a) ^ (b)) & 0xfefefefeL) >> 1) + ((a) & (b)))
28
29 static void ImageCopyResampled(RrPixel32 *dst, RrPixel32 *src,
30 gulong dstW, gulong dstH,
31 gulong srcW, gulong srcH)
32 {
33 gulong dstX, dstY, srcX, srcY;
34 gulong srcX1, srcX2, srcY1, srcY2;
35 gulong ratioX, ratioY;
36
37 ratioX = (srcW << FRACTION) / dstW;
38 ratioY = (srcH << FRACTION) / dstH;
39
40 srcY2 = 0;
41 for (dstY = 0; dstY < dstH; dstY++) {
42 srcY1 = srcY2;
43 srcY2 += ratioY;
44
45 srcX2 = 0;
46 for (dstX = 0; dstX < dstW; dstX++) {
47 gulong red = 0, green = 0, blue = 0, alpha = 0;
48 gulong portionX, portionY, portionXY, sumXY = 0;
49 RrPixel32 pixel;
50
51 srcX1 = srcX2;
52 srcX2 += ratioX;
53
54 for (srcY = srcY1; srcY < srcY2; srcY += (1UL << FRACTION)) {
55 if (srcY == srcY1) {
56 srcY = FLOOR(srcY);
57 portionY = (1UL << FRACTION) - (srcY1 - srcY);
58 if (portionY > srcY2 - srcY1)
59 portionY = srcY2 - srcY1;
60 }
61 else if (srcY == FLOOR(srcY2))
62 portionY = srcY2 - srcY;
63 else
64 portionY = (1UL << FRACTION);
65
66 for (srcX = srcX1; srcX < srcX2; srcX += (1UL << FRACTION)) {
67 if (srcX == srcX1) {
68 srcX = FLOOR(srcX);
69 portionX = (1UL << FRACTION) - (srcX1 - srcX);
70 if (portionX > srcX2 - srcX1)
71 portionX = srcX2 - srcX1;
72 }
73 else if (srcX == FLOOR(srcX2))
74 portionX = srcX2 - srcX;
75 else
76 portionX = (1UL << FRACTION);
77
78 portionXY = (portionX * portionY) >> FRACTION;
79 sumXY += portionXY;
80
81 pixel = *(src + (srcY >> FRACTION) * srcW + (srcX >> FRACTION));
82 red += ((pixel >> RrDefaultRedOffset) & 0xFF) * portionXY;
83 green += ((pixel >> RrDefaultGreenOffset) & 0xFF) * portionXY;
84 blue += ((pixel >> RrDefaultBlueOffset) & 0xFF) * portionXY;
85 alpha += ((pixel >> RrDefaultAlphaOffset) & 0xFF) * portionXY;
86 }
87 }
88
89 g_assert(sumXY != 0);
90 red /= sumXY;
91 green /= sumXY;
92 blue /= sumXY;
93 alpha /= sumXY;
94
95 *dst++ = (red << RrDefaultRedOffset) |
96 (green << RrDefaultGreenOffset) |
97 (blue << RrDefaultBlueOffset) |
98 (alpha << RrDefaultAlphaOffset);
99 }
100 }
101 }
102
103 void RrImageDraw(RrPixel32 *target, RrTextureRGBA *rgba,
104 gint target_w, gint target_h,
105 RrRect *area)
106 {
107 RrPixel32 *dest;
108 RrPixel32 *source;
109 gint sw, sh, dw, dh;
110 gint col, num_pixels;
111
112 sw = rgba->width;
113 sh = rgba->height;
114
115 /* keep the ratio */
116 dw = area->width;
117 dh = (gint)(dw * ((gdouble)sh / sw));
118 if (dh > area->height) {
119 dh = area->height;
120 dw = (gint)(dh * ((gdouble)sw / sh));
121 }
122
123 if (!(dw && dh))
124 return; /* XXX sanity check */
125
126 if (sw != dw || sh != dh) {
127 /*if (!(rgba->cache && dw == rgba->cwidth && dh == rgba->cheight))*/ {
128 g_free(rgba->cache);
129 rgba->cache = g_new(RrPixel32, dw * dh);
130 ImageCopyResampled(rgba->cache, rgba->data, dw, dh, sw, sh);
131 rgba->cwidth = dw;
132 rgba->cheight = dh;
133 }
134 source = rgba->cache;
135 } else {
136 source = rgba->data;
137 }
138
139 /* copy source -> dest, and apply the alpha channel */
140 col = 0;
141 num_pixels = dw * dh;
142 dest = target + area->x + target_w * area->y;
143 while (num_pixels-- > 0) {
144 guchar alpha, r, g, b, bgr, bgg, bgb;
145
146 alpha = *source >> RrDefaultAlphaOffset;
147 r = *source >> RrDefaultRedOffset;
148 g = *source >> RrDefaultGreenOffset;
149 b = *source >> RrDefaultBlueOffset;
150
151 /* background color */
152 bgr = *dest >> RrDefaultRedOffset;
153 bgg = *dest >> RrDefaultGreenOffset;
154 bgb = *dest >> RrDefaultBlueOffset;
155
156 r = bgr + (((r - bgr) * alpha) >> 8);
157 g = bgg + (((g - bgg) * alpha) >> 8);
158 b = bgb + (((b - bgb) * alpha) >> 8);
159
160 *dest = ((r << RrDefaultRedOffset) |
161 (g << RrDefaultGreenOffset) |
162 (b << RrDefaultBlueOffset));
163
164 dest++;
165 source++;
166
167 if (++col >= dw) {
168 col = 0;
169 dest += target_w - dw;
170 }
171 }
172 }
This page took 0.039297 seconds and 4 git commands to generate.