diff options
Diffstat (limited to 'modules/mod_effects/mod_effects.c')
-rw-r--r-- | modules/mod_effects/mod_effects.c | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/modules/mod_effects/mod_effects.c b/modules/mod_effects/mod_effects.c new file mode 100644 index 0000000..d5a181c --- /dev/null +++ b/modules/mod_effects/mod_effects.c @@ -0,0 +1,470 @@ +/* + * Copyright © 2006-2016 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 + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + */ + +/* --------------------------------------------------------------------------- */ + +#include <string.h> + +#include <math.h> +#include <stdlib.h> + +#include "bgddl.h" + +#include "libgrbase.h" + +#include "mod_effects.h" + +/* --------------------------------------------------------------------------- */ +/* + * FUNCTION : _get_pixel + * + * Read a pixel from a bitmap + * + * PARAMS : + * dest Destination bitmap + * x, y Pixel coordinates + * + * RETURN VALUE : + * 1, 8 or 16-bit integer with the pixel value + * + */ + +static int _get_pixel( GRAPH * dest, int x, int y ) +{ + if ( x < 0 || y < 0 || x >= ( int )dest->width || y >= ( int )dest->height ) return -1 ; + + switch ( dest->format->depth ) + { + case 8: + return *((( uint8_t * )dest->data ) + x + dest->pitch * y) ; + + case 16: + return *( uint16_t * )((( uint8_t *)dest->data) + ( x << 1 ) + dest->pitch * y) ; + + case 32: + return *( uint32_t * )((( uint8_t *)dest->data) + ( x << 2 ) + dest->pitch * y) ; + + case 1: + return ((( uint8_t * )dest->data )[x / 8 + dest->pitch * y] & ( 0x80 >> ( x & 7 ) ) ) ? 1 : 0; + } + return -1; +} + +/* + * FUNCTION : _put_pixel + * + * Paint a pixel with no clipping whatsoever, except by + * the bitmap's dimensions + * + * PARAMS : + * dest Destination bitmap + * x, y Pixel coordinates + * color 1, 8 or 16-bit pixel value + * + * RETURN VALUE : + * None + * + */ + +static void _put_pixel( GRAPH * dest, int x, int y, int color ) +{ + if ( x < 0 || y < 0 || x >= ( int )dest->width || y >= ( int )dest->height ) return ; + + dest->modified = 2 ; + + switch ( dest->format->depth ) + { + case 8: + *((( uint8_t * )dest->data ) + x + dest->pitch * y) = color ; + break; + + case 16: + *( uint16_t * )((( uint8_t *)dest->data) + ( x << 1 ) + dest->pitch * y) = color ; + break; + + case 32: + *( uint32_t * )((( uint8_t *)dest->data) + ( x << 2 ) + dest->pitch * y) = color ; + break; + + case 1: + if ( color ) + ((( uint8_t * )dest->data )[x / 8 + dest->pitch * y] ) |= ( 0x80 >> ( x & 7 ) ) ; + else + ((( uint8_t * )dest->data )[x / 8 + dest->pitch * y] ) &= ~( 0x80 >> ( x & 7 ) ) ; + break; + } +} + +/* ----------------------------------------------------------------- */ + +static int modeffects_filter( INSTANCE *my, int *params ) +{ //fpg,map,tabla10 + GRAPH * map = bitmap_get( params[0], params[1] ), * map2; + int *tabla = ( int* )params[2]; + int x, y, i, j; + int r, g, b, a, r2, g2, b2, c; + float r1, g1, b1; + int color; + + if ( !map ) return 0; + if ( map->format->depth < 16 ) return 0; + + map2 = bitmap_clone( map ); + + r1 = 0; + g1 = 0; + b1 = 0; + c = 0; + for ( i = 0;i < map->width;i++ ) + { + for ( j = 0;j < map->height;j++ ) + { + color = _get_pixel( map, i, j ); + if ( !color ) continue; + + gr_get_rgba_depth( map->format->depth, color, &r, &g, &b, &a ); // only need alpha + + for ( y = j - 1;y < j + 2;y++ ) + { + r2 = 0; + g2 = 0; + b2 = 0; + for ( x = i - 1;x < i + 2;x++, c++ ) + { + color = _get_pixel( map, ( x < 0 ) ? 0 : ( x > map->width - 1 ) ? map->width - 1 : x, ( y < 0 ) ? 0 : ( y > map->height - 1 ) ? map->height - 1 : y ); + if ( !color ) + { + /* Si es transparente, repetimos el ultimo color */ + r1 += ( float )( r2 * tabla[c] ); + g1 += ( float )( g2 * tabla[c] ); + b1 += ( float )( b2 * tabla[c] ); + continue; + } + + gr_get_rgb_depth( map->format->depth, color, &r2, &g2, &b2 ); + + r1 += ( float )( r2 * tabla[c] ); + g1 += ( float )( g2 * tabla[c] ); + b1 += ( float )( b2 * tabla[c] ); + } + } + + r1 /= tabla[9]; + g1 /= tabla[9]; + b1 /= tabla[9]; + + r = ((( int )r1 ) > 255 ) ? 255 : ( int )r1; + g = ((( int )g1 ) > 255 ) ? 255 : ( int )g1; + b = ((( int )b1 ) > 255 ) ? 255 : ( int )b1; + + if ( r < 0 )r = 0; + if ( g < 0 )g = 0; + if ( b < 0 )b = 0; + + if ( !r && !g && !b ) + c = 0; + else + c = gr_rgba_depth( map->format->depth, r, g, b, a ); + + _put_pixel( map2, i, j, c ); + + r1 = 0; + g1 = 0; + b1 = 0; + c = 0; + } + } + memcpy( map->data, map2->data, map->height*map->pitch ); + bitmap_destroy( map2 ); + + return 1 ; +} + +static int modeffects_blur( INSTANCE *my, int *params ) +{ // fpg,map,tipo + GRAPH * map = bitmap_get( params[0], params[1] ), *map2; + + int x, y, i, j, c; + int r, g, b, a, r2, g2, b2, a2; + int color; + + if ( !map ) return 0; + if ( map->format->depth < 16 ) return 0; + + switch ( params[2] ) + { + case BLUR_NORMAL: + //METODO 1 "RAPIDO" izq y arriba + for ( i = 0; i < map->width; i++ ) + for ( j = 0; j < map->height; j++ ) + { + color = _get_pixel( map, i, j ) ; + if ( !color ) continue; + gr_get_rgba_depth( map->format->depth, color, &r, &g, &b, &a ); + if ( i > 0 ) + { + gr_get_rgba_depth( map->format->depth, _get_pixel( map, i - 1, j ), &r2, &g2, &b2, &a2 ); + } + else + { + gr_get_rgba_depth( map->format->depth, _get_pixel( map, i + 1, j ), &r2, &g2, &b2, &a2 ); + } + r += r2; + g += g2; + b += b2; + if ( j > 0 ) + { + gr_get_rgba_depth( map->format->depth, _get_pixel( map, i, j - 1 ), &r2, &g2, &b2, &a2 ); + } + else + { + gr_get_rgba_depth( map->format->depth, _get_pixel( map, i, j + 1 ), &r2, &g2, &b2, &a2 ); + } + r += r2; + g += g2; + b += b2; + r /= 3; + g /= 3; + b /= 3; + _put_pixel( map, i, j, gr_rgba_depth( map->format->depth, r, g, b, a ) ); + } + break; + + case BLUR_3x3: + // METODO2 LENTO 3x3 + r = 0; + g = 0; + b = 0; + c = 0; + for ( i = 0;i < map->width;i++ ) + for ( j = 0;j < map->height;j++ ) + { + color = _get_pixel( map, i, j ) ; + if ( !color ) continue; + gr_get_rgba_depth( map->format->depth, color, &r, &g, &b, &a ); + c++; + for ( x = i - 1;x < i + 2;x++ ) + { + for ( y = j - 1;y < j + 2;y++ ) + { + if ( x < 0 || x > map->width - 1 || y < 0 || y > map->height - 1 ) continue; + gr_get_rgba_depth( map->format->depth, _get_pixel( map, x, y ), &r2, &g2, &b2, &a2 ); + r += r2; + g += g2; + b += b2; + c++; + } + } + if ( !c ) continue; + r /= c; + g /= c; + b /= c; + _put_pixel( map, i, j, gr_rgba_depth( map->format->depth, r, g, b, a ) ); + r = 0; + g = 0; + b = 0; + c = 0; + } + break; + + case BLUR_5x5: + // METODO3 aun mas LENTO 5x5 + r = 0; + g = 0; + b = 0; + c = 0; + for ( i = 0;i < map->width;i++ ) + { + for ( j = 0;j < map->height;j++ ) + { + color = _get_pixel( map, i, j ) ; + if ( !color ) continue; + gr_get_rgba_depth( map->format->depth, color, &r, &g, &b, &a ); + c++; + for ( x = i - 2;x < i + 3;x++ ) + { + for ( y = j - 2;y < j + 3;y++ ) + { + if ( x < 0 || x > map->width - 1 || y < 0 || y > map->height - 1 ) continue; + gr_get_rgba_depth( map->format->depth, _get_pixel( map, x, y ), &r2, &g2, &b2, &a2 ); + r += r2; + g += g2; + b += b2; + c++; + } + } + if ( !c ) continue; + r /= c; + g /= c; + b /= c; + _put_pixel( map, i, j, gr_rgba_depth( map->format->depth, r, g, b, a ) ); + r = 0; + g = 0; + b = 0; + c = 0; + } + } + break; + + case BLUR_5x5_MAP: + // METODO4 5x5 mapa adicional + map2 = bitmap_clone( map ); + r = 0; + g = 0; + b = 0; + c = 0; + for ( i = 0;i < map->width;i++ ) + { + for ( j = 0;j < map->height;j++ ) + { + color = _get_pixel( map, i, j ) ; + if ( !color ) continue; + gr_get_rgba_depth( map->format->depth, color, &r, &g, &b, &a ); + c++; + for ( x = i - 2;x < i + 3;x++ ) + { + for ( y = j - 2;y < j + 3;y++ ) + { + if ( x < 0 || x > map->width - 1 || y < 0 || y > map->height - 1 ) continue; + gr_get_rgba_depth( map->format->depth, _get_pixel( map, x, y ), &r2, &g2, &b2, &a2 ); + r += r2; + g += g2; + b += b2; + c++; + } + } + if ( !c ) continue; + r /= c; + g /= c; + b /= c; + _put_pixel( map2, i, j, gr_rgba_depth( map->format->depth, r, g, b, a ) ); + r = 0; + g = 0; + b = 0; + c = 0; + } + } + memcpy( map->data, map2->data, map->height*map->pitch ); + bitmap_destroy( map2 ); + break; + default: + break; + + } + return 1 ; +} + +static int modeffects_grayscale( INSTANCE *my, int *params ) +{ //fpg,map,tipo + GRAPH * map = bitmap_get( params[0], params[1] ) ; + uint32_t i, j, c; + int r, g, b, a; + + if ( !map ) return 0; + if ( map->format->depth < 16 ) return 0; + + for ( i = 0;i < map->height;i++ ) + for ( j = 0;j < map->width;j++ ) + { + gr_get_rgba_depth( map->format->depth, _get_pixel( map, j, i ), &r, &g, &b, &a ); + if ( !r && !g && !b )continue; + c = ( int )( 0.3 * r + 0.59 * g + 0.11 * b ); + switch ( params[2] ) + { + case GSCALE_RGB: // RGB + c = gr_rgba_depth( map->format->depth, c, c, c, a ); + break; + + case GSCALE_R: // R + c = gr_rgba_depth( map->format->depth, c, 0, 0, a ); + break; + + case GSCALE_G: // G + c = gr_rgba_depth( map->format->depth, 0, c, 0, a ); + break; + + case GSCALE_B: // B + c = gr_rgba_depth( map->format->depth, 0, 0, c, a ); + break; + + case GSCALE_RG: // RG + c = gr_rgba_depth( map->format->depth, c, c, 0, a ); + break; + + case GSCALE_RB: // RB + c = gr_rgba_depth( map->format->depth, c, 0, c, a ); + break; + + + case GSCALE_GB: // GB + c = gr_rgba_depth( map->format->depth, 0, c, c, a ); + break; + + case GSCALE_OFF: + default: + c = gr_rgba_depth( map->format->depth, r, g, b, a ); + } + _put_pixel( map, j, i, c ); + } + + return 1 ; +} + +static int modeffects_rgbscale( INSTANCE *my, int *params ) +{ //fpg, map, r, g, b + GRAPH * map = bitmap_get( params[0], params[1] ) ; + uint32_t i, j, c; + int r, g, b, a; + + if ( !map ) return 0; + if ( map->format->depth < 16 ) return 0; + + for ( i = 0;i < map->height;i++ ) + for ( j = 0;j < map->width;j++ ) + { + gr_get_rgba_depth( map->format->depth, _get_pixel( map, j, i ), &r, &g, &b, &a ); + if ( !r && !g && !b )continue; + c = ( int )( 0.3 * r + 0.59 * g + 0.11 * b ); + c = gr_rgba_depth( map->format->depth, + ( int )( c * *( float * )( ¶ms[2] ) ), + ( int )( c * *( float * )( ¶ms[3] ) ), + ( int )( c * *( float * )( ¶ms[4] ) ), + a ); + _put_pixel( map, j, i, c ); + } + + return 1 ; +} + +/* ----------------------------------------------------------------- */ +/* exports */ +/* ----------------------------------------------------------------- */ + +#include "mod_effects_exports.h" + +/* ----------------------------------------------------------------- */ |