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

g_conversion.c

/*
 *  Fenix - Videogame compiler/interpreter
 *  Current release       : FENIX - PROJECT 1.0 - R 0.84
 *  Last stable release   :
 *  Project documentation : http://fenix.divsite.net
 *
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 *  Copyright © 1999 José Luis Cebrián Pagüe
 *  Copyright © 2002 Fenix Team
 *
 */

/*
 * FILE        : g_conversion.c
 * DESCRIPTION : Functions to convert bitmap data between formats
 *
 * HISTORY:      0.83 - Alpha operations and tables
 *               0.82 - First version
 */

#include <stdlib.h>

#include "fxi.h"

/* Conversion tables - used by 16 bits conversions - 256K */
static Uint16 * convert565ToScreen ;
static Uint16 * convertScreenTo565 ;
static int      conversion_tables_ok = 0 ;

/* Alpha multiplication tables - multiply a color by its alpha.
 * There will be less than 256 levels
 */
static Uint16 * alpha16[256];
static Uint8  * alpha8[256];
static int      alpha16_tables_ok = 0 ;
static int      alpha8_tables_ok = 0 ;

/*
 *  FUNCTION : init_alpha16_tables
 *
 *  Init the 16 bit alpha tables (create as many tables as the parameter)
 *  Each alpha table has a 128K memory footprint. Having many alpha tables
 *  provides more transparency values.
 *
 *  PARAMS :
 *          count             Number of tables
 *
 *  RETURN VALUE :
 *      None
 *
 */

static void init_alpha16_tables (int count)
{
      int      i, color, inc, next = 0, factor;
      Uint16 * table16 = NULL;

      if (alpha16_tables_ok == count)
            return;
      if (count <= 0 || count > 128)
            return;

      inc = 256/count;

      /* Destroy existing tables */

      if (alpha16_tables_ok != 0)
      {
            for (table16 = NULL, i = 0 ; i < 256 ; i++)
            {
                  if (alpha16[i] != table16)
                  {
                        table16 = alpha16[i];
                        free(table16);
                  }
                  alpha16[i] = NULL;
            }
      }

      /* Make new ones */

      for (i = 0 ; i < 256 ; i++)
      {
            if (i == next)
            {
                  table16 = malloc(131072);
                  factor = next+inc/2;
                  next += inc;
                  if (factor > 255) factor = 256;

                  for (color = 0 ; color < 65536 ; color++)
                  {
                        int r = ((color & screen->format->Rmask) >> screen->format->Rshift << screen->format->Rloss) ;
                        int g = ((color & screen->format->Gmask) >> screen->format->Gshift << screen->format->Gloss) ;
                        int b = ((color & screen->format->Bmask) >> screen->format->Bshift << screen->format->Bloss) ;

                        table16[color] =
                              ((((r * factor) >> 8) >> screen->format->Rloss) << screen->format->Rshift) |
                              ((((g * factor) >> 8) >> screen->format->Gloss) << screen->format->Gshift) |
                              ((((b * factor) >> 8) >> screen->format->Bloss) << screen->format->Bshift) ;
                  }
            }
            alpha16[i] = table16;
      }

      alpha16_tables_ok = count;
}


/*
 *  FUNCTION : init_alpha8_tables
 *
 *  Init the 8 bit alpha tables (create as many tables as the parameter)
 *  Each alpha table has a 64K memory footprint. Having many alpha tables
 *  provides more transparency values. Those tables should be updated
 *  when the palette changes.
 *
 *  PARAMS :
 *          count             Number of tables
 *
 *  RETURN VALUE :
 *      None
 *
 */

extern Uint8 nearest_table[64][64][64] ;

static void init_alpha8_tables (int count)
{
      int     i, color, color2, inc, next = 0, factor;
      Uint8 * table8 = NULL;

      if (alpha8_tables_ok == count)
            return;
      if (count <= 0 || count > 128)
            return;

      inc = 256/count;

      gr_fill_nearest_table();

      /* Destroy existing tables */

      if (alpha8_tables_ok != 0)
      {
            for (table8 = NULL, i = 0 ; i < 256 ; i++)
            {
                  if (alpha8[i] != table8)
                  {
                        table8 = alpha8[i];
                        free(table8);
                  }
                  alpha8[i] = NULL;
            }
      }

      /* Make new ones */

      for (i = 0 ; i < 256 ; i++)
      {
            if (i == next)
            {
                  table8  = malloc(65536);
                  factor = next+inc/2;
                  next += inc;
                  if (factor > 255) factor = 256;

                  for (color = 0 ; color < 256 ; color++)
                  {
                        for (color2 = 0 ; color2 < 256 ; color2++)
                        {
                              int r = (palette[color].r * factor + palette[color2].r * (255-factor));
                              int g = (palette[color].g * factor + palette[color2].g * (255-factor));
                              int b = (palette[color].b * factor + palette[color2].b * (255-factor));
                              table8[(color << 8) + color2] = nearest_table[r >> 10][g >> 10][b >> 10];
                        }
                        table8[color] = color;
                  }
            }
            alpha8[i] = table8;
      }

      alpha8_tables_ok = count;
}


/*
 *  FUNCTION : init_conversion_tables
 *
 *  Static routine used to initialize the 16 bits conversion
 *  tables (this only needs to be done once)
 *
 *  PARAMS :
 *          None
 *
 *  RETURN VALUE :
 *      None
 *
 */

static void init_conversion_tables()
{
      Uint8 r, g, b ;
      int n ;

      /* Alloc space for the lookup tables */

      convert565ToScreen = (Uint16 *) malloc(sizeof(Uint16) * 65536);
      convertScreenTo565 = (Uint16 *) malloc(sizeof(Uint16) * 65536);
      if (convert565ToScreen == NULL && convertScreenTo565 == NULL)
      {
            gr_error ("init_conversion_tables: sin memoria");
            return;
      }

      if (!scr_initialized) gr_init(320,200);
      conversion_tables_ok = 1;

      /* Special case if screen already in 565 format */

      if (screen->format->Rmask == 0xF800 &&
            screen->format->Gmask == 0x07E0 &&
            screen->format->Bmask == 0x001F)
      {
            for (n = 0 ; n < 65536 ; n++)
            {
                  convert565ToScreen[n] = n;
                  convertScreenTo565[n] = n;
            }
            return;
      }

      /* Create a fast lookup array */

      for (n = 0 ; n < 65536 ; n++)
      {
            /* Calculate conversion from 565 to screen format */

            r = ((n >> 8) & 0xF8) >> screen->format->Rloss ;
            g = ((n >> 3) & 0xFC) >> screen->format->Gloss ;
            b = ((n << 3) & 0xF8) >> screen->format->Bloss ;

            convert565ToScreen[n] = (r << screen->format->Rshift) |
                                      (g << screen->format->Gshift) |
                                      (b << screen->format->Bshift) ;

            /* Calculate conversion from 565 to screen format */

            r = (((n & screen->format->Rmask) >> screen->format->Rshift)
                      << screen->format->Rloss);
            g = (((n & screen->format->Gmask) >> screen->format->Gshift)
                      << screen->format->Gloss);
            b = (((n & screen->format->Bmask) >> screen->format->Bshift)
                      << screen->format->Bloss);

            convertScreenTo565[n] = ((r & 0xF8) << 8) |
                                      ((g & 0xFC) << 3) |
                                      ((b & 0xF8) >> 3) ;
      }
}

/*
 *  FUNCTION : gr_convert16_565ToScreen
 *
 *  Convert a sequence of 16 bits pixels from 5:6:5 format to
 *  the format used by the screen (usually 5:5:5 or 5:6:5)
 *
 *  PARAMS :
 *          ptr                     Pointer to the first pixel
 *          len                     Number of pixels (not bytes!)
 *
 *  RETURN VALUE :
 *      None
 *
 */

void gr_convert16_565ToScreen (Uint16 * ptr, int len)
{
      if (!conversion_tables_ok) init_conversion_tables();

      while (len--) {
          *ptr = convert565ToScreen[*ptr] ;
          ptr++;
      }
}

/*
 *  FUNCTION : gr_convert16_ScreenTo565
 *
 *  Convert a sequence of 16 bits pixels in screen format
 *  (usually 5:5:5 or 5:6:5) to the 5:6:5 format used to
 *  store 16 bits pixel values to files in disk
 *
 *  PARAMS :
 *          ptr                     Pointer to the first pixel
 *          len                     Number of pixels (not bytes!)
 *
 *  RETURN VALUE :
 *      None
 *
 */

void gr_convert16_ScreenTo565 (Uint16 * ptr, int len)
{
      if (!conversion_tables_ok) init_conversion_tables();

      while (len--) {
          *ptr = convertScreenTo565[*ptr] ;
          ptr++;
      }
}

/*
 *  FUNCTION : gr_fade16
 *
 *  Fade a 16-bit graphic a given ammount. Fading values are given in percent
 *  (0% = black, 100% = original color, 200% = full color value)
 *
 *  PARAMS :
 *          graph             Pointer to the graphic object
 *          r                       Percent of Red component
 *          g                       Percent of Green component
 *          b                       Percent of Blue component
 *
 *  RETURN VALUE :
 *      None
 *
 */

void gr_fade16 (GRAPH * graph, int r, int g, int b)
{
      Uint16 Rtable[32];
      Uint16 Gtable[32];
      Uint16 Btable[32];
      Uint32 x, y;
      Uint32 Rmask;
      Uint32 Rshift;
      Uint32 Gmask;
      Uint32 Gshift;
      Uint32 Bmask;
      Uint32 Bshift;

      for (x = 0 ; x < 32 ; x++)
      {
            int c = 8*x+7;

            if (r <= 100)
                  Rtable[x] = (c * r / 100) >> screen->format->Rloss << screen->format->Rshift;
            else
                  Rtable[x] = (c + (255-c) * (r-100) / 100) >> screen->format->Rloss << screen->format->Rshift;

            if (g <= 100)
                  Gtable[x] = (c * g / 100) >> screen->format->Gloss << screen->format->Gshift;
            else
                  Gtable[x] = (c + (255-c) * (g-100) / 100) >> screen->format->Gloss << screen->format->Gshift;

            if (b <= 100)
                  Btable[x] = (c * b / 100) >> screen->format->Bloss << screen->format->Bshift;
            else
                  Btable[x] = (c + (255-c) * (b-100) / 100) >> screen->format->Bloss << screen->format->Bshift;
      }

      Rmask  = screen->format->Rmask;
      Gmask  = screen->format->Gmask;
      Bmask  = screen->format->Bmask;
      Rshift = screen->format->Rshift - screen->format->Rloss + 3;
      Gshift = screen->format->Gshift - screen->format->Gloss + 3;
      Bshift = screen->format->Bshift - screen->format->Bloss + 3;

      for (y = 0 ; y < graph->height ; y++)
      {
            Uint16 * ptr = (Uint16 *)graph->data + graph->pitch*y/2;

            for (x = 0 ; x < graph->width ; x++, ptr++)
            {
                  *ptr = (
                          Rtable[((*ptr & Rmask) >> Rshift)]
                        | Gtable[((*ptr & Gmask) >> Gshift)]
                        | Btable[((*ptr & Bmask) >> Bshift)] );
            }
      }
}

/*
 *  FUNCTION : gr_alpha16
 *
 *  Get an alpha multiplication table (a table that, given a 16 bit color,
 *  returns the color multiplied by the alpha value)
 *
 *  PARAMS :
 *          alpha             Alpha value for the requested table
 *
 *  RETURN VALUE :
 *      None
 *
 */

Uint16 * gr_alpha16 (int alpha)
{
      if (alpha16_tables_ok == 0)
            init_alpha16_tables(GLODWORD(ALPHA_STEPS));
      return alpha16[alpha];
}

/*
 *  FUNCTION : gr_alpha8
 *
 *  Get an alpha translation table (a table that, given two 8 bit color,
 *  returns the composite color given the alpha value)
 *
 *  PARAMS :
 *          alpha             Alpha value for the requested table
 *
 *  RETURN VALUE :
 *      None
 *
 */

Uint8 * gr_alpha8 (int alpha)
{
      if (alpha8_tables_ok == 0)
            init_alpha8_tables(GLODWORD(ALPHA_STEPS));
      return (Uint8 *) alpha8[alpha];
}

Generated by  Doxygen 1.6.0   Back to index