From 962d23dbc43dcd2b3d785faabd7e7fdafd2b3d69 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Tue, 31 Aug 2010 23:48:10 +0000 Subject: [PATCH] The gradients (Cycling or not) are now per-picture, so: The main and spare page have separate gradients; Loading a picture resets the gradients and loads the new image's (if any); Undo and Redo correctly navigate to the right gradients when you Undo/Redo Loading different color-cycling images. git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1600 416bcca6-2ee7-4201-b75f-2eb2f807beb1 --- src/buttons.c | 78 +++++++++++++++++++++++++------------------------- src/global.h | 2 -- src/init.c | 15 ++++++++-- src/input.c | 20 ++++++------- src/loadsave.c | 20 ++++++------- src/pages.c | 38 ++++++++++++++++++++++++ src/struct.h | 10 ++++++- 7 files changed, 118 insertions(+), 65 deletions(-) diff --git a/src/buttons.c b/src/buttons.c index da6ff168..65f76a1f 100644 --- a/src/buttons.c +++ b/src/buttons.c @@ -2440,19 +2440,19 @@ void Draw_button_gradient_style(short x_pos,short y_pos,int technique) void Load_gradient_data(int index) { - if (Gradient_array[index].Start>Gradient_array[index].End) + if (Main_backups->Pages->Gradients->Range[index].Start>Main_backups->Pages->Gradients->Range[index].End) Error(0); - Gradient_lower_bound =Gradient_array[index].Start; - Gradient_upper_bound =Gradient_array[index].End; - Gradient_is_inverted =Gradient_array[index].Inverse; - Gradient_random_factor=Gradient_array[index].Mix+1; + Gradient_lower_bound =Main_backups->Pages->Gradients->Range[index].Start; + Gradient_upper_bound =Main_backups->Pages->Gradients->Range[index].End; + Gradient_is_inverted =Main_backups->Pages->Gradients->Range[index].Inverse; + Gradient_random_factor=Main_backups->Pages->Gradients->Range[index].Mix+1; Gradient_bounds_range=(Gradient_lower_boundPages->Gradients->Range[index].Technique) { case 0 : // Degradé de base Gradient_function=Gradient_basic; @@ -2492,7 +2492,7 @@ void Button_Gradients(void) { short clicked_button; char str[3]; - T_Gradient_array backup_gradients[16]; + T_Gradient_array backup_gradients; int old_current_gradient; T_Scroller_button * mix_scroller; T_Scroller_button * speed_scroller; @@ -2514,7 +2514,7 @@ void Button_Gradients(void) Gradient_pixel=Pixel; old_current_gradient=Current_gradient; changed_gradient_index=0; - memcpy(backup_gradients,Gradient_array,sizeof(T_Gradient_array)*16); + memcpy(&backup_gradients,Main_backups->Pages->Gradients,sizeof(T_Gradient_array)); Open_window(235,146,"Gradation menu"); @@ -2523,19 +2523,19 @@ void Button_Gradients(void) gradient_scroller=Window_set_scroller_button(218,20,75,16,1,Current_gradient); // 2 // Slider for mix mix_scroller = Window_set_scroller_button(31,20,84,256,1, - Gradient_array[Current_gradient].Mix); // 3 + Main_backups->Pages->Gradients->Range[Current_gradient].Mix); // 3 // Direction Window_set_normal_button(8,20,15,14, - (Gradient_array[Current_gradient].Inverse)?"\033":"\032",0,1,SDLK_TAB); // 4 + (Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",0,1,SDLK_TAB); // 4 // Technique Window_set_normal_button(8,90,15,14,"",0,1,SDLK_TAB|MOD_SHIFT); // 5 - Draw_button_gradient_style(8,90,Gradient_array[Current_gradient].Technique); + Draw_button_gradient_style(8,90,Main_backups->Pages->Gradients->Range[Current_gradient].Technique); Window_set_normal_button(178,128,51,14,"OK",0,1,SDLK_RETURN); // 6 Window_set_normal_button(123,128,51,14,"Cancel",0,1,KEY_ESC); // 7 // Scrolling speed - speed_scroller = Window_set_horizontal_scroller_button(76,111,88,65,1,Gradient_array[Current_gradient].Speed); // 8 - Num2str(Gradient_array[Current_gradient].Speed,str,2); + speed_scroller = Window_set_horizontal_scroller_button(76,111,88,65,1,Main_backups->Pages->Gradients->Range[Current_gradient].Speed); // 8 + Num2str(Main_backups->Pages->Gradients->Range[Current_gradient].Speed,str,2); Print_in_window(169,113,str,MC_Black,MC_Light); Print_in_window(5,58,"MIX",MC_Dark,MC_Light); @@ -2545,7 +2545,7 @@ void Button_Gradients(void) Print_in_window(11,112,"Cycling",cycling_mode?MC_Black:MC_Dark,MC_Light); // On tagge les couleurs qui vont avec - Tag_color_range(Gradient_array[Current_gradient].Start,Gradient_array[Current_gradient].End); + Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End); Num2str(Current_gradient+1,str,2); Print_in_window(215,100,str,MC_Black,MC_Light); @@ -2555,7 +2555,7 @@ void Button_Gradients(void) // On affiche la preview Draw_gradient_preview(8,128,108,14,Current_gradient); - first_color=last_color=(Gradient_array[Current_gradient].Inverse)?Gradient_array[Current_gradient].End:Gradient_array[Current_gradient].Start; + first_color=last_color=(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?Main_backups->Pages->Gradients->Range[Current_gradient].End:Main_backups->Pages->Gradients->Range[Current_gradient].Start; Update_window_area(0,0,Window_width, Window_height); Display_cursor(); @@ -2577,19 +2577,19 @@ void Button_Gradients(void) Print_in_window(215,100,str,MC_Black,MC_Light); // On tagge les couleurs qui vont avec - Tag_color_range(Gradient_array[Current_gradient].Start,Gradient_array[Current_gradient].End); + Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End); // On affiche le sens qui va avec - Print_in_window(12,23,(Gradient_array[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light); + Print_in_window(12,23,(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light); // On raffiche le mélange (jauge) qui va avec - mix_scroller->Position=Gradient_array[Current_gradient].Mix; + mix_scroller->Position=Main_backups->Pages->Gradients->Range[Current_gradient].Mix; Window_draw_slider(mix_scroller); // Update speed - speed_scroller->Position=Gradient_array[Current_gradient].Speed; + speed_scroller->Position=Main_backups->Pages->Gradients->Range[Current_gradient].Speed; Window_draw_slider(speed_scroller); - Num2str(Gradient_array[Current_gradient].Speed,str,2); + Num2str(Main_backups->Pages->Gradients->Range[Current_gradient].Speed,str,2); Print_in_window(169,113,str,MC_Black,MC_Light); // Gradient # @@ -2597,7 +2597,7 @@ void Button_Gradients(void) Window_draw_slider(gradient_scroller); // Technique (flat, dithered, very dithered) - Draw_button_gradient_style(8,90,Gradient_array[Current_gradient].Technique); + Draw_button_gradient_style(8,90,Main_backups->Pages->Gradients->Range[Current_gradient].Technique); // Rectangular gradient preview Draw_gradient_preview(8,128,108,14,Current_gradient); @@ -2623,9 +2623,9 @@ void Button_Gradients(void) // On vient de clicker // On met à jour l'intervalle du dégradé - first_color=last_color=Gradient_array[Current_gradient].Start=Gradient_array[Current_gradient].End=temp_color; + first_color=last_color=Main_backups->Pages->Gradients->Range[Current_gradient].Start=Main_backups->Pages->Gradients->Range[Current_gradient].End=temp_color; // On tagge le bloc - Tag_color_range(Gradient_array[Current_gradient].Start,Gradient_array[Current_gradient].End); + Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End); // Tracé de la preview: Draw_gradient_preview(8,128,108,14,Current_gradient); } @@ -2637,18 +2637,18 @@ void Button_Gradients(void) // On commence par ordonner la 1ère et dernière couleur du bloc if (first_colorPages->Gradients->Range[Current_gradient].Start=first_color; + Main_backups->Pages->Gradients->Range[Current_gradient].End =temp_color; } else if (first_color>temp_color) { - Gradient_array[Current_gradient].Start=temp_color; - Gradient_array[Current_gradient].End =first_color; + Main_backups->Pages->Gradients->Range[Current_gradient].Start=temp_color; + Main_backups->Pages->Gradients->Range[Current_gradient].End =first_color; } else - Gradient_array[Current_gradient].Start=Gradient_array[Current_gradient].End=first_color; + Main_backups->Pages->Gradients->Range[Current_gradient].Start=Main_backups->Pages->Gradients->Range[Current_gradient].End=first_color; // On tagge le bloc - Tag_color_range(Gradient_array[Current_gradient].Start,Gradient_array[Current_gradient].End); + Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End); // Tracé de la preview: Draw_gradient_preview(8,128,108,14,Current_gradient); last_color=temp_color; @@ -2665,7 +2665,7 @@ void Button_Gradients(void) case 3 : // Nouveau mélange de dégradé Hide_cursor(); // Nouvel mélange dans Window_attribute2 - Gradient_array[Current_gradient].Mix=Window_attribute2; + Main_backups->Pages->Gradients->Range[Current_gradient].Mix=Window_attribute2; // On affiche la nouvelle preview Draw_gradient_preview(8,128,108,14,Current_gradient); Display_cursor(); @@ -2673,8 +2673,8 @@ void Button_Gradients(void) case 4 : // Changement de sens Hide_cursor(); // On inverse le sens (par un XOR de 1) - Gradient_array[Current_gradient].Inverse^=1; - Print_in_window(12,25,(Gradient_array[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light); + Main_backups->Pages->Gradients->Range[Current_gradient].Inverse^=1; + Print_in_window(12,25,(Main_backups->Pages->Gradients->Range[Current_gradient].Inverse)?"\033":"\032",MC_Black,MC_Light); // On affiche la nouvelle preview Draw_gradient_preview(8,128,108,14,Current_gradient); Display_cursor(); @@ -2682,14 +2682,14 @@ void Button_Gradients(void) case 5 : // Changement de technique Hide_cursor(); // On change la technique par (+1)%3 - Gradient_array[Current_gradient].Technique=(Gradient_array[Current_gradient].Technique+1)%3; - Draw_button_gradient_style(8,90,Gradient_array[Current_gradient].Technique); + Main_backups->Pages->Gradients->Range[Current_gradient].Technique=(Main_backups->Pages->Gradients->Range[Current_gradient].Technique+1)%3; + Draw_button_gradient_style(8,90,Main_backups->Pages->Gradients->Range[Current_gradient].Technique); // On affiche la nouvelle preview Draw_gradient_preview(8,128,108,14,Current_gradient); Display_cursor(); case 8 : // Speed - Gradient_array[Current_gradient].Speed=Window_attribute2; - Num2str(Gradient_array[Current_gradient].Speed,str,2); + Main_backups->Pages->Gradients->Range[Current_gradient].Speed=Window_attribute2; + Num2str(Main_backups->Pages->Gradients->Range[Current_gradient].Speed,str,2); Hide_cursor(); Print_in_window(169,113,str,MC_Black,MC_Light); Display_cursor(); @@ -2715,9 +2715,9 @@ void Button_Gradients(void) temp_color=color; // On met à jour l'intervalle du dégradé - first_color=last_color=Gradient_array[Current_gradient].Start=Gradient_array[Current_gradient].End=temp_color; + first_color=last_color=Main_backups->Pages->Gradients->Range[Current_gradient].Start=Main_backups->Pages->Gradients->Range[Current_gradient].End=temp_color; // On tagge le bloc - Tag_color_range(Gradient_array[Current_gradient].Start,Gradient_array[Current_gradient].End); + Tag_color_range(Main_backups->Pages->Gradients->Range[Current_gradient].Start,Main_backups->Pages->Gradients->Range[Current_gradient].End); // Tracé de la preview: Draw_gradient_preview(8,128,108,14,Current_gradient); Display_cursor(); @@ -2773,7 +2773,7 @@ void Button_Gradients(void) if (clicked_button==7) // Cancel { Current_gradient=old_current_gradient; - memcpy(Gradient_array,backup_gradients,sizeof(T_Gradient_array)*16); + memcpy(Main_backups->Pages->Gradients,&backup_gradients,sizeof(T_Gradient_array)); Load_gradient_data(Current_gradient); } } diff --git a/src/global.h b/src/global.h index 82faa890..3da8af4a 100644 --- a/src/global.h +++ b/src/global.h @@ -781,8 +781,6 @@ GFX2_GLOBAL Func_gradient Gradient_function; /// either ::Pixel (if the gradient must be drawn on menus only) /// or ::Display_pixel (if the gradient must be drawn on the image) GFX2_GLOBAL Func_pixel Gradient_pixel; -/// Settings for all gradients -GFX2_GLOBAL T_Gradient_array Gradient_array[16]; /// Index in ::Gradient_array of the currently selected gradient. GFX2_GLOBAL byte Current_gradient; /// Boolean, true when the color cycling is active. diff --git a/src/init.c b/src/init.c index e5dcc200..66c094f0 100644 --- a/src/init.c +++ b/src/init.c @@ -1999,7 +1999,10 @@ int Load_CFG(int reload_all) } break; case CHUNK_GRADIENTS: // Infos sur les dégradés - if (reload_all) + // The gradients chunk is deprecated since the data + // is now loaded/saved in GIF and LBM formats. + // The chunk will be completely ignored. + /*if (reload_all) { if (! Read_byte(Handle, &Current_gradient)) goto Erreur_lecture_config; @@ -2014,7 +2017,7 @@ int Load_CFG(int reload_all) } Load_gradient_data(Current_gradient); } - else + else*/ { if (fseek(Handle,Chunk.Size,SEEK_CUR)==-1) goto Erreur_lecture_config; @@ -2324,6 +2327,9 @@ int Save_CFG(void) goto Erreur_sauvegarde_config; // Sauvegarde des informations des dégradés + // The gradients chunk is deprecated since the data + // is now loaded/saved in GIF and LBM formats. + /* Chunk.Number=CHUNK_GRADIENTS; Chunk.Size=241; if (!Write_byte(Handle, Chunk.Number) || @@ -2340,6 +2346,7 @@ int Save_CFG(void) !Write_dword_le(Handle, Gradient_array[index].Technique) ) goto Erreur_sauvegarde_config; } + */ // Sauvegarde de la matrice du Smooth Chunk.Number=CHUNK_SMOOTH; @@ -2547,6 +2554,7 @@ void Set_config_defaults(void) Stencil[index]=1; // Dégradés + /* TODO Current_gradient=0; for(index=0;index<16;index++) { @@ -2557,7 +2565,8 @@ void Set_config_defaults(void) Gradient_array[index].Technique=0; } Load_gradient_data(Current_gradient); - + */ + // Smooth Smooth_matrix[0][0]=1; Smooth_matrix[0][1]=2; diff --git a/src/input.c b/src/input.c index b1bb97db..506fa3d7 100644 --- a/src/input.c +++ b/src/input.c @@ -920,13 +920,13 @@ int Color_cycling(__attribute__((unused)) void* useless) { int len; - len=Gradient_array[i].End-Gradient_array[i].Start+1; - if (len>1 && Gradient_array[i].Speed) + len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1; + if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed) { int new_offset; - new_offset=(now-start)/(int)(1000.0/(Gradient_array[i].Speed*0.2856)) % len; - if (!Gradient_array[i].Inverse) + new_offset=(now-start)/(int)(1000.0/(Main_backups->Pages->Gradients->Range[i].Speed*0.2856)) % len; + if (!Main_backups->Pages->Gradients->Range[i].Inverse) new_offset=len - new_offset; if (new_offset!=offset[i]) @@ -947,14 +947,14 @@ int Color_cycling(__attribute__((unused)) void* useless) { int len; - len=Gradient_array[i].End-Gradient_array[i].Start+1; - if (len>1 && Gradient_array[i].Speed) + len=Main_backups->Pages->Gradients->Range[i].End-Main_backups->Pages->Gradients->Range[i].Start+1; + if (len>1 && Main_backups->Pages->Gradients->Range[i].Speed) { - for(color=Gradient_array[i].Start;color<=Gradient_array[i].End;color++) + for(color=Main_backups->Pages->Gradients->Range[i].Start;color<=Main_backups->Pages->Gradients->Range[i].End;color++) { - PaletteSDL[color].r=Main_palette[Gradient_array[i].Start+((color-Gradient_array[i].Start+offset[i])%len)].R; - PaletteSDL[color].g=Main_palette[Gradient_array[i].Start+((color-Gradient_array[i].Start+offset[i])%len)].G; - PaletteSDL[color].b=Main_palette[Gradient_array[i].Start+((color-Gradient_array[i].Start+offset[i])%len)].B; + PaletteSDL[color].r=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].R; + PaletteSDL[color].g=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].G; + PaletteSDL[color].b=Main_palette[Main_backups->Pages->Gradients->Range[i].Start+((color-Main_backups->Pages->Gradients->Range[i].Start+offset[i])%len)].B; } } } diff --git a/src/loadsave.c b/src/loadsave.c index 70ade29c..29b70d63 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -719,13 +719,13 @@ void Load_image(T_IO_Context *context) // Color cyling ranges: for (i=0; i<16; i++) - Gradient_array[i].Speed=0; + Main_backups->Pages->Gradients->Range[i].Speed=0; for (i=0; iColor_cycles; i++) { - Gradient_array[i].Start=context->Cycle_range[i].Start; - Gradient_array[i].End=context->Cycle_range[i].End; - Gradient_array[i].Inverse=context->Cycle_range[i].Inverse; - Gradient_array[i].Speed=context->Cycle_range[i].Speed; + Main_backups->Pages->Gradients->Range[i].Start=context->Cycle_range[i].Start; + Main_backups->Pages->Gradients->Range[i].End=context->Cycle_range[i].End; + Main_backups->Pages->Gradients->Range[i].Inverse=context->Cycle_range[i].Inverse; + Main_backups->Pages->Gradients->Range[i].Speed=context->Cycle_range[i].Speed; } } @@ -1132,12 +1132,12 @@ void Init_context_layered_image(T_IO_Context * context, char *file_name, char *f // Color cyling ranges: for (i=0; i<16; i++) { - if (Gradient_array[i].Start!=Gradient_array[i].End && Gradient_array[i].Speed) + if (Main_backups->Pages->Gradients->Range[i].Start!=Main_backups->Pages->Gradients->Range[i].End && Main_backups->Pages->Gradients->Range[i].Speed) { - context->Cycle_range[context->Color_cycles].Start=Gradient_array[i].Start; - context->Cycle_range[context->Color_cycles].End=Gradient_array[i].End; - context->Cycle_range[context->Color_cycles].Inverse=Gradient_array[i].Inverse; - context->Cycle_range[context->Color_cycles].Speed=Gradient_array[i].Speed; + context->Cycle_range[context->Color_cycles].Start=Main_backups->Pages->Gradients->Range[i].Start; + context->Cycle_range[context->Color_cycles].End=Main_backups->Pages->Gradients->Range[i].End; + context->Cycle_range[context->Color_cycles].Inverse=Main_backups->Pages->Gradients->Range[i].Inverse; + context->Cycle_range[context->Color_cycles].Speed=Main_backups->Pages->Gradients->Range[i].Speed; context->Color_cycles++; } } diff --git a/src/pages.c b/src/pages.c index de7fccec..9712488d 100644 --- a/src/pages.c +++ b/src/pages.c @@ -75,6 +75,7 @@ T_Page * New_page(byte nb_layers) page->Filename[0]='\0'; page->File_format=DEFAULT_FILEFORMAT; page->Nb_layers=nb_layers; + page->Gradients=NULL; page->Transparent_color=0; // Default transparent color page->Background_transparent=0; page->Next = page->Prev = NULL; @@ -141,6 +142,24 @@ byte * Dup_layer(byte * layer) // ============================================================== +/// Adds a shared reference to the gradient data of another page. Pass NULL for new. +T_Gradient_array *Dup_gradient(T_Page * page) +{ + // new + if (page==NULL || page->Gradients==NULL) + { + T_Gradient_array *array; + array=(T_Gradient_array *)calloc(1, sizeof(T_Gradient_array)); + if (!array) + return NULL; + array->Used=1; + return array; + } + // shared + page->Gradients->Used++; + return page->Gradients; +} + void Download_infos_page_main(T_Page * page) // Affiche la page à l'écran { @@ -396,6 +415,16 @@ void Clear_page(T_Page * page) Free_layer(page, i); page->Image[i]=NULL; } + + // Free_gradient() : This data is reference-counted + if (page->Gradients) + { + page->Gradients->Used--; + if (page->Gradients->Used==0) + free(page->Gradients); + page->Gradients=NULL; + } + page->Width=0; page->Height=0; // On ne se préoccupe pas de ce que deviens le reste des infos de l'image. @@ -404,6 +433,7 @@ void Clear_page(T_Page * page) void Copy_S_page(T_Page * dest,T_Page * source) { *dest=*source; + dest->Gradients=NULL; } @@ -438,6 +468,10 @@ int Allocate_list_of_pages(T_List_of_pages * list) list->List_size=1; + page->Gradients=Dup_gradient(NULL); + if (!page->Gradients) + return 0; + return 1; // Succès } @@ -803,6 +837,7 @@ int Backup_with_new_dimensions(int upload,byte layers,int width,int height) new_page->Height=height; strcpy(new_page->Filename, Main_backups->Pages->Filename); strcpy(new_page->File_directory, Main_backups->Pages->File_directory); + new_page->Gradients=Dup_gradient(upload?Main_backups->Pages:NULL); if (Create_new_page(new_page,Main_backups,0xFFFFFFFF)) { for (i=0; iPages); + new_page->Gradients=Dup_gradient(Spare_backups->Pages); new_page->Width=width; new_page->Height=height; @@ -905,6 +941,7 @@ void Backup_layers(dword layer_mask) // Fill it with a copy of the latest history Copy_S_page(new_page,Main_backups->Pages); + new_page->Gradients=Dup_gradient(Main_backups->Pages); Create_new_page(new_page,Main_backups,layer_mask); Download_infos_page_main(new_page); @@ -941,6 +978,7 @@ void Backup_the_spare(dword layer_mask) // Fill it with a copy of the latest history Copy_S_page(new_page,Spare_backups->Pages); + new_page->Gradients=Dup_gradient(Spare_backups->Pages); Create_new_page(new_page,Spare_backups,layer_mask); // Copy the actual pixels from the backup to the latest page diff --git a/src/struct.h b/src/struct.h index 39f5cb8a..d6b4bb73 100644 --- a/src/struct.h +++ b/src/struct.h @@ -226,7 +226,14 @@ typedef struct dword Mix; ///< Amount of randomness to add to the mix (0-255) dword Technique;///< Gradient technique: 0 (no pattern) 1 (dithering), or 2 (big dithering) byte Speed; ///< Speed of cycling. 0 for disabled, 1-64 otherwise. -} T_Gradient_array; +} T_Gradient_range; + +/// Data for a full set of gradients. +typedef struct +{ + int Used; ///< Reference count + T_Gradient_range Range[16]; +} T_Gradient_array; /// Data for one setting of shade. Warning, this one is saved/loaded as binary. typedef struct @@ -351,6 +358,7 @@ 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 + T_Gradient_array *Gradients; ///< Pointer to the gradients used by the image. 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