• Main Page
  • Related Pages
  • Classes
  • Files
  • File List
  • File Members

image.cc

Go to the documentation of this file.
00001 /*
00002    $Id: image.cc,v 1.16 2004/10/25 06:55:01 ksterker Exp $
00003 
00004    Copyright (C) 1999/2000/2001/2002/2004 Alexandre Courbot
00005    Part of the Adonthell Project http://adonthell.linuxgames.com
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 
00016 /**
00017  * @file   image.cc
00018  * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
00019  * 
00020  * @brief  Defines the image class.
00021  * 
00022  * 
00023  */
00024 
00025 #include <SDL/SDL_endian.h>
00026 #include "image.h"
00027 #include "pnm.h"
00028 
00029 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00030 #define R_MASK 0x00ff0000
00031 #define G_MASK 0x0000ff00
00032 #define B_MASK 0x000000ff
00033 #define A_MASK 0xff000000
00034 #else
00035 #define R_MASK 0x000000ff
00036 #define G_MASK 0x0000ff00
00037 #define B_MASK 0x00ff0000
00038 #define A_MASK 0xff000000
00039 #endif
00040 
00041 using namespace std; 
00042 
00043 image::image () : surface ()
00044 {
00045 }
00046 
00047 image::image (u_int16 l, u_int16 h, bool mode) : surface (mode) 
00048 {
00049     resize (l, h); 
00050 }
00051 
00052 image::image (SDL_Surface *s, const SDL_Color & color) : surface (false)
00053 {
00054     if (screen::dbl_mode ()) {
00055         set_length (s->w >> 1);
00056         set_height (s->h >> 1);
00057     } else {
00058         set_length (s->w);
00059         set_height (s->h);
00060     }
00061     
00062     vis = SDL_DisplayFormat (s);
00063     SDL_SetColorKey (vis, SDL_SRCCOLORKEY | SDL_RLEACCEL, 
00064         SDL_MapRGB (vis->format, color.r, color.g, color.b)); 
00065     SDL_FreeSurface (s);
00066     changed = false;
00067 }
00068 
00069 image::~image () 
00070 {
00071 }
00072 
00073 void image::resize (u_int16 l, u_int16 h)
00074 {
00075     surface::resize (l, h); 
00076 }
00077 
00078 void image::clear ()
00079 {
00080     surface::clear ();  
00081 }
00082 
00083 s_int8 image::get (igzstream& file)
00084 {
00085     s_int8 ret;
00086 
00087     u_int8 m;
00088     u_int8 a;
00089     
00090     m << file;
00091     a << file;
00092     
00093     ret = get_raw (file);
00094     if (!ret)
00095     {
00096         set_mask (m); 
00097         set_alpha (a);
00098     }
00099     return ret;
00100 }
00101  
00102 s_int8 image::load (string fname)
00103 {
00104     igzstream file (fname);
00105     s_int8 ret = 0; 
00106 
00107     if (!file.is_open ())
00108         return 1;
00109     ret = get (file);
00110     file.close (); 
00111     return ret;
00112 }
00113 
00114 s_int8 image::get_raw (igzstream& file)
00115 {
00116     void * rawdata; 
00117 
00118     u_int16 l, h; 
00119 
00120     clear (); 
00121     
00122     l << file;
00123     h << file; 
00124 
00125     rawdata = new char[l * h * 3];
00126     file.get_block (rawdata, l * h * 3); 
00127     
00128     raw2display (rawdata, l, h); 
00129 
00130     delete[] (char *) rawdata;
00131     
00132     if (!vis) return -1;
00133 
00134     changed = true; 
00135     return 0;
00136 }
00137 
00138 
00139 s_int8 image::load_raw (string fname)
00140 {
00141     igzstream file (fname);
00142     s_int8 ret = 0; 
00143 
00144     if (!file.is_open ())
00145         return 1;
00146     ret = get_raw (file);
00147     file.close (); 
00148     return ret;
00149 }
00150 
00151 
00152 s_int8 image::get_pnm (SDL_RWops * file)
00153 {
00154     void *rawdata;
00155     u_int16 l, h; 
00156 
00157     clear (); 
00158 
00159     rawdata = pnm::get (file, &l, &h);
00160     
00161     raw2display (rawdata, l, h); 
00162 
00163     free (rawdata);
00164 
00165     if (!vis) return -1;
00166 
00167     changed = true; 
00168     return 0;
00169 }
00170 
00171 
00172 s_int8 image::load_pnm (string fname)
00173 {
00174     SDL_RWops *file;
00175     s_int8 ret = 0; 
00176 
00177     file = SDL_RWFromFile (fname.c_str (), "rb"); 
00178     if (!file)
00179         return 1;
00180     ret = get_pnm (file);
00181     SDL_RWclose (file);
00182     return ret;
00183 }
00184 
00185 s_int8 image::put (ogzstream& file) const
00186 {
00187     bool m = is_masked (); 
00188     s_int8 a = alpha ();
00189     
00190     m >> file;
00191     a >> file;
00192     
00193     put_raw (file); 
00194     
00195     return 0; 
00196 }
00197 
00198 s_int8 image::save (string fname) const
00199 {
00200     ogzstream file (fname);
00201     s_int8 ret = 0; 
00202 
00203     if (!file.is_open ())
00204         return 1;
00205     ret = put (file);
00206     file.close (); 
00207     return ret;
00208 }
00209 
00210 s_int8 image::put_raw (ogzstream& file) const
00211 {
00212     length () >> file;
00213     height () >> file; 
00214 
00215     if (!length () || !height ()) return 0; 
00216 
00217     SDL_Surface *tmp2 = SDL_CreateRGBSurface (0, 1, 1, 24, 
00218                                               R_MASK, G_MASK,
00219                                               B_MASK, 0);
00220 
00221     image * imt;
00222     SDL_Surface * toconvert;
00223     
00224     if (dbl_mode)
00225     {
00226         imt = new image();
00227         imt->double_size(*this);
00228         toconvert = imt->vis;
00229     }
00230     else
00231     {
00232         toconvert = vis;
00233     }
00234 
00235     SDL_Surface * temp = SDL_ConvertSurface (toconvert, tmp2->format, 0);
00236     
00237     SDL_LockSurface (temp); 
00238     
00239     // The pitch is ALWAYS a multiple of 4, no matter the length of the image.
00240     // We must be carefull not to record the pitch overlap.
00241     for (u_int16 j = 0; j < height (); j++) 
00242     { 
00243         file.put_block ((u_int8 *) temp->pixels + (temp->pitch * j), length () * 3); 
00244     }
00245 
00246     SDL_UnlockSurface (temp); 
00247 
00248     SDL_FreeSurface (temp);
00249     SDL_FreeSurface (tmp2); 
00250     if (dbl_mode) delete imt;
00251     return 0;
00252 }
00253 
00254 s_int8 image::save_raw (string fname) const
00255 {
00256     ogzstream file (fname);
00257     s_int8 ret = 0; 
00258 
00259     if (!file.is_open ())
00260         return 1;
00261     ret = put_raw (file);
00262     file.close (); 
00263     return ret;
00264 }
00265 
00266 s_int8 image::put_pnm (SDL_RWops * file) const
00267 {
00268     SDL_Surface *tmp2 = SDL_CreateRGBSurface (0, 1, 1, 24, 
00269                                               R_MASK, G_MASK,
00270                                               B_MASK, 0);
00271     
00272     SDL_Surface * temp;
00273 
00274     if (dbl_mode)
00275     {
00276         image imt;
00277         imt.half_size(*this);
00278         temp = SDL_ConvertSurface (imt.vis, tmp2->format, 0);
00279     }
00280     else
00281     {
00282         temp = SDL_ConvertSurface (vis, tmp2->format, 0);
00283     }
00284 
00285     pnm::put (file, temp->pixels, length (), height ()); 
00286 
00287     SDL_FreeSurface (temp);
00288     SDL_FreeSurface (tmp2); 
00289 
00290     return 0; 
00291 }
00292 
00293 s_int8 image::save_pnm (string fname) const
00294 {
00295     SDL_RWops *file;
00296     s_int8 ret = 0; 
00297 
00298     file = SDL_RWFromFile (fname.c_str (), "wb"); 
00299     if (!file)
00300         return 1;
00301     ret = put_pnm (file);
00302     SDL_RWclose (file);
00303     return ret;
00304 }
00305  
00306 void image::zoom (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
00307 { 
00308     // Calculate the step per pixel.
00309     // While the surface positions are u_int16s, we use u_int32s for step
00310     // and position during zoom, that we'll divide by 65535 ( >> 16). That
00311     // way,  we can perform our zoom without having to divide two times per
00312     // pixel we proceed (we can replace the divides with shift, much much
00313     // faster.
00314     u_int32 xstep = (u_int32) (((double) src.length () / (double) l) * 65535); 
00315     u_int32 ystep = (u_int32) (((double) src.height () / (double) h) * 65535); 
00316     u_int32 xcur;
00317     u_int32 ycur;
00318 
00319     u_int32 col;  
00320          
00321     lock ();
00322     src.lock (); 
00323     ycur = 0;
00324     u_int16 i, j;
00325     for (j = y; j < h + y; j++)
00326     {
00327         xcur = 0; 
00328         for (i = x; i < l + x; i++)
00329         {
00330             src.get_pix (xcur >> 16, ycur >> 16, col);
00331             put_pix (i, j, col); 
00332             xcur += xstep; 
00333         }
00334         ycur += ystep;  
00335     }
00336     src.unlock ();
00337     unlock (); 
00338 }
00339 
00340 void image::tile (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
00341 {
00342     u_int16 posx;
00343     u_int16 posy;
00344 
00345     drawing_area da (x, y, l, h); 
00346     
00347     for (posy = 0; posy < h; posy += src.height ())
00348         for (posx = 0; posx < l; posx += src.length ())
00349             src.draw (x + posx, y + posy, &da, this); 
00350 }
00351 
00352 void image::brightness (const surface& src, u_int8 cont, bool proceed_mask)
00353 {
00354     u_int16 i, j;
00355     u_int8 ir, ig, ib;
00356     u_int32 temp = 0;
00357     
00358     if (screen::dbl_mode () && !dbl_mode) resize (src.length () << 1, src.height () << 1);
00359     else resize (src.length (), src.height ());
00360     
00361     lock ();
00362     src.lock (); 
00363     for (j = 0; j < height (); j++)
00364         for (i = 0; i < length (); i++)
00365         {
00366             src.get_pix (i, j, temp);
00367             if ((proceed_mask) || temp != screen::trans_col ())
00368             {
00369                 src.get_pix (i, j, ir, ig, ib);
00370                 ir = (ir * cont) >> 8;
00371                 ig = (ig * cont) >> 8;
00372                 ib = (ib * cont) >> 8;
00373                 put_pix (i, j, ir, ig, ib);
00374             }
00375             else put_pix (i, j, temp);
00376         }
00377     src.unlock ();
00378     unlock ();
00379 
00380     set_mask (false);
00381     set_alpha (255); 
00382 }  
00383 
00384 image& image::operator = (const image& src)
00385 {
00386     (surface&) (*this) = (surface&) src;    
00387     return *this; 
00388 }
00389 
00390 
00391 
00392 
00393 // Private methods
00394 
00395 
00396 
00397 void image::raw2display (void * rawdata, u_int16 l, u_int16 h)
00398 {
00399     set_length (l);
00400     set_height (h);
00401    
00402     SDL_Surface *tmp2 = SDL_CreateRGBSurfaceFrom (rawdata, length (),
00403                                                   height (), 24,
00404                                                   length () * 3,
00405                                                   R_MASK, G_MASK,
00406                                                   B_MASK, 0);
00407     vis = SDL_DisplayFormat (tmp2);
00408     if (dbl_mode)
00409     {
00410         image imt;
00411         imt.double_size(*this);
00412         *this = imt;
00413     }
00414     SDL_FreeSurface (tmp2);
00415 }

Generated on Mon Sep 12 2011 for Adonthell by  doxygen 1.7.1