Bennu Game Development

Foros en Español => Sugerencias => Topic started by: DCelso on November 09, 2010, 03:48:39 PM

Title: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 09, 2010, 03:48:39 PM
Hola Splinter, dejo aquí mi sugerencia para mod_map para soporte de este tipo de imágenes que hemos visto que puede hacer mtpaint y que los visores de PNGs leen correctamente.
Bueno y ya para premio, podemos hacer que guarde bennu este formato cuando esté la pantalla en modo 16 bits ya que es el más próximo y fiel a la información guardada en memoria para este modo (y así ahorramos un poco de espacio, porque hasta ahora guardaba pngs de 32 bits con canales alfa a 0 o ff :D).

Resalto en negrita los cambios.
Archivo file_png.c

/*
*  Copyright � 2006-2010 SplinterGU (Fenix/Bennugd)
*  Copyright � 2002-2006 Fenix Team (Fenix)
*  Copyright � 1999-2002 Jos� Luis Cebri�n Pag�e (Fenix)
*
*  This file is part of Bennu - Game Development
*
*  Bennu 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.
*
*  Bennu 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
*
*/

/* --------------------------------------------------------------------------- */

#include <png.h>

#include "mod_map.h"

/* --------------------------------------------------------------------------- */

/*
*  GLOBAL VARIABLES
*/

/* --------------------------------------------------------------------------- */

static uint8_t colors[256 * 3] ;

static file * png ;

/* --------------------------------------------------------------------------- */

static void user_read_data( png_structp png_ptr, png_bytep data, png_size_t length )
{
    file_read( png, data, length ) ;
}

GRAPH * gr_read_png( const char * filename )
{
GRAPH * bitmap ;
    unsigned int n, x ;
    uint16_t * ptr ;
    uint32_t * ptr32 ;
    uint32_t * orig ;
    uint32_t * row ;
    uint32_t Rshift, Gshift, Bshift ;
    uint32_t Rmask, Gmask, Bmask ;

    png_bytep * rowpointers ;

    png_structp png_ptr ;
    png_infop info_ptr, end_info ;
    png_uint_32 width, height, rowbytes;
    int depth, color ;

    /* Abre el fichero y se asegura de que screen est� inicializada */

    png = file_open( filename, "rb" ) ;
    if ( !png ) return NULL;

    /* Prepara las estructuras internas */

    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ) ;
    if ( !png_ptr )
    {
        file_close( png );
        return NULL;
    }

    info_ptr = png_create_info_struct( png_ptr ) ;
    end_info = png_create_info_struct( png_ptr ) ;
    if ( !info_ptr || !end_info )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        file_close( png ) ;
        return NULL;
    }

    /* Rutina de error */

    if ( setjmp( png_ptr->jmpbuf ) )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        file_close( png ) ;
        return NULL;
    }

    /* Recupera informaci�n sobre el PNG */

    png_set_read_fn( png_ptr, 0, user_read_data ) ;
    png_read_info( png_ptr, info_ptr ) ;
    png_get_IHDR( png_ptr, info_ptr, &width, &height, &depth, &color, 0, 0, 0 ) ;

    row = malloc( sizeof( uint32_t ) * width );
    if ( !row )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        file_close( png ) ;
        return NULL;
    }

    rowpointers = malloc( sizeof( png_bytep ) * height );
    if ( !rowpointers )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        free( row ) ;
        file_close( png ) ;
        return NULL;
    }

    /* Configura los distintos modos disponibles */

    if ( color == PNG_COLOR_TYPE_GRAY /*|| color == PNG_COLOR_TYPE_GRAY_ALPHA*/ )
    {
        png_set_gray_to_rgb( png_ptr );
        if ( color == PNG_COLOR_TYPE_GRAY ) png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER ) ;
    }

    if ( depth == 16 ) png_set_strip_16( png_ptr ) ;

    if ( color == PNG_COLOR_TYPE_RGB ) png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER ) ;

    png_set_bgr( png_ptr ) ;

    /* Recupera el fichero, convirtiendo a 16 bits si es preciso */

    rowbytes = png_get_rowbytes( png_ptr, info_ptr ) ;
    bitmap = bitmap_new( 0, width, height, ( color == PNG_COLOR_TYPE_PALETTE ) ? 8 : ( sys_pixel_format->depth == 16 ? 16 : 32 ) ) ;
    if ( !bitmap )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        free( rowpointers ) ;
        free( row ) ;
        file_close( png ) ;
        return NULL;
    }

    if ( color == PNG_COLOR_TYPE_PALETTE )
    {
        /* Read the color palette */

        png_colorp png_palette = ( png_colorp ) png_malloc( png_ptr, 256 * sizeof( png_color ) ) ;
        if ( !png_palette )
        {
            png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
            free( rowpointers ) ;
            free( row ) ;
            file_close( png ) ;
            return NULL;
        }
        png_get_PLTE( png_ptr, info_ptr, &png_palette, ( int * ) &n ) ;

        uint8_t * p = colors;

        for ( n = 0; n < 256 ; n++ )
        {
            * p++ = png_palette[n].red;
            * p++ = png_palette[n].green;
            * p++ = png_palette[n].blue;
        }

        bitmap->format->palette = pal_new_rgb(( uint8_t * )colors );
        pal_refresh( bitmap->format->palette );

        if ( !sys_pixel_format->palette )
        {
            sys_pixel_format->palette = pal_new( bitmap->format->palette );
/*            pal_use( bitmap->format->palette ); */
            palette_changed = 1 ;
        }

        for ( n = 0 ; n < height ; n++ ) rowpointers[n] = (( uint8_t* )bitmap->data ) + n * bitmap->pitch ;
        png_read_image( png_ptr, rowpointers ) ;

        /* If the depth is less than 8, expand the pixel values */

        if ( depth == 4 )
        {
            for ( n =  0; n < height; n++ )
            {
                char * orig, * dest;
                orig = ( char *  ) ( rowpointers[n] );
                dest = orig + width - 1;
                orig += ( width - 1 ) / 2;

                for ( x = width; x--; )
                {
                    *dest-- = ( *orig >> ((( 1 - ( x & 0x01 ) ) << 2 ) ) ) & 0x0F ;
                    if ( !( x & 0x01 ) ) orig--;
                }
            }
        }
        else if ( depth == 2 )
        {
            for ( n = 0; n < height; n++ )
            {
                char * orig, * dest;
                orig = ( char * ) rowpointers[n];
                dest = orig + width - 1;
                orig += ( width - 1 ) / 4;

                for ( x = width; x--; )
                {
                    *dest-- = ( *orig >> ((( 3 - ( x & 0x03 ) ) << 1 ) ) ) & 0x03 ;
                    if ( !( x & 0x03 ) ) orig--;
                }
            }
        }
        else if ( depth == 1 )
        {
            for ( n = 0; n < height; n++ )
            {
                char * orig, * dest;
                orig = ( char * ) rowpointers[n];
                dest = orig + width - 1;
                orig += ( width - 1 ) / 8;

                for ( x = width; x--; )
                {
                    *dest-- = ( *orig >> ( 7 - ( x & 0x07 ) ) ) & 0x01 ;
                    if ( !( x & 0x07 ) ) orig--;
                }
            }
        }
    }
    else if ( depth == 8 && sys_pixel_format->depth != 16 )
    {
        for ( n = 0 ; n < height ; n++ )
        {
            rowpointers[0] = ( void * )row ;
            png_read_rows( png_ptr, rowpointers, 0, 1 ) ;

            ptr32 = ( uint32_t* )((( uint8_t * )bitmap->data ) + n * bitmap->pitch );
            orig = row ;
            for ( x = 0 ; x < width ; x++ )
            {
                ARRANGE_DWORD( orig );
                *ptr32 = *orig ;
<b>
                if ((color==PNG_COLOR_TYPE_RGB)&& (info_ptr->pixel_depth==24)&& (info_ptr->valid & PNG_INFO_tRNS)){
                    uint8_t * ptr8 = (uint8_t *)orig;
if(
(ptr8[0]==info_ptr->trans_values.red) &&
(ptr8[1]==info_ptr->trans_values.green) &&
(ptr8[2]==info_ptr->trans_values.blue)
)
*ptr32 = 0;

               }
</b>
                ptr32++, orig++ ;
            }
        }
    }
    else
    {
        Rshift = 8;
        Gshift = 5;
        Bshift = 3;

        Rmask = 0xF80000 ; // 3
        Gmask = 0x00FC00 ; // 2
        Bmask = 0x0000F8 ; // 3
        for ( n = 0 ; n < height ; n++ )
        {
            rowpointers[0] = ( void * )row ;
            png_read_rows( png_ptr, rowpointers, 0, 1 ) ;

            ptr = ( uint16_t* )((( uint8_t * )bitmap->data ) + n * bitmap->pitch );
            orig = row ;
            for ( x = 0 ; x < width ; x++ )
            {
                ARRANGE_DWORD( orig );

                if (( *orig ) & 0x80000000 )
                {
                    *ptr = (( *orig & Rmask ) >> Rshift ) | (( *orig & Gmask ) >> Gshift ) | (( *orig & Bmask ) >> Bshift )  ;
                    if ( !*ptr )( *ptr )++ ;
                }
                else
                    *ptr = 0 ;
<b>
                if ((color==PNG_COLOR_TYPE_RGB)&& (info_ptr->pixel_depth==24)&& (info_ptr->valid & PNG_INFO_tRNS)){
                uint8_t * ptr8 = (uint8_t *)orig;
        if(
        (ptr8[0]==info_ptr->trans_values.red) &&
        (ptr8[1]==info_ptr->trans_values.green) &&
        (ptr8[2]==info_ptr->trans_values.blue)
        ){
        *ptr = 0;

        }
                }
</b>
                ptr++, orig++ ;
            }
        }

    }

    /* Fin */

    if ( !setjmp( png_ptr->jmpbuf ) ) png_read_end( png_ptr, 0 ) ;

    bitmap->modified = 1 ;

    png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
    free( rowpointers ) ;
    free( row ) ;
    file_close( png ) ;

    return bitmap ;
}

/*
*  FUNCTION : gr_save_png
*
*  Save a GRAPH into a PNG file
*
*  PARAMS :
*      gr              GRAPH with the image to save
*      filename        name for the file
*
*  RETURN VALUE :
*      0 - FAILURE
*      1 - SUCCESS
*
*/

int gr_save_png( GRAPH * gr, const char * filename )
{
    if ( !gr ) return( 0 ) ;

    FILE * file = fopen( filename, "wb" ) ;
    png_structp png_ptr ;
    png_infop info_ptr ;
    png_uint_32 k, i ;
    png_bytep * rowpointers ;
    png_colorp pal ;
    uint32_t * data, * ptr ;
    uint16_t * orig ;
    uint32_t * orig32 ;
    rgb_component * gpal = NULL;

    if ( !file ) return( 0 ) ;

    rowpointers = malloc( sizeof( png_bytep ) * gr->height );
    if ( !rowpointers )
    {
        fclose( file ) ;
        return 0 ;
    }

    png_ptr  = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ) ;
    if ( !png_ptr )
    {
        free( rowpointers ) ;
        fclose( file ) ;
        return( 0 ) ;
    }

    info_ptr = png_create_info_struct( png_ptr ) ;
    if ( !info_ptr )
    {
        png_destroy_write_struct( &png_ptr, NULL ) ;
        free( rowpointers ) ;
        fclose( file ) ;
        return( 0 ) ;
    }

    /* Error handling... */

    if ( setjmp( png_ptr->jmpbuf ) )
    {
        png_destroy_write_struct( &png_ptr, NULL ) ;
        free( rowpointers ) ;
        fclose( file ) ;
        return( 0 ) ;
    }

    png_init_io( png_ptr, file ) ;

    if ( gr->format->depth == 8 )
    {
        /* 8 bits PNG file */
        png_set_IHDR( png_ptr, info_ptr, gr->width,
                gr->height, 8, PNG_COLOR_TYPE_PALETTE,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE ) ;

        pal = ( png_colorp ) png_malloc( png_ptr, 256 * sizeof( png_color ) ) ;
        if ( !pal )
        {
            png_destroy_write_struct( &png_ptr, NULL ) ;
            free( rowpointers ) ;
            fclose( file ) ;
            return( 0 ) ;
        }

        if ( gr->format->palette )
            gpal = gr->format->palette->rgb;
        else if ( sys_pixel_format->palette )
            gpal = sys_pixel_format->palette->rgb;
        else
            gpal = ( rgb_component * )default_palette;

        /* Generate palette info */
        for ( k = 0 ; k < 256 ; k++ )
        {
            pal[k].red   = gpal[k].r ;
            pal[k].green = gpal[k].g ;
            pal[k].blue  = gpal[k].b ;
        }
        png_set_PLTE( png_ptr, info_ptr, pal, 256 ) ;
        png_write_info( png_ptr, info_ptr ) ;

        /* no need to rearrange data */
        for ( k = 0 ; k < ( unsigned )gr->height ; k++ )
            rowpointers[k] = ( uint8_t * )gr->data + gr->pitch * k ;
        png_write_image( png_ptr, rowpointers ) ;

        /* Free allocated palette... */
        png_free( png_ptr, ( png_voidp ) pal ) ;
        info_ptr->palette = NULL ;
    }
    else
    {
        png_set_IHDR( png_ptr, info_ptr, gr->width,
                gr->height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE ) ;
<b>
        if ( gr->format->depth == 16 ){
        info_ptr->color_type=PNG_COLOR_TYPE_RGB;
        info_ptr->trans_values.red =0;
        info_ptr->trans_values.green=0;
        info_ptr->trans_values.blue=0;
        info_ptr->valid = info_ptr->valid | PNG_INFO_tRNS;
        }
</b>
        png_write_info( png_ptr, info_ptr ) ;

        data = malloc( gr->width * gr->height * 4 ) ;
        if ( !data )
        {
            png_destroy_write_struct( &png_ptr, NULL ) ;
            free( rowpointers ) ;
            fclose( file ) ;
            return( 0 ) ;
        }

        if ( gr->format->depth == 16 )
        {
<b>
           uint8_t *ptr8;
            ptr8 = (uint8_t *) data;
            for ( k = 0; k < ( unsigned )gr->height; k++ )
            {
                rowpointers[k] = ptr8 ;
                orig = ( uint16_t * )( gr->data + gr->pitch * k ) ;
                for ( i = 0 ; i < ( unsigned )gr->width ; i++ )
                {
ptr8[0] =( *orig & 0xf800 ) >> 8;
ptr8[1] =( *orig & 0x07e0 ) >> 3;
ptr8[2] =( *orig & 0x001f ) << 3;
                    orig++ ;
                    ptr8+=3  ;
                }
            }
</b>
        }
        else if ( gr->format->depth == 32 )
        {
            for ( k = 0; k < ( unsigned )gr->height; k++ )
            {
                ptr  = data + gr->width * k ; /* uses dword for each pixel! */
                orig32 = ( uint32_t * )( gr->data + gr->pitch * k ) ;
                rowpointers[k] = ( uint8_t * )ptr ;
                for ( i = 0 ; i < ( unsigned )gr->width ; i++ )
                {
/*
                    if ( !*orig32 && !( gr->info_flags & GI_NOCOLORKEY ) )
                        *ptr = 0 ;
                    else if ( !( *orig32 & 0xff000000 ) )
                        *ptr =
                            0xff000000 |
                            (( *orig32 & 0x00ff0000 ) >> 16 ) |
                            (( *orig32 & 0x0000ff00 ) ) |
                            (( *orig32 & 0x000000ff ) << 16 ) ;
                    else
*/
                        *ptr =
                            (( *orig32 & 0xff000000 ) ) |
                            (( *orig32 & 0x00ff0000 ) >> 16 ) |
                            (( *orig32 & 0x0000ff00 ) ) |
                            (( *orig32 & 0x000000ff ) << 16 ) ;

                    /* Rearrange data */
                    ARRANGE_DWORD( ptr ) ;

                    orig32++ ;
                    ptr++  ;
                }
            }
        }
        png_write_image( png_ptr, rowpointers ) ;
        free( data ) ;
    }

    png_write_end( png_ptr, info_ptr ) ;
    fclose( file ) ;
    png_destroy_write_struct( &png_ptr, NULL ) ;
    free( rowpointers ) ;
    return ( 1 ) ;
}

/* --------------------------------------------------------------------------- */

int gr_load_png( const char * mapname )
{
    GRAPH * gr = gr_read_png( mapname ) ;
    if ( !gr ) return 0 ;
    gr->code = bitmap_next_code() ;
    grlib_add_map( 0, gr ) ;
    return gr->code ;
}

/* --------------------------------------------------------------------------- */

Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 09, 2010, 03:52:43 PM
He probado todas las combinaciones que se me han ocurrido de imágenes cargadas en modo 16 bits y guardadas y también he probado a hacer lo mismo en modo 32 y no he encontrado aparentemente ningún problema con la integración de los cambios, no obstante puede que encuentres bastantes mejoras en el código ya que yo a veces no soy muy bueno optimizando y me voy por el camino rápido :D.
Un ejemplo base con el que he realizado pruebas:

import "mod_key";
import "mod_proc";
import "mod_map";
import "mod_screen";
import "mod_video";

process main()
private
int escape=0, was_clicked=0, mx=0;
string str1="", str2="";
int square, pic1, pic2, pic3, pic4,pic4b, pic5,pic6;
begin
  set_mode(320,240,26);
  square=new_map(300,220,16);
  map_clear(0,square,rgb(0,255,0));
  pic5=png_load("A24b.png");
repeat

  put(0,square,160,120);
  put(0,pic5,280,170);

  if(key(_ESC) ) escape=1; end
  frame;
until(escape);
save_png(0,pic5,"A24saved.png");
unload_map(0,square);
unload_map(0,pic5);
let_me_alone();
end

donde A24b.png puede ser cualquier tipo de PNG suportado por bennu. y A24saved es la imagen resultado PNG de 24 bits con transparencia usando el 0 absoluto como transparente.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 09, 2010, 03:54:16 PM
Se me ocurre que quizás sería bueno tener una save_png en el que pudieras especificar con un parámetro más si quieres guardar la información de transparencia.
Pero bueno, siempre puedes eliminarla a posteriori con un programa de diseño gráfico así que a lo mejor no es tan útil :D.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 04:02:04 PM
ah, ya veo, se agrega en la parte del "else if ( depth == 8 && sys_pixel_format->depth != 16 )"

cuando posteaste originalmente, entendi que le agregabas un if... pero asi me parece bien el cambio como lo has puesto aca.

no importa la optimizacion ahora, y el tema del png_save, no estaba seguro, pero acabo de ver el codigo y esta bien, es correcto que asi sea, ya que siempre el valor 0 es transparente, entonces esta bien guardarlo asi, para que luego no se ingrese como un valor no transparente.

gracias DCelso por la mejora.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 04:19:49 PM
estoy viendo el codigo, y esta parte en la funcion save_png, me parece que no es necesaria, tal cual esta en el codigo actual deberia funcionar.


           uint8_t *ptr8;
            ptr8 = (uint8_t *) data;
            for ( k = 0; k < ( unsigned )gr->height; k++ )
            {
                rowpointers[k] = ptr8 ;
                orig = ( uint16_t * )( gr->data + gr->pitch * k ) ;
                for ( i = 0 ; i < ( unsigned )gr->width ; i++ )
                {
ptr8[0] =( *orig & 0xf800 ) >> 8;
ptr8[1] =( *orig & 0x07e0 ) >> 3;
ptr8[2] =( *orig & 0x001f ) << 3;
                    orig++ ;
                    ptr8+=3  ;
                }
            }


tampoco entiendo porque quedo tan diferente esta parte con respecto a la original.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 04:28:04 PM
bueno, no, no funciona la save.

explicame por que la diferencia en los 16bits en el save, gracias.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 04:47:41 PM
sin los cambios en la save_png, cargo el png del otro hilo llamado A02.png y lo almaceno y respeta perfectamente las transparencias.

en realidad probe con los siguientes archivos:

A02.png
A03.png
A04.png
A08bis.png
A08.png
A24.png
A32.png

y al salvarlos con el actual save_png, salen los png con las mismas transparencias que el original.

esta bien eso?
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 04:52:17 PM
otra cosa que veo es que tu ejemplo, pusiste el set_mode a 26, pero termina seteando a 16bits, lo mismo pasa si pones 24, con eso responde a una duda que tenia de alguien que dijo que bennugd dejaba setear el video a 24bits, en realidad lo setea a 16.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: FreeYourMind on November 09, 2010, 05:04:48 PM
Sugerencia:

Se podria soportar semitransparencias, o sea, imagenes con varios niveles de transparencia ?
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: josebita on November 09, 2010, 06:51:20 PM
Quote from: FreeYourMind on November 09, 2010, 05:04:48 PM
Sugerencia:

Se podria soportar semitransparencias, o sea, imagenes con varios niveles de transparencia ?
Eso son los 32 bits :)
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: FreeYourMind on November 09, 2010, 06:54:42 PM
 :D
Vale, la lo pillo, como hay mas gama de colores, estan incluidos semi transparencias para cada uno  :D
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: josebita on November 09, 2010, 07:02:25 PM
En modo de 32 bits los colores se representan con cuatro componentes: RGBA donde "A" es el valor del alpha en cada pixel.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 09, 2010, 07:13:59 PM
Ups, eso del 26 fue un fallo , quería poner a 16 bits. :D,
En cuanto a la diferencia entre tu save_png y el mio es toda, tu save_png como está cuando tenemos set_mode a 16 bits guarda un PNG de 32 bits en el que el canal alfa está a FF o 00, dependiendo de si encuentra un negro. En el caso de este save_png guarda un PNG de 24 bits (con toda la información de la imagen de 16 bits que hay cargada) donde en otro campo de la cabecera guardas que el negro negro, el 0 es el color que usaran los visores para considerarlo transparente. por tanto ahorras 1 byte por cada pixel en el guardado. (a eso me refería con ahorrar espacio), claro está tu PNG es muy válido, esto no es una correción, podríamos decirlo "una mejora" pero como tu dices innecesaria, osea que si no te gusta pues no se sube y punto :D, tu mandas.

Para el caso de modo 32 bits este save_png sigue haciendo lo mismo de antes así que es igual de válido.

En cuanto a lo que me preguntas de 16 bits es por eso mismo, porque tu tienes guardado en memoria una imagen de 16 bits y vas a guardarlo en una imagen de 24 bits, de ahí la conversión.

En cuanto al tema de semitransparencias, no se puede, en modo 16 bits no se soporta así que es impensable poder guardarlas, además el mismo formato PNG de 24 bits solo tiene un campo para guardar un único valor RGB a tratar como transparente puro, y como bien dicen, para evitar esto y soportar semitransparencias está el modo 32 bits que asigna un nuevo byte a cada pixel para especificar el nivel de transparencia de ese pixel.

En cuanto a que no funciona mi save_png, ¿como? si lo he trasteado todo lo que pude :(, voy a revisarlo a ver si es que me salté algo o es simplemente porque me confundí en poner el código y puse 26 en vez de 16 :D.

Lo que estoy viendo es que los "containers" de bennu en memoria para imágenes son mucho más potentes que el .fpg y el .map, quizás habría que replantearse unos nuevos formatos de fichero para sacarle la mayor chica a este fantástico Bennu. :D. Incluso ganar velocidad en la carga :D.

Y bueno, splinterGu, esto son simples sugerencias, no tienes por qué usarlas si no las ves útiles ya que aqui tú mandas :D, y si quieres puedes retocarlas o reimplementarlas a tu manera que seguro que es más óptima
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 09, 2010, 09:15:28 PM
Resultados de las prueba a fondo.
Ahora también he añadido que guarde la información de color transparente en PNGs indexados (<=8 bits) ya que no cuesta y así nuestros visores de imágenes veran exactamente lo mismo que bennu, :D.

/*
*  Copyright � 2006-2010 SplinterGU (Fenix/Bennugd)
*  Copyright � 2002-2006 Fenix Team (Fenix)
*  Copyright � 1999-2002 Jos� Luis Cebri�n Pag�e (Fenix)
*
*  This file is part of Bennu - Game Development
*
*  Bennu 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.
*
*  Bennu 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
*
*/

/* --------------------------------------------------------------------------- */

#include <png.h>

#include "mod_map.h"

/* --------------------------------------------------------------------------- */

/*
*  GLOBAL VARIABLES
*/

/* --------------------------------------------------------------------------- */

static uint8_t colors[256 * 3] ;

static file * png ;

/* --------------------------------------------------------------------------- */

static void user_read_data( png_structp png_ptr, png_bytep data, png_size_t length )
{
    file_read( png, data, length ) ;
}

GRAPH * gr_read_png( const char * filename )
{
GRAPH * bitmap ;
    unsigned int n, x ;
    uint16_t * ptr ;
    uint32_t * ptr32 ;
    uint32_t * orig ;
    uint32_t * row ;
    uint32_t Rshift, Gshift, Bshift ;
    uint32_t Rmask, Gmask, Bmask ;

    png_bytep * rowpointers ;

    png_structp png_ptr ;
    png_infop info_ptr, end_info ;
    png_uint_32 width, height, rowbytes;
    int depth, color ;

    /* Abre el fichero y se asegura de que screen est� inicializada */

    png = file_open( filename, "rb" ) ;
    if ( !png ) return NULL;

    /* Prepara las estructuras internas */

    png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ) ;
    if ( !png_ptr )
    {
        file_close( png );
        return NULL;
    }

    info_ptr = png_create_info_struct( png_ptr ) ;
    end_info = png_create_info_struct( png_ptr ) ;
    if ( !info_ptr || !end_info )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        file_close( png ) ;
        return NULL;
    }

    /* Rutina de error */

    if ( setjmp( png_ptr->jmpbuf ) )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        file_close( png ) ;
        return NULL;
    }

    /* Recupera informaci�n sobre el PNG */

    png_set_read_fn( png_ptr, 0, user_read_data ) ;
    png_read_info( png_ptr, info_ptr ) ;
    png_get_IHDR( png_ptr, info_ptr, &width, &height, &depth, &color, 0, 0, 0 ) ;

    row = malloc( sizeof( uint32_t ) * width );
    if ( !row )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        file_close( png ) ;
        return NULL;
    }

    rowpointers = malloc( sizeof( png_bytep ) * height );
    if ( !rowpointers )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        free( row ) ;
        file_close( png ) ;
        return NULL;
    }

    /* Configura los distintos modos disponibles */

    if ( color == PNG_COLOR_TYPE_GRAY /*|| color == PNG_COLOR_TYPE_GRAY_ALPHA*/ )
    {
        png_set_gray_to_rgb( png_ptr );
        if ( color == PNG_COLOR_TYPE_GRAY ) png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER ) ;
    }

    if ( depth == 16 ) png_set_strip_16( png_ptr ) ;

    if ( color == PNG_COLOR_TYPE_RGB ) png_set_filler( png_ptr, 0xFF, PNG_FILLER_AFTER ) ;

    png_set_bgr( png_ptr ) ;

    /* Recupera el fichero, convirtiendo a 16 bits si es preciso */

    rowbytes = png_get_rowbytes( png_ptr, info_ptr ) ;
    bitmap = bitmap_new( 0, width, height, ( color == PNG_COLOR_TYPE_PALETTE ) ? 8 : ( sys_pixel_format->depth == 16 ? 16 : 32 ) ) ;
    if ( !bitmap )
    {
        png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
        free( rowpointers ) ;
        free( row ) ;
        file_close( png ) ;
        return NULL;
    }

    if ( color == PNG_COLOR_TYPE_PALETTE )
    {
        /* Read the color palette */

        png_colorp png_palette = ( png_colorp ) png_malloc( png_ptr, 256 * sizeof( png_color ) ) ;
        if ( !png_palette )
        {
            png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
            free( rowpointers ) ;
            free( row ) ;
            file_close( png ) ;
            return NULL;
        }
        png_get_PLTE( png_ptr, info_ptr, &png_palette, ( int * ) &n ) ;

        uint8_t * p = colors;

        for ( n = 0; n < 256 ; n++ )
        {
            * p++ = png_palette[n].red;
            * p++ = png_palette[n].green;
            * p++ = png_palette[n].blue;
        }

        bitmap->format->palette = pal_new_rgb(( uint8_t * )colors );
        pal_refresh( bitmap->format->palette );

        if ( !sys_pixel_format->palette )
        {
            sys_pixel_format->palette = pal_new( bitmap->format->palette );
/*            pal_use( bitmap->format->palette ); */
            palette_changed = 1 ;
        }

        for ( n = 0 ; n < height ; n++ ) rowpointers[n] = (( uint8_t* )bitmap->data ) + n * bitmap->pitch ;
        png_read_image( png_ptr, rowpointers ) ;

        /* If the depth is less than 8, expand the pixel values */

        if ( depth == 4 )
        {
            for ( n =  0; n < height; n++ )
            {
                char * orig, * dest;
                orig = ( char *  ) ( rowpointers[n] );
                dest = orig + width - 1;
                orig += ( width - 1 ) / 2;

                for ( x = width; x--; )
                {
                    *dest-- = ( *orig >> ((( 1 - ( x & 0x01 ) ) << 2 ) ) ) & 0x0F ;
                    if ( !( x & 0x01 ) ) orig--;
                }
            }
        }
        else if ( depth == 2 )
        {
            for ( n = 0; n < height; n++ )
            {
                char * orig, * dest;
                orig = ( char * ) rowpointers[n];
                dest = orig + width - 1;
                orig += ( width - 1 ) / 4;

                for ( x = width; x--; )
                {
                    *dest-- = ( *orig >> ((( 3 - ( x & 0x03 ) ) << 1 ) ) ) & 0x03 ;
                    if ( !( x & 0x03 ) ) orig--;
                }
            }
        }
        else if ( depth == 1 )
        {
            for ( n = 0; n < height; n++ )
            {
                char * orig, * dest;
                orig = ( char * ) rowpointers[n];
                dest = orig + width - 1;
                orig += ( width - 1 ) / 8;

                for ( x = width; x--; )
                {
                    *dest-- = ( *orig >> ( 7 - ( x & 0x07 ) ) ) & 0x01 ;
                    if ( !( x & 0x07 ) ) orig--;
                }
            }
        }
    }
    else if ( depth == 8 && sys_pixel_format->depth != 16 )
    {
        for ( n = 0 ; n < height ; n++ )
        {
            rowpointers[0] = ( void * )row ;
            png_read_rows( png_ptr, rowpointers, 0, 1 ) ;

            ptr32 = ( uint32_t* )((( uint8_t * )bitmap->data ) + n * bitmap->pitch );
            orig = row ;
            for ( x = 0 ; x < width ; x++ )
            {
                ARRANGE_DWORD( orig );
                <b>*ptr32 = *orig ;
                if ((color==PNG_COLOR_TYPE_RGB)&& (info_ptr->pixel_depth==24)&& (info_ptr->valid & PNG_INFO_tRNS)){
                    uint8_t * ptr8 = (uint8_t *)orig;
if(
(ptr8[0]==info_ptr->trans_values.red) &&
(ptr8[1]==info_ptr->trans_values.green) &&
(ptr8[2]==info_ptr->trans_values.blue)
)
*ptr32 = 0;

               }</b>
                ptr32++, orig++ ;
            }
        }
    }
    else
    {
        Rshift = 8;
        Gshift = 5;
        Bshift = 3;

        Rmask = 0xF80000 ; // 3
        Gmask = 0x00FC00 ; // 2
        Bmask = 0x0000F8 ; // 3
        for ( n = 0 ; n < height ; n++ )
        {
            rowpointers[0] = ( void * )row ;
            png_read_rows( png_ptr, rowpointers, 0, 1 ) ;

            ptr = ( uint16_t* )((( uint8_t * )bitmap->data ) + n * bitmap->pitch );
            orig = row ;
            for ( x = 0 ; x < width ; x++ )
            {
                ARRANGE_DWORD( orig );

                if (( *orig ) & 0x80000000 )
                {
                    *ptr = (( *orig & Rmask ) >> Rshift ) | (( *orig & Gmask ) >> Gshift ) | (( *orig & Bmask ) >> Bshift )  ;
                    if ( !*ptr )( *ptr )++ ;
                }
                else
                    *ptr = 0 ;<b>
                if ((color==PNG_COLOR_TYPE_RGB)&& (info_ptr->pixel_depth==24)&& (info_ptr->valid & PNG_INFO_tRNS)){
                uint8_t * ptr8 = (uint8_t *)orig;
        if(
        (ptr8[0]==info_ptr->trans_values.red) &&
        (ptr8[1]==info_ptr->trans_values.green) &&
        (ptr8[2]==info_ptr->trans_values.blue)
        ){
        *ptr = 0;

        }
                }</b>
                ptr++, orig++ ;
            }
        }

    }

    /* Fin */

    if ( !setjmp( png_ptr->jmpbuf ) ) png_read_end( png_ptr, 0 ) ;

    bitmap->modified = 1 ;

    png_destroy_read_struct( &png_ptr, &info_ptr, &end_info ) ;
    free( rowpointers ) ;
    free( row ) ;
    file_close( png ) ;

    return bitmap ;
}

/*
*  FUNCTION : gr_save_png
*
*  Save a GRAPH into a PNG file
*
*  PARAMS :
*      gr              GRAPH with the image to save
*      filename        name for the file
*
*  RETURN VALUE :
*      0 - FAILURE
*      1 - SUCCESS
*
*/

int gr_save_png( GRAPH * gr, const char * filename )
{
    if ( !gr ) return( 0 ) ;

    FILE * file = fopen( filename, "wb" ) ;
    png_structp png_ptr ;
    png_infop info_ptr ;
    png_uint_32 k, i ;
    png_bytep * rowpointers ;
    png_colorp pal ;
    uint32_t * data, * ptr ;
    uint16_t * orig ;
    uint32_t * orig32 ;
    rgb_component * gpal = NULL;

    if ( !file ) return( 0 ) ;

    rowpointers = malloc( sizeof( png_bytep ) * gr->height );
    if ( !rowpointers )
    {
        fclose( file ) ;
        return 0 ;
    }

    png_ptr  = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 ) ;
    if ( !png_ptr )
    {
        free( rowpointers ) ;
        fclose( file ) ;
        return( 0 ) ;
    }

    info_ptr = png_create_info_struct( png_ptr ) ;
    if ( !info_ptr )
    {
        png_destroy_write_struct( &png_ptr, NULL ) ;
        free( rowpointers ) ;
        fclose( file ) ;
        return( 0 ) ;
    }

    /* Error handling... */

    if ( setjmp( png_ptr->jmpbuf ) )
    {
        png_destroy_write_struct( &png_ptr, NULL ) ;
        free( rowpointers ) ;
        fclose( file ) ;
        return( 0 ) ;
    }

    png_init_io( png_ptr, file ) ;

    if ( gr->format->depth == 8 )
    {<b>
        uint8_t trans = 1;</b>
    /* 8 bits PNG file */
        png_set_IHDR( png_ptr, info_ptr, gr->width,
                gr->height, 8, PNG_COLOR_TYPE_PALETTE,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE ) ;<b>
        if (!( gr->info_flags & GI_NOCOLORKEY )){
info_ptr->num_trans =1;
info_ptr->trans =&trans;
info_ptr->valid = info_ptr->valid | PNG_INFO_tRNS;
        }</b>

        pal = ( png_colorp ) png_malloc( png_ptr, 256 * sizeof( png_color ) ) ;
        if ( !pal )
        {
            png_destroy_write_struct( &png_ptr, NULL ) ;
            free( rowpointers ) ;
            fclose( file ) ;
            return( 0 ) ;
        }

        if ( gr->format->palette )
            gpal = gr->format->palette->rgb;
        else if ( sys_pixel_format->palette )
            gpal = sys_pixel_format->palette->rgb;
        else
            gpal = ( rgb_component * )default_palette;

        /* Generate palette info */
        for ( k = 0 ; k < 256 ; k++ )
        {
            pal[k].red   = gpal[k].r ;
            pal[k].green = gpal[k].g ;
            pal[k].blue  = gpal[k].b ;
        }
        png_set_PLTE( png_ptr, info_ptr, pal, 256 ) ;
        png_write_info( png_ptr, info_ptr ) ;

        /* no need to rearrange data */
        for ( k = 0 ; k < ( unsigned )gr->height ; k++ )
            rowpointers[k] = ( uint8_t * )gr->data + gr->pitch * k ;
        png_write_image( png_ptr, rowpointers ) ;

        /* Free allocated palette... */
        png_free( png_ptr, ( png_voidp ) pal ) ;
        info_ptr->palette = NULL ;
    }
    else
    {
        png_set_IHDR( png_ptr, info_ptr, gr->width,
                gr->height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                PNG_FILTER_TYPE_BASE ) ;
        <b>
        if ( gr->format->depth == 16 ){
        info_ptr->color_type=PNG_COLOR_TYPE_RGB;
        if (!( gr->info_flags & GI_NOCOLORKEY )){
    info_ptr->trans_values.index =0;
    info_ptr->trans_values.red =0;
    info_ptr->trans_values.green=0;
    info_ptr->trans_values.blue=0;
    info_ptr->trans_values.gray=0;
        }
        info_ptr->valid = info_ptr->valid | PNG_INFO_tRNS;
        }</b>

        png_write_info( png_ptr, info_ptr ) ;

        data = malloc( gr->width * gr->height * 4 ) ;
        if ( !data )
        {
            png_destroy_write_struct( &png_ptr, NULL ) ;
            free( rowpointers ) ;
            fclose( file ) ;
            return( 0 ) ;
        }

        if ( gr->format->depth == 16 )<b>
        {
        uint8_t *ptr8;
            ptr8 = (uint8_t *) data;
            for ( k = 0; k < ( unsigned )gr->height; k++ )
            {
                rowpointers[k] = ptr8 ;
                orig = ( uint16_t * )( gr->data + gr->pitch * k ) ;
                for ( i = 0 ; i < ( unsigned )gr->width ; i++ )
                {
ptr8[0] =( *orig & 0xf800 ) >> 8;
ptr8[1] =( *orig & 0x07e0 ) >> 3;
ptr8[2] =( *orig & 0x001f ) << 3;
                    orig++ ;
                    ptr8+=3  ;
                }
            }
        }</b>
        else if ( gr->format->depth == 32 )
        {
            for ( k = 0; k < ( unsigned )gr->height; k++ )
            {
                ptr  = data + gr->width * k ; /* uses dword for each pixel! */
                orig32 = ( uint32_t * )( gr->data + gr->pitch * k ) ;
                rowpointers[k] = ( uint8_t * )ptr ;
                for ( i = 0 ; i < ( unsigned )gr->width ; i++ )
                {
/*
                    if ( !*orig32 && !( gr->info_flags & GI_NOCOLORKEY ) )
                        *ptr = 0 ;
                    else if ( !( *orig32 & 0xff000000 ) )
                        *ptr =
                            0xff000000 |
                            (( *orig32 & 0x00ff0000 ) >> 16 ) |
                            (( *orig32 & 0x0000ff00 ) ) |
                            (( *orig32 & 0x000000ff ) << 16 ) ;
                    else
*/
                        *ptr =
                            (( *orig32 & 0xff000000 ) ) |
                            (( *orig32 & 0x00ff0000 ) >> 16 ) |
                            (( *orig32 & 0x0000ff00 ) ) |
                            (( *orig32 & 0x000000ff ) << 16 ) ;

                    /* Rearrange data */
                    ARRANGE_DWORD( ptr ) ;

                    orig32++ ;
                    ptr++  ;
                }
            }
        }
        png_write_image( png_ptr, rowpointers ) ;
        free( data ) ;
    }

    png_write_end( png_ptr, info_ptr ) ;
    fclose( file ) ;
    png_destroy_write_struct( &png_ptr, NULL ) ;
    free( rowpointers ) ;
    return ( 1 ) ;
}

/* --------------------------------------------------------------------------- */

int gr_load_png( const char * mapname )
{
    GRAPH * gr = gr_read_png( mapname ) ;
    if ( !gr ) return 0 ;
    gr->code = bitmap_next_code() ;
    grlib_add_map( 0, gr ) ;
    return gr->code ;
}

/* --------------------------------------------------------------------------- */

En un set_mode a 16 bits (recordemos esto de aquí en adelante, modo 16 bits), he probado a cargar imagenes indexadas de 1,2,4,8 bits, imágenes de 24 bits e imágenes de 32 bits y luego guardarlas con los siguientes resultados:
En las imágenes indexadas:
Las imágenes cargadas no contienen información de transparente ya que bennu usa siempre el color del índice 0 como transparente y odvia la información de transparencia de las imágenes indexadas.
Las imágenes guardadas ponen en la información de color el índice 0 así los visores verán lo mismo que bennu.

En las imágenes de 24 bits:
Si la imagen no tiene información de transparencia, bennu no pone ningún color a transparente, pero cambia todos los negros 0,0,0 a 0,0,8.
Si la imagen tiene información de un color a tratar como transparente (), bennu cambia los pixeles con ese color al 0 (tranpsarente para bennu)-
Al guardar estas imágenes de 24bits bennu guarda estas imágenes informando que el 0,0,0 se tratará como transparente, por tanto nuestros visores verán lo mismo que bennu veía.

En las imágenes de 32 bits:
Bennu elimina los semitransparentes y pone a transparente los valores alfa del 0 al 127.
Al guardar estas imágenes se guardan en 24 bits con información de que el 0,0,0 se tratará como transparente, así se ve la imagen como la veía bennu en los visores, sin semitransparentes :D.

Adjunto test realizado con los diferentes formatos de imagen.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 09:22:32 PM
free... muy bueno tu comentario,  me rei un buen rato... gracias... ;)

DCelso, claro, eso era lo que me parecia raro, porque veia que en 16bits guardabas 24bits y no 32bits como se espera que lo haga bennugd, es cierto que no tiene mucho sentido guardar un mapa de 16bits en un png de 32bits, porque el canal alpha es 0 o 255 (0% o 100%), pero bueno, no importa mucho, mas si tenemos en cuenta que hasta tu mejora cargabamos pngs de 32bits y bennugd lo convierte a 16bits. No esta mal tu idea, pero prefiero dejarlo como esta, y en algun momento hacer una funcion sobrecargada para tal fin, porque si lo cambio ahora incompatibilizare el sistema con la version anterior que guardaba png de 32bits.

lo de que no funciona, me referia al cambio parcial que habia hecho yo, tu codigo funciona bien.

gracias nuevamente, ya esta subido al SVN.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 09:27:45 PM
el cambio de meterle la informacion del color transparente en 8bits me parece correcto, lo incluire.

gracias!
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: FreeYourMind on November 09, 2010, 09:56:44 PM
Quote from: SplinterGU on November 09, 2010, 09:22:32 PM
free... muy bueno tu comentario,  me rei un buen rato... gracias... ;)

O sea, te reiste de mi  :o
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: FreeYourMind on November 09, 2010, 10:04:14 PM
Felicidades Splinter, record de 3 revisiones en un día  ;D
Por cierto, eso de transparencias en 8 bits, me da un poco miedo de ver que todo lo antiguo sigue funcionando, modo 7, etc.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 09, 2010, 11:35:48 PM
Quote from: FreeYourMind on November 09, 2010, 09:56:44 PM
Quote from: SplinterGU on November 09, 2010, 09:22:32 PM
free... muy bueno tu comentario,  me rei un buen rato... gracias... ;)

O sea, te reiste de mi  :o

jajaja, si, de lo despistado que estuviste, hablamos 1000 veces sobre los alphas (transparencias) a nivel pixel (32bits).

Quote from: FreeYourMind on November 09, 2010, 10:04:14 PM
Felicidades Splinter, record de 3 revisiones en un día  ;D
Por cierto, eso de transparencias en 8 bits, me da un poco miedo de ver que todo lo antiguo sigue funcionando, modo 7, etc.

no cambia nada, solo cuando graba un png, pone en el la info del png guardado que el primer color de la paleta (tabla indexada de colores) es el transparente... cierto DCelso?
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 09, 2010, 11:48:57 PM
cierto
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 10, 2010, 12:18:00 AM
En cuanto al guardar, no crearía compatibilidades porque como guardas justo el mismo PNG que ahora podemos cargar, si lo vuelves a cargar verías el mismo PNG que guardaste y que podrías haber guardado con 32 bits.

De todas formas el guardar actual que tienes guarda la misma información que este pero añadiendo un byte más por pixel, yo veo más lógico no guardar un 32 bits ya que no tienes información de 32 bits porque la perdiste al convertirlo a 16, pero bueno  es un mal menor guardarlo en 32 o 24 , simplemente la diferencia radica en que ocupará más el PNG final, porque información tendrá la mismísima :D.

He visto también un ligero problemilla en el guardado actual en 16 bits que el mío también arrastra. Un png de 24 bits cargado en modo de 16 bits convierte todo color negro R=0, G=0, B=0 creado con tu editor de imágenes a R=0,G=0,B=8 (por el tema de poder usar 0 como transparente) y resulta que al guardarlo guarda R=0,G=0,B=8, así pues el png inicial no es el mismo que el png final y al cargarlo en tu editor de imágenes verás que no hay ningún pixel con  R=0, G=0, B=0. :D. El ejemplo lo puedes ver abriendo A24.png y salida24.png (adjuntos en el zip anterior que subí) con un editor de imágenes. Bueno, otro mal menor porque son muy parecidos :D.

Además con el nuevo formato PNG soportado pasa algo más, resulta que pierdes el color RGB que hay asignado a tratar como transparente (imagínate que pusiste el rojo puro R=255,G=0,B=0) ya que la carga actual busca todos los píxeles que tengan dicho color y le asigna el  R=0, G=0, B=0 (cero absoluto, osea 0) para que internamente bennu sepa que es el color transparente, así que al guardarlo, ya sea con tu guardar de 32 bits o con éste guardar nuevo guardas el R=0, G=0, B=0 (detrás del transparente) en lugar del original, (el R=255,G=0,B=0).

La solución para no perder ese color radicaría en insertar éste color en la estructura GRAPH de alguna forma, para que luego al hacer el save_png puedas reasignarlo y así tener la misma imagen que cargaste :D. Pero bueno es otro mal menor ya que como vas a tratarlo como transparente pues te da igual que en la nueva imagen tengas ahora el negro en vez del rojo detrás de tu color transparente :D.

Está claro que con todo en 32 bits esto no pasa :D, porque no hay trucos de por medio para mostrar transparentes :D.


Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 10, 2010, 12:23:28 AM
en PIXEL_FORMAT del BITMAP se usan todos estos valores?
    uint8_t  Rloss;
    uint8_t  Gloss;
    uint8_t  Bloss;
    uint8_t  Aloss;

    uint8_t  Rshift;
    uint8_t  Gshift;
    uint8_t  Bshift;
    uint8_t  Ashift;

    uint32_t Rmask;
    uint32_t Gmask;
    uint32_t Bmask;
    uint32_t Amask;

a lo mejor en alguno de estos se podría guardar la información del color que hay por detrás del transparente, solo necesitamos 24 bits.
o en
    int16_t * blend_table;   /* Pointer to 16 bits blend table if any */
de BITMAP.

O bien, crearle a BITMAP tres nuevos uint8_t llamados Rhidden,Ghidden,Bhidden, para guardar el color escondido detrás del transparente :D.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: FreeYourMind on November 10, 2010, 12:37:16 AM
Me pierdo en tanta charla tecnica :)
Yo nunca he salvado un png con Bennu (ni sabia que se podia :)), lo que me interesa, es que al recorrer los colores estos sigan estando en el mismo sitio (tanto en 8 como 16 bits), no vaya ser que ahora, al cambiar un color por otro, ya no tengan el mismo indice, o me salgan colores distintos al cargar png's con las nuevas versiones de Bennu :)
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 10, 2010, 02:10:43 AM
Quote from: DCelso on November 10, 2010, 12:18:00 AM
En cuanto al guardar, no crearía compatibilidades porque como guardas justo el mismo PNG que ahora podemos cargar, si lo vuelves a cargar verías el mismo PNG que guardaste y que podrías haber guardado con 32 bits.

De todas formas el guardar actual que tienes guarda la misma información que este pero añadiendo un byte más por pixel, yo veo más lógico no guardar un 32 bits ya que no tienes información de 32 bits porque la perdiste al convertirlo a 16, pero bueno  es un mal menor guardarlo en 32 o 24 , simplemente la diferencia radica en que ocupará más el PNG final, porque información tendrá la mismísima :D.

He visto también un ligero problemilla en el guardado actual en 16 bits que el mío también arrastra. Un png de 24 bits cargado en modo de 16 bits convierte todo color negro R=0, G=0, B=0 creado con tu editor de imágenes a R=0,G=0,B=8 (por el tema de poder usar 0 como transparente) y resulta que al guardarlo guarda R=0,G=0,B=8, así pues el png inicial no es el mismo que el png final y al cargarlo en tu editor de imágenes verás que no hay ningún pixel con  R=0, G=0, B=0. :D. El ejemplo lo puedes ver abriendo A24.png y salida24.png (adjuntos en el zip anterior que subí) con un editor de imágenes. Bueno, otro mal menor porque son muy parecidos :D.

Además con el nuevo formato PNG soportado pasa algo más, resulta que pierdes el color RGB que hay asignado a tratar como transparente (imagínate que pusiste el rojo puro R=255,G=0,B=0) ya que la carga actual busca todos los píxeles que tengan dicho color y le asigna el  R=0, G=0, B=0 (cero absoluto, osea 0) para que internamente bennu sepa que es el color transparente, así que al guardarlo, ya sea con tu guardar de 32 bits o con éste guardar nuevo guardas el R=0, G=0, B=0 (detrás del transparente) en lugar del original, (el R=255,G=0,B=0).

La solución para no perder ese color radicaría en insertar éste color en la estructura GRAPH de alguna forma, para que luego al hacer el save_png puedas reasignarlo y así tener la misma imagen que cargaste :D. Pero bueno es otro mal menor ya que como vas a tratarlo como transparente pues te da igual que en la nueva imagen tengas ahora el negro en vez del rojo detrás de tu color transparente :D.

Está claro que con todo en 32 bits esto no pasa :D, porque no hay trucos de por medio para mostrar transparentes :D.




la incompatibilidad que digo podria generar, seria sobre productos externos, por ejemplo, que yo hago algo en bennugd que genera png que alimentan a otro programa, prefiero no cambiar eso ahora, si antes generaba png de 32, que se sigan generando lo mismo, en todo caso se podria agregar una funcion adicional para esto, pero de momento no parece necesario.

de que se guarda un byte mas, estamos de acuerdo, como ya lo dije unos mensajes atras.

igual el cambio queda en el codigo comentado, para futuro aprovechamiento.

se lo del rgb008, y tambien que se pierde el color, y que se convierte, y que incluso si hay otro rgb008 previo, se perdera diferencias cual es cual, pero bueno, eso ya se comporta asi desde tiempos de fenix, lo se.

gracias.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 10, 2010, 02:13:18 AM
Quote from: FreeYourMind on November 10, 2010, 12:37:16 AM
Me pierdo en tanta charla tecnica :)
Yo nunca he salvado un png con Bennu (ni sabia que se podia :)), lo que me interesa, es que al recorrer los colores estos sigan estando en el mismo sitio (tanto en 8 como 16 bits), no vaya ser que ahora, al cambiar un color por otro, ya no tengan el mismo indice, o me salgan colores distintos al cargar png's con las nuevas versiones de Bennu :)

siempre se convirtieron colores desde fenix, no vas a tener problemas con la visualizacion no te preocupes, si no los tuviste hasta ahora, lamentablemente en 16 bits es necesario hacer ese cambio.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DjSonyk on November 17, 2010, 11:38:33 PM
Rebuenas a todos,siento haber estado ausente tanto tiempo ^^,no lo leido del todo bien,pero DCelso me estas diciendo que se puede poner en transparente algo que ya este pintado?,lo digo porque tengo el editor de niveles atascado por eso mismo porque al "borrar",lo que realmente es que pone un cuadrado negro,y claro si te equivocas al dibujar algo y lo quieres borrar no lo borras realmente sino que dejas un cuadro negro y eso en un mapa para un scroll se veria los cuadritos negro.... me explico?
O va de otra cosa .... ^^
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DCelso on November 18, 2010, 03:08:40 PM
pues no te entiendo, chico, lo siento, no se si está relaccionado con esto. Ponnos un ejemplo práctico corto de lo que te pasa a ver si veo la luz.
Y sí, si que puedes poner a transparente algo que se ve, pero solo en modo 32 bits, ya que no tocas el RGB del pixel sino su cuarta compontente alfa y variando este valor puedes hacer que se vea el color del pixel total o parcialmente (entremezclandose con los colores que haya por detrás) o nada (dejando ver los colores que haya por detrás).
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 18, 2010, 03:59:16 PM
lo que hace el fix de DCelso, es poder definir cual color (solo 1) es el color transparente, luego cuando se carga el png en memoria ese color se reemplaza por 0 (transparente)
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DjSonyk on November 19, 2010, 12:11:43 AM
A ver ,imaginate vas hacer el primer plano de un scroll con el editor ,(parte ladrillos) y te equivocas al poner un tile,el que esta en el aire en la imagen de arriba,al borrar lo que realmente ocurre esque se queda negro,vease en la imagen de abajo,el azul se supone que es el segundo plano,el cielo por ejemplo,pero como ves con el siguiente codigo no lo borro realmente si no que se crear un cuadrado negro que al ser el fondo del editor negro da la sensacion de que esta borrado pero no....
(http://www2.mediafire.com/imgbnc.php/72c542fad88c5564889550213955e283bdcde4946c781f9e8f1939cf46ab2a175g.jpg)
[code language="bennu"]
Este es el codigo que tengo para supuestamente borrar...
CapaAncho[CapaActual]=Graphic_Info(CapaGrafico[CapaFichero[CapaActual]],Capa[CapaActual].Graph,G_WIDTH);
CapaAlto [CapaActual]=Graphic_Info(CapaGrafico[CapaFichero[CapaActual]],Capa[CapaActual].Graph,G_HEIGHT);
MapaVirtual=Map_New(CapaAncho[CapaActual],CapaAlto[CapaActual],32);   //Crea un nuevo mapa Ancho,Alto,Profundidad del color
Map_Clear(0,MapaVirtual,RGB(0,0,0));
Fpg_Add(CapaGrafico[CapaFichero[CapaActual]],998,0,MapaVirtual);   // Añade el grafico de borrar al fichero
Map_Block_Copy(CapaGrafico[CapaFichero[CapaActual]],999,
(TileX*CapaAncho[CapaActual])+Scroll.X0,(TileY*CapaAltoCapaActual])+Scroll.Y0,998,0,0,20,20,0);
[/code]
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DjSonyk on November 19, 2010, 12:23:40 AM
Quote from: SplinterGU on November 18, 2010, 03:59:16 PM
lo que hace el fix de DCelso, es poder definir cual color (solo 1) es el color transparente, luego cuando se carga el png en memoria ese color se reemplaza por 0 (transparente)
Ah vale ,muchas gracias Splinter tan amable y tan claro como siempre ,sigue asi   :P .
Yo por la informacción que e intentado leer,casi ni papa de ingles,creo que la solución seria que me hiciera una sentencia en la que primero deveria pintarlo por ejemplo de negro y luego con una mascara ya pasarlo a transparente pero me parece un poco lento,aun asi me baje el archivo para modificarle y aun no lo he tocado ,por eso mismo me parece un poco lento....
¿Recomendaciones para hacerlo yo mismo ?Si alguien tiene algo mas de informacion vendria bien,pues se podria usar tambien como un borrador de FOG de guerra en los juegos de estrategia por ejemplo....
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 19, 2010, 12:46:00 AM
si lo que queres es que sea transparente, no uses rgb(0,0,0) usa directamente 0, o sea, la linea deberia quedar.

Map_Clear(0,MapaVirtual,0);

si es que te entendi lo que querias hacer, quizas no te entendi.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DjSonyk on November 19, 2010, 01:48:58 AM
Quote from: SplinterGU on November 19, 2010, 12:46:00 AM
si lo que queres es que sea transparente, no uses rgb(0,0,0) usa directamente 0, o sea, la linea deberia quedar.

Map_Clear(0,MapaVirtual,0);

si es que te entendi lo que querias hacer, quizas no te entendi.
Si se uso eso Splinter al quererlo borrar no borra, al copiar transparente en algo pintado que da lo pintado osea 1+0=1
1 lo que esta pintado 0 tranparente...Lo acabo de probar hago click derecho pero el tile sigue formando parte del grafico,lo grabe en PNG por si acaso el grafico si que se modificaba y nada.
A ver si me explico mejor que es el 1º problema que tenemos,yo pinto un tile este se aloja en el fichero X,en el grafico 999,pero si quiero "borrar,quitar,cortar"algo(vamos que sea de nuevo transparente no consigo como hacerlo con las sentencias que tenemos en Bennugd, ojo!!! no digo que no se pueda en caso de poder ,lo que digo esque no se como ....)

Edit: Este finde semana si tengo tiempo dejo la demo del remake que prometi a Wind ^^,y una Beta del editor ...
Saludos a todos.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 19, 2010, 02:32:00 AM
no puede ser, si haces map_clear, a 0, lo borra.

ahhh, ya veo... el ultimo parametro del map_block_copy en lugar de 0 tiene que ser b_nocolorkey
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: Drumpi on November 19, 2010, 03:18:38 AM
¿Y usar una primitiva gráfica? ¿DRAW_BOX con DRAWING_COLOR(0)? creo que es más rápido y efectivo.
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 19, 2010, 03:24:47 AM
Quote from: Drumpi on November 19, 2010, 03:18:38 AM
¿Y usar una primitiva gráfica? ¿DRAW_BOX con DRAWING_COLOR(0)? creo que es más rápido y efectivo.

no lo se
Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: DjSonyk on November 19, 2010, 11:58:07 PM
Quote from: SplinterGU on November 19, 2010, 02:32:00 AM
no puede ser, si haces map_clear, a 0, lo borra.

ahhh, ya veo... el ultimo parametro del map_block_copy en lugar de 0 tiene que ser b_nocolorkey

Karma Up!!! Mira que lo he dado vueltas,creo recordad que asi tambien lo mire "Map_Clear(0,MapaVirtual,0);" consegui muchos trucos con Map_Block_Copy pero el de poner lo pixels trasparentes nada de nada...

En fin muchas gracias a todos en especial a ti Splinter,eres una makina,y DCelso siento la intromision y tu hilo ^^.

Title: Re: modificaciones a mod_map para soporte de pngs de 24 bits con transparencias.
Post by: SplinterGU on November 20, 2010, 03:33:51 AM
de nada... ;)