File selector: display preview no longer changes GUI colors when the image uses less than 253 colors. Fixes many cases of issue 215, and generally allows much smoother browsing.

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1592 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2010-08-25 18:55:48 +00:00
parent fc42854490
commit 236a026137
5 changed files with 138 additions and 117 deletions

View File

@ -1772,7 +1772,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// On efface le commentaire précédent // On efface le commentaire précédent
Window_rectangle(45,70,32*8,8,MC_Light); Window_rectangle(45,70,32*8,8,MC_Light);
// On nettoie la zone où va s'afficher la preview: // On nettoie la zone où va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light); Window_rectangle(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT,MC_Light);
// On efface les dimensions de l'image // On efface les dimensions de l'image
Window_rectangle(143,59,72,8,MC_Light); Window_rectangle(143,59,72,8,MC_Light);
// On efface la taille du fichier // On efface la taille du fichier
@ -1788,7 +1788,7 @@ byte Button_Load_or_Save(byte load, T_IO_Context *context)
// Un update pour couvrir les 4 zones: 3 libellés plus le commentaire // Un update pour couvrir les 4 zones: 3 libellés plus le commentaire
Update_window_area(45,48,256,30); Update_window_area(45,48,256,30);
// Zone de preview // Zone de preview
Update_window_area(183,95,120,80); Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
} }
New_preview_is_needed=0; New_preview_is_needed=0;

View File

@ -180,38 +180,32 @@ void Set_pixel(T_IO_Context *context, short x_pos, short y_pos, byte color)
// Chargement des pixels dans la preview // Chargement des pixels dans la preview
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
// Skip pixels of transparent index if : // Skip pixels of transparent index if :
// - It's the first layer, and image has transparent background. // it's a layer above the first one
// - or it's a layer above the first one if (color == context->Transparent_color && context->Current_layer > 0)
if (color == context->Transparent_color && (context->Current_layer > 0 || context->Background_transparent))
break; break;
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0)) if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{ {
// Tag the color as 'used'
context->Preview_usage[color]=1;
// Store pixel
if (context->Ratio == PIXEL_WIDE && if (context->Ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE && Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2) Pixel_ratio != PIXEL_WIDE2)
{ {
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X*2), context->Preview_bitmap[x_pos/context->Preview_factor_X*2 + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X*2]=color;
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y), context->Preview_bitmap[x_pos/context->Preview_factor_X*2+1 + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X*2]=color;
color);
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X*2)+1,
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
} }
else if (context->Ratio == PIXEL_TALL && else if (context->Ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL && Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2) Pixel_ratio != PIXEL_TALL2)
{ {
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X), context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X*2]=color;
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y*2), context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X*2+1]=color;
color);
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y*2)+1,
color);
} }
else else
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X), context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y),
color);
} }
break; break;
@ -233,9 +227,9 @@ void Palette_loaded(T_IO_Context *context)
switch (context->Type) switch (context->Type)
{ {
case CONTEXT_MAIN_IMAGE: case CONTEXT_MAIN_IMAGE:
case CONTEXT_PREVIEW:
Set_palette(context->Palette); Set_palette(context->Palette);
break; break;
case CONTEXT_PREVIEW:
case CONTEXT_BRUSH: case CONTEXT_BRUSH:
case CONTEXT_SURFACE: case CONTEXT_SURFACE:
break; break;
@ -243,67 +237,7 @@ void Palette_loaded(T_IO_Context *context)
switch (context->Type) switch (context->Type)
{ {
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
Compute_optimal_menu_colors(context->Palette);
/*
if(
(
context->Palette[MC_Black].R==context->Palette[MC_Dark].R &&
context->Palette[MC_Black].G==context->Palette[MC_Dark].G &&
context->Palette[MC_Black].B==context->Palette[MC_Dark].B
) ||
(
context->Palette[MC_Light].R==context->Palette[MC_Dark].R &&
context->Palette[MC_Light].G==context->Palette[MC_Dark].G &&
context->Palette[MC_Light].B==context->Palette[MC_Dark].B
) ||
(
context->Palette[MC_White].R==context->Palette[MC_Light].R &&
context->Palette[MC_White].G==context->Palette[MC_Light].G &&
context->Palette[MC_White].B==context->Palette[MC_Light].B
)
)
{
// Si on charge une image monochrome, le fileselect ne sera plus visible. Dans ce cas on force quelques couleurs à des valeurs sures
int black =
Main_palette[MC_Black].R +
Main_palette[MC_Black].G +
Main_palette[MC_Black].B;
int white =
Main_palette[MC_White].R +
Main_palette[MC_White].G +
Main_palette[MC_White].B;
//Set_color(MC_Light,(2*white+black)/9,(2*white+black)/9,(2*white+black)/9);
//Set_color(MC_Dark,(2*black+white)/9,(2*black+white)/9,(2*black+white)/9);
Main_palette[MC_Dark].R=(2*black+white)/9;
Main_palette[MC_Dark].G=(2*black+white)/9;
Main_palette[MC_Dark].B=(2*black+white)/9;
Main_palette[MC_Light].R=(2*white+black)/9;
Main_palette[MC_Light].G=(2*white+black)/9;
Main_palette[MC_Light].B=(2*white+black)/9;
Set_palette(Main_palette);
}
*/
Remap_screen_after_menu_colors_change();
// Preview palette
if (Get_fileformat(context->Format)->Palette_only)
{
short index;
if (context->Type == CONTEXT_PREVIEW)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
Update_window_area(183,95,120,80);
}
break;
case CONTEXT_MAIN_IMAGE: case CONTEXT_MAIN_IMAGE:
case CONTEXT_BRUSH: case CONTEXT_BRUSH:
case CONTEXT_SURFACE: case CONTEXT_SURFACE:
@ -336,17 +270,17 @@ void Set_pixel_24b(T_IO_Context *context, short x_pos, short y_pos, byte r, byte
break; break;
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
{
if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0)) if (((x_pos % context->Preview_factor_X)==0) && ((y_pos % context->Preview_factor_Y)==0))
{ {
color=((r >> 5) << 5) | color=((r >> 5) << 5) |
((g >> 5) << 2) | ((g >> 5) << 2) |
((b >> 6)); ((b >> 6));
Pixel(context->Preview_pos_X+(x_pos/context->Preview_factor_X),
context->Preview_pos_Y+(y_pos/context->Preview_factor_Y), // Tag the color as 'used'
color); context->Preview_usage[color]=1;
}
context->Preview_bitmap[x_pos/context->Preview_factor_X + (y_pos/context->Preview_factor_Y)*PREVIEW_WIDTH*Menu_factor_X]=color;
} }
break; break;
} }
@ -388,6 +322,11 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
// Preview // Preview
case CONTEXT_PREVIEW: case CONTEXT_PREVIEW:
// Préparation du chargement d'une preview: // Préparation du chargement d'une preview:
context->Preview_bitmap=malloc(PREVIEW_WIDTH*PREVIEW_HEIGHT*Menu_factor_X*Menu_factor_Y);
if (!context->Preview_bitmap)
File_error=1;
// Affichage des données "Image size:" // Affichage des données "Image size:"
if ((width<10000) && (height<10000)) if ((width<10000) && (height<10000))
{ {
@ -443,8 +382,8 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
Pixel_ratio != PIXEL_TALL2) Pixel_ratio != PIXEL_TALL2)
height*=2; height*=2;
context->Preview_factor_X=Round_div_max(width,122*Menu_factor_X); context->Preview_factor_X=Round_div_max(width,120*Menu_factor_X);
context->Preview_factor_Y=Round_div_max(height, 82*Menu_factor_Y); context->Preview_factor_Y=Round_div_max(height, 80*Menu_factor_Y);
if ( (!Config.Maximize_preview) && (context->Preview_factor_X!=context->Preview_factor_Y) ) if ( (!Config.Maximize_preview) && (context->Preview_factor_X!=context->Preview_factor_Y) )
{ {
@ -458,12 +397,12 @@ void Pre_load(T_IO_Context *context, short width, short height, long file_size,
context->Preview_pos_Y=Window_pos_Y+ 95*Menu_factor_Y; context->Preview_pos_Y=Window_pos_Y+ 95*Menu_factor_Y;
// On nettoie la zone où va s'afficher la preview: // On nettoie la zone où va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light); Window_rectangle(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT,MC_Light);
// Un update pour couvrir les 4 zones: 3 libellés plus le commentaire // Un update pour couvrir les 4 zones: 3 libellés plus le commentaire
Update_window_area(45,48,256,30); Update_window_area(45,48,256,30);
// Zone de preview // Zone de preview
Update_window_area(183,95,120,80); Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
break; break;
// Other loading // Other loading
@ -838,6 +777,75 @@ void Load_image(T_IO_Context *context)
SDL_SetColors(context->Surface, colors, 0, 256); SDL_SetColors(context->Surface, colors, 0, 256);
} }
} }
else if (context->Type == CONTEXT_PREVIEW
/*&& !context->Buffer_image_24b*/
/*&& !Get_fileformat(context->Format)->Palette_only*/)
{
// Try to adapt the palette to accomodate the GUI.
int c;
int count_unused;
byte unused_color[4];
count_unused=0;
// Try find 4 unused colors and insert good colors there
for (c=255; c>=0 && count_unused<4; c--)
{
if (!context->Preview_usage[c])
{
unused_color[count_unused]=c;
count_unused++;
}
}
// Found! replace them with some favorites
if (count_unused==4)
{
int gui_index;
for (gui_index=0; gui_index<4; gui_index++)
{
context->Palette[unused_color[gui_index]]=*Favorite_GUI_color(gui_index);
}
}
// All preview display is here
// Update palette and screen first
Compute_optimal_menu_colors(context->Palette);
Remap_screen_after_menu_colors_change();
Set_palette(context->Palette);
// Display palette preview
if (Get_fileformat(context->Format)->Palette_only)
{
short index;
if (context->Type == CONTEXT_PREVIEW)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
}
// Display normal image
else if (context->Preview_bitmap)
{
int x_pos,y_pos;
for (y_pos=0; y_pos<context->Height/context->Preview_factor_Y;y_pos++)
for (x_pos=0; x_pos<context->Width/context->Preview_factor_X;x_pos++)
{
byte color=context->Preview_bitmap[x_pos+y_pos*PREVIEW_WIDTH*Menu_factor_X];
// Skip transparent if image has transparent background.
if (color == context->Transparent_color && context->Background_transparent)
color=MC_Window;
Pixel(context->Preview_pos_X+x_pos,
context->Preview_pos_Y+y_pos,
color);
}
}
// Refresh modified part
Update_window_area(183,95,PREVIEW_WIDTH,PREVIEW_HEIGHT);
}
} }
@ -1057,11 +1065,12 @@ byte Get_pixel(T_IO_Context *context, short x, short y)
return *(context->Target_address + y*context->Pitch + x); return *(context->Target_address + y*context->Pitch + x);
} }
/// Cleans up resources (currently: the 24bit buffer) /// Cleans up resources
void Destroy_context(T_IO_Context *context) void Destroy_context(T_IO_Context *context)
{ {
free(context->Buffer_image_24b); free(context->Buffer_image_24b);
free(context->Buffer_image); free(context->Buffer_image);
free(context->Preview_bitmap);
memset(context, 0, sizeof(T_IO_Context)); memset(context, 0, sizeof(T_IO_Context));
} }

View File

@ -98,12 +98,17 @@ typedef struct
short Preview_factor_Y; short Preview_factor_Y;
short Preview_pos_X; short Preview_pos_X;
short Preview_pos_Y; short Preview_pos_Y;
byte *Preview_bitmap;
byte Preview_usage[256];
// Internal: returned surface for SDL_Surface case // Internal: returned surface for SDL_Surface case
SDL_Surface * Surface; SDL_Surface * Surface;
} T_IO_Context; } T_IO_Context;
#define PREVIEW_WIDTH 120
#define PREVIEW_HEIGHT 80
/// Type of a function that can be called for a T_IO_Context. Kind of a method. /// Type of a function that can be called for a T_IO_Context. Kind of a method.
typedef void (* Func_IO) (T_IO_Context *); typedef void (* Func_IO) (T_IO_Context *);

View File

@ -396,13 +396,6 @@ void Set_nice_menu_colors(dword * color_usage,int not_picture)
byte color; byte color;
byte replace_table[256]; byte replace_table[256];
T_Components rgb[4]; T_Components rgb[4];
const T_Components * target_rgb[4];
const T_Components cpc_colors[4] = {
{ 0, 0, 0},
{128,128,128}, // Grey
{ 0,255,128}, // Soft light green
{255,255,255}
};
short new_colors[4]={255,254,253,252}; short new_colors[4]={255,254,253,252};
// On initialise la table de remplacement // On initialise la table de remplacement
@ -437,27 +430,20 @@ void Set_nice_menu_colors(dword * color_usage,int not_picture)
} }
} while (color); } while (color);
if (RGB_scale==3)
// Specialized colors for CPC palette
for (index=0; index<4; index++)
target_rgb[index] = &cpc_colors[index];
else
// Should be Config.Fav_menu_colors[index] if using user colors
for (index=0; index<4; index++)
target_rgb[index]=&(Gfx->Default_palette[Gfx->Color[index]]);
// On sauvegarde dans rgb les teintes qu'on va remplacer et on met les // On sauvegarde dans rgb les teintes qu'on va remplacer et on met les
// couleurs du menu par défaut // couleurs du menu par défaut
for (index=0; index<4; index++) for (index=0; index<4; index++)
{ {
const T_Components * target_rgb;
target_rgb=Favorite_GUI_color(index);
color=new_colors[index]; color=new_colors[index];
rgb[index].R=Main_palette[color].R; rgb[index].R=Main_palette[color].R;
rgb[index].G=Main_palette[color].G; rgb[index].G=Main_palette[color].G;
rgb[index].B=Main_palette[color].B; rgb[index].B=Main_palette[color].B;
// Should be Config.Fav_menu_colors[index] if using user colors Main_palette[color].R=Round_palette_component(target_rgb->R);
Main_palette[color].R=Round_palette_component(target_rgb[index]->R); Main_palette[color].G=Round_palette_component(target_rgb->G);
Main_palette[color].G=Round_palette_component(target_rgb[index]->G); Main_palette[color].B=Round_palette_component(target_rgb->B);
Main_palette[color].B=Round_palette_component(target_rgb[index]->B);
} }
// Maintenant qu'on a placé notre nouvelle palette, on va chercher quelles // Maintenant qu'on a placé notre nouvelle palette, on va chercher quelles
@ -2852,3 +2838,21 @@ int Get_clipboard_colors(T_Palette palette, byte start_color)
memcpy(palette+start_color, Palette_clipboard, nb_colors*sizeof(T_Components)); memcpy(palette+start_color, Palette_clipboard, nb_colors*sizeof(T_Components));
return nb_colors; return nb_colors;
} }
/// Get the favorite color to use for GUI's black,dark,light or white.
const T_Components * Favorite_GUI_color(byte color_index)
{
static const T_Components cpc_colors[4] = {
{ 0, 0, 0},
{128,128,128}, // Grey
{ 0,255,128}, // Soft light green
{255,255,255}
};
if (RGB_scale==3)
// Specialized colors for CPC palette
return &cpc_colors[color_index];
else
// Should be Config.Fav_menu_colors[index] if using user colors
return &(Gfx->Default_palette[Gfx->Color[color_index]]);
}

View File

@ -55,3 +55,6 @@ void Set_clipboard_colors(int nb_colors, T_Components *colors);
/// @param start_color Index of first color to replace /// @param start_color Index of first color to replace
/// @return Number of colors retrieved (0-256) /// @return Number of colors retrieved (0-256)
int Get_clipboard_colors(T_Palette palette, byte start_color); int Get_clipboard_colors(T_Palette palette, byte start_color);
/// Get the favorite color to use for GUI's black,dark,light or white.
const T_Components * Favorite_GUI_color(byte color_index);