1 /*
2 Copyright (C) 1999/2000/2001/2002/2004 Alexandre Courbot
3 Part of the Adonthell Project <http://adonthell.nongnu.org>
4
5 Adonthell is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 Adonthell is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Adonthell. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19
20 /**
21 * @file image.cc
22 * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
23 *
24 * @brief Defines the image class.
25 *
26 *
27 */
28
29 #include "image.h"
30 #include "pnm.h"
31 #include <iostream>
32
33 using namespace std;
34
image()35 image::image () : surface ()
36 {
37 }
38
image(u_int16 l,u_int16 h,const u_int8 & scale)39 image::image (u_int16 l, u_int16 h, const u_int8 & scale) : surface (scale)
40 {
41 resize (l, h);
42 }
43
image(SDL_Surface * s,const SDL_Color & color)44 image::image (SDL_Surface *s, const SDL_Color & color) : surface (screen::scale())
45 {
46 set_alpha(SDL_ALPHA_OPAQUE, true);
47 resize((s->w+screen::scale()-1)/screen::scale(), (s->h+screen::scale()-1)/screen::scale());
48
49 SDL_Surface *dest = to_sw_surface(NULL);
50 SDL_SetColorKey (s, 1, SDL_MapRGB (s->format, color.r, color.g, color.b));
51 SDL_BlitSurface (s, NULL, dest, NULL);
52
53 unlock();
54
55 SDL_FreeSurface (dest);
56 SDL_FreeSurface (s);
57 }
58
~image()59 image::~image ()
60 {
61 }
62
resize(u_int16 l,u_int16 h)63 void image::resize (u_int16 l, u_int16 h)
64 {
65 surface::resize (l, h);
66 }
67
clear()68 void image::clear ()
69 {
70 surface::clear ();
71 }
72
get(igzstream & file)73 s_int8 image::get (igzstream& file)
74 {
75 s_int8 ret;
76
77 u_int8 m;
78 u_int8 a;
79
80 m << file;
81 a << file;
82
83 ret = get_raw (file);
84 if (!ret)
85 {
86 set_mask (m);
87 set_alpha (a);
88 }
89 return ret;
90 }
91
load(string fname)92 s_int8 image::load (string fname)
93 {
94 igzstream file (fname);
95 s_int8 ret = 0;
96
97 if (!file.is_open ())
98 return 1;
99 ret = get (file);
100 file.close ();
101 return ret;
102 }
103
get_raw(igzstream & file)104 s_int8 image::get_raw (igzstream& file)
105 {
106 void * rawdata;
107
108 u_int16 l, h;
109
110 clear ();
111
112 l << file;
113 h << file;
114
115 rawdata = new char[l * h * 3];
116 file.get_block (rawdata, l * h * 3);
117
118 raw2display (rawdata, l, h);
119
120 delete[] (char *) rawdata;
121
122 if (!Surface) return -1;
123
124 return 0;
125 }
126
127
load_raw(string fname)128 s_int8 image::load_raw (string fname)
129 {
130 igzstream file (fname);
131 s_int8 ret = 0;
132
133 if (!file.is_open ())
134 {
135 std::cout << "cannot find file " << fname << std::endl;
136 return 1;
137 }
138 ret = get_raw (file);
139 file.close ();
140 return ret;
141 }
142
143
get_pnm(SDL_RWops * file)144 s_int8 image::get_pnm (SDL_RWops * file)
145 {
146 void *rawdata;
147 u_int16 l, h;
148
149 clear ();
150
151 rawdata = pnm::get (file, &l, &h);
152
153 raw2display (rawdata, l, h);
154
155 free (rawdata);
156
157 if (!Surface) return -1;
158
159 return 0;
160 }
161
162
load_pnm(string fname)163 s_int8 image::load_pnm (string fname)
164 {
165 SDL_RWops *file;
166 s_int8 ret = 0;
167
168 file = SDL_RWFromFile (fname.c_str (), "rb");
169 if (!file)
170 {
171 std::cout << "cannot find file " << fname << std::endl;
172 return 1;
173 }
174 ret = get_pnm (file);
175 SDL_RWclose (file);
176 return ret;
177 }
178
put(ogzstream & file) const179 s_int8 image::put (ogzstream& file) const
180 {
181 bool m = is_masked ();
182 s_int8 a = alpha ();
183
184 m >> file;
185 a >> file;
186
187 put_raw (file);
188
189 return 0;
190 }
191
save(string fname) const192 s_int8 image::save (string fname) const
193 {
194 ogzstream file (fname);
195 s_int8 ret = 0;
196
197 if (!file.is_open ())
198 return 1;
199 ret = put (file);
200 file.close ();
201 return ret;
202 }
203
put_raw(ogzstream & file) const204 s_int8 image::put_raw (ogzstream& file) const
205 {
206 length () >> file;
207 height () >> file;
208
209 if (!length () || !height ()) return 0;
210
211 void *rawdata = get_data(3, R_MASK, G_MASK, B_MASK, 0);
212 file.put_block ((u_int8 *) rawdata, length () * height() * 3);
213 free(rawdata);
214
215 return 0;
216 }
217
save_raw(string fname) const218 s_int8 image::save_raw (string fname) const
219 {
220 ogzstream file (fname);
221 s_int8 ret = 0;
222
223 if (!file.is_open ())
224 return 1;
225 ret = put_raw (file);
226 file.close ();
227 return ret;
228 }
229
put_pnm(SDL_RWops * file) const230 s_int8 image::put_pnm (SDL_RWops * file) const
231 {
232 void *rawdata = get_data(3, R_MASK, G_MASK, B_MASK, 0);
233 pnm::put (file, rawdata, length (), height ());
234 free(rawdata);
235
236 return 0;
237 }
238
save_pnm(string fname) const239 s_int8 image::save_pnm (string fname) const
240 {
241 SDL_RWops *file;
242 s_int8 ret = 0;
243
244 file = SDL_RWFromFile (fname.c_str (), "wb");
245 if (!file)
246 return 1;
247 ret = put_pnm (file);
248 SDL_RWclose (file);
249 return ret;
250 }
251
zoom(const surface & src,u_int16 l,u_int16 h,u_int16 x,u_int16 y)252 void image::zoom (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
253 {
254 // Calculate the step per pixel.
255 // While the surface positions are u_int16s, we use u_int32s for step
256 // and position during zoom, that we'll divide by 65535 ( >> 16). That
257 // way, we can perform our zoom without having to divide two times per
258 // pixel we proceed (we can replace the divides with shift, much much
259 // faster.
260 u_int32 xstep = (u_int32) (((double) src.length () / (double) l) * 65535);
261 u_int32 ystep = (u_int32) (((double) src.height () / (double) h) * 65535);
262 u_int32 xcur;
263 u_int32 ycur;
264
265 u_int32 col;
266
267 lock ();
268 src.lock ();
269 ycur = 0;
270 u_int16 i, j;
271 for (j = y; j < h + y; j++)
272 {
273 xcur = 0;
274 for (i = x; i < l + x; i++)
275 {
276 col = src.get_pix ((u_int16)(xcur >> 16), (u_int16)(ycur >> 16));
277 put_pix (i, j, col);
278 xcur += xstep;
279 }
280 ycur += ystep;
281 }
282 src.unlock ();
283 unlock ();
284 }
285
tile(const surface & src,u_int16 l,u_int16 h,u_int16 x,u_int16 y)286 void image::tile (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
287 {
288 u_int16 posx;
289 u_int16 posy;
290
291 drawing_area da (x, y, l, h);
292
293 for (posy = 0; posy < h; posy += src.height ())
294 for (posx = 0; posx < l; posx += src.length ())
295 src.draw (x + posx, y + posy, &da, this);
296 }
297
brightness(const surface & src,u_int8 cont,bool proceed_mask)298 void image::brightness (const surface& src, u_int8 cont, bool proceed_mask)
299 {
300 u_int16 i, j;
301 u_int8 ir, ig, ib, ia;
302 u_int32 temp = 0;
303
304 clear();
305 set_scale(src.scale());
306 resize (src.length (), src.height ());
307
308 u_int16 real_height = height() * scale();
309 u_int16 real_length = length() * scale();
310
311 lock ();
312 src.lock ();
313 for (j = 0; j < real_height; j++)
314 for (i = 0; i < real_length; i++)
315 {
316 temp = src.get_pix (i, j);
317 if ((proceed_mask) || temp != screen::trans_col ())
318 {
319 unmap_color (temp, ir, ig, ib, ia);
320 ir = (ir * cont) >> 8;
321 ig = (ig * cont) >> 8;
322 ib = (ib * cont) >> 8;
323 temp = map_color(ir, ig, ib, ia);
324 }
325 put_pix (i, j, temp);
326 }
327 src.unlock ();
328 unlock ();
329 }
330
operator =(const image & src)331 image& image::operator = (const image& src)
332 {
333 (surface&) (*this) = (surface&) src;
334 return *this;
335 }
336
337
338
339
340 // Private methods
341
342
343
raw2display(void * rawdata,u_int16 l,u_int16 h)344 void image::raw2display (void * rawdata, u_int16 l, u_int16 h)
345 {
346 set_data(rawdata, l, h, 3, R_MASK, G_MASK, B_MASK, 0);
347 }
348