Doxygen for GIF.

add Extension documentations, etc.
This commit is contained in:
Thomas Bernard 2018-12-11 12:18:48 +01:00
parent 747dcacbad
commit 337129f760
No known key found for this signature in database
GPG Key ID: 0FF11B67A5C0863C

View File

@ -3851,38 +3851,56 @@ void Save_ICO(T_IO_Context * context)
//////////////////////////////////// GIF //////////////////////////////////// //////////////////////////////////// GIF ////////////////////////////////////
typedef struct /**
{ * @defgroup GIF GIF format
word Width; // Width of the complete image area * Graphics Interchange Format
word Height; // Height of the complete image area *
byte Resol; // Informations about the resolution (and other) * The GIF format uses LZW compression and stores indexed color pictures
byte Backcol; // Proposed background color * up to 256 colors. It has the ability to store several pictures in the same
byte Aspect; // Informations about aspect ratio (and other) * file : GrafX2 takes advantage of this feature for storing layered images
} T_GIF_LSDB; // Logical Screen Descriptor Block * and animations.
*
* GrafX2 implements GIF89a :
* https://www.w3.org/Graphics/GIF/spec-gif89a.txt
*
* @{
*/
/// Logical Screen Descriptor Block
typedef struct typedef struct
{ {
word Pos_X; // X offset where the image should be pasted word Width; ///< Width of the complete image area
word Pos_Y; // Y offset where the image should be pasted word Height; ///< Height of the complete image area
word Image_width; // Width of image byte Resol; ///< Informations about the resolution (and other)
word Image_height; // Height of image byte Backcol; ///< Proposed background color
byte Indicator; // Misc image information byte Aspect; ///< Informations about aspect ratio. Ratio = (Aspect + 15) / 64
byte Nb_bits_pixel; // Nb de bits par pixel } T_GIF_LSDB;
} T_GIF_IDB; // Image Descriptor Block
/// Image Descriptor Block
typedef struct typedef struct
{ {
byte Block_identifier; // 0x21 word Pos_X; ///< X offset where the image should be pasted
byte Function; // 0xF9 word Pos_Y; ///< Y offset where the image should be pasted
byte Block_size; // 4 word Image_width; ///< Width of image
byte Packed_fields; // 11100000 : Reserved word Image_height; ///< Height of image
// 00011100 : Disposal method byte Indicator; ///< Misc image information
// 00000010 : User input flag byte Nb_bits_pixel; ///< Nb de bits par pixel
// 00000001 : Transparent flag } T_GIF_IDB;
word Delay_time; // Time for this frame to stay displayed
byte Transparent_color; // Which color index acts as transparent /// Graphic Control Extension
word Block_terminator; // 0x00 typedef struct
} T_GIF_GCE; // Graphic Control Extension {
byte Block_identifier; ///< 0x21
byte Function; ///< 0xF9
byte Block_size; ///< 4
byte Packed_fields; ///< 11100000 : Reserved
///< 00011100 : Disposal method
///< 00000010 : User input flag
///< 00000001 : Transparent flag
word Delay_time; ///< Time for this frame to stay displayed
byte Transparent_color; ///< Which color index acts as transparent
word Block_terminator; ///< 0x00
} T_GIF_GCE;
enum DISPOSAL_METHOD enum DISPOSAL_METHOD
{ {
@ -3892,8 +3910,9 @@ enum DISPOSAL_METHOD
DISPOSAL_METHOD_RESTORE_PREVIOUS = 3, DISPOSAL_METHOD_RESTORE_PREVIOUS = 3,
}; };
// -- Tester si un fichier est au format GIF --------------------------------
/// @ingroup loadsaveformats GIF
/// Test if a file is GIF format
void Test_GIF(T_IO_Context * context, FILE * file) void Test_GIF(T_IO_Context * context, FILE * file)
{ {
char signature[6]; char signature[6];
@ -3903,6 +3922,7 @@ void Test_GIF(T_IO_Context * context, FILE * file)
if (Read_bytes(file,signature,6)) if (Read_bytes(file,signature,6))
{ {
/// checks if the signature (6 first bytes) is either GIF87a or GIF89a
if ((!memcmp(signature,"GIF87a",6))||(!memcmp(signature,"GIF89a",6))) if ((!memcmp(signature,"GIF87a",6))||(!memcmp(signature,"GIF89a",6)))
File_error=0; File_error=0;
} }
@ -3911,6 +3931,7 @@ void Test_GIF(T_IO_Context * context, FILE * file)
// -- Lire un fichier au format GIF ----------------------------------------- // -- Lire un fichier au format GIF -----------------------------------------
/// @todo avoid using global variables, define a "GIF context" instead
// Définition de quelques variables globales au chargement du GIF87a // Définition de quelques variables globales au chargement du GIF87a
word GIF_nb_bits; // Nb de bits composants un code complet word GIF_nb_bits; // Nb de bits composants un code complet
word GIF_remainder_bits; // Nb de bits encore dispos dans GIF_last_byte word GIF_remainder_bits; // Nb de bits encore dispos dans GIF_last_byte
@ -3924,9 +3945,8 @@ word GIF_finished_interlaced_image; // L'image entrelacée est finie de charger
word GIF_pass; // index de passe de l'image entrelacée word GIF_pass; // index de passe de l'image entrelacée
FILE *GIF_file; // L'handle du fichier FILE *GIF_file; // L'handle du fichier
// -- Lit le code à GIF_nb_bits suivant -- /// Reads the next code (GIF_nb_bits bits)
static word GIF_get_next_code(void)
word GIF_get_next_code(void)
{ {
word nb_bits_to_process=GIF_nb_bits; word nb_bits_to_process=GIF_nb_bits;
word nb_bits_processed =0; word nb_bits_processed =0;
@ -3964,12 +3984,11 @@ word GIF_get_next_code(void)
return GIF_current_code; return GIF_current_code;
} }
// -- Affiche un nouveau pixel -- /// Put a new pixel
static void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, int is_transparent, byte color)
void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, int is_transparent, byte color)
{ {
if (!is_transparent || color!=context->Transparent_color) if (!is_transparent || color!=context->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++; GIF_pos_X++;
@ -4010,6 +4029,8 @@ void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, int is_transparent, b
} }
/// @ingroup loadsaveformats GIF
/// Load GIF file
void Load_GIF(T_IO_Context * context) void Load_GIF(T_IO_Context * context)
{ {
int image_mode = -1; int image_mode = -1;
@ -4531,9 +4552,8 @@ void Load_GIF(T_IO_Context * context)
int GIF_stop; // "On peut arrêter la sauvegarde du fichier" int GIF_stop; // "On peut arrêter la sauvegarde du fichier"
byte GIF_buffer[256]; // buffer d'écriture de bloc de données compilées byte GIF_buffer[256]; // buffer d'écriture de bloc de données compilées
// -- Vider le buffer GIF dans le buffer KM -- /// Flush ::GIF_buffer
static void GIF_empty_buffer(void)
void GIF_empty_buffer(void)
{ {
word index; word index;
@ -4548,9 +4568,8 @@ void Load_GIF(T_IO_Context * context)
} }
} }
// -- Ecrit un code à GIF_nb_bits -- /// Write a code (GIF_nb_bits bits)
static void GIF_set_code(word Code)
void GIF_set_code(word Code)
{ {
word nb_bits_to_process=GIF_nb_bits; word nb_bits_to_process=GIF_nb_bits;
word nb_bits_processed =0; word nb_bits_processed =0;
@ -4583,9 +4602,8 @@ void Load_GIF(T_IO_Context * context)
} }
// -- Lire le pixel suivant -- /// Read the next pixel
static byte GIF_next_pixel(T_IO_Context *context, T_GIF_IDB *idb)
byte GIF_next_pixel(T_IO_Context *context, T_GIF_IDB *idb)
{ {
byte temp; byte temp;
@ -4602,7 +4620,8 @@ void Load_GIF(T_IO_Context * context)
} }
/// @ingroup loadsaveformats GIF
/// Save a GIF file
void Save_GIF(T_IO_Context * context) void Save_GIF(T_IO_Context * context)
{ {
word * alphabet_prefix; // Table des préfixes des codes word * alphabet_prefix; // Table des préfixes des codes
@ -4704,13 +4723,18 @@ void Save_GIF(T_IO_Context * context)
{ {
// La palette a été correctement écrite. // La palette a été correctement écrite.
// Ecriture de la transparence /// - "Netscape" animation extension :
//Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8); /// <pre>
/// 0x21 Extension Label
// "Netscape" animation extension /// 0xFF Application Extension Label
// Write_bytes(GIF_file,"\x21\xFF\x0BNETSCAPE2.0\x03\xLL\xSS\xSS\x00",19); /// 0x0B Block Size
// LL : 01 to loop /// "NETSCAPE" Application Identifier (8 bytes)
// SSSS : number of loops /// "2.0" Application Authentication Code (3 bytes)
/// 0x03 Sub-block Data Size
/// 0xLL 01 to loop
/// 0xSSSS (little endian) number of loops, 0 means infinite loop
/// 0x00 Block terminator </pre>
/// see http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension
if (context->Type == CONTEXT_MAIN_IMAGE && Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION) if (context->Type == CONTEXT_MAIN_IMAGE && Main.backups->Pages->Image_mode == IMAGE_MODE_ANIMATION)
{ {
if (context->Nb_layers>1) if (context->Nb_layers>1)
@ -4718,16 +4742,30 @@ void Save_GIF(T_IO_Context * context)
} }
else if (context->Type == CONTEXT_MAIN_IMAGE && Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION) else if (context->Type == CONTEXT_MAIN_IMAGE && Main.backups->Pages->Image_mode > IMAGE_MODE_ANIMATION)
{ {
/// - GrafX2 extension to store ::IMAGE_MODES :
/// <pre>
/// 0x21 Extension Label
/// 0xFF Application Extension Label
/// 0x0B Block Size
/// "GFX2MODE" Application Identifier (8 bytes)
/// "2.6" Application Authentication Code (3 bytes)
/// 0xll Sub-block Data Size
/// string label
/// 0x00 Block terminator </pre>
/// @see Constraint_mode_label()
const char * label = Constraint_mode_label(Main.backups->Pages->Image_mode); const char * label = Constraint_mode_label(Main.backups->Pages->Image_mode);
size_t len = strlen(label); if (label != NULL)
// Write extension for storing IMAGE_MODE {
Write_byte(GIF_file,0x21); // Extension Introducer size_t len = strlen(label);
Write_byte(GIF_file,0xff); // Extension Label // Write extension for storing IMAGE_MODE
Write_byte(GIF_file, 11); // Block size Write_byte(GIF_file,0x21); // Extension Introducer
Write_bytes(GIF_file, "GFX2MODE2.6", 11); // Application Identifier + Appl. Authentication Code Write_byte(GIF_file,0xff); // Extension Label
Write_byte(GIF_file, (byte)len); // Block size Write_byte(GIF_file, 11); // Block size
Write_bytes(GIF_file, label, len); // Data Write_bytes(GIF_file, "GFX2MODE2.6", 11); // Application Identifier + Appl. Authentication Code
Write_byte(GIF_file, 0); // Block terminator Write_byte(GIF_file, (byte)len); // Block size
Write_bytes(GIF_file, label, len); // Data
Write_byte(GIF_file, 0); // Block terminator
}
} }
// Ecriture du commentaire // Ecriture du commentaire
@ -4737,7 +4775,20 @@ void Save_GIF(T_IO_Context * context)
Write_byte(GIF_file,strlen(context->Comment)); Write_byte(GIF_file,strlen(context->Comment));
Write_bytes(GIF_file,context->Comment,strlen(context->Comment)+1); Write_bytes(GIF_file,context->Comment,strlen(context->Comment)+1);
} }
// Write cycling colors /// - "CRNG" Color cycing extension :
/// <pre>
/// 0x21 Extension Label
/// 0xFF Application Extension Label
/// 0x0B Block Size
/// "CRNG\0\0\0\0" "CRNG" Application Identifier (8 bytes)
/// "1.0" Application Authentication Code (3 bytes)
/// 0xll Sub-block Data Size (6 bytes per color cycle)
/// For each color cycle :
/// 0xRRRR (big endian) Rate
/// 0xFFFF (big endian) Flags
/// 0xSS start (lower color index)
/// 0xEE end (higher color index)
/// 0x00 Block terminator </pre>
if (context->Color_cycles) if (context->Color_cycles)
{ {
int i; int i;
@ -5050,14 +5101,21 @@ void Save_GIF(T_IO_Context * context)
// After writing all layers // After writing all layers
if (!File_error) if (!File_error)
{ {
// If requested, write a specific extension for storing /// - If requested, write a specific extension for storing
// original file path. /// original file path.
// This is used by the backup system. /// This is used by the backup system.
// The format is : /// The format is :
// 21 FF 0B G F X 2 P A T H 00 00 00 /// <pre>
// <size of path (byte)> <null-terminated path> /// 0x21 Extension Label
// <size of filename (byte)> <null-terminated filename> /// 0xFF Application Extension Label
// 00 /// 0x0B Block Size
/// "GFX2PATH" "GFX2PATH" Application Identifier (8 bytes)
/// "\0\0\0" Application Authentication Code (3 bytes)
/// 0xll Sub-block Data Size : path size (including null)
/// "..path.." path (null-terminated)
/// 0xll Sub-block Data Size : filename size (including null)
/// "..file.." file name (null-terminated)
/// 0x00 Block terminator </pre>
if (context->Original_file_name != NULL if (context->Original_file_name != NULL
&& context->Original_file_directory != NULL) && context->Original_file_directory != NULL)
{ {
@ -5108,6 +5166,7 @@ void Save_GIF(T_IO_Context * context)
} }
/* @} */
//////////////////////////////////// PCX //////////////////////////////////// //////////////////////////////////// PCX ////////////////////////////////////