/* * This file is part of the MLV Library. * * Copyright (C) 2010,2011,2012 Adrien Boussicault, Marc Zipstein * * * This Library 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 3 of the License, or * (at your option) any later version. * * This Library 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 Library. If not, see . */ #include "MLV_image.h" #include "data_structure.h" #include "platform.h" #ifndef MEMORY_DEBUG #if defined( OS_WINDOWS ) # include # include # include #elif defined( OS_APPLE ) # include # include # include #else # include # include # include #endif #else #include "memory_debug.h" #endif #include "warning_error.h" #include "memory_management.h" #include "data_structure.h" #include "image.h" extern DataMLV* MLV_data; SDL_Surface* create_surface( int width, int height ){ Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif #if defined( OS_ANDROID ) return SDL_CreateRGBSurface( SDL_SWSURFACE|SDL_SRCALPHA, width, height, MLV_BPP, rmask, gmask, bmask, amask ); #else return SDL_CreateRGBSurface( SDL_HWSURFACE|SDL_SRCALPHA, width, height, MLV_BPP, rmask, gmask, bmask, amask ); #endif } MLV_Image* MLV_load_image( const char* file_image ){ if( MLV_data==NULL ){ ERROR("Before using MLV_load_image, you have to initialise the MLV library by calling MLV_create_windows."); } SDL_Surface* surface = IMG_Load( file_image ); if( surface==NULL ){ return NULL; } MLV_Image* image = MLV_MALLOC( 1, MLV_Image ); image->surface = SDL_DisplayFormatAlpha( surface ); SDL_FreeSurface( surface ); return image; } int MLV_save_image_as_bmp( const MLV_Image* image, const char* file_image ){ return SDL_SaveBMP( image->surface, file_image ); } void MLV_resize_image( MLV_Image* image, int width, int height ){ double scalar_x = ((double) width) / ((double) image->surface->w); double scalar_y = ((double) height) / ((double) image->surface->h); MLV_scale_xy_image( image, scalar_x, scalar_y ); } void MLV_vertical_image_mirror( MLV_Image* image ){ int width, height; MLV_get_image_size( image, &width, &height ); Uint32 *pixel_src, *pixel_dst, tmp; int i=0; int j=0; for( i=0; i< width/2; i++ ){ for( j=0; jsurface->pixels) + j*image->surface->pitch/4 + i; pixel_dst = ((Uint32*) image->surface->pixels) + j*image->surface->pitch/4 + width-1-i; tmp = *pixel_dst; *pixel_dst = *pixel_src; *pixel_src = tmp; } } } void MLV_horizontal_image_mirror( MLV_Image* image ){ int width, height; MLV_get_image_size( image, &width, &height ); Uint32 *pixel_src, *pixel_dst, tmp; int i=0; int j=0; for( i=0; i< width; i++ ){ for( j=0; jsurface->pixels) + j*image->surface->pitch/4 + i; pixel_dst = ((Uint32*) image->surface->pixels) + (height-1-j)*image->surface->pitch/4 + i; tmp = *pixel_dst; *pixel_dst = *pixel_src; *pixel_src = tmp; } } } void MLV_resize_image_with_proportions( MLV_Image* image, int width, int height ){ double scalar_x = -1.0; double scalar_y = -1.0; if( width<=0 && height<=0 ) return; if( width > 0){ scalar_x = ((double) width) / ((double) image->surface->w); } if( height > 0){ scalar_y = ((double) height) / ((double) image->surface->h); } if( scalar_x < 0 ){ scalar_x = scalar_y; } if( scalar_y < 0 ){ scalar_y = scalar_x; } MLV_scale_image( image, ( scalar_x < scalar_y )? scalar_x : scalar_y ); } void MLV_get_image_size( const MLV_Image* image, int* width, int* height ){ if( width ){ *width = image->surface->w; } if( height ){ *height = image->surface->h; } } int MLV_get_image_width( const MLV_Image* image ){ return image->surface->w; } int MLV_get_image_height( const MLV_Image* image ){ return image->surface->h; } void MLV_scale_xy_image( MLV_Image* image, double scalar_x, double scalar_y ){ MLV_rotate_and_scale_xy_image( image, 0.0, scalar_x, scalar_y ); } void MLV_rotate_and_scale_xy_image( MLV_Image* image, double rotation, double scalar_x, double scalar_y ){ SDL_Surface* dst; dst = rotozoomSurfaceXY( image->surface, rotation, scalar_x, scalar_y, 0); SDL_FreeSurface( image->surface ); image->surface = dst; } void MLV_scale_image( MLV_Image* image, double scalar ){ MLV_rotate_and_scale_image( image, 0.0, scalar ); } void MLV_rotate_image( MLV_Image* image, double rotation ){ MLV_rotate_and_scale_image( image, rotation, 1.0 ); } void MLV_rotate_and_scale_image( MLV_Image* image, double rotation, double scalar ){ SDL_Surface* dst; dst = rotozoomSurface( image->surface, rotation, scalar, 0); SDL_FreeSurface( image->surface ); image->surface = dst; } MLV_Image* MLV_create_image( int width, int height ){ MLV_Image* result = MLV_MALLOC( 1, MLV_Image ); result->surface = create_surface( width, height ); int i,j; for( i=0; isurface ); MLV_FREE( image, MLV_Image ); } } MLV_Image* MLV_copy_image( const MLV_Image* image ){ MLV_Image* result = MLV_MALLOC( 1, MLV_Image ); result->surface = SDL_ConvertSurface( image->surface, image->surface->format, image->surface->flags ); return result; } MLV_Image* MLV_copy_partial_image( const MLV_Image* image, int x, int y, int width, int height ){ MLV_Image* result = MLV_MALLOC( 1, MLV_Image ); SDL_Surface* tmp = create_surface( width, height ); result->surface = SDL_DisplayFormatAlpha( tmp ); SDL_FreeSurface( tmp ); SDL_LockSurface( image->surface ); SDL_LockSurface( result->surface ); Uint32 *pixel_src, *pixel_dst; int i=0; int j=0; for( i=0; i< width; i++ ){ for( j=0; jsurface->pixels) + (y+j)*image->surface->pitch/4 + x+i; pixel_dst = ((Uint32*) result->surface->pixels) + j*result->surface->pitch/4 + i; *pixel_dst = * pixel_src; } } SDL_UnlockSurface( result->surface ); SDL_UnlockSurface( image->surface ); return result; } void MLV_draw_image( const MLV_Image* image, int x, int y ){ SDL_Rect rectangle; rectangle.x = x; rectangle.y = y; rectangle.h = image->surface->h; rectangle.w = image->surface->w; SDL_BlitSurface( image->surface, NULL, MLV_data->screen, &rectangle); } void MLV_draw_partial_image( const MLV_Image* image, int x_source, int y_source, int width_source, int height_source, int x, int y ){ SDL_Rect rectangle_source; rectangle_source.x = x_source; rectangle_source.y = y_source; rectangle_source.h = height_source; rectangle_source.w = width_source; SDL_Rect rectangle_dest; rectangle_dest.x = x; rectangle_dest.y = y; rectangle_dest.h = height_source; rectangle_dest.w = width_source; SDL_BlitSurface( image->surface, &rectangle_source, MLV_data->screen, &rectangle_dest); } void MLV_draw_scaled_rotated_image( MLV_Image* image, int centre_x, int centre_y, double rotation, double scalar ){ SDL_Surface* dst; dst = rotozoomSurface( image->surface, rotation, scalar, 0); SDL_Rect rectangle_dest; rectangle_dest.x = centre_x; rectangle_dest.y = centre_y; rectangle_dest.h = dst->h; rectangle_dest.w = dst->w; SDL_BlitSurface( dst, NULL, MLV_data->screen, &rectangle_dest); SDL_FreeSurface( dst ); } void MLV_draw_rotated_image( MLV_Image* image, int centre_x, int centre_y, double roation ){ MLV_draw_scaled_rotated_image( image, centre_x, centre_y, roation, 1.0 ); } void MLV_draw_scaled_image( MLV_Image* image, int centre_x, int centre_y, double scalar ){ MLV_draw_scaled_rotated_image( image, centre_x, centre_y, 0.0, scalar ); } void MLV_set_alpha_on_image( MLV_Alpha alpha, MLV_Image *image ){ SDL_Surface* surface = image->surface; SDL_LockSurface(surface); SDL_PixelFormat *fmt; Uint32 *pixel; Uint32 alpha32; fmt = surface->format; int x,y; int width, height; MLV_get_image_size( image, &width, &height ); for( x=0; xpixels)+ y*surface->pitch/4 + x; /* set the Alpha component */ alpha32 = alpha; alpha32 = alpha32 >> fmt->Aloss; alpha32 = alpha32 << fmt->Ashift; *pixel = ( *pixel & ( fmt->Rmask | fmt->Gmask | fmt->Bmask ) ) | alpha32; } } SDL_UnlockSurface(surface); } void MLV_set_pixel_on_image( int x, int y, MLV_Color color, MLV_Image *image ){ SDL_Surface* surface = image->surface; SDL_LockSurface(surface); SDL_PixelFormat *fmt; Uint32 *pixel; fmt = surface->format; pixel = ((Uint32*) surface->pixels)+ y*surface->pitch/4 + x; Uint8 red, blue, green, alpha; MLV_convert_color_to_rgba( color, &red, &green, &blue, &alpha ); Uint32 red32 = red, blue32 = blue, green32 = green, alpha32 = alpha; /* set the Red component */ red32 = red32 >> fmt->Rloss; red32 = red32 << fmt->Rshift; /* set the Green component */ green32 = green32 >> fmt->Gloss; green32 = green32 << fmt->Gshift; /* set the Blue component */ blue32 = blue32 >> fmt->Bloss; blue32 = blue32 << fmt->Bshift; /* set the Alpha component */ alpha32 = alpha32 >> fmt->Aloss; alpha32 = alpha32 << fmt->Ashift; *pixel = red32 | green32 | blue32 | alpha32; SDL_UnlockSurface(surface); } SDL_Surface* MLV_get_image_data( MLV_Image* image ){ return image->surface; } void get_pixel_on_image_unsafe( SDL_Surface* surface, int x, int y, int* red, int* green, int* blue, int* alpha ){ /* Extracting color components from a 32-bit color value */ SDL_PixelFormat *fmt; Uint32 temp, pixel; fmt = surface->format; pixel = *(((Uint32*) surface->pixels)+ y*surface->pitch/4 + x ); /* Get Red component */ if( red ){ temp = pixel & fmt->Rmask; /* Isolate red component */ temp = temp >> fmt->Rshift; /* Shift it down to 8-bit */ temp = temp << fmt->Rloss; /* Expand to a full 8-bit number */ *red = temp; } /* Get Green component */ if( green ){ temp = pixel & fmt->Gmask; /* Isolate green component */ temp = temp >> fmt->Gshift; /* Shift it down to 8-bit */ temp = temp << fmt->Gloss; /* Expand to a full 8-bit number */ *green = temp; } /* Get Blue component */ if( blue ){ temp = pixel & fmt->Bmask; /* Isolate blue component */ temp = temp >> fmt->Bshift; /* Shift it down to 8-bit */ temp = temp << fmt->Bloss; /* Expand to a full 8-bit number */ *blue = temp; } /* Get Alpha component */ if( alpha ){ temp = pixel & fmt->Amask; /* Isolate alpha component */ temp = temp >> fmt->Ashift; /* Shift it down to 8-bit */ temp = temp << fmt->Aloss; /* Expand to a full 8-bit number */ *alpha = temp; } } void get_pixel_on_image( SDL_Surface* surface, int x, int y, int* red, int* green, int* blue, int* alpha ){ SDL_LockSurface(surface); get_pixel_on_image_unsafe( surface, x, y, red, green, blue, alpha ); SDL_UnlockSurface(surface); } void MLV_get_pixel( int x, int y, int* red, int* green, int* blue, int* alpha ){ get_pixel_on_image( MLV_data->screen, x, y, red, green, blue, alpha ); } void MLV_get_pixel_on_image( const MLV_Image* image, int x, int y, int* red, int* green, int* blue, int* alpha ){ get_pixel_on_image( image->surface, x, y, red, green, blue, alpha ); } void MLV_draw_image_on_image( const MLV_Image* source_image, MLV_Image* destination_image, int destination_x, int destination_y ){ SDL_Rect rectangle; rectangle.x = destination_x; rectangle.y = destination_y; rectangle.h = source_image->surface->h; rectangle.w = source_image->surface->w; SDL_BlitSurface( source_image->surface, NULL, destination_image->surface , &rectangle); } void MLV_draw_partial_image_on_image( const MLV_Image* source_image, int source_x, int source_y, int width, int height, MLV_Image* destination_image, int destination_x, int destination_y ){ SDL_Rect rectangle_source,rectangle_destination; rectangle_destination.x = destination_x; rectangle_destination.y = destination_y; rectangle_destination.w = destination_image->surface->w; rectangle_destination.h = destination_image->surface->h; rectangle_source.x = source_x; rectangle_source.y = source_y; rectangle_source.w = width; rectangle_source.h = height; SDL_BlitSurface( source_image->surface, &rectangle_source, destination_image->surface , &rectangle_destination ); } /////////////////////////////////////////////////////////////////////////////// // Save screen // /////////////////////////////////////////////////////////////////////////////// void MLV_save_screen(){ SDL_BlitSurface( MLV_data->screen, NULL, MLV_data->save_screen, &(MLV_data->rectangle)); } void MLV_load_screen(){ SDL_BlitSurface( MLV_data->save_screen, NULL, MLV_data->screen, &(MLV_data->rectangle)); }