/[alephone]/aorta/image_ext.cpp
ViewVC logotype

Contents of /aorta/image_ext.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Fri Mar 7 03:52:53 2008 UTC (5 years, 3 months ago) by ghs
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +6 -10 lines
do color reconstruction in place

1 /*
2
3 image_ext.cpp: extra functionality for wxImage
4 Copyright (C) 2006 Gregory Smith
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (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 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19
20 */
21
22 #include "image_ext.h"
23 #include <vector>
24
25 void wxImageExt::White()
26 {
27 int NumBytes = GetWidth() * GetHeight() * 3;
28 for (int i = 0; i < NumBytes; i++)
29 {
30 GetData()[i] = 0xff;
31 }
32 }
33
34 void wxImageExt::RemoveAlpha()
35 {
36 wxImageExt image;
37 image.Create(GetWidth(), GetHeight());
38 memcpy(image.GetData(), GetData(), GetWidth() * GetHeight() * 3);
39
40 *this = image;
41 }
42
43 void wxImageExt::MaskToAlpha()
44 {
45 wxImageExt image;
46 image.Create(GetWidth(), GetHeight());
47 image.InitAlpha();
48 image.SetMask(false);
49
50 memcpy(image.GetData(), GetData(), GetWidth() * GetHeight() * 3);
51
52 for (int x = 0; x < GetWidth(); x++)
53 {
54 for (int y = 0; y < GetHeight(); y++)
55 {
56 if (IsTransparent(x, y))
57 {
58 image.GetAlpha()[x + y * GetWidth()] = 0x00;
59 }
60 else
61 {
62 image.GetAlpha()[x + y * GetWidth()] = 0xff;
63 }
64 }
65 }
66
67 *this = image;
68 }
69
70 void wxImageExt::PropRescale(int width, int height)
71 {
72 float scale = (float) std::max(width, height) / std::max(GetWidth(), GetHeight());
73 Rescale((int) (GetWidth() * scale), (int) (GetHeight() * scale));
74 Resize(wxSize(width, height), wxPoint((width - GetWidth()) / 2, (height - GetHeight()) / 2));
75 }
76
77 void wxImageExt::FromAlpha(const wxImageExt& source)
78 {
79 Create(source.GetWidth(), source.GetHeight());
80 int NumPixels = GetWidth() * GetHeight();
81 for (int i = 0; i < NumPixels; i++)
82 {
83 GetData()[i * 3 + 0] = GetData()[i * 3 + 1] = GetData()[i * 3 + 2] = source.GetAlpha()[i];
84 }
85 }
86
87 void wxImageExt::ToAlpha(wxImageExt& dest) const
88 {
89 if (!dest.HasAlpha())
90 {
91 dest.InitAlpha();
92 }
93
94 int NumPixels = GetWidth() * GetHeight();
95 for (int i = 0; i < NumPixels; i++)
96 {
97 unsigned int Average = (GetData()[i * 3 + 0] + GetData()[i * 3 + 1] + GetData()[i * 3 + 2]) / 3;
98 dest.GetAlpha()[i] = Average & 0xff;
99 }
100 }
101
102 void wxImageExt::MakeOpacTypeTwo()
103 {
104 wxImageExt image;
105 image.Create(GetWidth(), GetHeight());
106 int NumPixels = GetWidth() * GetHeight();
107 for (int i = 0; i < NumPixels; i++)
108 {
109 unsigned int Average = (GetData()[i * 3 + 0] + GetData()[i * 3 + 1] + GetData()[i * 3 + 2]) / 3;
110 image.GetData()[i * 3 + 0] = image.GetData()[i * 3 + 1] = image.GetData()[i * 3 + 2] = Average & 0xff;
111 }
112
113 *this = image;
114 }
115
116 void wxImageExt::MakeOpacTypeThree()
117 {
118 wxImageExt image;
119 image.Create(GetWidth(), GetHeight());
120 int NumPixels = GetWidth() * GetHeight();
121 for (int i = 0; i < NumPixels; i++)
122 {
123 unsigned char Max = std::max(GetData()[i * 3 + 0], std::max(GetData()[i * 3 + 1], GetData()[i * 3 + 2]));
124 image.GetData()[i * 3 + 0] = image.GetData()[i * 3 + 1] = image.GetData()[i * 3 + 2] = Max;
125 }
126
127 *this = image;
128 }
129
130 // thanks to the Virtual Terrain Project for this algorithm, and the code looks
131 // pretty similar too...
132
133 void wxImageExt::ReconstructColors(const wxColour& bgColor)
134 {
135 // restore the color of edge texels by guessing correct non-background color
136
137 for (int x = 0; x < GetWidth(); x++) {
138 for (int y = 0; y < GetHeight(); y++) {
139 if (GetAlpha(x, y) == 0) {
140 SetAlpha(x, y, 0);
141 SetRGB(x, y, bgColor.Red(), bgColor.Green(), bgColor.Blue());
142 } else if (GetAlpha(x, y) == 0xff) {
143 SetAlpha(x, y, 0xff);
144 SetRGB(x, y, GetRed(x, y), GetGreen(x, y), GetBlue(x, y));
145 } else {
146 float blend_factor = GetAlpha(x, y) / 255.0f;
147 SetAlpha(x, y, GetAlpha(x, y));
148 short rDiff = GetRed(x, y) - bgColor.Red();
149 short gDiff = GetGreen(x, y) - bgColor.Green();
150 short bDiff = GetBlue(x, y) - bgColor.Blue();
151
152 SetRGB(x, y, PIN(bgColor.Red() + (int) (rDiff * (1.0f / blend_factor)), 0, 255), PIN(bgColor.Green() + (int) (gDiff * (1.0f / blend_factor)), 0, 255), PIN(bgColor.Blue() + (int) (bDiff * (1.0f / blend_factor)), 0, 255));
153 }
154 }
155 }
156
157 }
158
159 void wxImageExt::UnpremultiplyAlpha()
160 {
161 for (int x = 0; x < GetWidth(); x++) {
162 for (int y = 0; y < GetHeight(); y++) {
163 if (GetAlpha(x, y) == 0) continue;
164 short red = GetRed(x, y);
165 short green = GetGreen(x, y);
166 short blue = GetBlue(x, y);
167
168 red = std::min(255, 255 * red / GetAlpha(x, y));
169 green = std::min(255, 255 * green / GetAlpha(x, y));
170 blue = std::min(255, 255 * blue / GetAlpha(x, y));
171
172 SetRGB(x, y, (unsigned char) red, (unsigned char) green, (unsigned char) blue);
173 }
174 }
175 }
176
177 static bool Downsample(wxImage &src, wxImage &dst)
178 {
179 if (src.GetWidth() == 2 || src.GetHeight() == 2) return false;
180 int holes = 0;
181 for (int y = 0; y < src.GetHeight(); y++) {
182 for (int x = 0; x < src.GetWidth(); x++) {
183 if (src.GetAlpha(x, y) == 0) {
184 holes++;
185 }
186 }
187 }
188
189 if (holes == 0) return false;
190
191 dst.Create(src.GetWidth() / 2, src.GetHeight() / 2, true);
192 dst.InitAlpha();
193
194 for (int y = 0; y < dst.GetHeight(); y++) {
195 for (int x = 0; x < dst.GetWidth(); x++) {
196
197 const int x0 = 2 * x + 0;
198 const int x1 = 2 * x + 1;
199 const int y0 = 2 * y + 0;
200 const int y1 = 2 * y + 1;
201
202 if (src.GetAlpha(x0, y0) || src.GetAlpha(x1, y0) || src.GetAlpha(x0, y1) || src.GetAlpha(x1, y1))
203 {
204 unsigned int rSum = 0;
205 unsigned int gSum = 0;
206 unsigned int bSum = 0;
207 unsigned int aSum = 0;
208 int total = 0;
209 if (src.GetAlpha(x0, y0)) {
210 rSum += src.GetRed(x0, y0);
211 gSum += src.GetGreen(x0, y0);
212 bSum += src.GetBlue(x0, y0);
213 total++;
214 }
215 if (src.GetAlpha(x1, y0)) {
216 rSum += src.GetRed(x1, y0);
217 gSum += src.GetGreen(x1, y0);
218 bSum += src.GetBlue(x1, y0);
219 total++;
220 }
221 if (src.GetAlpha(x0, y1)) {
222 rSum += src.GetRed(x0, y1);
223 gSum += src.GetGreen(x0, y1);
224 bSum += src.GetBlue(x0, y1);
225 total++;
226 }
227 if (src.GetAlpha(x1, y1)) {
228 rSum += src.GetRed(x1, y1);
229 gSum += src.GetGreen(x1, y1);
230 bSum += src.GetBlue(x1, y1);
231 total++;
232 }
233
234 dst.SetRGB(x, y, (unsigned char) (rSum / total), (unsigned char) (gSum / total), (unsigned char) (bSum / total));
235 dst.SetAlpha(x, y, 255);
236 } else {
237 dst.SetRGB(x, y, 0, 0, 0);
238 dst.SetAlpha(x, y, 0);
239 }
240 }
241 }
242
243 return true;
244
245 }
246
247 // This is the filter used in the Lumigraph paper. The Unreal engine uses something similar.
248 void wxImageExt::PrepareForMipmaps()
249 {
250 std::vector<wxImage> mipmaps;
251
252 mipmaps.push_back(*this);
253
254 wxImageExt temp;
255 while (Downsample(mipmaps.back(), temp))
256 {
257 mipmaps.push_back(temp);
258 }
259
260 for (int y = 0; y < GetHeight(); y++) {
261 for (int x = 0; x < GetWidth(); x++) {
262
263 int sx = x;
264 int sy = y;
265
266 for (int l = 0; l < mipmaps.size(); l++) {
267 if (mipmaps[l].GetAlpha(sx, sy))
268 {
269 SetRGB(x, y, mipmaps[l].GetRed(sx, sy), mipmaps[l].GetGreen(sx, sy), mipmaps[l].GetBlue(sx, sy));
270 break;
271 }
272
273 sx /= 2;
274 sy /= 2;
275 }
276 }
277 }
278 }

Christian Bauer">Christian Bauer
ViewVC Help
Powered by ViewVC 1.1.15