More efficiently store Animated GIFs
Do not store the whole canvas for additional images
This commit is contained in:
parent
5c932dd2d9
commit
9f3af34968
@ -3191,6 +3191,7 @@ void Save_GIF(T_IO_Context * context)
|
||||
{
|
||||
// Write a Graphic Control Extension
|
||||
T_GIF_GCE GCE;
|
||||
byte disposal_method;
|
||||
|
||||
Set_saving_layer(context, current_layer);
|
||||
|
||||
@ -3202,17 +3203,22 @@ void Save_GIF(T_IO_Context * context)
|
||||
{
|
||||
// Animation frame
|
||||
int duration;
|
||||
GCE.Packed_fields=(2<<2)|(context->Background_transparent);
|
||||
if(context->Background_transparent)
|
||||
disposal_method = DISPOSAL_METHOD_RESTORE_BGCOLOR;
|
||||
else
|
||||
disposal_method = DISPOSAL_METHOD_DO_NOT_DISPOSE;
|
||||
GCE.Packed_fields=(disposal_method<<2)|(context->Background_transparent);
|
||||
duration=Get_frame_duration(context)/10;
|
||||
GCE.Delay_time=duration<0xFFFF?duration:0xFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Layered image
|
||||
disposal_method = DISPOSAL_METHOD_DO_NOT_DISPOSE;
|
||||
if (current_layer==0)
|
||||
GCE.Packed_fields=(1<<2)|(context->Background_transparent);
|
||||
GCE.Packed_fields=(disposal_method<<2)|(context->Background_transparent);
|
||||
else
|
||||
GCE.Packed_fields=(1<<2)|(1);
|
||||
GCE.Packed_fields=(disposal_method<<2)|(1);
|
||||
GCE.Delay_time=5; // Duration 5/100s (minimum viable value for current web browsers)
|
||||
if (current_layer == context->Nb_layers -1)
|
||||
GCE.Delay_time=0xFFFF; // Infinity (10 minutes)
|
||||
@ -3229,11 +3235,51 @@ void Save_GIF(T_IO_Context * context)
|
||||
&& Write_byte(GIF_file,GCE.Block_terminator)
|
||||
)
|
||||
{
|
||||
// first look for the maximum pixel value
|
||||
// to decide how many bit per pixel are needed.
|
||||
byte temp, max = 0;
|
||||
|
||||
IDB.Pos_X=0;
|
||||
IDB.Pos_Y=0;
|
||||
IDB.Image_width=context->Width;
|
||||
IDB.Image_height=context->Height;
|
||||
if(current_layer > 0)
|
||||
{
|
||||
word min_X, max_X, min_Y, max_Y;
|
||||
// find bounding box of changes for Animated GIFs
|
||||
min_X = min_Y = 0xffff;
|
||||
max_X = max_Y = 0;
|
||||
temp = LSDB.Backcol;//=context->Transparent_color;
|
||||
for(GIF_pos_Y = 0; GIF_pos_Y < context->Height; GIF_pos_Y++) {
|
||||
for(GIF_pos_X = 0; GIF_pos_X < context->Width; GIF_pos_X++) {
|
||||
// compare Pixel from previous layer or from background depending on disposal method
|
||||
if(disposal_method == DISPOSAL_METHOD_DO_NOT_DISPOSE)
|
||||
temp = Main.backups->Pages->Image[current_layer - 1].Pixels[GIF_pos_Y * context->Pitch + GIF_pos_X];
|
||||
if(temp != Get_pixel(context, GIF_pos_X, GIF_pos_Y)) {
|
||||
if(GIF_pos_X < min_X) min_X = GIF_pos_X;
|
||||
if(GIF_pos_X > max_X) max_X = GIF_pos_X;
|
||||
if(GIF_pos_Y < min_Y) min_Y = GIF_pos_Y;
|
||||
if(GIF_pos_Y > max_Y) max_Y = GIF_pos_Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if((min_X <= max_X) && (min_Y <= max_Y))
|
||||
{
|
||||
IDB.Pos_X = min_X;
|
||||
IDB.Pos_Y = min_Y;
|
||||
IDB.Image_width = max_X + 1 - min_X;
|
||||
IDB.Image_height = max_Y + 1 - min_Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if no pixel changes, store a 1 pixel image
|
||||
IDB.Image_width = 1;
|
||||
IDB.Image_height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// look for the maximum pixel value
|
||||
// to decide how many bit per pixel are needed.
|
||||
for(GIF_pos_Y = IDB.Pos_Y; GIF_pos_Y < IDB.Image_height + IDB.Pos_Y; GIF_pos_Y++) {
|
||||
for(GIF_pos_X = IDB.Pos_X; GIF_pos_X < IDB.Image_width + IDB.Pos_X; GIF_pos_X++) {
|
||||
temp=Get_pixel(context, GIF_pos_X, GIF_pos_Y);
|
||||
if(temp > max) max = temp;
|
||||
}
|
||||
@ -3245,10 +3291,6 @@ void Save_GIF(T_IO_Context * context)
|
||||
|
||||
// On va écrire un block indicateur d'IDB et l'IDB du fichier
|
||||
block_identifier=0x2C;
|
||||
IDB.Pos_X=0;
|
||||
IDB.Pos_Y=0;
|
||||
IDB.Image_width=context->Width;
|
||||
IDB.Image_height=context->Height;
|
||||
IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale.
|
||||
clear = 1 << IDB.Nb_bits_pixel; // Clear Code
|
||||
eof = clear + 1; // End of Picture Code
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user