diff --git a/fileformats.c b/fileformats.c index 2244b8e5..1ae2eec2 100644 --- a/fileformats.c +++ b/fileformats.c @@ -1672,8 +1672,7 @@ word GIF_get_next_code(void) void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, byte color) { - if (color != context->Transparent_color) // transparent color - Set_pixel(context, idb->Pos_X+GIF_pos_X, idb->Pos_Y+GIF_pos_Y,color); + Set_pixel(context, idb->Pos_X+GIF_pos_X, idb->Pos_Y+GIF_pos_Y,color); GIF_pos_X++; @@ -1855,9 +1854,17 @@ void Load_GIF(T_IO_Context * context) && Read_byte(GIF_file,&(GCE.Transparent_color))) { if (GCE.Packed_fields & 1) + { + if (number_LID == 0) + context->Background_transparent = 1; context->Transparent_color= GCE.Transparent_color; + } else - context->Transparent_color = -1; + { + if (number_LID == 0) + context->Background_transparent = 0; + context->Transparent_color = 0; // Reset transparent color + } } else @@ -2170,7 +2177,7 @@ void Save_GIF(T_IO_Context * context) LSDB.Height=context->Height; } LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette - LSDB.Backcol=0; + LSDB.Backcol=context->Transparent_color; LSDB.Aspect =0; // Palette normale // On sauve le LSDB dans le fichier @@ -2213,9 +2220,15 @@ void Save_GIF(T_IO_Context * context) current_layer++) { // Write a Graphic Control Extension - char GCE_block[] = "\x21\xF9\x04\x05\x05\x00\x00\x00"; - //if (Main_current_layer > 0) - // GCE_block[3] = '\x05'; + char GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00"; + // 'Default' values: + // Disposal method "Do not dispose" + // Duration 5/100s (minimum viable value for current web browsers) + + if (current_layer > 0 || context->Background_transparent) + GCE_block[3] |= 1; // Transparent color flag + GCE_block[6] = context->Transparent_color; + Set_layer(context, current_layer); if (current_layer == context->Nb_layers -1) @@ -3231,6 +3244,9 @@ void Load_PNG(T_IO_Context * context) char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier byte png_header[8]; byte row_pointers_allocated; + png_bytep trans; + int num_trans; + png_color_16p trans_values; png_structp png_ptr; png_infop info_ptr; @@ -3388,11 +3404,24 @@ void Load_PNG(T_IO_Context * context) free(palette); palette = NULL; } - if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA) { Palette_loaded(context); } + // Transparency (tRNS) + if (png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values)) + { + int i; + for (i=0; iTransparent_color = i; + context->Background_transparent = 1; + break; + } + } + } context->Width=info_ptr->width; context->Height=info_ptr->height; @@ -3546,6 +3575,17 @@ void Save_PNG(T_IO_Context * context) } png_set_text(png_ptr, info_ptr, text_ptr, nb_text_chunks); } + if (context->Background_transparent) + { + // Transparency + byte opacity[256]; + // Need to fill a segment with '255', up to the transparent color + // which will have a 0. This piece of data (1 to 256 bytes) + // will be stored in the file. + memset(opacity, 255,context->Transparent_color); + opacity[context->Transparent_color]=0; + png_set_tRNS(png_ptr, info_ptr, opacity, (int)1 + context->Transparent_color,0); + } switch(Pixel_ratio) { case PIXEL_WIDE: diff --git a/fonts/GrafX2_Classic.gif b/fonts/GrafX2_Black.gif similarity index 82% rename from fonts/GrafX2_Classic.gif rename to fonts/GrafX2_Black.gif index af4d73c3..221e3abb 100644 Binary files a/fonts/GrafX2_Classic.gif and b/fonts/GrafX2_Black.gif differ diff --git a/fonts/GrafX2_Dark.gif b/fonts/GrafX2_Dark.gif new file mode 100644 index 00000000..96e4982a Binary files /dev/null and b/fonts/GrafX2_Dark.gif differ diff --git a/layers.c b/layers.c index 7253c0ee..1b3a27c0 100644 --- a/layers.c +++ b/layers.c @@ -25,6 +25,10 @@ #include "windows.h" #include "engine.h" #include "pages.h" +#include "sdlscreen.h" +#include "input.h" +#include "help.h" +#include "misc.h" void Layer_activate(byte layer, short side) { @@ -164,9 +168,93 @@ void Button_Layer_toggle(void) Layer_activate(layer, RIGHT_SIDE); } +static void Draw_transparent_color(byte color) +{ + char buf[4]; + Num2str(color, buf, 3); + Print_in_window(63,39,buf,MC_Black,MC_Light); + Window_rectangle(90,39,13,7,color); +} + +static void Draw_transparent_background(byte background) +{ + Print_in_window(99,57,background?"X":" ",MC_Black,MC_Light); +} + + void Button_Layer_menu(void) { + byte transparent_color = Main_backups->Pages->Transparent_color; + byte transparent_background = Main_backups->Pages->Background_transparent; + short clicked_button; + byte color; + byte click; + + Open_window(122,100,"Layers"); + + Window_display_frame_in( 6, 21,110, 52); + Print_in_window(14,18,"Transparency",MC_Dark,MC_Light); + + Print_in_window(11,38,"Color",MC_Black,MC_Light); + Window_set_normal_button(54, 36, 56,13,"" , 0,1,KEY_NONE); // 1 + Draw_transparent_color(transparent_color); + + Print_in_window(11,57,"Background",MC_Black,MC_Light); + Window_set_normal_button(95, 54, 15,13,"" , 0,1,KEY_NONE); // 2 + Draw_transparent_background(transparent_background); + + Window_set_normal_button( 7, 78, 51,14,"OK" , 0,1,SDLK_RETURN); // 3 + Window_set_normal_button(63, 78, 51,14,"Cancel", 0,1,KEY_ESC); // 4 + + Update_window_area(0,0,Window_width, Window_height); + + do + { + + clicked_button=Window_clicked_button(); + //if (Is_shortcut(Key,0x100+BUTTON_HELP)) + // Window_help(BUTTON_LAYERS, NULL); + switch(clicked_button) + { + case 1: // color + Get_color_behind_window(&color,&click); + if (click && transparent_color!=color) + { + transparent_color=color; + Hide_cursor(); + Draw_transparent_color(transparent_color); + Display_cursor(); + Wait_end_of_click(); + } + break; + + case 2: // background + transparent_background = !transparent_background; + Hide_cursor(); + Draw_transparent_background(transparent_background); + Display_cursor(); + break; + } + } + while (clicked_button<3); + + // On exit Hide_cursor(); + Close_window(); + if (clicked_button==3) + { + // Accept changes + if (Main_backups->Pages->Transparent_color != transparent_color || + Main_backups->Pages->Background_transparent != transparent_background) + { + Backup_layers(-1); + Main_backups->Pages->Transparent_color = transparent_color; + Main_backups->Pages->Background_transparent = transparent_background; + Redraw_layered_image(); + Display_all_screen(); + End_of_modification(); + } + } Unselect_button(BUTTON_LAYER_MENU); Display_cursor(); } diff --git a/loadsave.c b/loadsave.c index 6d2e1e31..2ced475d 100644 --- a/loadsave.c +++ b/loadsave.c @@ -179,6 +179,11 @@ void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color) // Chargement des pixels dans la preview case CONTEXT_PREVIEW: + // Skip pixels of transparent index if : + // - It's the first layer, and image has transparent background. + // - or it's a layer above the first one + if (color == context->Transparent_color && (context->Current_layer > 0 || context->Background_transparent)) + break; if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0)) { if (context->Ratio == PIXEL_WIDE && @@ -375,6 +380,8 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size, context->Height = height; context->Ratio = ratio; context->Nb_layers = 1; + context->Transparent_color=0; + context->Background_transparent=0; switch(context->Type) { @@ -741,6 +748,10 @@ void Load_image(T_IO_Context *context) Main_current_layer = context->Nb_layers - 1; Main_layers_visible = (2<Pages->Transparent_color = context->Transparent_color; + Main_backups->Pages->Background_transparent = context->Background_transparent; // Correction des dimensions if (Main_image_width<1) @@ -1032,7 +1043,6 @@ void Init_context_preview(T_IO_Context * context, char *file_name, char *file_di context->File_name = file_name; context->File_directory = file_directory; context->Format = Main_fileformat; // FIXME ? - } /// Setup for loading/saving the current main image @@ -1050,6 +1060,7 @@ void Init_context_layered_image(T_IO_Context * context, char *file_name, char *f context->Nb_layers = Main_backups->Pages->Nb_layers; strcpy(context->Comment, Main_comment); context->Transparent_color=Main_backups->Pages->Transparent_color; + context->Background_transparent=Main_backups->Pages->Background_transparent; if (Pixel_ratio == PIXEL_WIDE || Pixel_ratio == PIXEL_WIDE2) context->Ratio=PIXEL_WIDE; else if (Pixel_ratio == PIXEL_TALL || Pixel_ratio == PIXEL_TALL2) @@ -1082,7 +1093,8 @@ void Init_context_brush(T_IO_Context * context, char *file_name, char *file_dire context->Height = Brush_height; context->Nb_layers = 1; // Solid save... could use BG color maybe - context->Transparent_color=-1; + context->Transparent_color=0; + context->Background_transparent=0; context->Ratio=PIXEL_SIMPLE; context->Target_address=Brush; context->Pitch=Brush_width; @@ -1102,7 +1114,8 @@ void Init_context_surface(T_IO_Context * context, char *file_name, char *file_di // context->Width // context->Height context->Nb_layers = 1; - context->Transparent_color=-1; + context->Transparent_color=0; + context->Background_transparent=0; context->Ratio=PIXEL_SIMPLE; //context->Target_address //context->Pitch @@ -1111,6 +1124,8 @@ void Init_context_surface(T_IO_Context * context, char *file_name, char *file_di /// Function to call when need to switch layers. void Set_layer(T_IO_Context *context, byte layer) { + context->Current_layer = layer; + if (context->Type == CONTEXT_MAIN_IMAGE) { // This awful thing is the part that happens on load diff --git a/loadsave.h b/loadsave.h index ec488fd1..2e56cdc3 100644 --- a/loadsave.h +++ b/loadsave.h @@ -56,7 +56,8 @@ typedef struct short Height; byte Nb_layers; char Comment[COMMENT_SIZE+1]; - short Transparent_color; + byte Background_transparent; + byte Transparent_color; /// Pixel ratio of the image enum PIXEL_RATIO Ratio; @@ -64,7 +65,10 @@ typedef struct byte *Target_address; /// Pitch: Difference of addresses between one pixel and the one just "below" it long Pitch; - + + /// Internal: during load, marks which layer is being loaded. + short Current_layer; + /// Internal: Used to mark truecolor images on loading. Only used by preview. //byte Is_truecolor; /// Internal: Temporary RGB buffer when loading 24bit images diff --git a/pages.c b/pages.c index 0c5ae407..7ba40e6d 100644 --- a/pages.c +++ b/pages.c @@ -76,6 +76,7 @@ T_Page * New_page(byte nb_layers) page->File_format=DEFAULT_FILEFORMAT; page->Nb_layers=nb_layers; page->Transparent_color=0; // Default transparent color + page->Background_transparent=0; page->Next = page->Prev = NULL; } return page; diff --git a/struct.h b/struct.h index c16f1ce6..413f5458 100644 --- a/struct.h +++ b/struct.h @@ -347,7 +347,8 @@ typedef struct T_Page byte File_format; ///< File format, in enum ::FILE_FORMATS struct T_Page *Next; ///< Pointer to the next backup struct T_Page *Prev; ///< Pointer to the previous backup - word Transparent_color; ///< Index of transparent color. -1 or 0 to 255. + byte Background_transparent; ///< Boolean, true if Layer 0 should have transparent pixels + byte Transparent_color; ///< Index of transparent color. 0 to 255. byte Nb_layers; ///< Number of layers byte * Image[0]; ///< Pixel data for the (first layer of) image. // No field after Image[] ! Dynamic layer allocation for Image[1], [2] etc.