grafX2/loadsave.c
Adrien Destugues 1a2ac678e0 Splitted loadsave.c :
- loadsave.c : common things
- fileformats.c : format that make a full backup of any picture without palette loss
- miscfileformats.c : formats that are not saving all the picture (palette only, pixels only, constrained palette)

I was not very precise in the splitting and we may rethink the flags that mark if a picture is fully saved or not... it was not updated after we decided to allow the full palette range 0.255 instead of 0.63, so most of the atari format were marked as saving everything.


git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1120 416bcca6-2ee7-4201-b75f-2eb2f807beb1
2009-10-31 15:20:44 +00:00

923 lines
26 KiB
C
Raw Blame History

/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Petter Lindquist
Copyright 2008 Yves Rizoud
Copyright 2008 Franck Charlet
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; version 2
of the License.
Grafx2 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
*/
#define _XOPEN_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <SDL_image.h>
#include <SDL_endian.h>
#include "buttons.h"
#include "const.h"
#include "errors.h"
#include "global.h"
#include "io.h"
#include "loadsave.h"
#include "misc.h"
#include "op_c.h"
#include "pages.h"
#include "palette.h"
#include "sdlscreen.h"
#include "struct.h"
#include "windows.h"
#include "engine.h"
// -- PKM -------------------------------------------------------------------
void Test_PKM(void);
void Load_PKM(void);
void Save_PKM(void);
// -- LBM -------------------------------------------------------------------
void Test_LBM(void);
void Load_LBM(void);
void Save_LBM(void);
// -- GIF -------------------------------------------------------------------
void Test_GIF(void);
void Load_GIF(void);
void Save_GIF(void);
// -- PCX -------------------------------------------------------------------
void Test_PCX(void);
void Load_PCX(void);
void Save_PCX(void);
// -- BMP -------------------------------------------------------------------
void Test_BMP(void);
void Load_BMP(void);
void Save_BMP(void);
// -- IMG -------------------------------------------------------------------
void Test_IMG(void);
void Load_IMG(void);
void Save_IMG(void);
// -- SCx -------------------------------------------------------------------
void Test_SCx(void);
void Load_SCx(void);
void Save_SCx(void);
// -- CEL -------------------------------------------------------------------
void Test_CEL(void);
void Load_CEL(void);
void Save_CEL(void);
// -- KCF -------------------------------------------------------------------
void Test_KCF(void);
void Load_KCF(void);
void Save_KCF(void);
// -- PAL -------------------------------------------------------------------
void Test_PAL(void);
void Load_PAL(void);
void Save_PAL(void);
// -- PI1 -------------------------------------------------------------------
void Test_PI1(void);
void Load_PI1(void);
void Save_PI1(void);
// -- PC1 -------------------------------------------------------------------
void Test_PC1(void);
void Load_PC1(void);
void Save_PC1(void);
// -- NEO -------------------------------------------------------------------
void Test_NEO(void);
void Load_NEO(void);
void Save_NEO(void);
// -- C64 -------------------------------------------------------------------
void Test_C64(void);
void Load_C64(void);
void Save_C64(void);
// -- PNG -------------------------------------------------------------------
#ifndef __no_pnglib__
void Test_PNG(void);
void Load_PNG(void);
void Save_PNG(void);
#endif
// -- SDL_Image -------------------------------------------------------------
// (TGA, BMP, PNM, XPM, XCF, PCX, GIF, JPG, TIF, LBM, PNG, ICO)
void Load_SDL_Image(void);
void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio);
// ENUM Name TestFunc LoadFunc SaveFunc Backup Comment Ext Exts
T_Format File_formats[NB_KNOWN_FORMATS] = {
{FORMAT_ALL_IMAGES,"(all)",NULL, NULL, NULL, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
{FORMAT_ALL_FILES,"(*.*)",NULL, NULL, NULL, 0, 0, "", "*"},
{FORMAT_GIF, " gif", Test_GIF, Load_GIF, Save_GIF, 1, 1, "gif", "gif"},
#ifndef __no_pnglib__
{FORMAT_PNG, " png", Test_PNG, Load_PNG, Save_PNG, 1, 1, "png", "png"},
#endif
{FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 1, 0, "bmp", "bmp"},
{FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 1, 0, "pcx", "pcx"},
{FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, "pkm", "pkm"}, // Not a backup since it does not save the full palette
{FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0, "lbm", "lbm;iff"},
{FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 1, 0, "img", "img"},
{FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 1, 0, "sc?", "sci;scq;scf;scn;sco"},
{FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, "pi1", "pi1"},
{FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 0, 0, "pc1", "pc1"},
{FORMAT_CEL, " cel", Test_CEL, Load_CEL, Save_CEL, 1, 0, "cel", "cel"},
{FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 0, 0, "neo", "neo"},
{FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0, "kcf", "kcf"},
{FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 0, 0, "pal", "pal"},
{FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, "c64", "c64;koa"},
{FORMAT_MISC,"misc.", NULL, NULL, NULL, 1, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
};
// Cette variable est aliment<6E>e apr<70>s chargement r<>ussi d'une image.
// Actuellement seul le format PNG peut donner autre chose que PIXEL_SIMPLE.
enum PIXEL_RATIO Ratio_of_loaded_image=PIXEL_SIMPLE;
// Chargement des pixels dans l'<27>cran principal
void Pixel_load_in_current_screen(word x_pos,word y_pos,byte color)
{
//if ((x_pos>=0) && (y_pos>=0)) //Toujours vrai ?
if ((x_pos<Main_image_width) && (y_pos<Main_image_height))
Pixel_in_current_screen(x_pos,y_pos,color);
}
// Chargement des pixels dans la brosse
void Pixel_load_in_brush(word x_pos,word y_pos,byte color)
{
//if ((x_pos>=0) && (y_pos>=0))
if ((x_pos<Brush_width) && (y_pos<Brush_height))
Pixel_in_brush(x_pos,y_pos,color);
}
short Preview_factor_X;
short Preview_factor_Y;
short Preview_pos_X;
short Preview_pos_Y;
// Chargement des pixels dans la preview
void Pixel_load_in_preview(word x_pos,word y_pos,byte color)
{
if (((x_pos % Preview_factor_X)==0) && ((y_pos % Preview_factor_Y)==0))
if ((x_pos<Main_image_width) && (y_pos<Main_image_height))
{
if (Ratio_of_loaded_image == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2)
{
Pixel(Preview_pos_X+(x_pos/Preview_factor_X*2),
Preview_pos_Y+(y_pos/Preview_factor_Y),
color);
Pixel(Preview_pos_X+(x_pos/Preview_factor_X*2)+1,
Preview_pos_Y+(y_pos/Preview_factor_Y),
color);
}
else if (Ratio_of_loaded_image == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2)
{
Pixel(Preview_pos_X+(x_pos/Preview_factor_X),
Preview_pos_Y+(y_pos/Preview_factor_Y*2),
color);
Pixel(Preview_pos_X+(x_pos/Preview_factor_X),
Preview_pos_Y+(y_pos/Preview_factor_Y*2)+1,
color);
}
else
Pixel(Preview_pos_X+(x_pos/Preview_factor_X),
Preview_pos_Y+(y_pos/Preview_factor_Y),
color);
}
}
void Remap_fileselector(void)
{
if (Pixel_load_function==Pixel_load_in_preview)
{
Compute_optimal_menu_colors(Main_palette);
if(
(
Main_palette[MC_Black].R==Main_palette[MC_Dark].R &&
Main_palette[MC_Black].G==Main_palette[MC_Dark].G &&
Main_palette[MC_Black].B==Main_palette[MC_Dark].B
) ||
(
Main_palette[MC_Light].R==Main_palette[MC_Dark].R &&
Main_palette[MC_Light].G==Main_palette[MC_Dark].G &&
Main_palette[MC_Light].B==Main_palette[MC_Dark].B
) ||
(
Main_palette[MC_White].R==Main_palette[MC_Light].R &&
Main_palette[MC_White].G==Main_palette[MC_Light].G &&
Main_palette[MC_White].B==Main_palette[MC_Light].B
)
)
{
// Si on charge une image monochrome, le fileselect ne sera plus visible. Dans ce cas on force quelques couleurs <20> 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();
}
}
int Image_24b;
T_Components * Buffer_image_24b;
Func_24b_display Pixel_load_24b;
// Chargement des pixels dans le buffer 24b
void Pixel_load_in_24b_buffer(short x_pos,short y_pos,byte r,byte g,byte b)
{
int index;
if ((x_pos>=0) && (y_pos>=0))
if ((x_pos<Main_image_width) && (y_pos<Main_image_height))
{
index=(y_pos*Main_image_width)+x_pos;
Buffer_image_24b[index].R=r;
Buffer_image_24b[index].G=g;
Buffer_image_24b[index].B=b;
}
}
// Chargement des pixels dans la preview en 24b
void Pixel_load_in_24b_preview(short x_pos,short y_pos,byte r,byte g,byte b)
{
byte color;
if (((x_pos % Preview_factor_X)==0) && ((y_pos % Preview_factor_Y)==0))
if ((x_pos<Main_image_width) && (y_pos<Main_image_height))
{
color=((r >> 5) << 5) |
((g >> 5) << 2) |
((b >> 6));
Pixel(Preview_pos_X+(x_pos/Preview_factor_X),
Preview_pos_Y+(y_pos/Preview_factor_Y),
color);
}
}
// Cr<43>ation d'une palette fake
void Set_palette_fake_24b(T_Palette palette)
{
int color;
// G<>n<EFBFBD>ration de la palette
for (color=0;color<256;color++)
{
palette[color].R=((color & 0xE0)>>5)<<5;
palette[color].G=((color & 0x1C)>>2)<<5;
palette[color].B=((color & 0x03)>>0)<<6;
}
}
// Initialization for a 24bit image
void Init_preview_24b(short width,short height,long size,int format)
{
// Call common processing
Init_preview(width,height,size,format, PIXEL_SIMPLE);
if (File_error)
return;
if (Pixel_load_function==Pixel_load_in_preview)
{
// Choose 24bit pixel "writer"
Pixel_load_24b=Pixel_load_in_24b_preview;
// Load palette
Set_palette_fake_24b(Main_palette);
Set_palette(Main_palette);
Remap_fileselector();
}
else
{
// Choose 24bit pixel "writer"
Pixel_load_24b=Pixel_load_in_24b_buffer;
// Allocate 24bit buffer
Buffer_image_24b=
(T_Components *)Borrow_memory_from_page(width*height*sizeof(T_Components));
if (!Buffer_image_24b)
{
// Print an error message
// The following is to be sure the messagfe is readable
Compute_optimal_menu_colors(Main_palette);
Message_out_of_memory();
if (Pixel_load_function==Pixel_load_in_current_screen)
File_error=1; // 1 => On n'a pas perdu l'image courante
else
File_error=3; // 3 => Chargement de brosse <20>chou<6F>
}
else
Image_24b=1; // On a un buffer <20> traiter en fin de chargement
}
}
void Init_preview(short width,short height,long size,int format, enum PIXEL_RATIO ratio)
//
// Cette proc<6F>dure doit <20>tre appel<65>e par les routines de chargement
// d'images.
// Elle doit <20>tre appel<65>e entre le moment o<> l'on connait la dimension de
// l'image (dimension r<>elle, pas dimension tronqu<71>e) et l'affichage du
// premier point.
//
{
char str[10];
if (Pixel_load_function==Pixel_load_in_preview)
{
// Pr<50>paration du chargement d'une preview:
// Affichage des donn<6E>es "Image size:"
if ((width<10000) && (height<10000))
{
Num2str(width,str,4);
Num2str(height,str+5,4);
str[4]='x';
Print_in_window(143,59,str,MC_Black,MC_Light);
}
else
{
Print_in_window(143,59,"VERY BIG!",MC_Black,MC_Light);
}
// Affichage de la taille du fichier
if (size<1048576)
{
// Le fichier fait moins d'un Mega, on affiche sa taille direct
Num2str(size,str,7);
Print_in_window(236,59,str,MC_Black,MC_Light);
}
else if ((size/1024)<100000)
{
// Le fichier fait plus d'un Mega, on peut afficher sa taille en Ko
Num2str(size/1024,str,5);
strcpy(str+5,"Kb");
Print_in_window(236,59,str,MC_Black,MC_Light);
}
else
{
// Le fichier fait plus de 100 Mega octets (cas tr<74>s rare :))
Print_in_window(236,59,"LARGE!!",MC_Black,MC_Light);
}
// Affichage du vrai format
if (format!=Main_format)
{
Print_in_window( 59,59,Get_fileformat(format)->Label,MC_Black,MC_Light);
}
// On efface le commentaire pr<70>c<EFBFBD>dent
Window_rectangle(45,70,32*8,8,MC_Light);
// Affichage du commentaire
if (Get_fileformat(format)->Comment)
Print_in_window(45,70,Main_comment,MC_Black,MC_Light);
// Calculs des donn<6E>es n<>cessaires <20> l'affichage de la preview:
if (ratio == PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE &&
Pixel_ratio != PIXEL_WIDE2)
width*=2;
else if (ratio == PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL &&
Pixel_ratio != PIXEL_TALL2)
height*=2;
Preview_factor_X=Round_div_max(width,122*Menu_factor_X);
Preview_factor_Y=Round_div_max(height, 82*Menu_factor_Y);
if ( (!Config.Maximize_preview) && (Preview_factor_X!=Preview_factor_Y) )
{
if (Preview_factor_X>Preview_factor_Y)
Preview_factor_Y=Preview_factor_X;
else
Preview_factor_X=Preview_factor_Y;
}
Preview_pos_X=Window_pos_X+183*Menu_factor_X;
Preview_pos_Y=Window_pos_Y+ 95*Menu_factor_Y;
// On nettoie la zone o<> va s'afficher la preview:
Window_rectangle(183,95,120,80,MC_Light);
// Un update pour couvrir les 4 zones: 3 libell<6C>s plus le commentaire
Update_window_area(45,48,256,30);
// Zone de preview
Update_window_area(183,95,120,80);
}
else
{
if (Pixel_load_function==Pixel_load_in_current_screen)
{
if (Backup_with_new_dimensions(0,width,height))
{
// La nouvelle page a pu <20>tre allou<6F>e, elle est pour l'instant pleine
// de 0s. Elle fait Main_image_width de large.
// Normalement tout va bien, tout est sous contr<74>le...
}
else
{
// Afficher un message d'erreur
// Pour <20>tre s<>r que ce soit lisible.
Compute_optimal_menu_colors(Main_palette);
Message_out_of_memory();
File_error=1; // 1 => On n'a pas perdu l'image courante
}
}
else // chargement dans la brosse
{
free(Brush);
free(Smear_brush);
Brush=(byte *)malloc(width*height);
Brush_width=width;
Brush_height=height;
if (Brush)
{
Smear_brush=(byte *)malloc(width*height);
if (!Smear_brush)
File_error=3;
}
else
File_error=3;
}
}
}
void Draw_palette_preview(void)
{
short index;
if (Pixel_load_function==Pixel_load_in_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);
}
// Calcul du nom complet du fichier
void Get_full_filename(char * filename, byte is_colorix_format)
{
byte last_char;
strcpy(filename,Main_file_directory);
//On va ajouter un s<>parateur <20> la fin du chemin s'il n'y est pas encore
if (filename[strlen(filename)-1]!=PATH_SEPARATOR[0])
strcat(filename,PATH_SEPARATOR);
// Si on est en train de sauvegarder une image Colorix, on calcule son ext.
if (is_colorix_format)
{
last_char=strlen(Main_filename)-1;
if (Main_filename[last_char]=='?')
{
if (Main_image_width<=320)
Main_filename[last_char]='I';
else
{
if (Main_image_width<=360)
Main_filename[last_char]='Q';
else
{
if (Main_image_width<=640)
Main_filename[last_char]='F';
else
{
if (Main_image_width<=800)
Main_filename[last_char]='N';
else
Main_filename[last_char]='O';
}
}
}
}
}
strcat(filename,Main_filename);
}
/////////////////////////////////////////////////////////////////////////////
// Gestion des lectures et <20>critures //
/////////////////////////////////////////////////////////////////////////////
byte * Write_buffer;
word Write_buffer_index;
void Init_write_buffer(void)
{
Write_buffer=(byte *)malloc(64000);
Write_buffer_index=0;
}
void Write_one_byte(FILE *file, byte b)
{
Write_buffer[Write_buffer_index++]=b;
if (Write_buffer_index>=64000)
{
if (! Write_bytes(file,Write_buffer,64000))
File_error=1;
Write_buffer_index=0;
}
}
void End_write(FILE *file)
{
if (Write_buffer_index)
if (! Write_bytes(file,Write_buffer,Write_buffer_index))
File_error=1;
free(Write_buffer);
}
/////////////////////////////////////////////////////////////////////////////
// -------- Modifier la valeur du code d'erreur d'acc<63>s <20> un fichier --------
// On n'est pas oblig<69> d'utiliser cette fonction <20> chaque fois mais il est
// important de l'utiliser dans les cas du type:
// if (!File_error) *** else File_error=***;
// En fait, dans le cas o<> l'on modifie File_error alors qu'elle contient
// d<>j<EFBFBD> un code d'erreur.
void Set_file_error(int value)
{
if (File_error>=0)
File_error=value;
}
// -- Charger n'importe connu quel type de fichier d'image (ou palette) -----
void Load_image(byte image)
{
unsigned int index; // index de balayage des formats
T_Format *format = &(File_formats[2]); // Format du fichier <20> charger
// On place par d<>faut File_error <20> vrai au cas o<> on ne sache pas
// charger le format du fichier:
File_error=1;
if (Main_format>FORMAT_ALL_FILES)
{
format = Get_fileformat(Main_format);
if (format->Test)
format->Test();
}
if (File_error)
{
// Sinon, on va devoir scanner les diff<66>rents formats qu'on connait pour
// savoir <20> quel format est le fichier:
for (index=0; index < NB_KNOWN_FORMATS; index++)
{
format = Get_fileformat(index);
// Loadable format
if (format->Test == NULL)
continue;
// On appelle le testeur du format:
format->Test();
// On s'arr<72>te si le fichier est au bon format:
if (File_error==0)
break;
}
}
if (File_error)
{
// Last try: with SDL_image
Image_24b=0;
Ratio_of_loaded_image=PIXEL_SIMPLE;
Load_SDL_Image();
if (File_error)
{
// Sinon, l'appelant sera au courant de l'<27>chec grace <20> File_error;
// et si on s'appr<70>tait <20> faire un chargement d<>finitif de l'image (pas
// une preview), alors on flash l'utilisateur.
if (Pixel_load_function!=Pixel_load_in_preview)
Error(0);
return;
}
}
else
// Si on a su d<>terminer avec succ<63>s le format du fichier:
{
// On peut charger le fichier:
Image_24b=0;
Ratio_of_loaded_image=PIXEL_SIMPLE;
// Dans certains cas il est possible que le chargement plante
// apr<70>s avoir modifi<66> la palette. TODO
format->Load();
}
if (File_error>0)
{
Error(0);
}
if (Image_24b)
{
// On vient de charger une image 24b
if (!File_error)
{
// Le chargement a r<>ussi, on peut faire la conversion en 256 couleurs
if (Pixel_load_function==Pixel_load_in_current_screen)
{
// Cas d'un chargement dans l'image
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Flush_update();
if (Convert_24b_bitmap_to_256(Main_screen,Buffer_image_24b,Main_image_width,Main_image_height,Main_palette))
File_error=2;
else
{
Set_palette(Main_palette);
}
}
else
{
// Cas d'un chargement dans la brosse
Hide_cursor();
Cursor_shape=CURSOR_SHAPE_HOURGLASS;
Display_cursor();
Flush_update();
if (Convert_24b_bitmap_to_256(Brush,Buffer_image_24b,Brush_width,Brush_height,Main_palette))
File_error=2;
}
}
free(Buffer_image_24b);
}
if (image)
{
if ( (File_error!=1) && (format->Backup_done) )
{
if (Pixel_load_function==Pixel_load_in_preview)
{
dword color_usage[256];
Count_used_colors_screen_area(color_usage,Preview_pos_X,Preview_pos_Y,Main_image_width/Preview_factor_X,Main_image_height/Preview_factor_Y);
//Count_used_colors(color_usage);
Display_cursor();
Set_nice_menu_colors(color_usage,1);
Hide_cursor();
}
// On consid<69>re que l'image charg<72>e n'est plus modifi<66>e
Main_image_is_modified=0;
// Et on documente la variable Main_fileformat avec la valeur:
Main_fileformat=format->Identifier;
// Correction des dimensions
if (Main_image_width<1)
Main_image_width=1;
if (Main_image_height<1)
Main_image_height=1;
}
else if (File_error!=1)
{
// On consid<69>re que l'image charg<72>e est encore modifi<66>e
Main_image_is_modified=1;
// Et on documente la variable Main_fileformat avec la valeur:
Main_fileformat=format->Identifier;
}
else
{
// Dans ce cas, on sait que l'image n'a pas chang<6E>, mais ses
// param<61>tres (dimension, palette, ...) si. Donc on les restaures.
Download_infos_page_main(Main_backups->Pages);
}
}
}
// -- Sauver n'importe quel type connu de fichier d'image (ou palette) ------
void Save_image(byte image)
{
T_Format *format;
// On place par d<>faut File_error <20> vrai au cas o<> on ne sache pas
// sauver le format du fichier: (Est-ce vraiment utile??? Je ne crois pas!)
File_error=1;
Read_pixel_function=(image)?Read_pixel_from_current_screen:Read_pixel_from_brush;
format = Get_fileformat(Main_fileformat);
if (format->Save)
format->Save();
if (File_error)
Error(0);
else
{
if ((image) && (Get_fileformat(Main_fileformat)->Backup_done))
Main_image_is_modified=0;
}
}
void Load_SDL_Image(void)
{
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
word x_pos,y_pos;
// long file_size;
dword pixel;
long file_size;
SDL_Surface * surface;
Get_full_filename(filename,0);
File_error=0;
surface = IMG_Load(filename);
if (!surface)
{
File_error=1;
return;
}
file_size=File_length(filename);
if (surface->format->BytesPerPixel == 1)
{
// 8bpp image
Init_preview(surface->w, surface->h, file_size ,FORMAT_MISC, PIXEL_SIMPLE);
// Read palette
if (surface->format->palette)
{
Get_SDL_Palette(surface->format->palette, Main_palette);
Set_palette(Main_palette);
Remap_fileselector();
}
Main_image_width=surface->w;
Main_image_height=surface->h;
for (y_pos=0; y_pos<Main_image_height; y_pos++)
{
for (x_pos=0; x_pos<Main_image_width; x_pos++)
{
Pixel_load_function(x_pos,y_pos,Get_SDL_pixel_8(surface, x_pos, y_pos));
}
}
}
else
{
// Hi/Trucolor
Init_preview_24b(surface->w, surface->h, file_size ,FORMAT_ALL_IMAGES);
Main_image_width=surface->w;
Main_image_height=surface->h;
for (y_pos=0; y_pos<Main_image_height; y_pos++)
{
for (x_pos=0; x_pos<Main_image_width; x_pos++)
{
pixel = Get_SDL_pixel_hicolor(surface, x_pos, y_pos);
Pixel_load_24b(
x_pos,
y_pos,
((pixel & surface->format->Rmask) >> surface->format->Rshift) << surface->format->Rloss,
((pixel & surface->format->Gmask) >> surface->format->Gshift) << surface->format->Gloss,
((pixel & surface->format->Bmask) >> surface->format->Bshift) << surface->format->Bloss);
}
}
}
SDL_FreeSurface(surface);
}
/// Saves an image.
/// This routine will only be called when all hope is lost, memory thrashed, etc
/// It's the last chance to save anything, but the code has to be extremely
/// careful, anything could happen.
/// The chosen format is IMG since it's extremely simple, difficult to make it
/// create an unusable image.
void Emergency_backup(const char *fname, byte *source, int width, int height, T_Palette *palette)
{
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
FILE *file;
short x_pos,y_pos;
T_IMG_Header IMG_header;
strcpy(filename,Config_directory);
strcat(filename,fname);
// Ouverture du fichier
file=fopen(filename,"wb");
if (!file)
return;
memcpy(IMG_header.Filler1,"\x01\x00\x47\x12\x6D\xB0",6);
memset(IMG_header.Filler2,0,118);
IMG_header.Filler2[4]=0xFF;
IMG_header.Filler2[22]=64; // Lo(Longueur de la signature)
IMG_header.Filler2[23]=0; // Hi(Longueur de la signature)
memcpy(IMG_header.Filler2+23,"GRAFX2 by SunsetDesign (IMG format taken from PV (c)W.Wiedmann)",64);
if (!Write_bytes(file,IMG_header.Filler1,6) ||
!Write_word_le(file,width) ||
!Write_word_le(file,height) ||
!Write_bytes(file,IMG_header.Filler2,118) ||
!Write_bytes(file,palette,sizeof(T_Palette)))
{
fclose(file);
return;
}
for (y_pos=0; ((y_pos<height) && (!File_error)); y_pos++)
for (x_pos=0; x_pos<width; x_pos++)
if (!Write_byte(file,*(source+y_pos*width+x_pos)))
{
fclose(file);
return;
}
// Ouf, sauv<75>
fclose(file);
}
void Image_emergency_backup()
{
Emergency_backup("phoenix.img",Main_screen, Main_image_width, Main_image_height, &Main_palette);
Emergency_backup("phoenix2.img",Spare_screen, Spare_image_width, Spare_image_height, &Spare_palette);
}
T_Format * Get_fileformat(byte format)
{
unsigned int i;
T_Format * safe_default = File_formats;
for (i=0; i < NB_KNOWN_FORMATS; i++)
{
if (File_formats[i].Identifier == format)
return &(File_formats[i]);
if (File_formats[i].Identifier == FORMAT_GIF)
safe_default=&(File_formats[i]);
}
// Normally impossible to reach this point, unless called with an invalid
// enum....
return safe_default;
}