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 }
s_int8 get_pnm(SDL_RWops *file)
Loads an image from an opened file, in PNM format, without alpha and mask values. ...
Definition: image.cc:152
Class to write data from a Gzip compressed file.
Definition: fileops.h:223
void close()
Close the file that was opened.
Definition: fileops.cc:59
void set_length(u_int16 l)
Sets the length of the drawable.
Definition: drawable.h:125
u_int16 length() const
Returns the length of the drawable.
Definition: drawable.h:76
bool is_masked() const
Returns whether a surface is masked or not.
Definition: surface.h:84
Class to read data from a Gzip compressed file.
Definition: fileops.h:131
void resize(u_int16 l, u_int16 h)
Resize this image.
Definition: image.cc:73
#define u_int16
16 bits long unsigned integer
Definition: types.h:32
~image()
Destructor.
Definition: image.cc:69
s_int8 load(string fname)
Loads an image from a file name, in game internal format, with alpha and mask values.
Definition: image.cc:102
void set_height(u_int16 h)
Sets the height of the drawable.
Definition: drawable.h:135
bool dbl_mode
double mode
Definition: surface.h:416
Class where drawables can actually be drawn to.
Definition: surface.h:51
Definition: str_hash.h:36
static void put(SDL_RWops *file, void *image, u_int16 length, u_int16 height)
Saves a PNM image into an opened file.
Definition: pnm.cc:78
Image manipulation class.
Definition: image.h:41
#define u_int32
32 bits long unsigned integer
Definition: types.h:35
#define u_int8
8 bits long unsigned integer
Definition: types.h:29
void resize(u_int16 l, u_int16 h)
Resize this surface.
Definition: surface.cc:422
image()
Default constructor.
Definition: image.cc:43
void tile(const surface &src)
Tiles a surface.
Definition: image.h:299
Declares the image class.
void clear()
Resets the image to it's initial state, that is totally empty.
Definition: image.cc:78
s_int8 save(string fname) const
Saves an image into an file, in game format, with alpha and mask values.
Definition: image.cc:198
s_int8 load_raw(string fname)
Loads an image from a file name, in game internal format, without alpha and mask values.
Definition: image.cc:139
void unlock() const
Unlock the surface after you've worked on it's pixels with the get_pix () and put_pix () methods...
Definition: surface.cc:294
u_int8 alpha() const
Returns the alpha value of the surface.
Definition: surface.h:102
void clear()
Resets the surface to it's initial state, that is totally empty.
Definition: surface.cc:447
void draw(s_int16 x, s_int16 y, const drawing_area *da_opt=NULL, surface *target=NULL) const
Draw the surface.
Definition: surface.h:138
s_int8 put_pnm(SDL_RWops *file) const
Saves an image into an opened file, in PNM format, without alpha and mask values. ...
Definition: image.cc:266
s_int8 save_pnm(string fname) const
Saves an image into an file, in PNM format, without alpha and mask values.
Definition: image.cc:293
bool is_open()
Returns whether the file is opened or not.
Definition: fileops.h:99
s_int8 put(ogzstream &file) const
Saves an image into an opened file, in game format, with alpha and mask values.
Definition: image.cc:185
Implements "drawing zones" for drawing operations.
Definition: drawing_area.h:50
image & operator=(const image &src)
Image copy (similar to copy ()).
Definition: image.cc:384
void set_alpha(u_int8 a)
Sets the alpha value of the surface.
Definition: surface.cc:208
u_int16 height() const
Returns the height of the drawable.
Definition: drawable.h:87
SDL_Surface * vis
The actual surface.
Definition: surface.h:382
void zoom(const surface &src)
Zooms a surface.
Definition: image.h:261
s_int8 get(igzstream &file)
Loads an image from an opened file, saved in game internal format, with alpha and mask values...
Definition: image.cc:83
s_int8 put_raw(ogzstream &file) const
Saves an image into an opened file, in game format, without alpha and mask values.
Definition: image.cc:210
Declares the pnm static class.
void brightness(const surface &src, u_int8 cont, bool proceed_mask=false)
Applies a "brightness" to a surface.
Definition: image.cc:352
s_int8 load_pnm(string fname)
Loads an image from a file name, in PNM format, without alpha and mask values.
Definition: image.cc:172
void get_pix(u_int16 x, u_int16 y, u_int32 &col) const
Gets a pixel from the surface.
Definition: surface.cc:360
bool changed
Must be set to true when you change the surface by something else than class surface operations...
Definition: surface.h:405
s_int8 save_raw(string fname) const
Saves an image into an file, in game format, without alpha and mask values.
Definition: image.cc:254
s_int8 get_raw(igzstream &file)
Loads an image from an opened file, saved in game internal format, without alpha and mask values...
Definition: image.cc:114
static void * get(SDL_RWops *file, u_int16 *length, u_int16 *height)
Reads a PNM image from an opened file.
Definition: pnm.cc:33
static u_int32 trans_col()
Returns the translucent color in screen's depth format.
Definition: screen.h:89
#define s_int8
8 bits long signed integer
Definition: types.h:38
void set_mask(bool m)
Sets the mask parameter of the surface.
Definition: surface.cc:198
void get_block(void *to, u_int32 size)
Reads a block of bytes from the file.
Definition: fileops.cc:106
void lock() const
Locks the surface.
Definition: surface.cc:287
void put_block(void *to, u_int32 size)
Writes a block of bytes to the file.
Definition: fileops.cc:267
void put_pix(u_int16 x, u_int16 y, u_int32 col)
Puts a pixel of a given color.
Definition: surface.cc:301