Logo Search packages:      
Sourcecode: adonthell version File versions  Download package

image.cc

Go to the documentation of this file.
/*
   $Id: image.cc,v 1.16 2004/10/25 06:55:01 ksterker Exp $

   Copyright (C) 1999/2000/2001/2002/2004 Alexandre Courbot
   Part of the Adonthell Project http://adonthell.linuxgames.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/


/**
 * @file   image.cc
 * @author Alexandre Courbot <alexandrecourbot@linuxgames.com>
 * 
 * @brief  Defines the image class.
 * 
 * 
 */

#include <SDL/SDL_endian.h>
#include "image.h"
#include "pnm.h"

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
#define R_MASK 0x00ff0000
#define G_MASK 0x0000ff00
#define B_MASK 0x000000ff
#define A_MASK 0xff000000
#else
#define R_MASK 0x000000ff
#define G_MASK 0x0000ff00
#define B_MASK 0x00ff0000
#define A_MASK 0xff000000
#endif

using namespace std; 

00043 image::image () : surface ()
{
}

00047 image::image (u_int16 l, u_int16 h, bool mode) : surface (mode) 
{
    resize (l, h); 
}

00052 image::image (SDL_Surface *s, const SDL_Color & color) : surface (false)
{
    if (screen::dbl_mode ()) {
        set_length (s->w >> 1);
        set_height (s->h >> 1);
    } else {
        set_length (s->w);
        set_height (s->h);
    }
    
    vis = SDL_DisplayFormat (s);
    SDL_SetColorKey (vis, SDL_SRCCOLORKEY | SDL_RLEACCEL, 
        SDL_MapRGB (vis->format, color.r, color.g, color.b)); 
    SDL_FreeSurface (s);
    changed = false;
}

00069 image::~image () 
{
}

00073 void image::resize (u_int16 l, u_int16 h)
{
    surface::resize (l, h); 
}

00078 void image::clear ()
{
    surface::clear ();  
}

00083 s_int8 image::get (igzstream& file)
{
    s_int8 ret;

    u_int8 m;
    u_int8 a;
    
    m << file;
    a << file;
    
    ret = get_raw (file);
    if (!ret)
    {
        set_mask (m); 
        set_alpha (a);
    }
    return ret;
}
 
00102 s_int8 image::load (string fname)
{
    igzstream file (fname);
    s_int8 ret = 0; 

    if (!file.is_open ())
        return 1;
    ret = get (file);
    file.close (); 
    return ret;
}

00114 s_int8 image::get_raw (igzstream& file)
{
    void * rawdata; 

    u_int16 l, h; 

    clear (); 
    
    l << file;
    h << file; 

    rawdata = new char[l * h * 3];
    file.get_block (rawdata, l * h * 3); 
    
    raw2display (rawdata, l, h); 

    delete[] (char *) rawdata;
    
    if (!vis) return -1;

    changed = true; 
    return 0;
}


00139 s_int8 image::load_raw (string fname)
{
    igzstream file (fname);
    s_int8 ret = 0; 

    if (!file.is_open ())
        return 1;
    ret = get_raw (file);
    file.close (); 
    return ret;
}


00152 s_int8 image::get_pnm (SDL_RWops * file)
{
    void *rawdata;
    u_int16 l, h; 

    clear (); 

    rawdata = pnm::get (file, &l, &h);
    
    raw2display (rawdata, l, h); 

    free (rawdata);

    if (!vis) return -1;

    changed = true; 
    return 0;
}


00172 s_int8 image::load_pnm (string fname)
{
    SDL_RWops *file;
    s_int8 ret = 0; 

    file = SDL_RWFromFile (fname.c_str (), "rb"); 
    if (!file)
        return 1;
    ret = get_pnm (file);
    SDL_RWclose (file);
    return ret;
}

00185 s_int8 image::put (ogzstream& file) const
{
    bool m = is_masked (); 
    s_int8 a = alpha ();
    
    m >> file;
    a >> file;
    
    put_raw (file); 
    
    return 0; 
}

00198 s_int8 image::save (string fname) const
{
    ogzstream file (fname);
    s_int8 ret = 0; 

    if (!file.is_open ())
        return 1;
    ret = put (file);
    file.close (); 
    return ret;
}

00210 s_int8 image::put_raw (ogzstream& file) const
{
    length () >> file;
    height () >> file; 

    if (!length () || !height ()) return 0; 

    SDL_Surface *tmp2 = SDL_CreateRGBSurface (0, 1, 1, 24, 
                                              R_MASK, G_MASK,
                                              B_MASK, 0);

    image * imt;
    SDL_Surface * toconvert;
    
    if (dbl_mode)
    {
        imt = new image();
        imt->double_size(*this);
        toconvert = imt->vis;
    }
    else
    {
        toconvert = vis;
    }

    SDL_Surface * temp = SDL_ConvertSurface (toconvert, tmp2->format, 0);
    
    SDL_LockSurface (temp); 
    
    // The pitch is ALWAYS a multiple of 4, no matter the length of the image.
    // We must be carefull not to record the pitch overlap.
    for (u_int16 j = 0; j < height (); j++) 
    { 
        file.put_block ((u_int8 *) temp->pixels + (temp->pitch * j), length () * 3); 
    }

    SDL_UnlockSurface (temp); 

    SDL_FreeSurface (temp);
    SDL_FreeSurface (tmp2); 
    if (dbl_mode) delete imt;
    return 0;
}

00254 s_int8 image::save_raw (string fname) const
{
    ogzstream file (fname);
    s_int8 ret = 0; 

    if (!file.is_open ())
        return 1;
    ret = put_raw (file);
    file.close (); 
    return ret;
}

00266 s_int8 image::put_pnm (SDL_RWops * file) const
{
    SDL_Surface *tmp2 = SDL_CreateRGBSurface (0, 1, 1, 24, 
                                              R_MASK, G_MASK,
                                              B_MASK, 0);
    
    SDL_Surface * temp;

    if (dbl_mode)
    {
        image imt;
        imt.half_size(*this);
        temp = SDL_ConvertSurface (imt.vis, tmp2->format, 0);
    }
    else
    {
        temp = SDL_ConvertSurface (vis, tmp2->format, 0);
    }

    pnm::put (file, temp->pixels, length (), height ()); 

    SDL_FreeSurface (temp);
    SDL_FreeSurface (tmp2); 

    return 0; 
}

00293 s_int8 image::save_pnm (string fname) const
{
    SDL_RWops *file;
    s_int8 ret = 0; 

    file = SDL_RWFromFile (fname.c_str (), "wb"); 
    if (!file)
        return 1;
    ret = put_pnm (file);
    SDL_RWclose (file);
    return ret;
}
 
00306 void image::zoom (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
{ 
    // Calculate the step per pixel.
    // While the surface positions are u_int16s, we use u_int32s for step
    // and position during zoom, that we'll divide by 65535 ( >> 16). That
    // way,  we can perform our zoom without having to divide two times per
    // pixel we proceed (we can replace the divides with shift, much much
    // faster.
    u_int32 xstep = (u_int32) (((double) src.length () / (double) l) * 65535); 
    u_int32 ystep = (u_int32) (((double) src.height () / (double) h) * 65535); 
    u_int32 xcur;
    u_int32 ycur;

    u_int32 col;  
         
    lock ();
    src.lock (); 
    ycur = 0;
    u_int16 i, j;
    for (j = y; j < h + y; j++)
    {
        xcur = 0; 
        for (i = x; i < l + x; i++)
        {
            src.get_pix (xcur >> 16, ycur >> 16, col);
            put_pix (i, j, col); 
            xcur += xstep; 
        }
        ycur += ystep;  
    }
    src.unlock ();
    unlock (); 
}

00340 void image::tile (const surface& src, u_int16 l, u_int16 h, u_int16 x, u_int16 y)
{
    u_int16 posx;
    u_int16 posy;

    drawing_area da (x, y, l, h); 
    
    for (posy = 0; posy < h; posy += src.height ())
        for (posx = 0; posx < l; posx += src.length ())
            src.draw (x + posx, y + posy, &da, this); 
}

00352 void image::brightness (const surface& src, u_int8 cont, bool proceed_mask)
{
    u_int16 i, j;
    u_int8 ir, ig, ib;
    u_int32 temp = 0;
    
    if (screen::dbl_mode () && !dbl_mode) resize (src.length () << 1, src.height () << 1);
    else resize (src.length (), src.height ());
    
    lock ();
    src.lock (); 
    for (j = 0; j < height (); j++)
        for (i = 0; i < length (); i++)
        {
            src.get_pix (i, j, temp);
            if ((proceed_mask) || temp != screen::trans_col ())
            {
                src.get_pix (i, j, ir, ig, ib);
                ir = (ir * cont) >> 8;
                ig = (ig * cont) >> 8;
                ib = (ib * cont) >> 8;
                put_pix (i, j, ir, ig, ib);
            }
            else put_pix (i, j, temp);
        }
    src.unlock ();
    unlock ();

    set_mask (false);
    set_alpha (255); 
}  

00384 image& image::operator = (const image& src)
{
    (surface&) (*this) = (surface&) src;    
    return *this; 
}




// Private methods



00397 void image::raw2display (void * rawdata, u_int16 l, u_int16 h)
{
    set_length (l);
    set_height (h);
   
    SDL_Surface *tmp2 = SDL_CreateRGBSurfaceFrom (rawdata, length (),
                                                  height (), 24,
                                                  length () * 3,
                                                  R_MASK, G_MASK,
                                                  B_MASK, 0);
    vis = SDL_DisplayFormat (tmp2);
    if (dbl_mode)
    {
        image imt;
        imt.double_size(*this);
        *this = imt;
    }
    SDL_FreeSurface (tmp2);
}

Generated by  Doxygen 1.6.0   Back to index