Adonthell  0.4
image.cc
Go to the documentation of this file.
1 /*
2  $Id: image.cc,v 1.16 2004/10/25 06:55:01 ksterker Exp $
3 
4  Copyright (C) 1999/2000/2001/2002/2004 Alexandre Courbot
5  Part of the Adonthell Project http://adonthell.linuxgames.com
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 
16 /**
17  * @file image.cc
18  * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
19  *
20  * @brief Defines the image class.
21  *
22  *
23  */
24 
25 #include <SDL/SDL_endian.h>
26 #include "image.h"
27 #include "pnm.h"
28 
29 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
30 #define R_MASK 0x00ff0000
31 #define G_MASK 0x0000ff00
32 #define B_MASK 0x000000ff
33 #define A_MASK 0xff000000
34 #else
35 #define R_MASK 0x000000ff
36 #define G_MASK 0x0000ff00
37 #define B_MASK 0x00ff0000
38 #define A_MASK 0xff000000
39 #endif
40 
41 using namespace std;
42 
44 {
45 }
46 
47 image::image (u_int16 l, u_int16 h, bool mode) : surface (mode)
48 {
49  resize (l, h);
50 }
51 
52 image::image (SDL_Surface *s, const SDL_Color & color) : surface (false)
53 {
54  if (screen::dbl_mode ()) {
55  set_length (s->w >> 1);
56  set_height (s->h >> 1);
57  } else {
58  set_length (s->w);
59  set_height (s->h);
60  }
61 
62  vis = SDL_DisplayFormat (s);
63  SDL_SetColorKey (vis, SDL_SRCCOLORKEY | SDL_RLEACCEL,
64  SDL_MapRGB (vis->format, color.r, color.g, color.b));
65  SDL_FreeSurface (s);
66  changed = false;
67 }
68 
70 {
71 }
72 
74 {
75  surface::resize (l, h);
76 }
77 
78 void image::clear ()
79 {
80  surface::clear ();
81 }
82 
84 {
85  s_int8 ret;
86 
87  u_int8 m;
88  u_int8 a;
89 
90  m << file;
91  a << file;
92 
93  ret = get_raw (file);
94  if (!ret)
95  {
96  set_mask (m);
97  set_alpha (a);
98  }
99  return ret;
100 }
101 
102 s_int8 image::load (string fname)
103 {
104  igzstream file (fname);
105  s_int8 ret = 0;
106 
107  if (!file.is_open ())
108  return 1;
109  ret = get (file);
110  file.close ();
111  return ret;
112 }
113 
115 {
116  void * rawdata;
117 
118  u_int16 l, h;
119 
120  clear ();
121 
122  l << file;
123  h << file;
124 
125  rawdata = new char[l * h * 3];
126  file.get_block (rawdata, l * h * 3);
127 
128  raw2display (rawdata, l, h);
129 
130  delete[] (char *) rawdata;
131 
132  if (!vis) return -1;
133 
134  changed = true;
135  return 0;
136 }
137 
138 
139 s_int8 image::load_raw (string fname)
140 {
141  igzstream file (fname);
142  s_int8 ret = 0;
143 
144  if (!file.is_open ())
145  return 1;
146  ret = get_raw (file);
147  file.close ();
148  return ret;
149 }
150 
151 
152 s_int8 image::get_pnm (SDL_RWops * file)
153 {
154  void *rawdata;
155  u_int16 l, h;
156 
157  clear ();
158 
159  rawdata = pnm::get (file, &l, &h);
160 
161  raw2display (rawdata, l, h);
162 
163  free (rawdata);
164 
165  if (!vis) return -1;
166 
167  changed = true;
168  return 0;
169 }
170 
171 
172 s_int8 image::load_pnm (string fname)
173 {
174  SDL_RWops *file;
175  s_int8 ret = 0;
176 
177  file = SDL_RWFromFile (fname.c_str (), "rb");
178  if (!file)
179  return 1;
180  ret = get_pnm (file);
181  SDL_RWclose (file);
182  return ret;
183 }
184 
186 {
187  bool m = is_masked ();
188  s_int8 a = alpha ();
189 
190  m >> file;
191  a >> file;
192 
193  put_raw (file);
194 
195  return 0;
196 }
197 
198 s_int8 image::save (string fname) const
199 {
200  ogzstream file (fname);
201  s_int8 ret = 0;
202 
203  if (!file.is_open ())
204  return 1;
205  ret = put (file);
206  file.close ();
207  return ret;
208 }
209 
211 {
212  length () >> file;
213  height () >> file;
214 
215  if (!length () || !height ()) return 0;
216 
217  SDL_Surface *tmp2 = SDL_CreateRGBSurface (0, 1, 1, 24,
218  R_MASK, G_MASK,
219  B_MASK, 0);
220 
221  image * imt;
222  SDL_Surface * toconvert;
223 
224  if (dbl_mode)
225  {
226  imt = new image();
227  imt->double_size(*this);
228  toconvert = imt->vis;
229  }
230  else
231  {
232  toconvert = vis;
233  }
234 
235  SDL_Surface * temp = SDL_ConvertSurface (toconvert, tmp2->format, 0);
236 
237  SDL_LockSurface (temp);
238 
239  // The pitch is ALWAYS a multiple of 4, no matter the length of the image.
240  // We must be carefull not to record the pitch overlap.
241  for (u_int16 j = 0; j < height (); j++)
242  {
243  file.put_block ((u_int8 *) temp->pixels + (temp->pitch * j), length () * 3);
244  }
245 
246  SDL_UnlockSurface (temp);
247 
248  SDL_FreeSurface (temp);
249  SDL_FreeSurface (tmp2);
250  if (dbl_mode) delete imt;
251  return 0;
252 }
253 
254 s_int8 image::save_raw (string fname) const
255 {
256  ogzstream file (fname);
257  s_int8 ret = 0;
258 
259  if (!file.is_open ())
260  return 1;
261  ret = put_raw (file);
262  file.close ();
263  return ret;
264 }
265 
266 s_int8 image::put_pnm (SDL_RWops * file) const
267 {
268  SDL_Surface *tmp2 = SDL_CreateRGBSurface (0, 1, 1, 24,
269  R_MASK, G_MASK,
270  B_MASK, 0);
271 
272  SDL_Surface * temp;
273 
274  if (dbl_mode)
275  {
276  image imt;
277  imt.half_size(*this);
278  temp = SDL_ConvertSurface (imt.vis, tmp2->format, 0);
279  }
280  else
281  {
282  temp = SDL_ConvertSurface (vis, tmp2->format, 0);
283  }
284 
285  pnm::put (file, temp->pixels, length (), height ());
286 
287  SDL_FreeSurface (temp);
288  SDL_FreeSurface (tmp2);
289 
290  return 0;
291 }
292 
293 s_int8 image::save_pnm (string fname) const
294 {
295  SDL_RWops *file;
296  s_int8 ret = 0;
297 
298  file = SDL_RWFromFile (fname.c_str (), "wb");
299  if (!file)
300  return 1;
301  ret = put_pnm (file);
302  SDL_RWclose (file);
303  return ret;
304 }
305 
306 void image::zoom (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
307 {
308  // Calculate the step per pixel.
309  // While the surface positions are u_int16s, we use u_int32s for step
310  // and position during zoom, that we'll divide by 65535 ( >> 16). That
311  // way, we can perform our zoom without having to divide two times per
312  // pixel we proceed (we can replace the divides with shift, much much
313  // faster.
314  u_int32 xstep = (u_int32) (((double) src.length () / (double) l) * 65535);
315  u_int32 ystep = (u_int32) (((double) src.height () / (double) h) * 65535);
316  u_int32 xcur;
317  u_int32 ycur;
318 
319  u_int32 col;
320 
321  lock ();
322  src.lock ();
323  ycur = 0;
324  u_int16 i, j;
325  for (j = y; j < h + y; j++)
326  {
327  xcur = 0;
328  for (i = x; i < l + x; i++)
329  {
330  src.get_pix (xcur >> 16, ycur >> 16, col);
331  put_pix (i, j, col);
332  xcur += xstep;
333  }
334  ycur += ystep;
335  }
336  src.unlock ();
337  unlock ();
338 }
339 
340 void image::tile (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
341 {
342  u_int16 posx;
343  u_int16 posy;
344 
345  drawing_area da (x, y, l, h);
346 
347  for (posy = 0; posy < h; posy += src.height ())
348  for (posx = 0; posx < l; posx += src.length ())
349  src.draw (x + posx, y + posy, &da, this);
350 }
351 
352 void image::brightness (const surface& src, u_int8 cont, bool proceed_mask)
353 {
354  u_int16 i, j;
355  u_int8 ir, ig, ib;
356  u_int32 temp = 0;
357 
358  if (screen::dbl_mode () && !dbl_mode) resize (src.length () << 1, src.height () << 1);
359  else resize (src.length (), src.height ());
360 
361  lock ();
362  src.lock ();
363  for (j = 0; j < height (); j++)
364  for (i = 0; i < length (); i++)
365  {
366  src.get_pix (i, j, temp);
367  if ((proceed_mask) || temp != screen::trans_col ())
368  {
369  src.get_pix (i, j, ir, ig, ib);
370  ir = (ir * cont) >> 8;
371  ig = (ig * cont) >> 8;
372  ib = (ib * cont) >> 8;
373  put_pix (i, j, ir, ig, ib);
374  }
375  else put_pix (i, j, temp);
376  }
377  src.unlock ();
378  unlock ();
379 
380  set_mask (false);
381  set_alpha (255);
382 }
383 
385 {
386  (surface&) (*this) = (surface&) src;
387  return *this;
388 }
389 
390 
391 
392 
393 // Private methods
394 
395 
396 
397 void image::raw2display (void * rawdata, u_int16 l, u_int16 h)
398 {
399  set_length (l);
400  set_height (h);
401 
402  SDL_Surface *tmp2 = SDL_CreateRGBSurfaceFrom (rawdata, length (),
403  height (), 24,
404  length () * 3,
405  R_MASK, G_MASK,
406  B_MASK, 0);
407  vis = SDL_DisplayFormat (tmp2);
408  if (dbl_mode)
409  {
410  image imt;
411  imt.double_size(*this);
412  *this = imt;
413  }
414  SDL_FreeSurface (tmp2);
415 }