From 1a2ac678e087ffc16fdcaa77e8c66d03b5df077e Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 31 Oct 2009 15:20:44 +0000 Subject: [PATCH] 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 --- Makefile | 2 +- fileformats.c | 3496 ++++++++++++++++++++++++++ loadsave.c | 6131 +-------------------------------------------- loadsave.h | 35 +- miscfileformats.c | 2485 ++++++++++++++++++ 5 files changed, 6026 insertions(+), 6123 deletions(-) create mode 100644 fileformats.c create mode 100644 miscfileformats.c diff --git a/Makefile b/Makefile index f3e7bc5d..cf0e13f3 100644 --- a/Makefile +++ b/Makefile @@ -279,7 +279,7 @@ endif .PHONY : all debug release clean depend zip version force install uninstall # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. -OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) +OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png diff --git a/fileformats.c b/fileformats.c new file mode 100644 index 00000000..5e8052da --- /dev/null +++ b/fileformats.c @@ -0,0 +1,3496 @@ +/* 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 +*/ + +///@file fileformats.c +/// Saving and loading different picture formats. + +#ifndef __no_pnglib__ +#include +#endif + +#include "errors.h" +#include "global.h" +#include "loadsave.h" +#include "misc.h" +#include "struct.h" + +//////////////////////////////////// IMG //////////////////////////////////// + +// -- Tester si un fichier est au format IMG -------------------------------- +void Test_IMG(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + T_IMG_Header IMG_header; + byte signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0}; + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture et vérification de la signature + if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) + { + if ( (!memcmp(IMG_header.Filler1,signature,6)) + && IMG_header.Width && IMG_header.Height) + File_error=0; + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format IMG ----------------------------------------- +void Load_IMG(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + byte * buffer; + FILE *file; + word x_pos,y_pos; + long width_read; + long file_size; + T_IMG_Header IMG_header; + + Get_full_filename(filename,0); + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) + { + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + IMG_header.Width = SDL_Swap16(IMG_header.Width); + IMG_header.Height = SDL_Swap16(IMG_header.Height); +#endif + + buffer=(byte *)malloc(IMG_header.Width); + + Init_preview(IMG_header.Width,IMG_header.Height,file_size,FORMAT_IMG,PIXEL_SIMPLE); + if (File_error==0) + { + memcpy(Main_palette,IMG_header.Palette,sizeof(T_Palette)); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=IMG_header.Width; + Main_image_height=IMG_header.Height; + width_read=IMG_header.Width; + + for (y_pos=0;(y_pos=0)?temp:0; + } + if ((i-7)&2) + { + temp=Main_palette[j].G-16; + Main_palette[color].G=(temp>=0)?temp:0; + } + if ((i-7)&4) + { + temp=Main_palette[j].B-16; + Main_palette[color].B=(temp>=0)?temp:0; + } + } + } + } + // Ici, il reste les 16 dernières couleurs à modifier + for (i=240,j=0; j<16; i++,j++) + { + temp=Main_palette[j].R+8; + Main_palette[i].R=(temp<63)?temp:63; + temp=Main_palette[j].G+8; + Main_palette[i].G=(temp<63)?temp:63; + temp=Main_palette[j].B+8; + Main_palette[i].B=(temp<63)?temp:63; + } + } + else if (Image_HAM==8) + { + for (i=1; i<=3; i++) + { + // On recopie la palette de base + memcpy(Main_palette+(i<<6),Main_palette,192); + // On modifie les teintes de cette palette + for (j=0; j<64; j++) + { + color=(i<<6)+j; + switch (i) + { + case 1 : + temp=Main_palette[j].R+16; + Main_palette[color].R=(temp<63)?temp:63; + break; + case 2 : + temp=Main_palette[j].G+16; + Main_palette[color].G=(temp<63)?temp:63; + break; + default: + temp=Main_palette[j].B+16; + Main_palette[color].B=(temp<63)?temp:63; + } + } + } + } + else // Image 64 couleurs sauvée en 32. + { + for (i=0; i<32; i++) + { + j=i+32; + Main_palette[j].R=Main_palette[i].R>>1; + Main_palette[j].G=Main_palette[i].G>>1; + Main_palette[j].B=Main_palette[i].B>>1; + } + } + } + + // ------------------------- Attendre une section ------------------------- + byte Wait_for(byte * expected_section) + { + // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur) + dword Taille_section; + byte section_read[4]; + + if (! Read_bytes(LBM_file,section_read,4)) + return 0; + while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée + { + if (!Read_dword_be(LBM_file,&Taille_section)) + return 0; + if (Taille_section&1) + Taille_section++; + if (fseek(LBM_file,Taille_section,SEEK_CUR)) + return 0; + if (! Read_bytes(LBM_file,section_read,4)) + return 0; + } + return 1; + } + +// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour +// en faire du chunky + +byte Color_ILBM_line(word x_pos, word real_line_size, byte HBPm1) +{ + // Renvoie la couleur du pixel (ILBM) en x_pos. + // CL sera le rang auquel on extrait les bits de la couleur + byte cl = 7 - (x_pos & 7); + int ax,bh,dx; + byte bl=0; + + for(dx=HBPm1;dx>=0;dx--) + { + //CIL_Loop + ax = (real_line_size * dx + x_pos) >> 3; + bh = (LBM_buffer[ax] >> cl) & 1; + + bl = (bl << 1) + bh; + } + + return bl; +} + +byte HBPm1; // header.BitPlanes-1 + + // ----------------------- Afficher une ligne ILBM ------------------------ + void Draw_ILBM_line(short y_pos, short real_line_size) + { + byte color; + byte red,green,blue; + byte temp; + short x_pos; + + if (Image_HAM<=1) // ILBM + { + for (x_pos=0; x_pos>2; + color=Best_color(red,green,blue); + break; + case 0x02: // red + red=temp>>2; + color=Best_color(red,green,blue); + break; + case 0x03: // green + green=temp>>2; + color=Best_color(red,green,blue); + break; + default: // Nouvelle couleur + color=temp; + red=Main_palette[color].R; + green =Main_palette[color].G; + blue =Main_palette[color].B; + } + Pixel_load_function(x_pos,y_pos,color); + } + } + } + + +void Load_LBM(void) +{ + char filename[MAX_PATH_CHARACTERS]; + T_LBM_Header header; + char format[4]; + char section[4]; + byte temp_byte; + short b256; + dword nb_colors; + dword image_size; + short x_pos; + short y_pos; + short counter; + short line_size; // Taille d'une ligne en octets + short real_line_size; // Taille d'une ligne en pixels + byte color; + long file_size; + dword dummy; + + Get_full_filename(filename,0); + + File_error=0; + + if ((LBM_file=fopen(filename, "rb"))) + { + file_size=File_length_file(LBM_file); + + // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été) + Read_bytes(LBM_file,section,4); + Read_dword_be(LBM_file,&dummy); + Read_bytes(LBM_file,format,4); + if (!Wait_for((byte *)"BMHD")) + File_error=1; + Read_dword_be(LBM_file,&dummy); + + // Maintenant on lit le header pour pouvoir commencer le chargement de l'image + if ( (Read_word_be(LBM_file,&header.Width)) + && (Read_word_be(LBM_file,&header.Height)) + && (Read_word_be(LBM_file,&header.X_org)) + && (Read_word_be(LBM_file,&header.Y_org)) + && (Read_byte(LBM_file,&header.BitPlanes)) + && (Read_byte(LBM_file,&header.Mask)) + && (Read_byte(LBM_file,&header.Compression)) + && (Read_byte(LBM_file,&header.Pad1)) + && (Read_word_be(LBM_file,&header.Transp_col)) + && (Read_byte(LBM_file,&header.X_aspect)) + && (Read_byte(LBM_file,&header.Y_aspect)) + && (Read_word_be(LBM_file,&header.X_screen)) + && (Read_word_be(LBM_file,&header.Y_screen)) + && header.Width && header.Height) + { + if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) ) + { + Read_dword_be(LBM_file,&nb_colors); + nb_colors/=3; + + if (((dword)1< il faut copier les 32 coul. + } // sur les 32 suivantes et assombrir ces dernières. + else + { + if ((header.BitPlanes==6) || (header.BitPlanes==8)) + Image_HAM=header.BitPlanes; + else + /* File_error=1;*/ /* C'est censé être incorrect mais j'ai */ + Image_HAM=0; /* trouvé un fichier comme ça, alors... */ + } + } + else + Image_HAM=0; + + if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) ) + { + HBPm1=header.BitPlanes-1; + if (header.Mask==1) + header.BitPlanes++; + + // Deluxe paint le fait... alors on le fait... + Back_color=header.Transp_col; + + // On commence par passer la palette en 256 comme ça, si la nouvelle + // palette a moins de 256 coul, la précédente ne souffrira pas d'un + // assombrissement préjudiciable. + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + else + Palette_64_to_256(Main_palette); + // On peut maintenant charger la nouvelle palette + if (Read_bytes(LBM_file,Main_palette,3*nb_colors)) + { + Palette_256_to_64(Main_palette); + if (Image_HAM) + Adapt_palette_HAM(); + Palette_64_to_256(Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + // On lit l'octet de padding du CMAP si la taille est impaire + if (nb_colors&1) + if (Read_byte(LBM_file,&temp_byte)) + File_error=2; + + if ( (Wait_for((byte *)"BODY")) && (!File_error) ) + { + Read_dword_be(LBM_file,&image_size); + //swab((char *)&header.Width ,(char *)&Main_image_width,2); + //swab((char *)&header.Height,(char *)&Main_image_height,2); + Main_image_width = header.Width; + Main_image_height = header.Height; + + //swab((char *)&header.X_screen,(char *)&Original_screen_X,2); + //swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2); + Original_screen_X = header.X_screen; + Original_screen_Y = header.Y_screen; + + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_LBM,PIXEL_SIMPLE); + if (File_error==0) + { + if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap + { + // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques) + if (Main_image_width & 15) + { + real_line_size=( (Main_image_width+16) >> 4 ) << 4; + line_size=( (Main_image_width+16) >> 4 )*(header.BitPlanes<<1); + } + else + { + real_line_size=Main_image_width; + line_size=(Main_image_width>>3)*header.BitPlanes; + } + + if (!header.Compression) + { // non compressé + LBM_buffer=(byte *)malloc(line_size); + for (y_pos=0; ((y_pos 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant + // Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants + if (temp_byte>127) + { + if(Read_byte(LBM_file, &color)!=1) + { + File_error=2; + break; + } + b256=(short)(256-temp_byte); + for (counter=0; counter<=b256; counter++) + if (x_pos=line_size || Read_byte(LBM_file, &(LBM_buffer[x_pos++]))!=1) + File_error=2; + } + if (!File_error) + Draw_ILBM_line(y_pos,real_line_size); + } + + free(LBM_buffer); + /*Close_lecture();*/ + } + } + else // "PBM ": Planar(?) BitMap + { + real_line_size=Main_image_width+(Main_image_width&1); + + if (!header.Compression) + { // non compressé + LBM_buffer=(byte *)malloc(real_line_size); + for (y_pos=0; ((y_pos127) + { + if(Read_byte(LBM_file, &color)!=1) + { + File_error=2; + break; + } + b256=256-temp_byte; + for (counter=0; counter<=b256; counter++) + Pixel_load_function(x_pos++,y_pos,color); + } + else + for (counter=0; counter<=temp_byte; counter++) + { + byte byte_read=0; + if(Read_byte(LBM_file, &byte_read)!=1) + { + File_error=2; + break; + } + Pixel_load_function(x_pos++,y_pos,byte_read); + } + } + } + /*Close_lecture();*/ + } + } + } + } + else + Set_file_error(2); + } + else + { + File_error=1; + } + } + else + Set_file_error(1); + } + else + File_error=1; + } + else + File_error=1; + + fclose(LBM_file); + } + else + File_error=1; +} + + +// -- Sauver un fichier au format LBM --------------------------------------- + + byte LBM_color_list[129]; + word LBM_list_size; + byte LBM_repetition_mode; + + // ------------- Ecrire les couleurs que l'on vient de traiter ------------ + void Transfer_colors(void) + { + byte index; + + if (LBM_list_size>0) + { + if (LBM_repetition_mode) + { + Write_one_byte(LBM_file,257-LBM_list_size); + Write_one_byte(LBM_file,LBM_color_list[0]); + } + else + { + Write_one_byte(LBM_file,LBM_list_size-1); + for (index=0; index et on a 3 couleurs qui se suivent + { + LBM_list_size-=2; + Transfer_colors(); + LBM_color_list[0]=color; + LBM_color_list[1]=color; + LBM_color_list[2]=color; + LBM_list_size=3; + LBM_repetition_mode=1; + } + } + else // La couleur n'est pas la même que la précédente + { + if (!LBM_repetition_mode) // On conserve le mode... + { + LBM_color_list[LBM_list_size++]=color; + if (LBM_list_size==128) + Transfer_colors(); + } + else // On change de mode... + { + Transfer_colors(); + LBM_color_list[LBM_list_size]=color; + LBM_list_size++; + } + } + } + } + + +void Save_LBM(void) +{ + char filename[MAX_PATH_CHARACTERS]; + T_LBM_Header header; + word x_pos; + word y_pos; + byte temp_byte; + word real_width; + int file_size; + + File_error=0; + Get_full_filename(filename,0); + + // Ouverture du fichier + if ((LBM_file=fopen(filename,"wb"))) + { + Write_bytes(LBM_file,"FORM",4); + Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin + + Write_bytes(LBM_file,"PBM BMHD",8); + Write_dword_be(LBM_file,20); + + // On corrige la largeur de l'image pour qu'elle soit multiple de 2 + real_width=Main_image_width+(Main_image_width&1); + + //swab((byte *)&real_width,(byte *)&header.Width,2); + header.Width=Main_image_width; + header.Height=Main_image_height; + header.X_org=0; + header.Y_org=0; + header.BitPlanes=8; + header.Mask=0; + header.Compression=1; + header.Pad1=0; + header.Transp_col=Back_color; + header.X_aspect=1; + header.Y_aspect=1; + header.X_screen = Screen_width; + header.Y_screen = Screen_height; + + Write_word_be(LBM_file,header.Width); + Write_word_be(LBM_file,header.Height); + Write_word_be(LBM_file,header.X_org); + Write_word_be(LBM_file,header.Y_org); + Write_bytes(LBM_file,&header.BitPlanes,1); + Write_bytes(LBM_file,&header.Mask,1); + Write_bytes(LBM_file,&header.Compression,1); + Write_bytes(LBM_file,&header.Pad1,1); + Write_word_be(LBM_file,header.Transp_col); + Write_bytes(LBM_file,&header.X_aspect,1); + Write_bytes(LBM_file,&header.Y_aspect,1); + Write_word_be(LBM_file,header.X_screen); + Write_word_be(LBM_file,header.Y_screen); + + Write_bytes(LBM_file,"CMAP",4); + Write_dword_be(LBM_file,sizeof(T_Palette)); + + Write_bytes(LBM_file,Main_palette,sizeof(T_Palette)); + + Write_bytes(LBM_file,"BODY",4); + Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin + + Init_write_buffer(); + + LBM_list_size=0; + + for (y_pos=0; ((y_pos on efface le fichier + remove(filename); + } + else + File_error=1; +} + + + +//////////////////////////////////// BMP //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + word Signature; // ='BM' = 0x4D42 + dword Size_1; // =Taille du fichier + word Reserved_1; // =0 + word Reserved_2; // =0 + dword Offset; // Nb octets avant les données bitmap + + dword Size_2; // =40 + dword Width; + dword Height; + word Planes; // =1 + word Nb_bits; // =1,4,8 ou 24 + dword Compression; + dword Size_3; + dword XPM; + dword YPM; + dword Nb_Clr; + dword Clr_Imprt; +} T_BMP_Header; +#pragma pack() + +// -- Tester si un fichier est au format BMP -------------------------------- +void Test_BMP(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_BMP_Header header; + + File_error=1; + Get_full_filename(filename,0); + + if ((file=fopen(filename, "rb"))) + { + if (Read_bytes(file,&(header.Signature),2) // "BM" + && Read_dword_le(file,&(header.Size_1)) + && Read_word_le(file,&(header.Reserved_1)) + && Read_word_le(file,&(header.Reserved_2)) + && Read_dword_le(file,&(header.Offset)) + && Read_dword_le(file,&(header.Size_2)) + && Read_dword_le(file,&(header.Width)) + && Read_dword_le(file,&(header.Height)) + && Read_word_le(file,&(header.Planes)) + && Read_word_le(file,&(header.Nb_bits)) + && Read_dword_le(file,&(header.Compression)) + && Read_dword_le(file,&(header.Size_3)) + && Read_dword_le(file,&(header.XPM)) + && Read_dword_le(file,&(header.YPM)) + && Read_dword_le(file,&(header.Nb_Clr)) + && Read_dword_le(file,&(header.Clr_Imprt)) + ) + { + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Signature = SDL_Swap16(header.Signature); +#endif + + if ( (header.Signature==0x4D42) && (header.Size_2==40) + && header.Width && header.Height ) + File_error=0; + } + fclose(file); + } +} + +// Find the 8 important bits in a dword +byte Bitmap_mask(dword pixel, dword mask) +{ + byte result; + int i; + int bits_found; + + switch(mask) + { + // Shortcuts to quickly handle the common 24/32bit cases + case 0x000000FF: + return (pixel & 0x000000FF); + case 0x0000FF00: + return (pixel & 0x0000FF00)>>8; + case 0x00FF0000: + return (pixel & 0x00FF0000)>>16; + case 0xFF000000: + return (pixel & 0xFF000000)>>24; + } + // Uncommon : do it bit by bit. + bits_found=0; + result=0; + // Process the mask from low to high bit + for (i=0;i<32;i++) + { + // Found a bit in the mask + if (mask & (1<=8) + return result; + } + } + // Less than 8 bits in the mask: scale the result to 8 bits + return result << (8-bits_found); +} + +// -- Charger un fichier au format BMP -------------------------------------- +void Load_BMP(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_BMP_Header header; + byte * buffer; + word index; + byte local_palette[256][4]; // R,G,B,0 + word nb_colors = 0; + short x_pos; + short y_pos; + word line_size; + byte a,b,c=0; + long file_size; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if (Read_word_le(file,&(header.Signature)) + && Read_dword_le(file,&(header.Size_1)) + && Read_word_le(file,&(header.Reserved_1)) + && Read_word_le(file,&(header.Reserved_2)) + && Read_dword_le(file,&(header.Offset)) + && Read_dword_le(file,&(header.Size_2)) + && Read_dword_le(file,&(header.Width)) + && Read_dword_le(file,&(header.Height)) + && Read_word_le(file,&(header.Planes)) + && Read_word_le(file,&(header.Nb_bits)) + && Read_dword_le(file,&(header.Compression)) + && Read_dword_le(file,&(header.Size_3)) + && Read_dword_le(file,&(header.XPM)) + && Read_dword_le(file,&(header.YPM)) + && Read_dword_le(file,&(header.Nb_Clr)) + && Read_dword_le(file,&(header.Clr_Imprt)) + ) + { + switch (header.Nb_bits) + { + case 1 : + case 4 : + case 8 : + if (header.Nb_Clr) + nb_colors=header.Nb_Clr; + else + nb_colors=1<>3; + + buffer=(byte *)malloc(line_size); + for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0; x_pos>1] & 0xF); + else + Pixel_load_function(x_pos,y_pos,buffer[x_pos>>1] >> 4 ); + break; + case 1 : + if ( buffer[x_pos>>3] & (0x80>>(x_pos&7)) ) + Pixel_load_function(x_pos,y_pos,1); + else + Pixel_load_function(x_pos,y_pos,0); + } + else + File_error=2; + } + free(buffer); + break; + + case 1 : // Compression RLE 8 bits + x_pos=0; + y_pos=Main_image_height-1; + + /*Init_lecture();*/ + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; + while (!File_error) + { + if (a) // Encoded mode + for (index=1; index<=a; index++) + Pixel_load_function(x_pos++,y_pos,b); + else // Absolute mode + switch (b) + { + case 0 : // End of line + x_pos=0; + y_pos--; + break; + case 1 : // End of bitmap + break; + case 2 : // Delta + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; + x_pos+=a; + y_pos-=b; + break; + default: // Nouvelle série + while (b) + { + if(Read_byte(file, &a)!=1) + File_error=2; + //Read_one_byte(file, &c); + Pixel_load_function(x_pos++,y_pos,a); + //if (--c) + //{ + // Pixel_load_function(x_pos++,y_pos,c); + // b--; + //} + b--; + } + if (ftell(file) & 1) fseek(file, 1, SEEK_CUR); + } + if (a==0 && b==1) + break; + if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1) + { + File_error=2; + } + } + /*Close_lecture();*/ + break; + + case 2 : // Compression RLE 4 bits + x_pos=0; + y_pos=Main_image_height-1; + + /*Init_lecture();*/ + if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1) + File_error =2; + while ( (!File_error) && ((a)||(b!=1)) ) + { + if (a) // Encoded mode (A fois les 1/2 pixels de B) + for (index=1; index<=a; index++) + { + if (index & 1) + Pixel_load_function(x_pos,y_pos,b>>4); + else + Pixel_load_function(x_pos,y_pos,b&0xF); + x_pos++; + } + else // Absolute mode + switch (b) + { + case 0 : //End of line + x_pos=0; + y_pos--; + break; + case 1 : // End of bitmap + break; + case 2 : // Delta + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) + File_error=2; + x_pos+=a; + y_pos-=b; + break; + default: // Nouvelle série (B 1/2 pixels bruts) + for (index=1; ((index<=b) && (!File_error)); index++,x_pos++) + { + if (index&1) + { + if(Read_byte(file, &c)!=1) File_error=2; + Pixel_load_function(x_pos,y_pos,c>>4); + } + else + Pixel_load_function(x_pos,y_pos,c&0xF); + } + // On lit l'octet rendant le nombre d'octets pair, si + // nécessaire. Encore un truc de crétin "made in MS". + if ( ((b&3)==1) || ((b&3)==2) ) + { + byte dummy; + if(Read_byte(file, &dummy)!=1) File_error=2; + } + } + if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) File_error=2; + } + /*Close_lecture();*/ + } + fclose(file); + } + else + { + fclose(file); + File_error=1; + } + } + } + else + { + // Image 16/24/32 bits + dword red_mask; + dword green_mask; + dword blue_mask; + if (header.Nb_bits == 16) + { + red_mask = 0x00007C00; + green_mask = 0x000003E0; + blue_mask = 0x0000001F; + } + else + { + red_mask = 0x00FF0000; + green_mask = 0x0000FF00; + blue_mask = 0x000000FF; + } + File_error=0; + + Main_image_width=header.Width; + Main_image_height=header.Height; + Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP); + if (File_error==0) + { + switch (header.Compression) + { + case 3: // BI_BITFIELDS + if (!Read_dword_le(file,&red_mask) || + !Read_dword_le(file,&green_mask) || + !Read_dword_le(file,&blue_mask)) + File_error=2; + break; + default: + break; + } + if (fseek(file, header.Offset, SEEK_SET)) + File_error=2; + } + if (File_error==0) + { + switch (header.Nb_bits) + { + // 24bit bitmap + default: + case 24: + line_size=Main_image_width*3; + x_pos=(line_size % 4); // x_pos sert de variable temporaire + if (x_pos>0) + line_size+=(4-x_pos); + + buffer=(byte *)malloc(line_size); + for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0,index=0; x_pos=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0; x_pos=0) && (!File_error)); y_pos--) + { + if (Read_bytes(file,buffer,line_size)) + for (x_pos=0; x_pos> 3)+1) << 3; + else + line_size=Main_image_width; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Signature = 0x424D; +#else + header.Signature = 0x4D42; +#endif + header.Size_1 =(line_size*Main_image_height)+1078; + header.Reserved_1 =0; + header.Reserved_2 =0; + header.Offset =1078; + header.Size_2 =40; + header.Width =Main_image_width; + header.Height =Main_image_height; + header.Planes =1; + header.Nb_bits =8; + header.Compression=0; + header.Size_3 =0; + header.XPM =0; + header.YPM =0; + header.Nb_Clr =0; + header.Clr_Imprt =0; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Size_1 = SDL_Swap32( header.Size_1 ); + header.Offset = SDL_Swap32( header.Offset ); + header.Size_2 = SDL_Swap32( header.Size_2 ); + header.Width = SDL_Swap32( header.Width ); + header.Height = SDL_Swap32( header.Height ); + header.Planes = SDL_Swap16( header.Planes ); + header.Nb_bits = SDL_Swap16( header.Nb_bits ); + // If you ever set any more fields to non-zero, please swap here! +#endif + + if (Write_bytes(file,&header,sizeof(T_BMP_Header))) + { + // Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre + // inverse, et pour faire chier, on va les mettre sur une échelle de + // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et + // puis comme c'est pas assez débile, on va aussi y rajouter un octet + // toujours à 0 pour forcer les gens à s'acheter des gros disques + // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira + // Windows 95." ... + for (index=0; index<256; index++) + { + local_palette[index][0]=Main_palette[index].B; + local_palette[index][1]=Main_palette[index].G; + local_palette[index][2]=Main_palette[index].R; + local_palette[index][3]=0; + } + + if (Write_bytes(file,local_palette,1024)) + { + Init_write_buffer(); + + // ... Et Bill, il a dit: "OK les gars! Mais seulement si vous rangez + // les pixels dans l'ordre inverse, mais que sur les Y quand-même + // parce que faut pas pousser." + for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) + for (x_pos=0; x_pos>=current_nb_bits; + nb_bits_processed +=current_nb_bits; + nb_bits_to_process-=current_nb_bits; + GIF_remainder_bits -=current_nb_bits; + } + + return GIF_current_code; + } + + // -- Affiche un nouveau pixel -- + + void GIF_new_pixel(byte color) + { + Pixel_load_function(GIF_pos_X,GIF_pos_Y,color); + + GIF_pos_X++; + + if (GIF_pos_X>=Main_image_width) + { + GIF_pos_X=0; + + if (!GIF_interlaced) + GIF_pos_Y++; + else + { + switch (GIF_pass) + { + case 0 : GIF_pos_Y+=8; + break; + case 1 : GIF_pos_Y+=8; + break; + case 2 : GIF_pos_Y+=4; + break; + default: GIF_pos_Y+=2; + } + + if (GIF_pos_Y>=Main_image_height) + { + switch(++GIF_pass) + { + case 1 : GIF_pos_Y=4; + break; + case 2 : GIF_pos_Y=2; + break; + case 3 : GIF_pos_Y=1; + break; + case 4 : GIF_finished_interlaced_image=1; + } + } + } + } + } + + +void Load_GIF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + char signature[6]; + + word * alphabet_stack; // Pile de décodage d'une chaîne + word * alphabet_prefix; // Table des préfixes des codes + word * alphabet_suffix; // Table des suffixes des codes + word alphabet_free; // Position libre dans l'alphabet + word alphabet_max; // Nombre d'entrées possibles dans l'alphabet + word alphabet_stack_pos; // Position dans la pile de décodage d'un chaîne + + T_GIF_LSDB LSDB; + T_GIF_IDB IDB; + + word nb_colors; // Nombre de couleurs dans l'image + word color_index; // index de traitement d'une couleur + byte size_to_read; // Nombre de données à lire (divers) + byte block_indentifier; // Code indicateur du type de bloc en cours + word initial_nb_bits; // Nb de bits au début du traitement LZW + word special_case=0; // Mémoire pour le cas spécial + word old_code=0; // Code précédent + word byte_read; // Sauvegarde du code en cours de lecture + word value_clr; // Valeur <=> Clear tables + word value_eof; // Valeur <=> End d'image + long file_size; + int number_LID; // Nombre d'images trouvées dans le fichier + + /////////////////////////////////////////////////// FIN DES DECLARATIONS // + + + GIF_pos_X=0; + GIF_pos_Y=0; + GIF_last_byte=0; + GIF_remainder_bits=0; + GIF_remainder_byte=0; + number_LID=0; + + Get_full_filename(filename,0); + + if ((GIF_file=fopen(filename, "rb"))) + { + file_size=File_length_file(GIF_file); + if ( (Read_bytes(GIF_file,signature,6)) && + ( (memcmp(signature,"GIF87a",6)==0) || + (memcmp(signature,"GIF89a",6)==0) ) ) + { + + // Allocation de mémoire pour les tables & piles de traitement: + alphabet_stack =(word *)malloc(4096*sizeof(word)); + alphabet_prefix=(word *)malloc(4096*sizeof(word)); + alphabet_suffix=(word *)malloc(4096*sizeof(word)); + + if (Read_word_le(GIF_file,&(LSDB.Width)) + && Read_word_le(GIF_file,&(LSDB.Height)) + && Read_byte(GIF_file,&(LSDB.Resol)) + && Read_byte(GIF_file,&(LSDB.Backcol)) + && Read_byte(GIF_file,&(LSDB.Aspect)) + ) + { + // Lecture du Logical Screen Descriptor Block réussie: + + Original_screen_X=LSDB.Width; + Original_screen_Y=LSDB.Height; + + // Palette globale dispo = (LSDB.Resol and $80) + // Profondeur de couleur =((LSDB.Resol and $70) shr 4)+1 + // Nombre de bits/pixel = (LSDB.Resol and $07)+1 + // Ordre de Classement = (LSDB.Aspect and $80) + + alphabet_stack_pos=0; + GIF_last_byte =0; + GIF_remainder_bits =0; + GIF_remainder_byte =0; + + nb_colors=(1 << ((LSDB.Resol & 0x07)+1)); + initial_nb_bits=(LSDB.Resol & 0x07)+2; + + if (LSDB.Resol & 0x80) + { + // Palette globale dispo: + + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + + // On peut maintenant charger la nouvelle palette: + if (!(LSDB.Aspect & 0x80)) + // Palette dans l'ordre: + for(color_index=0;color_indexnb_char_to_keep) + fseek(GIF_file,size_to_read-nb_char_to_keep,SEEK_CUR); + } + break; + case 0xF9: // Graphics Control Extension + // Prévu pour la transparence + + default: + // On saute le bloc: + fseek(GIF_file,size_to_read,SEEK_CUR); + break; + } + // Lecture de la taille du bloc suivant: + Read_byte(GIF_file,&size_to_read); + } + } + break; + case 0x2C: // Local Image Descriptor + { + // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort. + if (number_LID!=0) + { + File_error=2; + break; + } + number_LID++; + + // lecture de 10 derniers octets + if ( Read_word_le(GIF_file,&(IDB.Pos_X)) + && Read_word_le(GIF_file,&(IDB.Pos_Y)) + && Read_word_le(GIF_file,&(IDB.Image_width)) + && Read_word_le(GIF_file,&(IDB.Image_height)) + && Read_byte(GIF_file,&(IDB.Indicator)) + && Read_byte(GIF_file,&(IDB.Nb_bits_pixel)) + && IDB.Image_width && IDB.Image_height) + { + Main_image_width=IDB.Image_width; + Main_image_height=IDB.Image_height; + + Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE); + + // Palette locale dispo = (IDB.Indicator and $80) + // Image entrelacée = (IDB.Indicator and $40) + // Ordre de classement = (IDB.Indicator and $20) + // Nombre de bits/pixel = (IDB.Indicator and $07)+1 (si palette locale dispo) + + if (IDB.Indicator & 0x80) + { + // Palette locale dispo + + nb_colors=(1 << ((IDB.Indicator & 0x07)+1)); + initial_nb_bits=(IDB.Indicator & 0x07)+2; + + if (!(IDB.Indicator & 0x40)) + // Palette dans l'ordre: + for(color_index=0;color_indexvalue_clr) + { + alphabet_stack[alphabet_stack_pos++]=alphabet_suffix[GIF_current_code]; + GIF_current_code=alphabet_prefix[GIF_current_code]; + } + + special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code; + + do + GIF_new_pixel(alphabet_stack[--alphabet_stack_pos]); + while (alphabet_stack_pos!=0); + + alphabet_prefix[alphabet_free ]=old_code; + alphabet_suffix[alphabet_free++]=GIF_current_code; + old_code=byte_read; + + if (alphabet_free>alphabet_max) + { + if (GIF_nb_bits<12) + alphabet_max =((1 << (++GIF_nb_bits))-1); + } + } + else // Code Clear rencontré + { + GIF_nb_bits =initial_nb_bits; + alphabet_max =((1 << GIF_nb_bits)-1); + alphabet_free =nb_colors+2; + special_case =GIF_get_next_code(); + old_code =GIF_current_code; + GIF_new_pixel(GIF_current_code); + } + } + else + File_error=2; + } // Code End-Of-Information ou erreur de fichier rencontré + + /*Close_lecture();*/ + + if (File_error>=0) + if ( /* (GIF_pos_X!=0) || */ + ( ( (!GIF_interlaced) && (GIF_pos_Y!=Main_image_height) ) || + ( (GIF_interlaced) && (!GIF_finished_interlaced_image) ) + ) ) + File_error=2; + } // Le fichier contenait un IDB + else + File_error=2; + } + default: + break; + } + // Lecture du code de fonction suivant: + Read_byte(GIF_file,&block_indentifier); + } + } // Le fichier contenait un LSDB + else + File_error=1; + + // Libération de la mémoire utilisée par les tables & piles de traitement: + free(alphabet_suffix); + free(alphabet_prefix); + free(alphabet_stack); + } // Le fichier contenait au moins la signature GIF87a ou GIF89a + else + File_error=1; + + fclose(GIF_file); + + } // Le fichier était ouvrable + else + File_error=1; +} + + +// -- Sauver un fichier au format GIF --------------------------------------- + + 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 + + // -- Vider le buffer GIF dans le buffer KM -- + + void GIF_empty_buffer(void) + { + word index; + + if (GIF_remainder_byte) + { + GIF_buffer[0]=GIF_remainder_byte; + + for (index=0;index<=GIF_remainder_byte;index++) + Write_one_byte(GIF_file,GIF_buffer[index]); + + GIF_remainder_byte=0; + } + } + + // -- Ecrit un code à GIF_nb_bits -- + + void GIF_set_code(word Code) + { + word nb_bits_to_process=GIF_nb_bits; + word nb_bits_processed =0; + word current_nb_bits; + + while (nb_bits_to_process) + { + current_nb_bits=(nb_bits_to_process<=(8-GIF_remainder_bits))?nb_bits_to_process:(8-GIF_remainder_bits); + + GIF_last_byte|=(Code & ((1<>=current_nb_bits; + GIF_remainder_bits +=current_nb_bits; + nb_bits_processed +=current_nb_bits; + nb_bits_to_process-=current_nb_bits; + + if (GIF_remainder_bits==8) // Il ne reste plus de bits à coder sur l'octet courant + { + // Ecrire l'octet à balancer: + GIF_buffer[++GIF_remainder_byte]=GIF_last_byte; + + // Si on a atteint la fin du bloc de Raster Data + if (GIF_remainder_byte==255) + // On doit vider le buffer qui est maintenant plein + GIF_empty_buffer(); + + GIF_last_byte=0; + GIF_remainder_bits=0; + } + } + } + + + // -- Lire le pixel suivant -- + + byte GIF_next_pixel(void) + { + byte temp; + + temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y); + + if (++GIF_pos_X>=Main_image_width) + { + GIF_pos_X=0; + if (++GIF_pos_Y>=Main_image_height) + GIF_stop=1; + } + + return temp; + } + + + +void Save_GIF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + + word * alphabet_prefix; // Table des préfixes des codes + word * alphabet_suffix; // Table des suffixes des codes + word * alphabet_daughter; // Table des chaînes filles (plus longues) + word * alphabet_sister; // Table des chaînes soeurs (même longueur) + word alphabet_free; // Position libre dans l'alphabet + word alphabet_max; // Nombre d'entrées possibles dans l'alphabet + word start; // Code précédent (sert au linkage des chaînes) + int descend; // Booléen "On vient de descendre" + + T_GIF_LSDB LSDB; + T_GIF_IDB IDB; + + + byte block_indentifier; // Code indicateur du type de bloc en cours + word current_string; // Code de la chaîne en cours de traitement + byte current_char; // Caractère à coder + word index; // index de recherche de chaîne + + + /////////////////////////////////////////////////// FIN DES DECLARATIONS // + + + GIF_pos_X=0; + GIF_pos_Y=0; + GIF_last_byte=0; + GIF_remainder_bits=0; + GIF_remainder_byte=0; + + Get_full_filename(filename,0); + + if ((GIF_file=fopen(filename,"wb"))) + { + // On écrit la signature du fichier + if (Write_bytes(GIF_file,"GIF89a",6)) + { + // La signature du fichier a été correctement écrite. + + // Allocation de mémoire pour les tables + alphabet_prefix=(word *)malloc(4096*sizeof(word)); + alphabet_suffix=(word *)malloc(4096*sizeof(word)); + alphabet_daughter =(word *)malloc(4096*sizeof(word)); + alphabet_sister =(word *)malloc(4096*sizeof(word)); + + // On initialise le LSDB du fichier + if (Config.Screen_size_in_GIF) + { + LSDB.Width=Screen_width; + LSDB.Height=Screen_height; + } + else + { + LSDB.Width=Main_image_width; + LSDB.Height=Main_image_height; + } + LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette + LSDB.Backcol=0; + LSDB.Aspect =0; // Palette normale + + // On sauve le LSDB dans le fichier + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + LSDB.Width = SDL_Swap16(LSDB.Width); + LSDB.Height = SDL_Swap16(LSDB.Height); +#endif + + if (Write_bytes(GIF_file,&LSDB,sizeof(T_GIF_LSDB))) + { + // Le LSDB a été correctement écrit. + + // On sauve la palette + if (Write_bytes(GIF_file,Main_palette,768)) + { + // La palette a été correctement écrite. + + // Le jour où on se servira des blocks d'extensions pour placer + // des commentaires, on le fera ici. + + // Ecriture de la transparence + //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8); + + // Ecriture du commentaire + if (Main_comment[0]) + { + Write_bytes(GIF_file,"\x21\xFE",2); + Write_byte(GIF_file,strlen(Main_comment)); + Write_bytes(GIF_file,Main_comment,strlen(Main_comment)+1); + } + + + + // On va écrire un block indicateur d'IDB et l'IDB du fichier + + block_indentifier=0x2C; + IDB.Pos_X=0; + IDB.Pos_Y=0; + IDB.Image_width=Main_image_width; + IDB.Image_height=Main_image_height; + IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale. + IDB.Nb_bits_pixel=8; // Image 256 couleurs; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + IDB.Image_width = SDL_Swap16(IDB.Image_width); + IDB.Image_height = SDL_Swap16(IDB.Image_height); +#endif + + if ( Write_bytes(GIF_file,&block_indentifier,1) && + Write_bytes(GIF_file,&IDB,sizeof(T_GIF_IDB)) ) + { + // Le block indicateur d'IDB et l'IDB ont étés correctements + // écrits. + + Init_write_buffer(); + + index=4096; + File_error=0; + GIF_stop=0; + + // Réintialisation de la table: + alphabet_free=258; + GIF_nb_bits =9; + alphabet_max =511; + GIF_set_code(256); + for (start=0;start<4096;start++) + { + alphabet_daughter[start]=4096; + alphabet_sister[start]=4096; + } + + ////////////////////////////////////////////// COMPRESSION LZW // + + start=current_string=GIF_next_pixel(); + descend=1; + + do + { + current_char=GIF_next_pixel(); + + // On regarde si dans la table on aurait pas une chaîne + // équivalente à current_string+Caractere + + while ( (index0xFFF) + { + // Réintialisation de la table: + GIF_set_code(256); + alphabet_free=258; + GIF_nb_bits =9; + alphabet_max =511; + for (start=0;start<4096;start++) + { + alphabet_daughter[start]=4096; + alphabet_sister[start]=4096; + } + } + else if (alphabet_free>alphabet_max+1) + { + // On augmente le nb de bits + + GIF_nb_bits++; + alphabet_max=(1< 16c , 1 => 256c , ... + word Bytes_per_plane_line;// Doit toujours être pair + word Palette_info; // 1 => color , 2 => Gris (ignoré à partir de la version 4) + word Screen_X; // |_ Dimensions de + word Screen_Y; // | l'écran d'origine + byte Filler[54]; // Ca... J'adore! + } T_PCX_Header; +#pragma pack() + +T_PCX_Header PCX_header; + +// -- Tester si un fichier est au format PCX -------------------------------- + +void Test_PCX(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + + File_error=0; + Get_full_filename(filename,0); + + if ((file=fopen(filename, "rb"))) + { + if (Read_byte(file,&(PCX_header.Manufacturer)) && + Read_byte(file,&(PCX_header.Version)) && + Read_byte(file,&(PCX_header.Compression)) && + Read_byte(file,&(PCX_header.Depth)) && + Read_word_le(file,&(PCX_header.X_min)) && + Read_word_le(file,&(PCX_header.Y_min)) && + Read_word_le(file,&(PCX_header.X_max)) && + Read_word_le(file,&(PCX_header.Y_max)) && + Read_word_le(file,&(PCX_header.X_dpi)) && + Read_word_le(file,&(PCX_header.Y_dpi)) && + Read_bytes(file,&(PCX_header.Palette_16c),48) && + Read_byte(file,&(PCX_header.Reserved)) && + Read_byte(file,&(PCX_header.Plane)) && + Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && + Read_word_le(file,&(PCX_header.Palette_info)) && + Read_word_le(file,&(PCX_header.Screen_X)) && + Read_word_le(file,&(PCX_header.Screen_Y)) && + Read_bytes(file,&(PCX_header.Filler),54) ) + { + + // Vu que ce header a une signature de merde et peu significative, il + // va falloir que je teste différentes petites valeurs dont je connais + // l'intervalle. Grrr! + if ( (PCX_header.Manufacturer!=10) + || (PCX_header.Compression>1) + || ( (PCX_header.Depth!=1) && (PCX_header.Depth!=2) && (PCX_header.Depth!=4) && (PCX_header.Depth!=8) ) + || ( (PCX_header.Plane!=1) && (PCX_header.Plane!=2) && (PCX_header.Plane!=4) && (PCX_header.Plane!=8) && (PCX_header.Plane!=3) ) + || (PCX_header.X_max>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask; + Pixel_load_function(x_pos,y_pos,color); + } + } + +void Load_PCX(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + + short line_size; + short real_line_size; // width de l'image corrigée + short width_read; + short x_pos; + short y_pos; + byte byte1; + byte byte2; + byte index; + dword nb_colors; + long file_size; + byte palette_CGA[9]={ 84,252,252, 252, 84,252, 252,252,252}; + + long position; + long image_size; + byte * buffer; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + /* + if (Read_bytes(file,&PCX_header,sizeof(T_PCX_Header))) + {*/ + + if (Read_byte(file,&(PCX_header.Manufacturer)) && + Read_byte(file,&(PCX_header.Version)) && + Read_byte(file,&(PCX_header.Compression)) && + Read_byte(file,&(PCX_header.Depth)) && + Read_word_le(file,&(PCX_header.X_min)) && + Read_word_le(file,&(PCX_header.Y_min)) && + Read_word_le(file,&(PCX_header.X_max)) && + Read_word_le(file,&(PCX_header.Y_max)) && + Read_word_le(file,&(PCX_header.X_dpi)) && + Read_word_le(file,&(PCX_header.Y_dpi)) && + Read_bytes(file,&(PCX_header.Palette_16c),48) && + Read_byte(file,&(PCX_header.Reserved)) && + Read_byte(file,&(PCX_header.Plane)) && + Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && + Read_word_le(file,&(PCX_header.Palette_info)) && + Read_word_le(file,&(PCX_header.Screen_X)) && + Read_word_le(file,&(PCX_header.Screen_Y)) && + Read_bytes(file,&(PCX_header.Filler),54) ) + { + + Main_image_width=PCX_header.X_max-PCX_header.X_min+1; + Main_image_height=PCX_header.Y_max-PCX_header.Y_min+1; + + Original_screen_X=PCX_header.Screen_X; + Original_screen_Y=PCX_header.Screen_Y; + + if (PCX_header.Plane!=3) + { + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE); + if (File_error==0) + { + // On prépare la palette à accueillir les valeurs du fichier PCX + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + nb_colors=(dword)(1<4) + memcpy(Main_palette,PCX_header.Palette_16c,48); + else + { + Main_palette[1].R=0; + Main_palette[1].G=0; + Main_palette[1].B=0; + byte1=PCX_header.Palette_16c[3]>>5; + if (nb_colors==4) + { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :)) + memcpy(Main_palette+1,palette_CGA,9); + if (!(byte1&2)) + { + Main_palette[1].B=84; + Main_palette[2].B=84; + Main_palette[3].B=84; + } + } // Palette monochrome (on va dire que c'est du N&B) + else + { + Main_palette[1].R=252; + Main_palette[1].G=252; + Main_palette[1].B=252; + } + } + + // On se positionne à la fin du fichier - 769 octets pour voir s'il y + // a une palette. + if ( (PCX_header.Depth==8) && (PCX_header.Version>=5) && (file_size>(256*3)) ) + { + fseek(file,file_size-((256*3)+1),SEEK_SET); + // On regarde s'il y a une palette après les données de l'image + if (Read_byte(file,&byte1)) + if (byte1==12) // Lire la palette si c'est une image en 256 couleurs + { + int index; + // On lit la palette 256c que ces crétins ont foutue à la fin du fichier + for(index=0;index<256;index++) + if ( ! Read_byte(file,&Main_palette[index].R) + || ! Read_byte(file,&Main_palette[index].G) + || ! Read_byte(file,&Main_palette[index].B) ) + { + File_error=2; + DEBUG("ERROR READING PCX PALETTE !",index); + break; + } + } + } + Set_palette(Main_palette); + Remap_fileselector(); + + // Maintenant qu'on a lu la palette que ces crétins sont allés foutre + // à la fin, on retourne juste après le header pour lire l'image. + fseek(file,128,SEEK_SET); + if (!File_error) + { + line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; + real_line_size=(short)PCX_header.Bytes_per_plane_line<<3; + // On se sert de données LBM car le dessin de ligne en moins de 256 + // couleurs se fait comme avec la structure ILBM. + Image_HAM=0; + HBPm1=PCX_header.Plane-1; + LBM_buffer=(byte *)malloc(line_size); + + // Chargement de l'image + if (PCX_header.Compression) // Image compressée + { + /*Init_lecture();*/ + + image_size=(long)PCX_header.Bytes_per_plane_line*Main_image_height; + + if (PCX_header.Depth==8) // 256 couleurs (1 plan) + { + for (position=0; ((position=line_size) + { + for (x_pos=0; x_pos=line_size) + { + for (x_pos=0; x_pos1) || (last_pixel>=0xC0) ) + Write_one_byte(file,counter|0xC0); + Write_one_byte(file,last_pixel); + + } + } + + // Ecriture de l'octet (12) indiquant que la palette arrive + if (!File_error) + Write_one_byte(file,12); + + End_write(file); + + // Ecriture de la palette + if (!File_error) + { + if (! Write_bytes(file,Main_palette,sizeof(T_Palette))) + File_error=1; + } + } + else + File_error=1; + + fclose(file); + + if (File_error) + remove(filename); + + } + else + File_error=1; +} + + +//////////////////////////////////// SCx //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + byte Filler1[4]; + word Width; + word Height; + byte Filler2; + byte Planes; +} T_SCx_Header; +#pragma pack() + +// -- Tester si un fichier est au format SCx -------------------------------- +void Test_SCx(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + //byte Signature[3]; + T_SCx_Header SCx_header; + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture et vérification de la signature + if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) + { + if ( (!memcmp(SCx_header.Filler1,"RIX",3)) + && SCx_header.Width && SCx_header.Height) + File_error=0; + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format SCx ----------------------------------------- +void Load_SCx(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + word x_pos,y_pos; + long size,real_size; + long file_size; + T_SCx_Header SCx_header; + T_Palette SCx_Palette; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) + { + Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE); + if (File_error==0) + { + if (!SCx_header.Planes) + size=sizeof(T_Palette); + else + size=sizeof(T_Components)*(1<>3)*SCx_header.Planes; + real_size=(size/SCx_header.Planes)<<3; + LBM_buffer=(byte *)malloc(size); + HBPm1=SCx_header.Planes-1; + Image_HAM=0; + + for (y_pos=0;(y_poscolor_type; + bit_depth = info_ptr->bit_depth; + + // If it's any supported file + // (Note: As of writing this, this test covers every possible + // image format of libpng) + if (color_type == PNG_COLOR_TYPE_PALETTE + || color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA + || color_type == PNG_COLOR_TYPE_RGB + || color_type == PNG_COLOR_TYPE_RGB_ALPHA + ) + { + int num_text; + png_text *text_ptr; + + int unit_type; + png_uint_32 res_x; + png_uint_32 res_y; + + // Comment (tEXt) + Main_comment[0]='\0'; // Clear the previous comment + if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL))) + { + while (num_text--) + { + if (!strcmp(text_ptr[num_text].key,"Title")) + { + int size; + size = Min(text_ptr[num_text].text_length, COMMENT_SIZE); + strncpy(Main_comment, text_ptr[num_text].text, size); + Main_comment[size]='\0'; + break; // Skip all others tEXt chunks + } + } + } + // Pixel Ratio (pHYs) + if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type)) + { + // Ignore unit, and use the X/Y ratio as a hint for + // WIDE or TALL pixels + if (res_x>0 && res_y>0) + { + if (res_y/res_x>1) + { + Ratio_of_loaded_image=PIXEL_WIDE; + } + else if (res_x/res_y>1) + { + Ratio_of_loaded_image=PIXEL_TALL; + } + } + } + if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) + Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG); + else + Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image); + + if (File_error==0) + { + int x,y; + png_colorp palette; + int num_palette; + + // 16-bit images + if (bit_depth == 16) + { + // Reduce to 8-bit + png_set_strip_16(png_ptr); + } + else if (bit_depth < 8) + { + // Inform libpng we want one byte per pixel, + // even though the file was less than 8bpp + png_set_packing(png_ptr); + } + + // Images with alpha channel + if (color_type & PNG_COLOR_MASK_ALPHA) + { + // Tell libpng to ignore it + png_set_strip_alpha(png_ptr); + } + + // Greyscale images : + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + // Map low bpp greyscales to full 8bit (0-255 range) + if (bit_depth < 8) + png_set_gray_1_2_4_to_8(png_ptr); + + // Create greyscale palette + for (x=0;x<256;x++) + { + Main_palette[x].R=x; + Main_palette[x].G=x; + Main_palette[x].B=x; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) // Palette images + { + + if (bit_depth < 8) + { + // Clear unused colors + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + } + // Load the palette + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + for (x=0;xwidth; + Main_image_height=info_ptr->height; + + png_set_interlace_handling(png_ptr); + png_read_update_info(png_ptr, info_ptr); + + // Allocate row pointers + Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height); + row_pointers_allocated = 0; + + /* read file */ + if (!setjmp(png_jmpbuf(png_ptr))) + { + if (color_type == PNG_COLOR_TYPE_GRAY + || color_type == PNG_COLOR_TYPE_GRAY_ALPHA + || color_type == PNG_COLOR_TYPE_PALETTE + ) + { + // 8bpp + + for (y=0; yrowbytes); + row_pointers_allocated = 1; + + png_read_image(png_ptr, Row_pointers); + + for (y=0; yrowbytes); + row_pointers_allocated = 1; + + png_read_image(png_ptr, Row_pointers); + + for (y=0; y #include #include -#ifndef __no_pnglib__ -#include -#endif #include #include @@ -132,26 +129,27 @@ 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_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, 1, 1, "pkm", "pkm"}, + {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, 1, 0, "pi1", "pi1"}, - {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 1, 0, "pc1", "pc1"}, + {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, 1, 0, "neo", "neo"}, + {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, 1, 1, "c64", "c64;koa"}, + {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"}, }; @@ -182,8 +180,6 @@ short Preview_factor_Y; short Preview_pos_X; short Preview_pos_Y; -byte HBPm1; // header.BitPlanes-1 - // Chargement des pixels dans la preview void Pixel_load_in_preview(word x_pos,word y_pos,byte color) @@ -271,12 +267,7 @@ void Remap_fileselector(void) } } - - -// Données pour la gestion du chargement en 24b -#define FORMAT_24B 0x100 -typedef void (* Func_24b_display) (short,short,byte,byte,byte); -int Image_24b; +int Image_24b; T_Components * Buffer_image_24b; Func_24b_display Pixel_load_24b; @@ -784,6098 +775,6 @@ void Save_image(byte image) } -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// PAL //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -// -- Tester si un fichier est au format PAL -------------------------------- -void Test_PAL(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - long file_size; // Taille du fichier - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture de la taille du fichier - file_size=File_length_file(file); - fclose(file); - // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets - if (file_size==sizeof(T_Palette)) - File_error=0; - } -} - - -// -- Lire un fichier au format PAL ----------------------------------------- -void Load_PAL(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - //long file_size; // Taille du fichier - - - Get_full_filename(filename,0); - File_error=0; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - T_Palette palette_64; - // Init_preview(?); // Pas possible... pas d'image... - - // Lecture du fichier dans Main_palette - if (Read_bytes(file,palette_64,sizeof(T_Palette))) - { - Palette_64_to_256(palette_64); - memcpy(Main_palette,palette_64,sizeof(T_Palette)); - Set_palette(Main_palette); - Remap_fileselector(); - - // On dessine une preview de la palette (si chargement=preview) - Draw_palette_preview(); - } - else - File_error=2; - - // Fermeture du fichier - fclose(file); - } - else - // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur - File_error=1; -} - - -// -- Sauver un fichier au format PAL --------------------------------------- -void Save_PAL(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - //long file_size; // Taille du fichier - - Get_full_filename(filename,0); - - File_error=0; - - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - T_Palette palette_64; - memcpy(palette_64,Main_palette,sizeof(T_Palette)); - Palette_256_to_64(palette_64); - // Enregistrement de Main_palette dans le fichier - if (! Write_bytes(file,palette_64,sizeof(T_Palette))) - { - File_error=1; - fclose(file); - remove(filename); - } - else // Ecriture correcte => Fermeture normale du fichier - fclose(file); - } - else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur - { - File_error=1; - fclose(file); - remove(filename); - // On se fout du résultat de l'opération car si ça - // renvoie 0 c'est que le fichier avait été partiel- - // -lement écrit, sinon pas du tout. Or dans tous les - // cas ça revient au même pour nous: Sauvegarde ratée! - } -} - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// IMG //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - byte Filler1[6]; - word Width; - word Height; - byte Filler2[118]; - T_Palette Palette; -} T_IMG_Header; -#pragma pack() - -// -- Tester si un fichier est au format IMG -------------------------------- -void Test_IMG(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - T_IMG_Header IMG_header; - byte signature[6]={0x01,0x00,0x47,0x12,0x6D,0xB0}; - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture et vérification de la signature - if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) - { - if ( (!memcmp(IMG_header.Filler1,signature,6)) - && IMG_header.Width && IMG_header.Height) - File_error=0; - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format IMG ----------------------------------------- -void Load_IMG(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - byte * buffer; - FILE *file; - word x_pos,y_pos; - long width_read; - long file_size; - T_IMG_Header IMG_header; - - Get_full_filename(filename,0); - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - - if (Read_bytes(file,&IMG_header,sizeof(T_IMG_Header))) - { - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - IMG_header.Width = SDL_Swap16(IMG_header.Width); - IMG_header.Height = SDL_Swap16(IMG_header.Height); -#endif - - buffer=(byte *)malloc(IMG_header.Width); - - Init_preview(IMG_header.Width,IMG_header.Height,file_size,FORMAT_IMG,PIXEL_SIMPLE); - if (File_error==0) - { - memcpy(Main_palette,IMG_header.Palette,sizeof(T_Palette)); - Set_palette(Main_palette); - Remap_fileselector(); - - Main_image_width=IMG_header.Width; - Main_image_height=IMG_header.Height; - width_read=IMG_header.Width; - - for (y_pos=0;(y_posCOMMENT_SIZE) - { - color=temp_byte; // On se sert de color comme - temp_byte=COMMENT_SIZE; // variable temporaire - color-=COMMENT_SIZE; - } - else - color=0; - - if (Read_bytes(file,Main_comment,temp_byte)) - { - index+=temp_byte; - Main_comment[temp_byte]='\0'; - if (color) - if (fseek(file,color,SEEK_CUR)) - File_error=2; - } - else - File_error=2; - } - else - File_error=2; - break; - - case 1 : // Dimensions de l'écran d'origine - if (Read_byte(file,&temp_byte)) - { - if (temp_byte==4) - { - index+=4; - if ( ! Read_word_le(file,(word *) &Original_screen_X) - || !Read_word_le(file,(word *) &Original_screen_Y) ) - File_error=2; - } - else - File_error=2; - } - else - File_error=2; - break; - - case 2 : // color de transparence - if (Read_byte(file,&temp_byte)) - { - if (temp_byte==1) - { - index++; - if (! Read_byte(file,&Back_color)) - File_error=2; - } - else - File_error=2; - } - else - File_error=2; - break; - - default: - if (Read_byte(file,&temp_byte)) - { - index+=temp_byte; - if (fseek(file,temp_byte,SEEK_CUR)) - File_error=2; - } - else - File_error=2; - } - } - else - File_error=2; - } - if ( (!File_error) && (index!=header.Jump) ) - File_error=2; - } - - /*Init_lecture();*/ - - if (!File_error) - { - Init_preview(header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE); - if (File_error==0) - { - - Main_image_width=header.Width; - Main_image_height=header.Height; - image_size=(dword)(Main_image_width*Main_image_height); - // Palette lue en 64 - memcpy(Main_palette,header.Palette,sizeof(T_Palette)); - Palette_64_to_256(Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - Compteur_de_donnees_packees=0; - Compteur_de_pixels=0; - Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump; - - // Boucle de décompression: - while ( (Compteur_de_pixels>8); - Write_one_byte(file,Screen_height&0xFF); - Write_one_byte(file,Screen_height>>8); - // Ecriture de la back-color - Write_one_byte(file,2); - Write_one_byte(file,1); - Write_one_byte(file,Back_color); - - // Routine de compression PKM de l'image - image_size=(dword)(Main_image_width*Main_image_height); - Compteur_de_pixels=0; - pixel_value=Read_pixel_function(0,0); - - while ( (Compteur_de_pixels=image_size) break; - pixel_value=Read_pixel_function(Compteur_de_pixels % Main_image_width,Compteur_de_pixels / Main_image_width); - } - - if ( (last_color!=header.recog1) && (last_color!=header.recog2) ) - { - if (repetitions==1) - Write_one_byte(file,last_color); - else - if (repetitions==2) - { - Write_one_byte(file,last_color); - Write_one_byte(file,last_color); - } - else - if ( (repetitions>2) && (repetitions<256) ) - { // RECON1/couleur/nombre - Write_one_byte(file,header.recog1); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions&0xFF); - } - else - if (repetitions>=256) - { // RECON2/couleur/hi(nombre)/lo(nombre) - Write_one_byte(file,header.recog2); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions>>8); - Write_one_byte(file,repetitions&0xFF); - } - } - else - { - if (repetitions<256) - { - Write_one_byte(file,header.recog1); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions&0xFF); - } - else - { - Write_one_byte(file,header.recog2); - Write_one_byte(file,last_color); - Write_one_byte(file,repetitions>>8); - Write_one_byte(file,repetitions&0xFF); - } - } - } - - End_write(file); - } - else - File_error=1; - fclose(file); - } - else - { - File_error=1; - fclose(file); - } - // S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser - // ce fichier pourri traîner... Ca fait pas propre. - if (File_error) - remove(filename); -} - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// LBM //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - word Width; - word Height; - word X_org; // Inutile - word Y_org; // Inutile - byte BitPlanes; - byte Mask; - byte Compression; - byte Pad1; // Inutile - word Transp_col; - byte X_aspect; // Inutile - byte Y_aspect; // Inutile - word X_screen; - word Y_screen; -} T_LBM_Header; -#pragma pack() - -byte * LBM_buffer; -FILE *LBM_file; - -// -- Tester si un fichier est au format LBM -------------------------------- - -void Test_LBM(void) -{ - char filename[MAX_PATH_CHARACTERS]; - char format[4]; - char section[4]; - dword dummy; - - Get_full_filename(filename,0); - - File_error=0; - - if ((LBM_file=fopen(filename, "rb"))) - { - if (! Read_bytes(LBM_file,section,4)) - File_error=1; - else - if (memcmp(section,"FORM",4)) - File_error=1; - else - { - Read_dword_be(LBM_file, &dummy); - // On aurait pu vérifier que ce long est égal à la taille - // du fichier - 8, mais ça aurait interdit de charger des - // fichiers tronqués (et déjà que c'est chiant de perdre - // une partie du fichier il faut quand même pouvoir en - // garder un peu... Sinon, moi je pleure :'( !!! ) - if (! Read_bytes(LBM_file,format,4)) - File_error=1; - else - if ( (memcmp(format,"ILBM",4)) && (memcmp(format,"PBM ",4)) ) - File_error=1; - } - fclose(LBM_file); - } - else - File_error=1; -} - - -// -- Lire un fichier au format LBM ----------------------------------------- - - byte Image_HAM; - - // ---------------- Adapter la palette pour les images HAM ---------------- - void Adapt_palette_HAM(void) - { - short i,j,temp; - byte color; - - if (Image_HAM==6) - { - for (i=1; i<=14; i++) - { - // On recopie a palette de base - memcpy(Main_palette+(i<<4),Main_palette,48); - // On modifie les teintes de cette palette - for (j=0; j<16; j++) - { - color=(i<<4)+j; - if (i<=7) - { - if (i&1) - { - temp=Main_palette[j].R+16; - Main_palette[color].R=(temp<63)?temp:63; - } - if (i&2) - { - temp=Main_palette[j].G+16; - Main_palette[color].G=(temp<63)?temp:63; - } - if (i&4) - { - temp=Main_palette[j].B+16; - Main_palette[color].B=(temp<63)?temp:63; - } - } - else - { - if ((i-7)&1) - { - temp=Main_palette[j].R-16; - Main_palette[color].R=(temp>=0)?temp:0; - } - if ((i-7)&2) - { - temp=Main_palette[j].G-16; - Main_palette[color].G=(temp>=0)?temp:0; - } - if ((i-7)&4) - { - temp=Main_palette[j].B-16; - Main_palette[color].B=(temp>=0)?temp:0; - } - } - } - } - // Ici, il reste les 16 dernières couleurs à modifier - for (i=240,j=0; j<16; i++,j++) - { - temp=Main_palette[j].R+8; - Main_palette[i].R=(temp<63)?temp:63; - temp=Main_palette[j].G+8; - Main_palette[i].G=(temp<63)?temp:63; - temp=Main_palette[j].B+8; - Main_palette[i].B=(temp<63)?temp:63; - } - } - else if (Image_HAM==8) - { - for (i=1; i<=3; i++) - { - // On recopie la palette de base - memcpy(Main_palette+(i<<6),Main_palette,192); - // On modifie les teintes de cette palette - for (j=0; j<64; j++) - { - color=(i<<6)+j; - switch (i) - { - case 1 : - temp=Main_palette[j].R+16; - Main_palette[color].R=(temp<63)?temp:63; - break; - case 2 : - temp=Main_palette[j].G+16; - Main_palette[color].G=(temp<63)?temp:63; - break; - default: - temp=Main_palette[j].B+16; - Main_palette[color].B=(temp<63)?temp:63; - } - } - } - } - else // Image 64 couleurs sauvée en 32. - { - for (i=0; i<32; i++) - { - j=i+32; - Main_palette[j].R=Main_palette[i].R>>1; - Main_palette[j].G=Main_palette[i].G>>1; - Main_palette[j].B=Main_palette[i].B>>1; - } - } - } - - // ------------------------- Attendre une section ------------------------- - byte Wait_for(byte * expected_section) - { - // Valeur retournée: 1=Section trouvée, 0=Section non trouvée (erreur) - dword Taille_section; - byte section_read[4]; - - if (! Read_bytes(LBM_file,section_read,4)) - return 0; - while (memcmp(section_read,expected_section,4)) // Sect. pas encore trouvée - { - if (!Read_dword_be(LBM_file,&Taille_section)) - return 0; - if (Taille_section&1) - Taille_section++; - if (fseek(LBM_file,Taille_section,SEEK_CUR)) - return 0; - if (! Read_bytes(LBM_file,section_read,4)) - return 0; - } - return 1; - } - -// Les images ILBM sont stockés en bitplanes donc on doit trifouiller les bits pour -// en faire du chunky - -byte Color_ILBM_line(word x_pos, word real_line_size, byte HBPm1) -{ - // Renvoie la couleur du pixel (ILBM) en x_pos. - // CL sera le rang auquel on extrait les bits de la couleur - byte cl = 7 - (x_pos & 7); - int ax,bh,dx; - byte bl=0; - - for(dx=HBPm1;dx>=0;dx--) - { - //CIL_Loop - ax = (real_line_size * dx + x_pos) >> 3; - bh = (LBM_buffer[ax] >> cl) & 1; - - bl = (bl << 1) + bh; - } - - return bl; -} - - // ----------------------- Afficher une ligne ILBM ------------------------ - void Draw_ILBM_line(short y_pos, short real_line_size) - { - byte color; - byte red,green,blue; - byte temp; - short x_pos; - - if (Image_HAM<=1) // ILBM - { - for (x_pos=0; x_pos>2; - color=Best_color(red,green,blue); - break; - case 0x02: // red - red=temp>>2; - color=Best_color(red,green,blue); - break; - case 0x03: // green - green=temp>>2; - color=Best_color(red,green,blue); - break; - default: // Nouvelle couleur - color=temp; - red=Main_palette[color].R; - green =Main_palette[color].G; - blue =Main_palette[color].B; - } - Pixel_load_function(x_pos,y_pos,color); - } - } - } - - -void Load_LBM(void) -{ - char filename[MAX_PATH_CHARACTERS]; - T_LBM_Header header; - char format[4]; - char section[4]; - byte temp_byte; - short b256; - dword nb_colors; - dword image_size; - short x_pos; - short y_pos; - short counter; - short line_size; // Taille d'une ligne en octets - short real_line_size; // Taille d'une ligne en pixels - byte color; - long file_size; - dword dummy; - - Get_full_filename(filename,0); - - File_error=0; - - if ((LBM_file=fopen(filename, "rb"))) - { - file_size=File_length_file(LBM_file); - - // On avance dans le fichier (pas besoin de tester ce qui l'a déjà été) - Read_bytes(LBM_file,section,4); - Read_dword_be(LBM_file,&dummy); - Read_bytes(LBM_file,format,4); - if (!Wait_for((byte *)"BMHD")) - File_error=1; - Read_dword_be(LBM_file,&dummy); - - // Maintenant on lit le header pour pouvoir commencer le chargement de l'image - if ( (Read_word_be(LBM_file,&header.Width)) - && (Read_word_be(LBM_file,&header.Height)) - && (Read_word_be(LBM_file,&header.X_org)) - && (Read_word_be(LBM_file,&header.Y_org)) - && (Read_byte(LBM_file,&header.BitPlanes)) - && (Read_byte(LBM_file,&header.Mask)) - && (Read_byte(LBM_file,&header.Compression)) - && (Read_byte(LBM_file,&header.Pad1)) - && (Read_word_be(LBM_file,&header.Transp_col)) - && (Read_byte(LBM_file,&header.X_aspect)) - && (Read_byte(LBM_file,&header.Y_aspect)) - && (Read_word_be(LBM_file,&header.X_screen)) - && (Read_word_be(LBM_file,&header.Y_screen)) - && header.Width && header.Height) - { - if ( (header.BitPlanes) && (Wait_for((byte *)"CMAP")) ) - { - Read_dword_be(LBM_file,&nb_colors); - nb_colors/=3; - - if (((dword)1< il faut copier les 32 coul. - } // sur les 32 suivantes et assombrir ces dernières. - else - { - if ((header.BitPlanes==6) || (header.BitPlanes==8)) - Image_HAM=header.BitPlanes; - else - /* File_error=1;*/ /* C'est censé être incorrect mais j'ai */ - Image_HAM=0; /* trouvé un fichier comme ça, alors... */ - } - } - else - Image_HAM=0; - - if ( (!File_error) && (nb_colors>=2) && (nb_colors<=256) ) - { - HBPm1=header.BitPlanes-1; - if (header.Mask==1) - header.BitPlanes++; - - // Deluxe paint le fait... alors on le fait... - Back_color=header.Transp_col; - - // On commence par passer la palette en 256 comme ça, si la nouvelle - // palette a moins de 256 coul, la précédente ne souffrira pas d'un - // assombrissement préjudiciable. - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - else - Palette_64_to_256(Main_palette); - // On peut maintenant charger la nouvelle palette - if (Read_bytes(LBM_file,Main_palette,3*nb_colors)) - { - Palette_256_to_64(Main_palette); - if (Image_HAM) - Adapt_palette_HAM(); - Palette_64_to_256(Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - // On lit l'octet de padding du CMAP si la taille est impaire - if (nb_colors&1) - if (Read_byte(LBM_file,&temp_byte)) - File_error=2; - - if ( (Wait_for((byte *)"BODY")) && (!File_error) ) - { - Read_dword_be(LBM_file,&image_size); - //swab((char *)&header.Width ,(char *)&Main_image_width,2); - //swab((char *)&header.Height,(char *)&Main_image_height,2); - Main_image_width = header.Width; - Main_image_height = header.Height; - - //swab((char *)&header.X_screen,(char *)&Original_screen_X,2); - //swab((char *)&header.Y_screen,(char *)&Original_screen_Y,2); - Original_screen_X = header.X_screen; - Original_screen_Y = header.Y_screen; - - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_LBM,PIXEL_SIMPLE); - if (File_error==0) - { - if (!memcmp(format,"ILBM",4)) // "ILBM": InterLeaved BitMap - { - // Calcul de la taille d'une ligne ILBM (pour les images ayant des dimensions exotiques) - if (Main_image_width & 15) - { - real_line_size=( (Main_image_width+16) >> 4 ) << 4; - line_size=( (Main_image_width+16) >> 4 )*(header.BitPlanes<<1); - } - else - { - real_line_size=Main_image_width; - line_size=(Main_image_width>>3)*header.BitPlanes; - } - - if (!header.Compression) - { // non compressé - LBM_buffer=(byte *)malloc(line_size); - for (y_pos=0; ((y_pos 127 alors il faut répéter 256-'temp_byte' fois la couleur de l'octet suivant - // Si temp_byte <= 127 alors il faut afficher directement les 'temp_byte' octets suivants - if (temp_byte>127) - { - if(Read_byte(LBM_file, &color)!=1) - { - File_error=2; - break; - } - b256=(short)(256-temp_byte); - for (counter=0; counter<=b256; counter++) - if (x_pos=line_size || Read_byte(LBM_file, &(LBM_buffer[x_pos++]))!=1) - File_error=2; - } - if (!File_error) - Draw_ILBM_line(y_pos,real_line_size); - } - - free(LBM_buffer); - /*Close_lecture();*/ - } - } - else // "PBM ": Planar(?) BitMap - { - real_line_size=Main_image_width+(Main_image_width&1); - - if (!header.Compression) - { // non compressé - LBM_buffer=(byte *)malloc(real_line_size); - for (y_pos=0; ((y_pos127) - { - if(Read_byte(LBM_file, &color)!=1) - { - File_error=2; - break; - } - b256=256-temp_byte; - for (counter=0; counter<=b256; counter++) - Pixel_load_function(x_pos++,y_pos,color); - } - else - for (counter=0; counter<=temp_byte; counter++) - { - byte byte_read=0; - if(Read_byte(LBM_file, &byte_read)!=1) - { - File_error=2; - break; - } - Pixel_load_function(x_pos++,y_pos,byte_read); - } - } - } - /*Close_lecture();*/ - } - } - } - } - else - Set_file_error(2); - } - else - { - File_error=1; - } - } - else - Set_file_error(1); - } - else - File_error=1; - } - else - File_error=1; - - fclose(LBM_file); - } - else - File_error=1; -} - - -// -- Sauver un fichier au format LBM --------------------------------------- - - byte LBM_color_list[129]; - word LBM_list_size; - byte LBM_repetition_mode; - - // ------------- Ecrire les couleurs que l'on vient de traiter ------------ - void Transfer_colors(void) - { - byte index; - - if (LBM_list_size>0) - { - if (LBM_repetition_mode) - { - Write_one_byte(LBM_file,257-LBM_list_size); - Write_one_byte(LBM_file,LBM_color_list[0]); - } - else - { - Write_one_byte(LBM_file,LBM_list_size-1); - for (index=0; index et on a 3 couleurs qui se suivent - { - LBM_list_size-=2; - Transfer_colors(); - LBM_color_list[0]=color; - LBM_color_list[1]=color; - LBM_color_list[2]=color; - LBM_list_size=3; - LBM_repetition_mode=1; - } - } - else // La couleur n'est pas la même que la précédente - { - if (!LBM_repetition_mode) // On conserve le mode... - { - LBM_color_list[LBM_list_size++]=color; - if (LBM_list_size==128) - Transfer_colors(); - } - else // On change de mode... - { - Transfer_colors(); - LBM_color_list[LBM_list_size]=color; - LBM_list_size++; - } - } - } - } - - -void Save_LBM(void) -{ - char filename[MAX_PATH_CHARACTERS]; - T_LBM_Header header; - word x_pos; - word y_pos; - byte temp_byte; - word real_width; - int file_size; - - File_error=0; - Get_full_filename(filename,0); - - // Ouverture du fichier - if ((LBM_file=fopen(filename,"wb"))) - { - Write_bytes(LBM_file,"FORM",4); - Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin - - Write_bytes(LBM_file,"PBM BMHD",8); - Write_dword_be(LBM_file,20); - - // On corrige la largeur de l'image pour qu'elle soit multiple de 2 - real_width=Main_image_width+(Main_image_width&1); - - //swab((byte *)&real_width,(byte *)&header.Width,2); - header.Width=Main_image_width; - header.Height=Main_image_height; - header.X_org=0; - header.Y_org=0; - header.BitPlanes=8; - header.Mask=0; - header.Compression=1; - header.Pad1=0; - header.Transp_col=Back_color; - header.X_aspect=1; - header.Y_aspect=1; - header.X_screen = Screen_width; - header.Y_screen = Screen_height; - - Write_word_be(LBM_file,header.Width); - Write_word_be(LBM_file,header.Height); - Write_word_be(LBM_file,header.X_org); - Write_word_be(LBM_file,header.Y_org); - Write_bytes(LBM_file,&header.BitPlanes,1); - Write_bytes(LBM_file,&header.Mask,1); - Write_bytes(LBM_file,&header.Compression,1); - Write_bytes(LBM_file,&header.Pad1,1); - Write_word_be(LBM_file,header.Transp_col); - Write_bytes(LBM_file,&header.X_aspect,1); - Write_bytes(LBM_file,&header.Y_aspect,1); - Write_word_be(LBM_file,header.X_screen); - Write_word_be(LBM_file,header.Y_screen); - - Write_bytes(LBM_file,"CMAP",4); - Write_dword_be(LBM_file,sizeof(T_Palette)); - - Write_bytes(LBM_file,Main_palette,sizeof(T_Palette)); - - Write_bytes(LBM_file,"BODY",4); - Write_dword_be(LBM_file,0); // On mettra la taille à jour à la fin - - Init_write_buffer(); - - LBM_list_size=0; - - for (y_pos=0; ((y_pos on efface le fichier - remove(filename); - } - else - File_error=1; -} - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// BMP //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - word Signature; // ='BM' = 0x4D42 - dword Size_1; // =Taille du fichier - word Reserved_1; // =0 - word Reserved_2; // =0 - dword Offset; // Nb octets avant les données bitmap - - dword Size_2; // =40 - dword Width; - dword Height; - word Planes; // =1 - word Nb_bits; // =1,4,8 ou 24 - dword Compression; - dword Size_3; - dword XPM; - dword YPM; - dword Nb_Clr; - dword Clr_Imprt; -} T_BMP_Header; -#pragma pack() - -// -- Tester si un fichier est au format BMP -------------------------------- -void Test_BMP(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_BMP_Header header; - - File_error=1; - Get_full_filename(filename,0); - - if ((file=fopen(filename, "rb"))) - { - if (Read_bytes(file,&(header.Signature),2) // "BM" - && Read_dword_le(file,&(header.Size_1)) - && Read_word_le(file,&(header.Reserved_1)) - && Read_word_le(file,&(header.Reserved_2)) - && Read_dword_le(file,&(header.Offset)) - && Read_dword_le(file,&(header.Size_2)) - && Read_dword_le(file,&(header.Width)) - && Read_dword_le(file,&(header.Height)) - && Read_word_le(file,&(header.Planes)) - && Read_word_le(file,&(header.Nb_bits)) - && Read_dword_le(file,&(header.Compression)) - && Read_dword_le(file,&(header.Size_3)) - && Read_dword_le(file,&(header.XPM)) - && Read_dword_le(file,&(header.YPM)) - && Read_dword_le(file,&(header.Nb_Clr)) - && Read_dword_le(file,&(header.Clr_Imprt)) - ) - { - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - header.Signature = SDL_Swap16(header.Signature); -#endif - - if ( (header.Signature==0x4D42) && (header.Size_2==40) - && header.Width && header.Height ) - File_error=0; - } - fclose(file); - } -} - -// Find the 8 important bits in a dword -byte Bitmap_mask(dword pixel, dword mask) -{ - byte result; - int i; - int bits_found; - - switch(mask) - { - // Shortcuts to quickly handle the common 24/32bit cases - case 0x000000FF: - return (pixel & 0x000000FF); - case 0x0000FF00: - return (pixel & 0x0000FF00)>>8; - case 0x00FF0000: - return (pixel & 0x00FF0000)>>16; - case 0xFF000000: - return (pixel & 0xFF000000)>>24; - } - // Uncommon : do it bit by bit. - bits_found=0; - result=0; - // Process the mask from low to high bit - for (i=0;i<32;i++) - { - // Found a bit in the mask - if (mask & (1<=8) - return result; - } - } - // Less than 8 bits in the mask: scale the result to 8 bits - return result << (8-bits_found); -} - -// -- Charger un fichier au format BMP -------------------------------------- -void Load_BMP(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_BMP_Header header; - byte * buffer; - word index; - byte local_palette[256][4]; // R,G,B,0 - word nb_colors = 0; - short x_pos; - short y_pos; - word line_size; - byte a,b,c=0; - long file_size; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - - if (Read_word_le(file,&(header.Signature)) - && Read_dword_le(file,&(header.Size_1)) - && Read_word_le(file,&(header.Reserved_1)) - && Read_word_le(file,&(header.Reserved_2)) - && Read_dword_le(file,&(header.Offset)) - && Read_dword_le(file,&(header.Size_2)) - && Read_dword_le(file,&(header.Width)) - && Read_dword_le(file,&(header.Height)) - && Read_word_le(file,&(header.Planes)) - && Read_word_le(file,&(header.Nb_bits)) - && Read_dword_le(file,&(header.Compression)) - && Read_dword_le(file,&(header.Size_3)) - && Read_dword_le(file,&(header.XPM)) - && Read_dword_le(file,&(header.YPM)) - && Read_dword_le(file,&(header.Nb_Clr)) - && Read_dword_le(file,&(header.Clr_Imprt)) - ) - { - switch (header.Nb_bits) - { - case 1 : - case 4 : - case 8 : - if (header.Nb_Clr) - nb_colors=header.Nb_Clr; - else - nb_colors=1<>3; - - buffer=(byte *)malloc(line_size); - for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0; x_pos>1] & 0xF); - else - Pixel_load_function(x_pos,y_pos,buffer[x_pos>>1] >> 4 ); - break; - case 1 : - if ( buffer[x_pos>>3] & (0x80>>(x_pos&7)) ) - Pixel_load_function(x_pos,y_pos,1); - else - Pixel_load_function(x_pos,y_pos,0); - } - else - File_error=2; - } - free(buffer); - break; - - case 1 : // Compression RLE 8 bits - x_pos=0; - y_pos=Main_image_height-1; - - /*Init_lecture();*/ - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; - while (!File_error) - { - if (a) // Encoded mode - for (index=1; index<=a; index++) - Pixel_load_function(x_pos++,y_pos,b); - else // Absolute mode - switch (b) - { - case 0 : // End of line - x_pos=0; - y_pos--; - break; - case 1 : // End of bitmap - break; - case 2 : // Delta - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; - x_pos+=a; - y_pos-=b; - break; - default: // Nouvelle série - while (b) - { - if(Read_byte(file, &a)!=1) - File_error=2; - //Read_one_byte(file, &c); - Pixel_load_function(x_pos++,y_pos,a); - //if (--c) - //{ - // Pixel_load_function(x_pos++,y_pos,c); - // b--; - //} - b--; - } - if (ftell(file) & 1) fseek(file, 1, SEEK_CUR); - } - if (a==0 && b==1) - break; - if(Read_byte(file, &a) !=1 || Read_byte(file, &b)!=1) - { - File_error=2; - } - } - /*Close_lecture();*/ - break; - - case 2 : // Compression RLE 4 bits - x_pos=0; - y_pos=Main_image_height-1; - - /*Init_lecture();*/ - if(Read_byte(file, &a)!=1 || Read_byte(file, &b) != 1) - File_error =2; - while ( (!File_error) && ((a)||(b!=1)) ) - { - if (a) // Encoded mode (A fois les 1/2 pixels de B) - for (index=1; index<=a; index++) - { - if (index & 1) - Pixel_load_function(x_pos,y_pos,b>>4); - else - Pixel_load_function(x_pos,y_pos,b&0xF); - x_pos++; - } - else // Absolute mode - switch (b) - { - case 0 : //End of line - x_pos=0; - y_pos--; - break; - case 1 : // End of bitmap - break; - case 2 : // Delta - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) - File_error=2; - x_pos+=a; - y_pos-=b; - break; - default: // Nouvelle série (B 1/2 pixels bruts) - for (index=1; ((index<=b) && (!File_error)); index++,x_pos++) - { - if (index&1) - { - if(Read_byte(file, &c)!=1) File_error=2; - Pixel_load_function(x_pos,y_pos,c>>4); - } - else - Pixel_load_function(x_pos,y_pos,c&0xF); - } - // On lit l'octet rendant le nombre d'octets pair, si - // nécessaire. Encore un truc de crétin "made in MS". - if ( ((b&3)==1) || ((b&3)==2) ) - { - byte dummy; - if(Read_byte(file, &dummy)!=1) File_error=2; - } - } - if(Read_byte(file, &a)!=1 || Read_byte(file, &b)!=1) File_error=2; - } - /*Close_lecture();*/ - } - fclose(file); - } - else - { - fclose(file); - File_error=1; - } - } - } - else - { - // Image 16/24/32 bits - dword red_mask; - dword green_mask; - dword blue_mask; - if (header.Nb_bits == 16) - { - red_mask = 0x00007C00; - green_mask = 0x000003E0; - blue_mask = 0x0000001F; - } - else - { - red_mask = 0x00FF0000; - green_mask = 0x0000FF00; - blue_mask = 0x000000FF; - } - File_error=0; - - Main_image_width=header.Width; - Main_image_height=header.Height; - Init_preview_24b(header.Width,header.Height,file_size,FORMAT_BMP); - if (File_error==0) - { - switch (header.Compression) - { - case 3: // BI_BITFIELDS - if (!Read_dword_le(file,&red_mask) || - !Read_dword_le(file,&green_mask) || - !Read_dword_le(file,&blue_mask)) - File_error=2; - break; - default: - break; - } - if (fseek(file, header.Offset, SEEK_SET)) - File_error=2; - } - if (File_error==0) - { - switch (header.Nb_bits) - { - // 24bit bitmap - default: - case 24: - line_size=Main_image_width*3; - x_pos=(line_size % 4); // x_pos sert de variable temporaire - if (x_pos>0) - line_size+=(4-x_pos); - - buffer=(byte *)malloc(line_size); - for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0,index=0; x_pos=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0; x_pos=0) && (!File_error)); y_pos--) - { - if (Read_bytes(file,buffer,line_size)) - for (x_pos=0; x_pos> 3)+1) << 3; - else - line_size=Main_image_width; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - header.Signature = 0x424D; -#else - header.Signature = 0x4D42; -#endif - header.Size_1 =(line_size*Main_image_height)+1078; - header.Reserved_1 =0; - header.Reserved_2 =0; - header.Offset =1078; - header.Size_2 =40; - header.Width =Main_image_width; - header.Height =Main_image_height; - header.Planes =1; - header.Nb_bits =8; - header.Compression=0; - header.Size_3 =0; - header.XPM =0; - header.YPM =0; - header.Nb_Clr =0; - header.Clr_Imprt =0; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - header.Size_1 = SDL_Swap32( header.Size_1 ); - header.Offset = SDL_Swap32( header.Offset ); - header.Size_2 = SDL_Swap32( header.Size_2 ); - header.Width = SDL_Swap32( header.Width ); - header.Height = SDL_Swap32( header.Height ); - header.Planes = SDL_Swap16( header.Planes ); - header.Nb_bits = SDL_Swap16( header.Nb_bits ); - // If you ever set any more fields to non-zero, please swap here! -#endif - - if (Write_bytes(file,&header,sizeof(T_BMP_Header))) - { - // Chez Bill, ils ont dit: "On va mettre les couleur dans l'ordre - // inverse, et pour faire chier, on va les mettre sur une échelle de - // 0 à 255 parce que le standard VGA c'est de 0 à 63 (logique!). Et - // puis comme c'est pas assez débile, on va aussi y rajouter un octet - // toujours à 0 pour forcer les gens à s'acheter des gros disques - // durs... Comme ça, ça fera passer la pillule lorsqu'on sortira - // Windows 95." ... - for (index=0; index<256; index++) - { - local_palette[index][0]=Main_palette[index].B; - local_palette[index][1]=Main_palette[index].G; - local_palette[index][2]=Main_palette[index].R; - local_palette[index][3]=0; - } - - if (Write_bytes(file,local_palette,1024)) - { - Init_write_buffer(); - - // ... Et Bill, il a dit: "OK les gars! Mais seulement si vous rangez - // les pixels dans l'ordre inverse, mais que sur les Y quand-même - // parce que faut pas pousser." - for (y_pos=Main_image_height-1; ((y_pos>=0) && (!File_error)); y_pos--) - for (x_pos=0; x_pos>=current_nb_bits; - nb_bits_processed +=current_nb_bits; - nb_bits_to_process-=current_nb_bits; - GIF_remainder_bits -=current_nb_bits; - } - - return GIF_current_code; - } - - // -- Affiche un nouveau pixel -- - - void GIF_new_pixel(byte color) - { - Pixel_load_function(GIF_pos_X,GIF_pos_Y,color); - - GIF_pos_X++; - - if (GIF_pos_X>=Main_image_width) - { - GIF_pos_X=0; - - if (!GIF_interlaced) - GIF_pos_Y++; - else - { - switch (GIF_pass) - { - case 0 : GIF_pos_Y+=8; - break; - case 1 : GIF_pos_Y+=8; - break; - case 2 : GIF_pos_Y+=4; - break; - default: GIF_pos_Y+=2; - } - - if (GIF_pos_Y>=Main_image_height) - { - switch(++GIF_pass) - { - case 1 : GIF_pos_Y=4; - break; - case 2 : GIF_pos_Y=2; - break; - case 3 : GIF_pos_Y=1; - break; - case 4 : GIF_finished_interlaced_image=1; - } - } - } - } - } - - -void Load_GIF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - char signature[6]; - - word * alphabet_stack; // Pile de décodage d'une chaîne - word * alphabet_prefix; // Table des préfixes des codes - word * alphabet_suffix; // Table des suffixes des codes - word alphabet_free; // Position libre dans l'alphabet - word alphabet_max; // Nombre d'entrées possibles dans l'alphabet - word alphabet_stack_pos; // Position dans la pile de décodage d'un chaîne - - T_GIF_LSDB LSDB; - T_GIF_IDB IDB; - - word nb_colors; // Nombre de couleurs dans l'image - word color_index; // index de traitement d'une couleur - byte size_to_read; // Nombre de données à lire (divers) - byte block_indentifier; // Code indicateur du type de bloc en cours - word initial_nb_bits; // Nb de bits au début du traitement LZW - word special_case=0; // Mémoire pour le cas spécial - word old_code=0; // Code précédent - word byte_read; // Sauvegarde du code en cours de lecture - word value_clr; // Valeur <=> Clear tables - word value_eof; // Valeur <=> End d'image - long file_size; - int number_LID; // Nombre d'images trouvées dans le fichier - - /////////////////////////////////////////////////// FIN DES DECLARATIONS // - - - GIF_pos_X=0; - GIF_pos_Y=0; - GIF_last_byte=0; - GIF_remainder_bits=0; - GIF_remainder_byte=0; - number_LID=0; - - Get_full_filename(filename,0); - - if ((GIF_file=fopen(filename, "rb"))) - { - file_size=File_length_file(GIF_file); - if ( (Read_bytes(GIF_file,signature,6)) && - ( (memcmp(signature,"GIF87a",6)==0) || - (memcmp(signature,"GIF89a",6)==0) ) ) - { - - // Allocation de mémoire pour les tables & piles de traitement: - alphabet_stack =(word *)malloc(4096*sizeof(word)); - alphabet_prefix=(word *)malloc(4096*sizeof(word)); - alphabet_suffix=(word *)malloc(4096*sizeof(word)); - - if (Read_word_le(GIF_file,&(LSDB.Width)) - && Read_word_le(GIF_file,&(LSDB.Height)) - && Read_byte(GIF_file,&(LSDB.Resol)) - && Read_byte(GIF_file,&(LSDB.Backcol)) - && Read_byte(GIF_file,&(LSDB.Aspect)) - ) - { - // Lecture du Logical Screen Descriptor Block réussie: - - Original_screen_X=LSDB.Width; - Original_screen_Y=LSDB.Height; - - // Palette globale dispo = (LSDB.Resol and $80) - // Profondeur de couleur =((LSDB.Resol and $70) shr 4)+1 - // Nombre de bits/pixel = (LSDB.Resol and $07)+1 - // Ordre de Classement = (LSDB.Aspect and $80) - - alphabet_stack_pos=0; - GIF_last_byte =0; - GIF_remainder_bits =0; - GIF_remainder_byte =0; - - nb_colors=(1 << ((LSDB.Resol & 0x07)+1)); - initial_nb_bits=(LSDB.Resol & 0x07)+2; - - if (LSDB.Resol & 0x80) - { - // Palette globale dispo: - - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - - // On peut maintenant charger la nouvelle palette: - if (!(LSDB.Aspect & 0x80)) - // Palette dans l'ordre: - for(color_index=0;color_indexnb_char_to_keep) - fseek(GIF_file,size_to_read-nb_char_to_keep,SEEK_CUR); - } - break; - case 0xF9: // Graphics Control Extension - // Prévu pour la transparence - - default: - // On saute le bloc: - fseek(GIF_file,size_to_read,SEEK_CUR); - break; - } - // Lecture de la taille du bloc suivant: - Read_byte(GIF_file,&size_to_read); - } - } - break; - case 0x2C: // Local Image Descriptor - { - // Si on a deja lu une image, c'est une GIF animée ou bizarroide, on sort. - if (number_LID!=0) - { - File_error=2; - break; - } - number_LID++; - - // lecture de 10 derniers octets - if ( Read_word_le(GIF_file,&(IDB.Pos_X)) - && Read_word_le(GIF_file,&(IDB.Pos_Y)) - && Read_word_le(GIF_file,&(IDB.Image_width)) - && Read_word_le(GIF_file,&(IDB.Image_height)) - && Read_byte(GIF_file,&(IDB.Indicator)) - && Read_byte(GIF_file,&(IDB.Nb_bits_pixel)) - && IDB.Image_width && IDB.Image_height) - { - Main_image_width=IDB.Image_width; - Main_image_height=IDB.Image_height; - - Init_preview(IDB.Image_width,IDB.Image_height,file_size,FORMAT_GIF,PIXEL_SIMPLE); - - // Palette locale dispo = (IDB.Indicator and $80) - // Image entrelacée = (IDB.Indicator and $40) - // Ordre de classement = (IDB.Indicator and $20) - // Nombre de bits/pixel = (IDB.Indicator and $07)+1 (si palette locale dispo) - - if (IDB.Indicator & 0x80) - { - // Palette locale dispo - - nb_colors=(1 << ((IDB.Indicator & 0x07)+1)); - initial_nb_bits=(IDB.Indicator & 0x07)+2; - - if (!(IDB.Indicator & 0x40)) - // Palette dans l'ordre: - for(color_index=0;color_indexvalue_clr) - { - alphabet_stack[alphabet_stack_pos++]=alphabet_suffix[GIF_current_code]; - GIF_current_code=alphabet_prefix[GIF_current_code]; - } - - special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code; - - do - GIF_new_pixel(alphabet_stack[--alphabet_stack_pos]); - while (alphabet_stack_pos!=0); - - alphabet_prefix[alphabet_free ]=old_code; - alphabet_suffix[alphabet_free++]=GIF_current_code; - old_code=byte_read; - - if (alphabet_free>alphabet_max) - { - if (GIF_nb_bits<12) - alphabet_max =((1 << (++GIF_nb_bits))-1); - } - } - else // Code Clear rencontré - { - GIF_nb_bits =initial_nb_bits; - alphabet_max =((1 << GIF_nb_bits)-1); - alphabet_free =nb_colors+2; - special_case =GIF_get_next_code(); - old_code =GIF_current_code; - GIF_new_pixel(GIF_current_code); - } - } - else - File_error=2; - } // Code End-Of-Information ou erreur de fichier rencontré - - /*Close_lecture();*/ - - if (File_error>=0) - if ( /* (GIF_pos_X!=0) || */ - ( ( (!GIF_interlaced) && (GIF_pos_Y!=Main_image_height) ) || - ( (GIF_interlaced) && (!GIF_finished_interlaced_image) ) - ) ) - File_error=2; - } // Le fichier contenait un IDB - else - File_error=2; - } - default: - break; - } - // Lecture du code de fonction suivant: - Read_byte(GIF_file,&block_indentifier); - } - } // Le fichier contenait un LSDB - else - File_error=1; - - // Libération de la mémoire utilisée par les tables & piles de traitement: - free(alphabet_suffix); - free(alphabet_prefix); - free(alphabet_stack); - } // Le fichier contenait au moins la signature GIF87a ou GIF89a - else - File_error=1; - - fclose(GIF_file); - - } // Le fichier était ouvrable - else - File_error=1; -} - - -// -- Sauver un fichier au format GIF --------------------------------------- - - 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 - - // -- Vider le buffer GIF dans le buffer KM -- - - void GIF_empty_buffer(void) - { - word index; - - if (GIF_remainder_byte) - { - GIF_buffer[0]=GIF_remainder_byte; - - for (index=0;index<=GIF_remainder_byte;index++) - Write_one_byte(GIF_file,GIF_buffer[index]); - - GIF_remainder_byte=0; - } - } - - // -- Ecrit un code à GIF_nb_bits -- - - void GIF_set_code(word Code) - { - word nb_bits_to_process=GIF_nb_bits; - word nb_bits_processed =0; - word current_nb_bits; - - while (nb_bits_to_process) - { - current_nb_bits=(nb_bits_to_process<=(8-GIF_remainder_bits))?nb_bits_to_process:(8-GIF_remainder_bits); - - GIF_last_byte|=(Code & ((1<>=current_nb_bits; - GIF_remainder_bits +=current_nb_bits; - nb_bits_processed +=current_nb_bits; - nb_bits_to_process-=current_nb_bits; - - if (GIF_remainder_bits==8) // Il ne reste plus de bits à coder sur l'octet courant - { - // Ecrire l'octet à balancer: - GIF_buffer[++GIF_remainder_byte]=GIF_last_byte; - - // Si on a atteint la fin du bloc de Raster Data - if (GIF_remainder_byte==255) - // On doit vider le buffer qui est maintenant plein - GIF_empty_buffer(); - - GIF_last_byte=0; - GIF_remainder_bits=0; - } - } - } - - - // -- Lire le pixel suivant -- - - byte GIF_next_pixel(void) - { - byte temp; - - temp=Read_pixel_function(GIF_pos_X,GIF_pos_Y); - - if (++GIF_pos_X>=Main_image_width) - { - GIF_pos_X=0; - if (++GIF_pos_Y>=Main_image_height) - GIF_stop=1; - } - - return temp; - } - - - -void Save_GIF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - - word * alphabet_prefix; // Table des préfixes des codes - word * alphabet_suffix; // Table des suffixes des codes - word * alphabet_daughter; // Table des chaînes filles (plus longues) - word * alphabet_sister; // Table des chaînes soeurs (même longueur) - word alphabet_free; // Position libre dans l'alphabet - word alphabet_max; // Nombre d'entrées possibles dans l'alphabet - word start; // Code précédent (sert au linkage des chaînes) - int descend; // Booléen "On vient de descendre" - - T_GIF_LSDB LSDB; - T_GIF_IDB IDB; - - - byte block_indentifier; // Code indicateur du type de bloc en cours - word current_string; // Code de la chaîne en cours de traitement - byte current_char; // Caractère à coder - word index; // index de recherche de chaîne - - - /////////////////////////////////////////////////// FIN DES DECLARATIONS // - - - GIF_pos_X=0; - GIF_pos_Y=0; - GIF_last_byte=0; - GIF_remainder_bits=0; - GIF_remainder_byte=0; - - Get_full_filename(filename,0); - - if ((GIF_file=fopen(filename,"wb"))) - { - // On écrit la signature du fichier - if (Write_bytes(GIF_file,"GIF89a",6)) - { - // La signature du fichier a été correctement écrite. - - // Allocation de mémoire pour les tables - alphabet_prefix=(word *)malloc(4096*sizeof(word)); - alphabet_suffix=(word *)malloc(4096*sizeof(word)); - alphabet_daughter =(word *)malloc(4096*sizeof(word)); - alphabet_sister =(word *)malloc(4096*sizeof(word)); - - // On initialise le LSDB du fichier - if (Config.Screen_size_in_GIF) - { - LSDB.Width=Screen_width; - LSDB.Height=Screen_height; - } - else - { - LSDB.Width=Main_image_width; - LSDB.Height=Main_image_height; - } - LSDB.Resol =0x97; // Image en 256 couleurs, avec une palette - LSDB.Backcol=0; - LSDB.Aspect =0; // Palette normale - - // On sauve le LSDB dans le fichier - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - LSDB.Width = SDL_Swap16(LSDB.Width); - LSDB.Height = SDL_Swap16(LSDB.Height); -#endif - - if (Write_bytes(GIF_file,&LSDB,sizeof(T_GIF_LSDB))) - { - // Le LSDB a été correctement écrit. - - // On sauve la palette - if (Write_bytes(GIF_file,Main_palette,768)) - { - // La palette a été correctement écrite. - - // Le jour où on se servira des blocks d'extensions pour placer - // des commentaires, on le fera ici. - - // Ecriture de la transparence - //Write_bytes(GIF_file,"\x21\xF9\x04\x01\x00\x00\xNN\x00",8); - - // Ecriture du commentaire - if (Main_comment[0]) - { - Write_bytes(GIF_file,"\x21\xFE",2); - Write_byte(GIF_file,strlen(Main_comment)); - Write_bytes(GIF_file,Main_comment,strlen(Main_comment)+1); - } - - - - // On va écrire un block indicateur d'IDB et l'IDB du fichier - - block_indentifier=0x2C; - IDB.Pos_X=0; - IDB.Pos_Y=0; - IDB.Image_width=Main_image_width; - IDB.Image_height=Main_image_height; - IDB.Indicator=0x07; // Image non entrelacée, pas de palette locale. - IDB.Nb_bits_pixel=8; // Image 256 couleurs; - -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - IDB.Image_width = SDL_Swap16(IDB.Image_width); - IDB.Image_height = SDL_Swap16(IDB.Image_height); -#endif - - if ( Write_bytes(GIF_file,&block_indentifier,1) && - Write_bytes(GIF_file,&IDB,sizeof(T_GIF_IDB)) ) - { - // Le block indicateur d'IDB et l'IDB ont étés correctements - // écrits. - - Init_write_buffer(); - - index=4096; - File_error=0; - GIF_stop=0; - - // Réintialisation de la table: - alphabet_free=258; - GIF_nb_bits =9; - alphabet_max =511; - GIF_set_code(256); - for (start=0;start<4096;start++) - { - alphabet_daughter[start]=4096; - alphabet_sister[start]=4096; - } - - ////////////////////////////////////////////// COMPRESSION LZW // - - start=current_string=GIF_next_pixel(); - descend=1; - - do - { - current_char=GIF_next_pixel(); - - // On regarde si dans la table on aurait pas une chaîne - // équivalente à current_string+Caractere - - while ( (index0xFFF) - { - // Réintialisation de la table: - GIF_set_code(256); - alphabet_free=258; - GIF_nb_bits =9; - alphabet_max =511; - for (start=0;start<4096;start++) - { - alphabet_daughter[start]=4096; - alphabet_sister[start]=4096; - } - } - else if (alphabet_free>alphabet_max+1) - { - // On augmente le nb de bits - - GIF_nb_bits++; - alphabet_max=(1< 16c , 1 => 256c , ... - word Bytes_per_plane_line;// Doit toujours être pair - word Palette_info; // 1 => color , 2 => Gris (ignoré à partir de la version 4) - word Screen_X; // |_ Dimensions de - word Screen_Y; // | l'écran d'origine - byte Filler[54]; // Ca... J'adore! - } T_PCX_Header; -#pragma pack() - -T_PCX_Header PCX_header; - -// -- Tester si un fichier est au format PCX -------------------------------- - -void Test_PCX(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - - File_error=0; - Get_full_filename(filename,0); - - if ((file=fopen(filename, "rb"))) - { - if (Read_byte(file,&(PCX_header.Manufacturer)) && - Read_byte(file,&(PCX_header.Version)) && - Read_byte(file,&(PCX_header.Compression)) && - Read_byte(file,&(PCX_header.Depth)) && - Read_word_le(file,&(PCX_header.X_min)) && - Read_word_le(file,&(PCX_header.Y_min)) && - Read_word_le(file,&(PCX_header.X_max)) && - Read_word_le(file,&(PCX_header.Y_max)) && - Read_word_le(file,&(PCX_header.X_dpi)) && - Read_word_le(file,&(PCX_header.Y_dpi)) && - Read_bytes(file,&(PCX_header.Palette_16c),48) && - Read_byte(file,&(PCX_header.Reserved)) && - Read_byte(file,&(PCX_header.Plane)) && - Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && - Read_word_le(file,&(PCX_header.Palette_info)) && - Read_word_le(file,&(PCX_header.Screen_X)) && - Read_word_le(file,&(PCX_header.Screen_Y)) && - Read_bytes(file,&(PCX_header.Filler),54) ) - { - - // Vu que ce header a une signature de merde et peu significative, il - // va falloir que je teste différentes petites valeurs dont je connais - // l'intervalle. Grrr! - if ( (PCX_header.Manufacturer!=10) - || (PCX_header.Compression>1) - || ( (PCX_header.Depth!=1) && (PCX_header.Depth!=2) && (PCX_header.Depth!=4) && (PCX_header.Depth!=8) ) - || ( (PCX_header.Plane!=1) && (PCX_header.Plane!=2) && (PCX_header.Plane!=4) && (PCX_header.Plane!=8) && (PCX_header.Plane!=3) ) - || (PCX_header.X_max>((reduction_minus_one-(x_pos%reduction))*depth)) & byte_mask; - Pixel_load_function(x_pos,y_pos,color); - } - } - -void Load_PCX(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - - short line_size; - short real_line_size; // width de l'image corrigée - short width_read; - short x_pos; - short y_pos; - byte byte1; - byte byte2; - byte index; - dword nb_colors; - long file_size; - byte palette_CGA[9]={ 84,252,252, 252, 84,252, 252,252,252}; - - long position; - long image_size; - byte * buffer; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - /* - if (Read_bytes(file,&PCX_header,sizeof(T_PCX_Header))) - {*/ - - if (Read_byte(file,&(PCX_header.Manufacturer)) && - Read_byte(file,&(PCX_header.Version)) && - Read_byte(file,&(PCX_header.Compression)) && - Read_byte(file,&(PCX_header.Depth)) && - Read_word_le(file,&(PCX_header.X_min)) && - Read_word_le(file,&(PCX_header.Y_min)) && - Read_word_le(file,&(PCX_header.X_max)) && - Read_word_le(file,&(PCX_header.Y_max)) && - Read_word_le(file,&(PCX_header.X_dpi)) && - Read_word_le(file,&(PCX_header.Y_dpi)) && - Read_bytes(file,&(PCX_header.Palette_16c),48) && - Read_byte(file,&(PCX_header.Reserved)) && - Read_byte(file,&(PCX_header.Plane)) && - Read_word_le(file,&(PCX_header.Bytes_per_plane_line)) && - Read_word_le(file,&(PCX_header.Palette_info)) && - Read_word_le(file,&(PCX_header.Screen_X)) && - Read_word_le(file,&(PCX_header.Screen_Y)) && - Read_bytes(file,&(PCX_header.Filler),54) ) - { - - Main_image_width=PCX_header.X_max-PCX_header.X_min+1; - Main_image_height=PCX_header.Y_max-PCX_header.Y_min+1; - - Original_screen_X=PCX_header.Screen_X; - Original_screen_Y=PCX_header.Screen_Y; - - if (PCX_header.Plane!=3) - { - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_PCX,PIXEL_SIMPLE); - if (File_error==0) - { - // On prépare la palette à accueillir les valeurs du fichier PCX - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - nb_colors=(dword)(1<4) - memcpy(Main_palette,PCX_header.Palette_16c,48); - else - { - Main_palette[1].R=0; - Main_palette[1].G=0; - Main_palette[1].B=0; - byte1=PCX_header.Palette_16c[3]>>5; - if (nb_colors==4) - { // Pal. CGA "alakon" (du Turc Allahkoum qui signifie "à la con" :)) - memcpy(Main_palette+1,palette_CGA,9); - if (!(byte1&2)) - { - Main_palette[1].B=84; - Main_palette[2].B=84; - Main_palette[3].B=84; - } - } // Palette monochrome (on va dire que c'est du N&B) - else - { - Main_palette[1].R=252; - Main_palette[1].G=252; - Main_palette[1].B=252; - } - } - - // On se positionne à la fin du fichier - 769 octets pour voir s'il y - // a une palette. - if ( (PCX_header.Depth==8) && (PCX_header.Version>=5) && (file_size>(256*3)) ) - { - fseek(file,file_size-((256*3)+1),SEEK_SET); - // On regarde s'il y a une palette après les données de l'image - if (Read_byte(file,&byte1)) - if (byte1==12) // Lire la palette si c'est une image en 256 couleurs - { - int index; - // On lit la palette 256c que ces crétins ont foutue à la fin du fichier - for(index=0;index<256;index++) - if ( ! Read_byte(file,&Main_palette[index].R) - || ! Read_byte(file,&Main_palette[index].G) - || ! Read_byte(file,&Main_palette[index].B) ) - { - File_error=2; - DEBUG("ERROR READING PCX PALETTE !",index); - break; - } - } - } - Set_palette(Main_palette); - Remap_fileselector(); - - // Maintenant qu'on a lu la palette que ces crétins sont allés foutre - // à la fin, on retourne juste après le header pour lire l'image. - fseek(file,128,SEEK_SET); - if (!File_error) - { - line_size=PCX_header.Bytes_per_plane_line*PCX_header.Plane; - real_line_size=(short)PCX_header.Bytes_per_plane_line<<3; - // On se sert de données LBM car le dessin de ligne en moins de 256 - // couleurs se fait comme avec la structure ILBM. - Image_HAM=0; - HBPm1=PCX_header.Plane-1; - LBM_buffer=(byte *)malloc(line_size); - - // Chargement de l'image - if (PCX_header.Compression) // Image compressée - { - /*Init_lecture();*/ - - image_size=(long)PCX_header.Bytes_per_plane_line*Main_image_height; - - if (PCX_header.Depth==8) // 256 couleurs (1 plan) - { - for (position=0; ((position=line_size) - { - for (x_pos=0; x_pos=line_size) - { - for (x_pos=0; x_pos1) || (last_pixel>=0xC0) ) - Write_one_byte(file,counter|0xC0); - Write_one_byte(file,last_pixel); - - } - } - - // Ecriture de l'octet (12) indiquant que la palette arrive - if (!File_error) - Write_one_byte(file,12); - - End_write(file); - - // Ecriture de la palette - if (!File_error) - { - if (! Write_bytes(file,Main_palette,sizeof(T_Palette))) - File_error=1; - } - } - else - File_error=1; - - fclose(file); - - if (File_error) - remove(filename); - - } - else - File_error=1; -} - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// CEL //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - word Width; // width de l'image - word Height; // height de l'image -} T_CEL_Header1; - -typedef struct -{ - byte Signature[4]; // Signature du format - byte Kind; // Type de fichier ($10=PALette $20=BitMaP) - byte Nb_bits; // Nombre de bits - word Filler1; // ??? - word Width; // width de l'image - word Height; // height de l'image - word X_offset; // Offset en X de l'image - word Y_offset; // Offset en Y de l'image - byte Filler2[16]; // ??? -} T_CEL_Header2; -#pragma pack() - -// -- Tester si un fichier est au format CEL -------------------------------- - -void Test_CEL(void) -{ - char filename[MAX_PATH_CHARACTERS]; - int size; - FILE *file; - T_CEL_Header1 header1; - T_CEL_Header2 header2; - int file_size; - - File_error=0; - Get_full_filename(filename,0); - file_size=File_length(filename); - if (file_size==0) - { - File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber - return; - } - - if (! (file=fopen(filename, "rb"))) - { - File_error = 1; - return; - } - if (Read_word_le(file,&header1.Width) && - Read_word_le(file,&header1.Height) ) - { - // Vu que ce header n'a pas de signature, il va falloir tester la - // cohérence de la dimension de l'image avec celle du fichier. - - size=file_size-sizeof(T_CEL_Header1); - if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) ) - { - // Tentative de reconnaissance de la signature des nouveaux fichiers - - fseek(file,0,SEEK_SET); - if (Read_bytes(file,&header2.Signature,4) && - !memcmp(header2.Signature,"KiSS",4) && - Read_byte(file,&header2.Kind) && - (header2.Kind==0x20) && - Read_byte(file,&header2.Nb_bits) && - Read_word_le(file,&header2.Filler1) && - Read_word_le(file,&header2.Width) && - Read_word_le(file,&header2.Height) && - Read_word_le(file,&header2.X_offset) && - Read_word_le(file,&header2.Y_offset) && - Read_bytes(file,&header2.Filler2,16)) - { - // ok - } - else - File_error=1; - } - else - File_error=1; - } - else - { - File_error=1; - } - fclose(file); -} - - -// -- Lire un fichier au format CEL ----------------------------------------- - -void Load_CEL(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_CEL_Header1 header1; - T_CEL_Header2 header2; - short x_pos; - short y_pos; - byte last_byte=0; - long file_size; - - File_error=0; - Get_full_filename(filename,0); - if ((file=fopen(filename, "rb"))) - { - if (Read_bytes(file,&header1,sizeof(T_CEL_Header1))) - { - file_size=File_length_file(file); - if ( (file_size>(long int)sizeof(T_CEL_Header1)) - && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-(long int)sizeof(T_CEL_Header1)) ) ) - { - // Chargement d'un fichier CEL sans signature (vieux fichiers) - Main_image_width=header1.Width; - Main_image_height=header1.Height; - Original_screen_X=Main_image_width; - Original_screen_Y=Main_image_height; - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); - if (File_error==0) - { - // Chargement de l'image - /*Init_lecture();*/ - for (y_pos=0;((y_pos> 4)); - } - else - Pixel_load_function(x_pos,y_pos,(last_byte & 15)); - /*Close_lecture();*/ - } - } - else - { - // On réessaye avec le nouveau format - - fseek(file,0,SEEK_SET); - if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) - { - // Chargement d'un fichier CEL avec signature (nouveaux fichiers) - - Main_image_width=header2.Width+header2.X_offset; - Main_image_height=header2.Height+header2.Y_offset; - Original_screen_X=Main_image_width; - Original_screen_Y=Main_image_height; - Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); - if (File_error==0) - { - // Chargement de l'image - /*Init_lecture();*/ - - if (!File_error) - { - // Effacement du décalage - for (y_pos=0;y_pos> 4)); - } - else - Pixel_load_function(x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15)); - break; - - case 8: - for (y_pos=0;((y_pos16 sont utilisées dans l'image - for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++); - - if (x_pos==256) - { - // Cas d'une image 16 couleurs (écriture à l'ancien format) - - header1.Width =Main_image_width; - header1.Height=Main_image_height; - - if (Write_bytes(file,&header1,sizeof(T_CEL_Header1))) - { - // Sauvegarde de l'image - Init_write_buffer(); - for (y_pos=0;((y_pos>4)!=0) - File_error=1; - } - else - { - if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) - { - if (memcmp(header2.Signature,"KiSS",4)==0) - { - if (header2.Kind!=0x10) - File_error=1; - } - else - File_error=1; - } - else - File_error=1; - } - fclose(file); - } - else - File_error=1; -} - - -// -- Lire un fichier au format KCF ----------------------------------------- - -void Load_KCF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_KCF_Header buffer; - T_CEL_Header2 header2; - byte bytes[3]; - int pal_index; - int color_index; - int index; - long file_size; - - - File_error=0; - Get_full_filename(filename,0); - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - if (file_size==sizeof(T_KCF_Header)) - { - // Fichier KCF à l'ancien format - - if (Read_bytes(file,&buffer,sizeof(T_KCF_Header))) - { - // Init_preview(?); // Pas possible... pas d'image... - - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - - // Chargement de la palette - for (pal_index=0;pal_index<10;pal_index++) - for (color_index=0;color_index<16;color_index++) - { - index=16+(pal_index*16)+color_index; - Main_palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4); - Main_palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4); - Main_palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4); - } - - for (index=0;index<16;index++) - { - Main_palette[index].R=Main_palette[index+16].R; - Main_palette[index].G=Main_palette[index+16].G; - Main_palette[index].B=Main_palette[index+16].B; - } - - Set_palette(Main_palette); - Remap_fileselector(); - } - else - File_error=1; - } - else - { - // Fichier KCF au nouveau format - - if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) - { - // Init_preview(?); // Pas possible... pas d'image... - - index=(header2.Nb_bits==12)?16:0; - for (pal_index=0;pal_index> 4) << 4; - Main_palette[index].B=(bytes[0] & 15) << 4; - Main_palette[index].G=(bytes[1] & 15) << 4; - break; - - case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB - Read_bytes(file,bytes,3); - Main_palette[index].R=bytes[0]; - Main_palette[index].G=bytes[1]; - Main_palette[index].B=bytes[2]; - } - - index++; - } - } - - if (header2.Nb_bits==12) - for (index=0;index<16;index++) - { - Main_palette[index].R=Main_palette[index+16].R; - Main_palette[index].G=Main_palette[index+16].G; - Main_palette[index].B=Main_palette[index+16].B; - } - - Set_palette(Main_palette); - Remap_fileselector(); - } - else - File_error=1; - } - fclose(file); - } - else - File_error=1; - - if (!File_error) Draw_palette_preview(); -} - - -// -- Ecrire un fichier au format KCF --------------------------------------- - -void Save_KCF(void) -{ - char filename[MAX_PATH_CHARACTERS]; - FILE *file; - T_KCF_Header buffer; - T_CEL_Header2 header2; - byte bytes[3]; - int pal_index; - int color_index; - int index; - dword Utilisation[256]; // Table d'utilisation de couleurs - - // On commence par compter l'utilisation de chaque couleurs - Count_used_colors(Utilisation); - - File_error=0; - Get_full_filename(filename,0); - if ((file=fopen(filename,"wb"))) - { - // Sauvegarde de la palette - - // On regarde si des couleurs >16 sont utilisées dans l'image - for (index=16;((index<256) && (!Utilisation[index]));index++); - - if (index==256) - { - // Cas d'une image 16 couleurs (écriture à l'ancien format) - - for (pal_index=0;pal_index<10;pal_index++) - for (color_index=0;color_index<16;color_index++) - { - index=16+(pal_index*16)+color_index; - buffer.Palette[pal_index].color[color_index].Byte1=((Main_palette[index].R>>4)<<4) | (Main_palette[index].B>>4); - buffer.Palette[pal_index].color[color_index].Byte2=Main_palette[index].G>>4; - } - - if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header))) - File_error=1; - } - else - { - // Cas d'une image 256 couleurs (écriture au nouveau format) - - memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature - header2.Kind=0x10; // Initialisation du type (PALette) - header2.Nb_bits=24; // Initialisation du nombre de bits - header2.Filler1=0; // Initialisation du filler 1 (?) - header2.Width=256; // Initialisation du nombre de couleurs - header2.Height=1; // Initialisation du nombre de palettes - header2.X_offset=0; // Initialisation du décalage X - header2.Y_offset=0; // Initialisation du décalage Y - for (index=0;index<16;index++) // Initialisation du filler 2 (?) - header2.Filler2[index]=0; - - if (! Write_bytes(file,&header2,sizeof(T_CEL_Header2))) - File_error=1; - - for (index=0;(index<256) && (!File_error);index++) - { - bytes[0]=Main_palette[index].R; - bytes[1]=Main_palette[index].G; - bytes[2]=Main_palette[index].B; - if (! Write_bytes(file,bytes,3)) - File_error=1; - } - } - - fclose(file); - - if (File_error) - remove(filename); - } - else - File_error=1; -} - - - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// SCx //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -#pragma pack(1) -typedef struct -{ - byte Filler1[4]; - word Width; - word Height; - byte Filler2; - byte Planes; -} T_SCx_Header; -#pragma pack() - -// -- Tester si un fichier est au format SCx -------------------------------- -void Test_SCx(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - //byte Signature[3]; - T_SCx_Header SCx_header; - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture et vérification de la signature - if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) - { - if ( (!memcmp(SCx_header.Filler1,"RIX",3)) - && SCx_header.Width && SCx_header.Height) - File_error=0; - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format SCx ----------------------------------------- -void Load_SCx(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - word x_pos,y_pos; - long size,real_size; - long file_size; - T_SCx_Header SCx_header; - T_Palette SCx_Palette; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - file_size=File_length_file(file); - - if ((Read_bytes(file,&SCx_header,sizeof(T_SCx_Header)))) - { - Init_preview(SCx_header.Width,SCx_header.Height,file_size,FORMAT_SCx,PIXEL_SIMPLE); - if (File_error==0) - { - if (!SCx_header.Planes) - size=sizeof(T_Palette); - else - size=sizeof(T_Components)*(1<>3)*SCx_header.Planes; - real_size=(size/SCx_header.Planes)<<3; - LBM_buffer=(byte *)malloc(size); - HBPm1=SCx_header.Planes-1; - Image_HAM=0; - - for (y_pos=0;(y_pos>=1; - } -} - -//// CODAGE d'une partie d'IMAGE //// - -void PI1_16p_to_8b(byte * src,byte * dest) -{ - int i; // index du pixel à calculer - word byte_mask; // Masque de codage - word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination - - byte_mask=0x8000; - w0=w1=w2=w3=0; - for (i=0;i<16;i++) - { - // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit - // correspondant à celui du masque - - w0|=(src[i] & 0x01)?byte_mask:0x00; - w1|=(src[i] & 0x02)?byte_mask:0x00; - w2|=(src[i] & 0x04)?byte_mask:0x00; - w3|=(src[i] & 0x08)?byte_mask:0x00; - byte_mask>>=1; - } - dest[0]=w0 >> 8; - dest[1]=w0 & 0x00FF; - dest[2]=w1 >> 8; - dest[3]=w1 & 0x00FF; - dest[4]=w2 >> 8; - dest[5]=w2 & 0x00FF; - dest[6]=w3 >> 8; - dest[7]=w3 & 0x00FF; -} - -//// DECODAGE de la PALETTE //// - -void PI1_decode_palette(byte * src,byte * palette) -{ - int i; // Numéro de la couleur traitée - int ip; // index dans la palette - word w; // Word contenant le code - - // Schéma d'un word = - // - // Low High - // VVVV RRRR | 0000 BBBB - // 0321 0321 | 0321 - - ip=0; - for (i=0;i<16;i++) - { - w=((word)src[(i*2)+1]<<8) | src[(i*2)+0]; - - // Traitement des couleurs rouge, verte et bleue: - palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4; - palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4; - palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4; - } -} - -//// CODAGE de la PALETTE //// - -void PI1_code_palette(byte * palette,byte * dest) -{ - int i; // Numéro de la couleur traitée - int ip; // index dans la palette - word w; // Word contenant le code - - // Schéma d'un word = - // - // Low High - // VVVV RRRR | 0000 BBBB - // 0321 0321 | 0321 - - ip=0; - for (i=0;i<16;i++) - { - // Traitement des couleurs rouge, verte et bleue: - w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++; - w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++; - w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++; - - dest[(i*2)+0]=w & 0x00FF; - dest[(i*2)+1]=(w>>8); - } -} - - -// -- Tester si un fichier est au format PI1 -------------------------------- -void Test_PI1(void) -{ - FILE * file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - int size; // Taille du fichier - word resolution; // Résolution de l'image - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Vérification de la taille - size=File_length_file(file); - if ((size==32034) || (size==32066)) - { - // Lecture et vérification de la résolution - if (Read_word_le(file,&resolution)) - { - if (resolution==0x0000) - File_error=0; - } - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format PI1 ----------------------------------------- -void Load_PI1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - word x_pos,y_pos; - byte * buffer; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - if ((file=fopen(filename, "rb"))) - { - // allocation d'un buffer mémoire - buffer=(byte *)malloc(32034); - if (buffer!=NULL) - { - // Lecture du fichier dans le buffer - if (Read_bytes(file,buffer,32034)) - { - // Initialisation de la preview - Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE); - if (File_error==0) - { - // Initialisation de la palette - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - PI1_decode_palette(buffer+2,(byte *)Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - Main_image_width=320; - Main_image_height=200; - - // Chargement/décompression de l'image - ptr=buffer+34; - for (y_pos=0;y_pos<200;y_pos++) - { - for (x_pos=0;x_pos<(320>>4);x_pos++) - { - PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); - ptr+=8; - } - for (x_pos=0;x_pos<320;x_pos++) - Pixel_load_function(x_pos,y_pos,pixels[x_pos]); - } - } - } - else - File_error=1; - free(buffer); - } - else - File_error=1; - fclose(file); - } - else - File_error=1; -} - - -// -- Sauver un fichier au format PI1 --------------------------------------- -void Save_PI1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - short x_pos,y_pos; - byte * buffer; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - // allocation d'un buffer mémoire - buffer=(byte *)malloc(32066); - // Codage de la résolution - buffer[0]=0x00; - buffer[1]=0x00; - // Codage de la palette - PI1_code_palette((byte *)Main_palette,buffer+2); - // Codage de l'image - ptr=buffer+34; - for (y_pos=0;y_pos<200;y_pos++) - { - // Codage de la ligne - memset(pixels,0,320); - if (y_pos>4);x_pos++) - { - PI1_16p_to_8b(pixels+(x_pos<<4),ptr); - ptr+=8; - } - } - - memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy - - if (Write_bytes(file,buffer,32066)) - { - fclose(file); - } - else // Error d'écriture (disque plein ou protégé) - { - fclose(file); - remove(filename); - File_error=1; - } - // Libération du buffer mémoire - free(buffer); - } - else - { - fclose(file); - remove(filename); - File_error=1; - } -} - - - - - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// PC1 //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - - -//// DECOMPRESSION d'un buffer selon la méthode PACKBITS //// - -void PC1_uncompress_packbits(byte * src,byte * dest) -{ - int is,id; // Les indices de parcour des buffers - int n; // Octet de contrôle - - for (is=id=0;id<32000;) - { - n=src[is++]; - - if (n & 0x80) - { - // Recopier src[is] -n+1 fois - n=257-n; - for (;(n>0) && (id<32000);n--) - dest[id++]=src[is]; - is++; - } - else - { - // Recopier n+1 octets littéralement - n=n+1; - for (;(n>0) && (id<32000);n--) - dest[id++]=src[is++]; - } - - // Contrôle des erreurs - if (n>0) - File_error=1; - } -} - -//// COMPRESSION d'un buffer selon la méthode PACKBITS //// - -void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size) -{ - int is; // index dans la source - int id; // index dans la destination - int ir; // index de la répétition - int n; // Taille des séquences - int repet; // "Il y a répétition" - - for (is=id=0;is0;n--) - dest[id++]=src[is++]; - } - - // On code la partie sans répétitions - if (repet) - { - // On compte la quantité de fois qu'il faut répéter la valeur - for (ir+=3;ir>=1; - } - } -} - -//// CODAGE d'une partie d'IMAGE //// - -// Transformation d'1 ligne de pixels en 4 plans de bits - -void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3) -{ - int i,j; // Compteurs - int ip; // index du pixel à calculer - byte byte_mask; // Masque de decodage - byte b0,b1,b2,b3; // Les 4 octets des plans bits sources - - ip=0; - // Pour chacun des 40 octets des plans de bits - for (i=0;i<40;i++) - { - // Pour chacun des 8 bits des octets - byte_mask=0x80; - b0=b1=b2=b3=0; - for (j=0;j<8;j++) - { - b0|=(src[ip] & 0x01)?byte_mask:0x00; - b1|=(src[ip] & 0x02)?byte_mask:0x00; - b2|=(src[ip] & 0x04)?byte_mask:0x00; - b3|=(src[ip] & 0x08)?byte_mask:0x00; - ip++; - byte_mask>>=1; - } - dst0[i]=b0; - dst1[i]=b1; - dst2[i]=b2; - dst3[i]=b3; - } -} - - -// -- Tester si un fichier est au format PC1 -------------------------------- -void Test_PC1(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - int size; // Taille du fichier - word resolution; // Résolution de l'image - - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Vérification de la taille - size=File_length_file(file); - if ((size<=32066)) - { - // Lecture et vérification de la résolution - if (Read_word_le(file,&resolution)) - { - if (resolution==0x0080) - File_error=0; - } - } - // Fermeture du fichier - fclose(file); - } -} - - -// -- Lire un fichier au format PC1 ----------------------------------------- -void Load_PC1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - int size; - word x_pos,y_pos; - byte * buffercomp; - byte * bufferdecomp; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - if ((file=fopen(filename, "rb"))) - { - size=File_length_file(file); - // allocation des buffers mémoire - buffercomp=(byte *)malloc(size); - bufferdecomp=(byte *)malloc(32000); - if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) ) - { - // Lecture du fichier dans le buffer - if (Read_bytes(file,buffercomp,size)) - { - // Initialisation de la preview - Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE); - if (File_error==0) - { - // Initialisation de la palette - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - PI1_decode_palette(buffercomp+2,(byte *)Main_palette); - Set_palette(Main_palette); - Remap_fileselector(); - - Main_image_width=320; - Main_image_height=200; - - // Décompression du buffer - PC1_uncompress_packbits(buffercomp+34,bufferdecomp); - - // Décodage de l'image - ptr=bufferdecomp; - for (y_pos=0;y_pos<200;y_pos++) - { - // Décodage de la scanline - PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels); - ptr+=160; - // Chargement de la ligne - for (x_pos=0;x_pos<320;x_pos++) - Pixel_load_function(x_pos,y_pos,pixels[x_pos]); - } - } - } - else - File_error=1; - free(bufferdecomp); - free(buffercomp); - } - else - { - File_error=1; - free(bufferdecomp); - free(buffercomp); - } - fclose(file); - } - else - File_error=1; -} - - -// -- Sauver un fichier au format PC1 --------------------------------------- -void Save_PC1(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - int size; - short x_pos,y_pos; - byte * buffercomp; - byte * bufferdecomp; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - // Allocation des buffers mémoire - bufferdecomp=(byte *)malloc(32000); - buffercomp =(byte *)malloc(64066); - // Codage de la résolution - buffercomp[0]=0x80; - buffercomp[1]=0x00; - // Codage de la palette - PI1_code_palette((byte *)Main_palette,buffercomp+2); - // Codage de l'image - ptr=bufferdecomp; - for (y_pos=0;y_pos<200;y_pos++) - { - // Codage de la ligne - memset(pixels,0,320); - if (y_pos>4);x_pos++) - { - PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); - ptr+=8; - } - for (x_pos=0;x_pos<320;x_pos++) - Pixel_load_function(x_pos,y_pos,pixels[x_pos]); - } - } - } - else - File_error=1; - free(buffer); - } - else - File_error=1; - fclose(file); - } - else - File_error=1; -} - -void Save_NEO(void) -{ - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - FILE *file; - short x_pos,y_pos; - byte * buffer; - byte * ptr; - byte pixels[320]; - - Get_full_filename(filename,0); - - File_error=0; - // Ouverture du fichier - if ((file=fopen(filename,"wb"))) - { - // allocation d'un buffer mémoire - buffer=(byte *)malloc(32128); - // Codage de la résolution - buffer[0]=0x00; - buffer[1]=0x00; - buffer[2]=0x00; - buffer[3]=0x00; - // Codage de la palette - PI1_code_palette((byte *)Main_palette,buffer+4); - // Codage de l'image - ptr=buffer+128; - for (y_pos=0;y_pos<200;y_pos++) - { - // Codage de la ligne - memset(pixels,0,320); - if (y_pos>4);x_pos++) - { - PI1_16p_to_8b(pixels+(x_pos<<4),ptr); - ptr+=8; - } - } - - if (Write_bytes(file,buffer,32128)) - { - fclose(file); - } - else // Error d'écriture (disque plein ou protégé) - { - fclose(file); - remove(filename); - File_error=1; - } - // Libération du buffer mémoire - free(buffer); - } - else - { - fclose(file); - remove(filename); - File_error=1; - } -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// C64 //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -void Test_C64(void) -{ - FILE* file; - char filename[MAX_PATH_CHARACTERS]; - long file_size; - - Get_full_filename(filename,0); - - file = fopen(filename,"rb"); - - if (file) - { - file_size = File_length_file(file); - switch (file_size) - { - case 1000: // screen or color - case 1002: // (screen or color) + loadaddr - case 8000: // raw bitmap - case 8002: // raw bitmap with loadaddr - case 9000: // bitmap + screen - case 9002: // bitmap + screen + loadaddr - case 10001: // multicolor - case 10003: // multicolor + loadaddr - File_error = 0; - break; - default: // then we don't know for now. - File_error = 1; - } - fclose (file); - } - else - { - File_error = 1; - } -} - -void Load_C64_hires(byte *bitmap, byte *colors) -{ - int cx,cy,x,y,c[4],pixel,color; - - for(cy=0; cy<25; cy++) - { - for(cx=0; cx<40; cx++) - { - c[1]=colors[cy*40+cx]&15; - c[0]=colors[cy*40+cx]>>4; - for(y=0; y<8; y++) - { - pixel=bitmap[cy*320+cx*8+y]; - for(x=0; x<8; x++) - { - color=c[pixel&(1<<(7-x))?1:0]; - Pixel_load_function(cx*8+x,cy*8+y,color); - } - } - } - } -} - -void Load_C64_multi(byte *bitmap, byte *colors, byte *nybble, byte background) -{ - int cx,cy,x,y,c[4],pixel,color; - c[0]=background; - for(cy=0; cy<25; cy++) - { - for(cx=0; cx<40; cx++) - { - c[1]=colors[cy*40+cx]>>4; - c[2]=colors[cy*40+cx]&15; - c[3]=nybble[cy*40+cx]; - - for(y=0; y<8; y++) - { - pixel=bitmap[cy*320+cx*8+y]; - for(x=0; x<4; x++) - { - color=c[(pixel&3)]; - pixel>>=2; - Pixel_load_function(cx*4+(3-x),cy*8+y,color); - } - } - } - } -} - -void Load_C64(void) -{ - FILE* file; - char filename[MAX_PATH_CHARACTERS]; - long file_size; - int i; - byte background,hasLoadAddr=0; - int loadFormat=0; - enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color}; - const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"}; - - // Palette from http://www.pepto.de/projects/colorvic/ - byte pal[48]={ - 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, - 0x68, 0x37, 0x2B, - 0x70, 0xA4, 0xB2, - 0x6F, 0x3D, 0x86, - 0x58, 0x8D, 0x43, - 0x35, 0x28, 0x79, - 0xB8, 0xC7, 0x6F, - 0x6F, 0x4F, 0x25, - 0x43, 0x39, 0x00, - 0x9A, 0x67, 0x59, - 0x44, 0x44, 0x44, - 0x6C, 0x6C, 0x6C, - 0x9A, 0xD2, 0x84, - 0x6C, 0x5E, 0xB5, - 0x95, 0x95, 0x95}; - - byte bitmap[8000],colors[1000],nybble[1000]; - word width=320, height=200; - - Get_full_filename(filename,0); - file = fopen(filename,"rb"); - - if (file) - { - File_error=0; - file_size = File_length_file(file); - - switch (file_size) - { - case 1000: // screen or color - hasLoadAddr=0; - loadFormat=F_screen; - break; - - case 1002: // (screen or color) + loadaddr - hasLoadAddr=1; - loadFormat=F_screen; - break; - - case 8000: // raw bitmap - hasLoadAddr=0; - loadFormat=F_bitmap; - - case 8002: // raw bitmap with loadaddr - hasLoadAddr=1; - loadFormat=F_bitmap; - break; - - case 9000: // bitmap + screen - hasLoadAddr=0; - loadFormat=F_hires; - break; - - case 9002: // bitmap + screen + loadaddr - hasLoadAddr=1; - loadFormat=F_hires; - break; - - case 10001: // multicolor - hasLoadAddr=0; - loadFormat=F_multi; - break; - - case 10003: // multicolor + loadaddr - hasLoadAddr=1; - loadFormat=F_multi; - break; - - default: // then we don't know what it is. - File_error = 1; - - } - - memcpy(Main_palette,pal,48); // this set the software palette for grafx2 - Set_palette(Main_palette); // this set the hardware palette for SDL - Remap_fileselector(); // Always call it if you change the palette - - if (file_size>9002) - width=160; - - if (hasLoadAddr) - { - // get load address - Read_byte(file,&background); - Read_byte(file,&background); - sprintf(filename,"load at $%02x00",background); - } - else - { - sprintf(filename,"no addr"); - } - - if(file_size>9002) - { - Ratio_of_loaded_image = PIXEL_WIDE; - } - sprintf(Main_comment,"C64 %s, %s", - c64_format_names[loadFormat],filename); - Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // Do this as soon as you can - - Main_image_width = width ; - Main_image_height = height; - - Read_bytes(file,bitmap,8000); - - if (file_size>8002) - Read_bytes(file,colors,1000); - else - { - for(i=0;i<1000;i++) - { - colors[i]=1; - } - } - - if(width==160) - { - Read_bytes(file,nybble,1000); - Read_byte(file,&background); - Load_C64_multi(bitmap,colors,nybble,background); - } - else - { - Load_C64_hires(bitmap,colors); - } - - File_error = 0; - fclose(file); - } - else - File_error = 1; -} - -int Save_C64_window(byte *saveWhat, byte *loadAddr) -{ - int button; - unsigned int i; - T_Dropdown_button *what, *addr; - char * what_label[] = { - "All", - "Bitmap", - "Screen", - "Color" - }; - char * address_label[] = { - "None", - "$2000", - "$4000", - "$6000", - "$8000", - "$A000", - "$C000", - "$E000" - }; - - Open_window(200,120,"c64 settings"); - Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN); - Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE); - - Print_in_window(13,18,"Data:",MC_Dark,MC_Light); - what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE); - Window_dropdown_clear_items(what); - for (i=0; i2) - { - Warning_message("More than 2 colors in 8x8 pixels"); - // TODO here we should hilite the offending block - printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors); - return 1; - } - for(i=0;i<16;i++) - { - if(cusage[i]) - { - c2=i; - break; - } - } - c1=c2; - for(i=c2+1;i<16;i++) - { - if(cusage[i]) - { - c1=i; - } - } - colors[cx+cy*40]=(c2<<4)|c1; - - for(y=0; y<8; y++) - { - bits=0; - for(x=0; x<8; x++) - { - pixel=Read_pixel_function(x+cx*8,y+cy*8); - if(pixel>15) - { - Warning_message("Color above 15 used"); - // TODO hilite offending block here too? - // or make it smarter with color allocation? - // However, the palette is fixed to the 16 first colors - return 1; - } - bits=bits<<1; - if (pixel==c1) bits|=1; - } - bitmap[pos++]=bits; - //Write_byte(file,bits&255); - } - } - } - - file = fopen(filename,"wb"); - - if(!file) - { - Warning_message("File open failed"); - File_error = 1; - return 1; - } - - if (loadAddr) - { - Write_byte(file,0); - Write_byte(file,loadAddr); - } - if (saveWhat==0 || saveWhat==1) - Write_bytes(file,bitmap,8000); - if (saveWhat==0 || saveWhat==2) - Write_bytes(file,colors,1000); - - fclose(file); - return 0; -} - -int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr) -{ - /* - BITS COLOR INFORMATION COMES FROM - 00 Background color #0 (screen color) - 01 Upper 4 bits of screen memory - 10 Lower 4 bits of screen memory - 11 Color nybble (nybble = 1/2 byte = 4 bits) - */ - - int cx,cy,x,y,c[4]={0,0,0,0},color,lut[16],bits,pixel,pos=0; - byte bitmap[8000],screen[1000],nybble[1000]; - word numcolors,count; - dword cusage[256]; - byte i,background=0; - FILE *file; - - numcolors=Count_used_colors(cusage); - - count=0; - for(x=0;x<16;x++) - { - //printf("color %d, pixels %d\n",x,cusage[x]); - if(cusage[x]>count) - { - count=cusage[x]; - background=x; - } - } - - for(cy=0; cy<25; cy++) - { - //printf("\ny:%2d ",cy); - for(cx=0; cx<40; cx++) - { - numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8); - if(numcolors>4) - { - Warning_message("More than 4 colors in 4x8"); - // TODO hilite offending block - return 1; - } - color=1; - c[0]=background; - for(i=0; i<16; i++) - { - lut[i]=0; - if(cusage[i]) - { - if(i!=background) - { - lut[i]=color; - c[color]=i; - color++; - } - else - { - lut[i]=0; - } - } - } - // add to screen and nybble - screen[cx+cy*40]=c[1]<<4|c[2]; - nybble[cx+cy*40]=c[3]; - //printf("%x%x%x ",c[1],c[2],c[3]); - for(y=0;y<8;y++) - { - bits=0; - for(x=0;x<4;x++) - { - pixel=Read_pixel_function(cx*4+x,cy*8+y); - if(pixel>15) - { - Warning_message("Color above 15 used"); - // TODO hilite as in hires, you should stay to - // the fixed 16 color palette - return 1; - } - bits=bits<<2; - bits|=lut[pixel]; - - } - //Write_byte(file,bits&255); - bitmap[pos++]=bits; - } - } - } - - file = fopen(filename,"wb"); - - if(!file) - { - Warning_message("File open failed"); - File_error = 1; - return 1; - } - - if (loadAddr) - { - Write_byte(file,0); - Write_byte(file,loadAddr); - } - - if (saveWhat==0 || saveWhat==1) - Write_bytes(file,bitmap,8000); - - if (saveWhat==0 || saveWhat==2) - Write_bytes(file,screen,1000); - - if (saveWhat==0 || saveWhat==3) - Write_bytes(file,nybble,1000); - - if (saveWhat==0) - Write_byte(file,background); - - fclose(file); - //printf("\nbg:%d\n",background); - return 0; -} - -void Save_C64(void) -{ - char filename[MAX_PATH_CHARACTERS]; - static byte saveWhat=0, loadAddr=0; - dword numcolors,cusage[256]; - numcolors=Count_used_colors(cusage); - - Get_full_filename(filename,0); - - if (numcolors>16) - { - Warning_message("Error: Max 16 colors"); - File_error = 1; - return; - } - if (((Main_image_width!=320) && (Main_image_width!=160)) || Main_image_height!=200) - { - Warning_message("must be 320x200 or 160x200"); - File_error = 1; - return; - } - - if(!Save_C64_window(&saveWhat,&loadAddr)) - { - File_error = 1; - return; - } - //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr); - - if (Main_image_width==320) - File_error = Save_C64_hires(filename,saveWhat,loadAddr); - else - File_error = Save_C64_multi(filename,saveWhat,loadAddr); -} - -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -//////////////////////////////////// PNG //////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////// - -#ifndef __no_pnglib__ - -// -- Tester si un fichier est au format PNG -------------------------------- -void Test_PNG(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - byte png_header[8]; - - Get_full_filename(filename,0); - - File_error=1; - - // Ouverture du fichier - if ((file=fopen(filename, "rb"))) - { - // Lecture du header du fichier - if (Read_bytes(file,png_header,8)) - { - if ( !png_sig_cmp(png_header, 0, 8)) - File_error=0; - } - fclose(file); - } -} - -png_bytep * Row_pointers; -// -- Lire un fichier au format PNG ----------------------------------------- -void Load_PNG(void) -{ - FILE *file; // Fichier du fichier - char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier - byte png_header[8]; - byte row_pointers_allocated; - - png_structp png_ptr; - png_infop info_ptr; - - Get_full_filename(filename,0); - - File_error=0; - - if ((file=fopen(filename, "rb"))) - { - // Load header (8 first bytes) - if (Read_bytes(file,png_header,8)) - { - // Do we recognize a png file signature ? - if ( !png_sig_cmp(png_header, 0, 8)) - { - // Prepare internal PNG loader - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr) - { - // Prepare internal PNG loader - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr) - { - png_byte color_type; - png_byte bit_depth; - - // Setup a return point. If a pnglib loading error occurs - // in this if(), the else will be executed. - if (!setjmp(png_jmpbuf(png_ptr))) - { - png_init_io(png_ptr, file); - // Inform pnglib we already loaded the header. - png_set_sig_bytes(png_ptr, 8); - - // Load file information - png_read_info(png_ptr, info_ptr); - color_type = info_ptr->color_type; - bit_depth = info_ptr->bit_depth; - - // If it's any supported file - // (Note: As of writing this, this test covers every possible - // image format of libpng) - if (color_type == PNG_COLOR_TYPE_PALETTE - || color_type == PNG_COLOR_TYPE_GRAY - || color_type == PNG_COLOR_TYPE_GRAY_ALPHA - || color_type == PNG_COLOR_TYPE_RGB - || color_type == PNG_COLOR_TYPE_RGB_ALPHA - ) - { - int num_text; - png_text *text_ptr; - - int unit_type; - png_uint_32 res_x; - png_uint_32 res_y; - - // Comment (tEXt) - Main_comment[0]='\0'; // Clear the previous comment - if ((num_text=png_get_text(png_ptr, info_ptr, &text_ptr, NULL))) - { - while (num_text--) - { - if (!strcmp(text_ptr[num_text].key,"Title")) - { - int size; - size = Min(text_ptr[num_text].text_length, COMMENT_SIZE); - strncpy(Main_comment, text_ptr[num_text].text, size); - Main_comment[size]='\0'; - break; // Skip all others tEXt chunks - } - } - } - // Pixel Ratio (pHYs) - if (png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type)) - { - // Ignore unit, and use the X/Y ratio as a hint for - // WIDE or TALL pixels - if (res_x>0 && res_y>0) - { - if (res_y/res_x>1) - { - Ratio_of_loaded_image=PIXEL_WIDE; - } - else if (res_x/res_y>1) - { - Ratio_of_loaded_image=PIXEL_TALL; - } - } - } - if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) - Init_preview_24b(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG); - else - Init_preview(info_ptr->width,info_ptr->height,File_length_file(file),FORMAT_PNG,Ratio_of_loaded_image); - - if (File_error==0) - { - int x,y; - png_colorp palette; - int num_palette; - - // 16-bit images - if (bit_depth == 16) - { - // Reduce to 8-bit - png_set_strip_16(png_ptr); - } - else if (bit_depth < 8) - { - // Inform libpng we want one byte per pixel, - // even though the file was less than 8bpp - png_set_packing(png_ptr); - } - - // Images with alpha channel - if (color_type & PNG_COLOR_MASK_ALPHA) - { - // Tell libpng to ignore it - png_set_strip_alpha(png_ptr); - } - - // Greyscale images : - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - { - // Map low bpp greyscales to full 8bit (0-255 range) - if (bit_depth < 8) - png_set_gray_1_2_4_to_8(png_ptr); - - // Create greyscale palette - for (x=0;x<256;x++) - { - Main_palette[x].R=x; - Main_palette[x].G=x; - Main_palette[x].B=x; - } - } - else if (color_type == PNG_COLOR_TYPE_PALETTE) // Palette images - { - - if (bit_depth < 8) - { - // Clear unused colors - if (Config.Clear_palette) - memset(Main_palette,0,sizeof(T_Palette)); - } - // Load the palette - png_get_PLTE(png_ptr, info_ptr, &palette, - &num_palette); - for (x=0;xwidth; - Main_image_height=info_ptr->height; - - png_set_interlace_handling(png_ptr); - png_read_update_info(png_ptr, info_ptr); - - // Allocate row pointers - Row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Main_image_height); - row_pointers_allocated = 0; - - /* read file */ - if (!setjmp(png_jmpbuf(png_ptr))) - { - if (color_type == PNG_COLOR_TYPE_GRAY - || color_type == PNG_COLOR_TYPE_GRAY_ALPHA - || color_type == PNG_COLOR_TYPE_PALETTE - ) - { - // 8bpp - - for (y=0; yrowbytes); - row_pointers_allocated = 1; - - png_read_image(png_ptr, Row_pointers); - - for (y=0; yrowbytes); - row_pointers_allocated = 1; - - png_read_image(png_ptr, Row_pointers); - - for (y=0; y +*/ + +///@file miscfileformats.c +/// Formats that aren't fully saving, either because of palette restrictions or other things + +#include "global.h" +#include "limits.h" +#include "loadsave.h" +#include "struct.h" +#include "windows.h" + +//////////////////////////////////// PAL //////////////////////////////////// + +// -- Tester si un fichier est au format PAL -------------------------------- +void Test_PAL(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + long file_size; // Taille du fichier + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture de la taille du fichier + file_size=File_length_file(file); + fclose(file); + // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets + if (file_size==sizeof(T_Palette)) + File_error=0; + } +} + + +// -- Lire un fichier au format PAL ----------------------------------------- +void Load_PAL(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + //long file_size; // Taille du fichier + + + Get_full_filename(filename,0); + File_error=0; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + T_Palette palette_64; + // Init_preview(?); // Pas possible... pas d'image... + + // Lecture du fichier dans Main_palette + if (Read_bytes(file,palette_64,sizeof(T_Palette))) + { + Palette_64_to_256(palette_64); + memcpy(Main_palette,palette_64,sizeof(T_Palette)); + Set_palette(Main_palette); + Remap_fileselector(); + + // On dessine une preview de la palette (si chargement=preview) + Draw_palette_preview(); + } + else + File_error=2; + + // Fermeture du fichier + fclose(file); + } + else + // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur + File_error=1; +} + + +// -- Sauver un fichier au format PAL --------------------------------------- +void Save_PAL(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + //long file_size; // Taille du fichier + + Get_full_filename(filename,0); + + File_error=0; + + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + T_Palette palette_64; + memcpy(palette_64,Main_palette,sizeof(T_Palette)); + Palette_256_to_64(palette_64); + // Enregistrement de Main_palette dans le fichier + if (! Write_bytes(file,palette_64,sizeof(T_Palette))) + { + File_error=1; + fclose(file); + remove(filename); + } + else // Ecriture correcte => Fermeture normale du fichier + fclose(file); + } + else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur + { + File_error=1; + fclose(file); + remove(filename); + // On se fout du résultat de l'opération car si ça + // renvoie 0 c'est que le fichier avait été partiel- + // -lement écrit, sinon pas du tout. Or dans tous les + // cas ça revient au même pour nous: Sauvegarde ratée! + } +} + + +//////////////////////////////////// PKM //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + char Ident[3]; // Chaîne "PKM" } + byte Method; // Compression method + // 0 = compression en ligne (c)KM + // autres = inconnues pour le moment + byte recog1; // Octet de reconnaissance sur 1 octet } + byte recog2; // Octet de reconnaissance sur 2 octets } + word Width; // width de l'image + word Height; // height de l'image + T_Palette Palette; // Palette RVB 256*3 + word Jump; // Taille du saut entre le header et l'image: + // On va s'en servir pour rajouter un commentaire +} T_PKM_Header; +#pragma pack() + +// -- Tester si un fichier est au format PKM -------------------------------- +void Test_PKM(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + T_PKM_Header header; + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Lecture du header du fichier + if (Read_bytes(file,&header,sizeof(T_PKM_Header))) + { + // On regarde s'il y a la signature PKM suivie de la méthode 0. + // La constante "PKM" étant un chaîne, elle se termine toujours par 0. + // Donc pas la peine de s'emm...er à regarder si la méthode est à 0. + if ( (!memcmp(&header,"PKM",4)) && header.Width && header.Height) + File_error=0; + } + fclose(file); + } +} + + +// -- Lire un fichier au format PKM ----------------------------------------- +void Load_PKM(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + T_PKM_Header header; + byte color; + byte temp_byte; + word len; + word index; + dword Compteur_de_pixels; + dword Compteur_de_donnees_packees; + dword image_size; + dword Taille_pack; + long file_size; + + Get_full_filename(filename,0); + + File_error=0; + + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + + if (Read_bytes(file,&header,sizeof(T_PKM_Header))) + { + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + header.Width = SDL_Swap16(header.Width); + header.Height = SDL_Swap16(header.Height); + header.Jump = SDL_Swap16(header.Jump); +#endif + + Main_comment[0]='\0'; // On efface le commentaire + if (header.Jump) + { + index=0; + while ( (indexCOMMENT_SIZE) + { + color=temp_byte; // On se sert de color comme + temp_byte=COMMENT_SIZE; // variable temporaire + color-=COMMENT_SIZE; + } + else + color=0; + + if (Read_bytes(file,Main_comment,temp_byte)) + { + index+=temp_byte; + Main_comment[temp_byte]='\0'; + if (color) + if (fseek(file,color,SEEK_CUR)) + File_error=2; + } + else + File_error=2; + } + else + File_error=2; + break; + + case 1 : // Dimensions de l'écran d'origine + if (Read_byte(file,&temp_byte)) + { + if (temp_byte==4) + { + index+=4; + if ( ! Read_word_le(file,(word *) &Original_screen_X) + || !Read_word_le(file,(word *) &Original_screen_Y) ) + File_error=2; + } + else + File_error=2; + } + else + File_error=2; + break; + + case 2 : // color de transparence + if (Read_byte(file,&temp_byte)) + { + if (temp_byte==1) + { + index++; + if (! Read_byte(file,&Back_color)) + File_error=2; + } + else + File_error=2; + } + else + File_error=2; + break; + + default: + if (Read_byte(file,&temp_byte)) + { + index+=temp_byte; + if (fseek(file,temp_byte,SEEK_CUR)) + File_error=2; + } + else + File_error=2; + } + } + else + File_error=2; + } + if ( (!File_error) && (index!=header.Jump) ) + File_error=2; + } + + /*Init_lecture();*/ + + if (!File_error) + { + Init_preview(header.Width,header.Height,file_size,FORMAT_PKM,PIXEL_SIMPLE); + if (File_error==0) + { + + Main_image_width=header.Width; + Main_image_height=header.Height; + image_size=(dword)(Main_image_width*Main_image_height); + // Palette lue en 64 + memcpy(Main_palette,header.Palette,sizeof(T_Palette)); + Palette_64_to_256(Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Compteur_de_donnees_packees=0; + Compteur_de_pixels=0; + Taille_pack=(file_size)-sizeof(T_PKM_Header)-header.Jump; + + // Boucle de décompression: + while ( (Compteur_de_pixels>8); + Write_one_byte(file,Screen_height&0xFF); + Write_one_byte(file,Screen_height>>8); + // Ecriture de la back-color + Write_one_byte(file,2); + Write_one_byte(file,1); + Write_one_byte(file,Back_color); + + // Routine de compression PKM de l'image + image_size=(dword)(Main_image_width*Main_image_height); + Compteur_de_pixels=0; + pixel_value=Read_pixel_function(0,0); + + while ( (Compteur_de_pixels=image_size) break; + pixel_value=Read_pixel_function(Compteur_de_pixels % Main_image_width,Compteur_de_pixels / Main_image_width); + } + + if ( (last_color!=header.recog1) && (last_color!=header.recog2) ) + { + if (repetitions==1) + Write_one_byte(file,last_color); + else + if (repetitions==2) + { + Write_one_byte(file,last_color); + Write_one_byte(file,last_color); + } + else + if ( (repetitions>2) && (repetitions<256) ) + { // RECON1/couleur/nombre + Write_one_byte(file,header.recog1); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions&0xFF); + } + else + if (repetitions>=256) + { // RECON2/couleur/hi(nombre)/lo(nombre) + Write_one_byte(file,header.recog2); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions>>8); + Write_one_byte(file,repetitions&0xFF); + } + } + else + { + if (repetitions<256) + { + Write_one_byte(file,header.recog1); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions&0xFF); + } + else + { + Write_one_byte(file,header.recog2); + Write_one_byte(file,last_color); + Write_one_byte(file,repetitions>>8); + Write_one_byte(file,repetitions&0xFF); + } + } + } + + End_write(file); + } + else + File_error=1; + fclose(file); + } + else + { + File_error=1; + fclose(file); + } + // S'il y a eu une erreur de sauvegarde, on ne va tout de même pas laisser + // ce fichier pourri traîner... Ca fait pas propre. + if (File_error) + remove(filename); +} + + +//////////////////////////////////// CEL //////////////////////////////////// +#pragma pack(1) +typedef struct +{ + word Width; // width de l'image + word Height; // height de l'image +} T_CEL_Header1; + +typedef struct +{ + byte Signature[4]; // Signature du format + byte Kind; // Type de fichier ($10=PALette $20=BitMaP) + byte Nb_bits; // Nombre de bits + word Filler1; // ??? + word Width; // width de l'image + word Height; // height de l'image + word X_offset; // Offset en X de l'image + word Y_offset; // Offset en Y de l'image + byte Filler2[16]; // ??? +} T_CEL_Header2; +#pragma pack() + +// -- Tester si un fichier est au format CEL -------------------------------- + +void Test_CEL(void) +{ + char filename[MAX_PATH_CHARACTERS]; + int size; + FILE *file; + T_CEL_Header1 header1; + T_CEL_Header2 header2; + int file_size; + + File_error=0; + Get_full_filename(filename,0); + file_size=File_length(filename); + if (file_size==0) + { + File_error = 1; // Si on ne peut pas faire de stat il vaut mieux laisser tomber + return; + } + + if (! (file=fopen(filename, "rb"))) + { + File_error = 1; + return; + } + if (Read_word_le(file,&header1.Width) && + Read_word_le(file,&header1.Height) ) + { + // Vu que ce header n'a pas de signature, il va falloir tester la + // cohérence de la dimension de l'image avec celle du fichier. + + size=file_size-sizeof(T_CEL_Header1); + if ( (!size) || ( (((header1.Width+1)>>1)*header1.Height)!=size ) ) + { + // Tentative de reconnaissance de la signature des nouveaux fichiers + + fseek(file,0,SEEK_SET); + if (Read_bytes(file,&header2.Signature,4) && + !memcmp(header2.Signature,"KiSS",4) && + Read_byte(file,&header2.Kind) && + (header2.Kind==0x20) && + Read_byte(file,&header2.Nb_bits) && + Read_word_le(file,&header2.Filler1) && + Read_word_le(file,&header2.Width) && + Read_word_le(file,&header2.Height) && + Read_word_le(file,&header2.X_offset) && + Read_word_le(file,&header2.Y_offset) && + Read_bytes(file,&header2.Filler2,16)) + { + // ok + } + else + File_error=1; + } + else + File_error=1; + } + else + { + File_error=1; + } + fclose(file); +} + + +// -- Lire un fichier au format CEL ----------------------------------------- + +void Load_CEL(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_CEL_Header1 header1; + T_CEL_Header2 header2; + short x_pos; + short y_pos; + byte last_byte=0; + long file_size; + + File_error=0; + Get_full_filename(filename,0); + if ((file=fopen(filename, "rb"))) + { + if (Read_bytes(file,&header1,sizeof(T_CEL_Header1))) + { + file_size=File_length_file(file); + if ( (file_size>(long int)sizeof(T_CEL_Header1)) + && ( (((header1.Width+1)>>1)*header1.Height)==(file_size-(long int)sizeof(T_CEL_Header1)) ) ) + { + // Chargement d'un fichier CEL sans signature (vieux fichiers) + Main_image_width=header1.Width; + Main_image_height=header1.Height; + Original_screen_X=Main_image_width; + Original_screen_Y=Main_image_height; + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); + if (File_error==0) + { + // Chargement de l'image + /*Init_lecture();*/ + for (y_pos=0;((y_pos> 4)); + } + else + Pixel_load_function(x_pos,y_pos,(last_byte & 15)); + /*Close_lecture();*/ + } + } + else + { + // On réessaye avec le nouveau format + + fseek(file,0,SEEK_SET); + if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) + { + // Chargement d'un fichier CEL avec signature (nouveaux fichiers) + + Main_image_width=header2.Width+header2.X_offset; + Main_image_height=header2.Height+header2.Y_offset; + Original_screen_X=Main_image_width; + Original_screen_Y=Main_image_height; + Init_preview(Main_image_width,Main_image_height,file_size,FORMAT_CEL,PIXEL_SIMPLE); + if (File_error==0) + { + // Chargement de l'image + /*Init_lecture();*/ + + if (!File_error) + { + // Effacement du décalage + for (y_pos=0;y_pos> 4)); + } + else + Pixel_load_function(x_pos+header2.X_offset,y_pos+header2.Y_offset,(last_byte & 15)); + break; + + case 8: + for (y_pos=0;((y_pos16 sont utilisées dans l'image + for (x_pos=16;((x_pos<256) && (!Utilisation[x_pos]));x_pos++); + + if (x_pos==256) + { + // Cas d'une image 16 couleurs (écriture à l'ancien format) + + header1.Width =Main_image_width; + header1.Height=Main_image_height; + + if (Write_bytes(file,&header1,sizeof(T_CEL_Header1))) + { + // Sauvegarde de l'image + Init_write_buffer(); + for (y_pos=0;((y_pos>4)!=0) + File_error=1; + } + else + { + if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) + { + if (memcmp(header2.Signature,"KiSS",4)==0) + { + if (header2.Kind!=0x10) + File_error=1; + } + else + File_error=1; + } + else + File_error=1; + } + fclose(file); + } + else + File_error=1; +} + + +// -- Lire un fichier au format KCF ----------------------------------------- + +void Load_KCF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_KCF_Header buffer; + T_CEL_Header2 header2; + byte bytes[3]; + int pal_index; + int color_index; + int index; + long file_size; + + + File_error=0; + Get_full_filename(filename,0); + if ((file=fopen(filename, "rb"))) + { + file_size=File_length_file(file); + if (file_size==sizeof(T_KCF_Header)) + { + // Fichier KCF à l'ancien format + + if (Read_bytes(file,&buffer,sizeof(T_KCF_Header))) + { + // Init_preview(?); // Pas possible... pas d'image... + + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + + // Chargement de la palette + for (pal_index=0;pal_index<10;pal_index++) + for (color_index=0;color_index<16;color_index++) + { + index=16+(pal_index*16)+color_index; + Main_palette[index].R=((buffer.Palette[pal_index].color[color_index].Byte1 >> 4) << 4); + Main_palette[index].B=((buffer.Palette[pal_index].color[color_index].Byte1 & 15) << 4); + Main_palette[index].G=((buffer.Palette[pal_index].color[color_index].Byte2 & 15) << 4); + } + + for (index=0;index<16;index++) + { + Main_palette[index].R=Main_palette[index+16].R; + Main_palette[index].G=Main_palette[index+16].G; + Main_palette[index].B=Main_palette[index+16].B; + } + + Set_palette(Main_palette); + Remap_fileselector(); + } + else + File_error=1; + } + else + { + // Fichier KCF au nouveau format + + if (Read_bytes(file,&header2,sizeof(T_CEL_Header2))) + { + // Init_preview(?); // Pas possible... pas d'image... + + index=(header2.Nb_bits==12)?16:0; + for (pal_index=0;pal_index> 4) << 4; + Main_palette[index].B=(bytes[0] & 15) << 4; + Main_palette[index].G=(bytes[1] & 15) << 4; + break; + + case 24: // RRRR RRRR | VVVV VVVV | BBBB BBBB + Read_bytes(file,bytes,3); + Main_palette[index].R=bytes[0]; + Main_palette[index].G=bytes[1]; + Main_palette[index].B=bytes[2]; + } + + index++; + } + } + + if (header2.Nb_bits==12) + for (index=0;index<16;index++) + { + Main_palette[index].R=Main_palette[index+16].R; + Main_palette[index].G=Main_palette[index+16].G; + Main_palette[index].B=Main_palette[index+16].B; + } + + Set_palette(Main_palette); + Remap_fileselector(); + } + else + File_error=1; + } + fclose(file); + } + else + File_error=1; + + if (!File_error) Draw_palette_preview(); +} + + +// -- Ecrire un fichier au format KCF --------------------------------------- + +void Save_KCF(void) +{ + char filename[MAX_PATH_CHARACTERS]; + FILE *file; + T_KCF_Header buffer; + T_CEL_Header2 header2; + byte bytes[3]; + int pal_index; + int color_index; + int index; + dword Utilisation[256]; // Table d'utilisation de couleurs + + // On commence par compter l'utilisation de chaque couleurs + Count_used_colors(Utilisation); + + File_error=0; + Get_full_filename(filename,0); + if ((file=fopen(filename,"wb"))) + { + // Sauvegarde de la palette + + // On regarde si des couleurs >16 sont utilisées dans l'image + for (index=16;((index<256) && (!Utilisation[index]));index++); + + if (index==256) + { + // Cas d'une image 16 couleurs (écriture à l'ancien format) + + for (pal_index=0;pal_index<10;pal_index++) + for (color_index=0;color_index<16;color_index++) + { + index=16+(pal_index*16)+color_index; + buffer.Palette[pal_index].color[color_index].Byte1=((Main_palette[index].R>>4)<<4) | (Main_palette[index].B>>4); + buffer.Palette[pal_index].color[color_index].Byte2=Main_palette[index].G>>4; + } + + if (! Write_bytes(file,&buffer,sizeof(T_KCF_Header))) + File_error=1; + } + else + { + // Cas d'une image 256 couleurs (écriture au nouveau format) + + memcpy(header2.Signature,"KiSS",4); // Initialisation de la signature + header2.Kind=0x10; // Initialisation du type (PALette) + header2.Nb_bits=24; // Initialisation du nombre de bits + header2.Filler1=0; // Initialisation du filler 1 (?) + header2.Width=256; // Initialisation du nombre de couleurs + header2.Height=1; // Initialisation du nombre de palettes + header2.X_offset=0; // Initialisation du décalage X + header2.Y_offset=0; // Initialisation du décalage Y + for (index=0;index<16;index++) // Initialisation du filler 2 (?) + header2.Filler2[index]=0; + + if (! Write_bytes(file,&header2,sizeof(T_CEL_Header2))) + File_error=1; + + for (index=0;(index<256) && (!File_error);index++) + { + bytes[0]=Main_palette[index].R; + bytes[1]=Main_palette[index].G; + bytes[2]=Main_palette[index].B; + if (! Write_bytes(file,bytes,3)) + File_error=1; + } + } + + fclose(file); + + if (File_error) + remove(filename); + } + else + File_error=1; +} + + +//////////////////////////////////// PI1 //////////////////////////////////// + +//// DECODAGE d'une partie d'IMAGE //// + +void PI1_8b_to_16p(byte * src,byte * dest) +{ + int i; // index du pixel à calculer + word byte_mask; // Masque de decodage + word w0,w1,w2,w3; // Les 4 words bien ordonnés de la source + + byte_mask=0x8000; + w0=(((word)src[0])<<8) | src[1]; + w1=(((word)src[2])<<8) | src[3]; + w2=(((word)src[4])<<8) | src[5]; + w3=(((word)src[6])<<8) | src[7]; + for (i=0;i<16;i++) + { + // Pour décoder le pixel n°i, il faut traiter les 4 words sur leur bit + // correspondant à celui du masque + + dest[i]=((w0 & byte_mask)?0x01:0x00) | + ((w1 & byte_mask)?0x02:0x00) | + ((w2 & byte_mask)?0x04:0x00) | + ((w3 & byte_mask)?0x08:0x00); + byte_mask>>=1; + } +} + +//// CODAGE d'une partie d'IMAGE //// + +void PI1_16p_to_8b(byte * src,byte * dest) +{ + int i; // index du pixel à calculer + word byte_mask; // Masque de codage + word w0,w1,w2,w3; // Les 4 words bien ordonnés de la destination + + byte_mask=0x8000; + w0=w1=w2=w3=0; + for (i=0;i<16;i++) + { + // Pour coder le pixel n°i, il faut modifier les 4 words sur leur bit + // correspondant à celui du masque + + w0|=(src[i] & 0x01)?byte_mask:0x00; + w1|=(src[i] & 0x02)?byte_mask:0x00; + w2|=(src[i] & 0x04)?byte_mask:0x00; + w3|=(src[i] & 0x08)?byte_mask:0x00; + byte_mask>>=1; + } + dest[0]=w0 >> 8; + dest[1]=w0 & 0x00FF; + dest[2]=w1 >> 8; + dest[3]=w1 & 0x00FF; + dest[4]=w2 >> 8; + dest[5]=w2 & 0x00FF; + dest[6]=w3 >> 8; + dest[7]=w3 & 0x00FF; +} + +//// DECODAGE de la PALETTE //// + +void PI1_decode_palette(byte * src,byte * palette) +{ + int i; // Numéro de la couleur traitée + int ip; // index dans la palette + word w; // Word contenant le code + + // Schéma d'un word = + // + // Low High + // VVVV RRRR | 0000 BBBB + // 0321 0321 | 0321 + + ip=0; + for (i=0;i<16;i++) + { + w=((word)src[(i*2)+1]<<8) | src[(i*2)+0]; + + // Traitement des couleurs rouge, verte et bleue: + palette[ip++]=(((w & 0x0007) << 1) | ((w & 0x0008) >> 3)) << 4; + palette[ip++]=(((w & 0x7000) >> 11) | ((w & 0x8000) >> 15)) << 4; + palette[ip++]=(((w & 0x0700) >> 7) | ((w & 0x0800) >> 11)) << 4; + } +} + +//// CODAGE de la PALETTE //// + +void PI1_code_palette(byte * palette,byte * dest) +{ + int i; // Numéro de la couleur traitée + int ip; // index dans la palette + word w; // Word contenant le code + + // Schéma d'un word = + // + // Low High + // VVVV RRRR | 0000 BBBB + // 0321 0321 | 0321 + + ip=0; + for (i=0;i<16;i++) + { + // Traitement des couleurs rouge, verte et bleue: + w =(((word)(palette[ip]>>2) & 0x38) >> 3) | (((word)(palette[ip]>>2) & 0x04) << 1); ip++; + w|=(((word)(palette[ip]>>2) & 0x38) << 9) | (((word)(palette[ip]>>2) & 0x04) << 13); ip++; + w|=(((word)(palette[ip]>>2) & 0x38) << 5) | (((word)(palette[ip]>>2) & 0x04) << 9); ip++; + + dest[(i*2)+0]=w & 0x00FF; + dest[(i*2)+1]=(w>>8); + } +} + + +// -- Tester si un fichier est au format PI1 -------------------------------- +void Test_PI1(void) +{ + FILE * file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + int size; // Taille du fichier + word resolution; // Résolution de l'image + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Vérification de la taille + size=File_length_file(file); + if ((size==32034) || (size==32066)) + { + // Lecture et vérification de la résolution + if (Read_word_le(file,&resolution)) + { + if (resolution==0x0000) + File_error=0; + } + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format PI1 ----------------------------------------- +void Load_PI1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + word x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + if ((file=fopen(filename, "rb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32034); + if (buffer!=NULL) + { + // Lecture du fichier dans le buffer + if (Read_bytes(file,buffer,32034)) + { + // Initialisation de la preview + Init_preview(320,200,File_length_file(file),FORMAT_PI1,PIXEL_SIMPLE); + if (File_error==0) + { + // Initialisation de la palette + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + PI1_decode_palette(buffer+2,(byte *)Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=320; + Main_image_height=200; + + // Chargement/décompression de l'image + ptr=buffer+34; + for (y_pos=0;y_pos<200;y_pos++) + { + for (x_pos=0;x_pos<(320>>4);x_pos++) + { + PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); + ptr+=8; + } + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(buffer); + } + else + File_error=1; + fclose(file); + } + else + File_error=1; +} + + +// -- Sauver un fichier au format PI1 --------------------------------------- +void Save_PI1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + short x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32066); + // Codage de la résolution + buffer[0]=0x00; + buffer[1]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffer+2); + // Codage de l'image + ptr=buffer+34; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_16p_to_8b(pixels+(x_pos<<4),ptr); + ptr+=8; + } + } + + memset(buffer+32034,0,32); // 32 extra NULL bytes at the end of the file to make ST Deluxe Paint happy + + if (Write_bytes(file,buffer,32066)) + { + fclose(file); + } + else // Error d'écriture (disque plein ou protégé) + { + fclose(file); + remove(filename); + File_error=1; + } + // Libération du buffer mémoire + free(buffer); + } + else + { + fclose(file); + remove(filename); + File_error=1; + } +} + + +//////////////////////////////////// PC1 //////////////////////////////////// + +//// DECOMPRESSION d'un buffer selon la méthode PACKBITS //// + +void PC1_uncompress_packbits(byte * src,byte * dest) +{ + int is,id; // Les indices de parcour des buffers + int n; // Octet de contrôle + + for (is=id=0;id<32000;) + { + n=src[is++]; + + if (n & 0x80) + { + // Recopier src[is] -n+1 fois + n=257-n; + for (;(n>0) && (id<32000);n--) + dest[id++]=src[is]; + is++; + } + else + { + // Recopier n+1 octets littéralement + n=n+1; + for (;(n>0) && (id<32000);n--) + dest[id++]=src[is++]; + } + + // Contrôle des erreurs + if (n>0) + File_error=1; + } +} + +//// COMPRESSION d'un buffer selon la méthode PACKBITS //// + +void PC1_compress_packbits(byte * src,byte * dest,int source_size,int * dest_size) +{ + int is; // index dans la source + int id; // index dans la destination + int ir; // index de la répétition + int n; // Taille des séquences + int repet; // "Il y a répétition" + + for (is=id=0;is0;n--) + dest[id++]=src[is++]; + } + + // On code la partie sans répétitions + if (repet) + { + // On compte la quantité de fois qu'il faut répéter la valeur + for (ir+=3;ir>=1; + } + } +} + +//// CODAGE d'une partie d'IMAGE //// + +// Transformation d'1 ligne de pixels en 4 plans de bits + +void PC1_1line_to_4bp(byte * src,byte * dst0,byte * dst1,byte * dst2,byte * dst3) +{ + int i,j; // Compteurs + int ip; // index du pixel à calculer + byte byte_mask; // Masque de decodage + byte b0,b1,b2,b3; // Les 4 octets des plans bits sources + + ip=0; + // Pour chacun des 40 octets des plans de bits + for (i=0;i<40;i++) + { + // Pour chacun des 8 bits des octets + byte_mask=0x80; + b0=b1=b2=b3=0; + for (j=0;j<8;j++) + { + b0|=(src[ip] & 0x01)?byte_mask:0x00; + b1|=(src[ip] & 0x02)?byte_mask:0x00; + b2|=(src[ip] & 0x04)?byte_mask:0x00; + b3|=(src[ip] & 0x08)?byte_mask:0x00; + ip++; + byte_mask>>=1; + } + dst0[i]=b0; + dst1[i]=b1; + dst2[i]=b2; + dst3[i]=b3; + } +} + + +// -- Tester si un fichier est au format PC1 -------------------------------- +void Test_PC1(void) +{ + FILE *file; // Fichier du fichier + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + int size; // Taille du fichier + word resolution; // Résolution de l'image + + + Get_full_filename(filename,0); + + File_error=1; + + // Ouverture du fichier + if ((file=fopen(filename, "rb"))) + { + // Vérification de la taille + size=File_length_file(file); + if ((size<=32066)) + { + // Lecture et vérification de la résolution + if (Read_word_le(file,&resolution)) + { + if (resolution==0x0080) + File_error=0; + } + } + // Fermeture du fichier + fclose(file); + } +} + + +// -- Lire un fichier au format PC1 ----------------------------------------- +void Load_PC1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + int size; + word x_pos,y_pos; + byte * buffercomp; + byte * bufferdecomp; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + if ((file=fopen(filename, "rb"))) + { + size=File_length_file(file); + // allocation des buffers mémoire + buffercomp=(byte *)malloc(size); + bufferdecomp=(byte *)malloc(32000); + if ( (buffercomp!=NULL) && (bufferdecomp!=NULL) ) + { + // Lecture du fichier dans le buffer + if (Read_bytes(file,buffercomp,size)) + { + // Initialisation de la preview + Init_preview(320,200,File_length_file(file),FORMAT_PC1,PIXEL_SIMPLE); + if (File_error==0) + { + // Initialisation de la palette + if (Config.Clear_palette) + memset(Main_palette,0,sizeof(T_Palette)); + PI1_decode_palette(buffercomp+2,(byte *)Main_palette); + Set_palette(Main_palette); + Remap_fileselector(); + + Main_image_width=320; + Main_image_height=200; + + // Décompression du buffer + PC1_uncompress_packbits(buffercomp+34,bufferdecomp); + + // Décodage de l'image + ptr=bufferdecomp; + for (y_pos=0;y_pos<200;y_pos++) + { + // Décodage de la scanline + PC1_4bp_to_1line(ptr,ptr+40,ptr+80,ptr+120,pixels); + ptr+=160; + // Chargement de la ligne + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(bufferdecomp); + free(buffercomp); + } + else + { + File_error=1; + free(bufferdecomp); + free(buffercomp); + } + fclose(file); + } + else + File_error=1; +} + + +// -- Sauver un fichier au format PC1 --------------------------------------- +void Save_PC1(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + int size; + short x_pos,y_pos; + byte * buffercomp; + byte * bufferdecomp; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // Allocation des buffers mémoire + bufferdecomp=(byte *)malloc(32000); + buffercomp =(byte *)malloc(64066); + // Codage de la résolution + buffercomp[0]=0x80; + buffercomp[1]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffercomp+2); + // Codage de l'image + ptr=bufferdecomp; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_8b_to_16p(ptr,pixels+(x_pos<<4)); + ptr+=8; + } + for (x_pos=0;x_pos<320;x_pos++) + Pixel_load_function(x_pos,y_pos,pixels[x_pos]); + } + } + } + else + File_error=1; + free(buffer); + } + else + File_error=1; + fclose(file); + } + else + File_error=1; +} + +void Save_NEO(void) +{ + char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier + FILE *file; + short x_pos,y_pos; + byte * buffer; + byte * ptr; + byte pixels[320]; + + Get_full_filename(filename,0); + + File_error=0; + // Ouverture du fichier + if ((file=fopen(filename,"wb"))) + { + // allocation d'un buffer mémoire + buffer=(byte *)malloc(32128); + // Codage de la résolution + buffer[0]=0x00; + buffer[1]=0x00; + buffer[2]=0x00; + buffer[3]=0x00; + // Codage de la palette + PI1_code_palette((byte *)Main_palette,buffer+4); + // Codage de l'image + ptr=buffer+128; + for (y_pos=0;y_pos<200;y_pos++) + { + // Codage de la ligne + memset(pixels,0,320); + if (y_pos>4);x_pos++) + { + PI1_16p_to_8b(pixels+(x_pos<<4),ptr); + ptr+=8; + } + } + + if (Write_bytes(file,buffer,32128)) + { + fclose(file); + } + else // Error d'écriture (disque plein ou protégé) + { + fclose(file); + remove(filename); + File_error=1; + } + // Libération du buffer mémoire + free(buffer); + } + else + { + fclose(file); + remove(filename); + File_error=1; + } +} + +//////////////////////////////////// C64 //////////////////////////////////// +void Test_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + + Get_full_filename(filename,0); + + file = fopen(filename,"rb"); + + if (file) + { + file_size = File_length_file(file); + switch (file_size) + { + case 1000: // screen or color + case 1002: // (screen or color) + loadaddr + case 8000: // raw bitmap + case 8002: // raw bitmap with loadaddr + case 9000: // bitmap + screen + case 9002: // bitmap + screen + loadaddr + case 10001: // multicolor + case 10003: // multicolor + loadaddr + File_error = 0; + break; + default: // then we don't know for now. + File_error = 1; + } + fclose (file); + } + else + { + File_error = 1; + } +} + +void Load_C64_hires(byte *bitmap, byte *colors) +{ + int cx,cy,x,y,c[4],pixel,color; + + for(cy=0; cy<25; cy++) + { + for(cx=0; cx<40; cx++) + { + c[1]=colors[cy*40+cx]&15; + c[0]=colors[cy*40+cx]>>4; + for(y=0; y<8; y++) + { + pixel=bitmap[cy*320+cx*8+y]; + for(x=0; x<8; x++) + { + color=c[pixel&(1<<(7-x))?1:0]; + Pixel_load_function(cx*8+x,cy*8+y,color); + } + } + } + } +} + +void Load_C64_multi(byte *bitmap, byte *colors, byte *nybble, byte background) +{ + int cx,cy,x,y,c[4],pixel,color; + c[0]=background; + for(cy=0; cy<25; cy++) + { + for(cx=0; cx<40; cx++) + { + c[1]=colors[cy*40+cx]>>4; + c[2]=colors[cy*40+cx]&15; + c[3]=nybble[cy*40+cx]; + + for(y=0; y<8; y++) + { + pixel=bitmap[cy*320+cx*8+y]; + for(x=0; x<4; x++) + { + color=c[(pixel&3)]; + pixel>>=2; + Pixel_load_function(cx*4+(3-x),cy*8+y,color); + } + } + } + } +} + +void Load_C64(void) +{ + FILE* file; + char filename[MAX_PATH_CHARACTERS]; + long file_size; + int i; + byte background,hasLoadAddr=0; + int loadFormat=0; + enum c64_format {F_hires,F_multi,F_bitmap,F_screen,F_color}; + const char *c64_format_names[]={"hires","multicolor","bitmap","screen","color"}; + + // Palette from http://www.pepto.de/projects/colorvic/ + byte pal[48]={ + 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, + 0x68, 0x37, 0x2B, + 0x70, 0xA4, 0xB2, + 0x6F, 0x3D, 0x86, + 0x58, 0x8D, 0x43, + 0x35, 0x28, 0x79, + 0xB8, 0xC7, 0x6F, + 0x6F, 0x4F, 0x25, + 0x43, 0x39, 0x00, + 0x9A, 0x67, 0x59, + 0x44, 0x44, 0x44, + 0x6C, 0x6C, 0x6C, + 0x9A, 0xD2, 0x84, + 0x6C, 0x5E, 0xB5, + 0x95, 0x95, 0x95}; + + byte bitmap[8000],colors[1000],nybble[1000]; + word width=320, height=200; + + Get_full_filename(filename,0); + file = fopen(filename,"rb"); + + if (file) + { + File_error=0; + file_size = File_length_file(file); + + switch (file_size) + { + case 1000: // screen or color + hasLoadAddr=0; + loadFormat=F_screen; + break; + + case 1002: // (screen or color) + loadaddr + hasLoadAddr=1; + loadFormat=F_screen; + break; + + case 8000: // raw bitmap + hasLoadAddr=0; + loadFormat=F_bitmap; + + case 8002: // raw bitmap with loadaddr + hasLoadAddr=1; + loadFormat=F_bitmap; + break; + + case 9000: // bitmap + screen + hasLoadAddr=0; + loadFormat=F_hires; + break; + + case 9002: // bitmap + screen + loadaddr + hasLoadAddr=1; + loadFormat=F_hires; + break; + + case 10001: // multicolor + hasLoadAddr=0; + loadFormat=F_multi; + break; + + case 10003: // multicolor + loadaddr + hasLoadAddr=1; + loadFormat=F_multi; + break; + + default: // then we don't know what it is. + File_error = 1; + + } + + memcpy(Main_palette,pal,48); // this set the software palette for grafx2 + Set_palette(Main_palette); // this set the hardware palette for SDL + Remap_fileselector(); // Always call it if you change the palette + + if (file_size>9002) + width=160; + + if (hasLoadAddr) + { + // get load address + Read_byte(file,&background); + Read_byte(file,&background); + sprintf(filename,"load at $%02x00",background); + } + else + { + sprintf(filename,"no addr"); + } + + if(file_size>9002) + { + Ratio_of_loaded_image = PIXEL_WIDE; + } + sprintf(Main_comment,"C64 %s, %s", + c64_format_names[loadFormat],filename); + Init_preview(width, height, file_size, FORMAT_C64, Ratio_of_loaded_image); // Do this as soon as you can + + Main_image_width = width ; + Main_image_height = height; + + Read_bytes(file,bitmap,8000); + + if (file_size>8002) + Read_bytes(file,colors,1000); + else + { + for(i=0;i<1000;i++) + { + colors[i]=1; + } + } + + if(width==160) + { + Read_bytes(file,nybble,1000); + Read_byte(file,&background); + Load_C64_multi(bitmap,colors,nybble,background); + } + else + { + Load_C64_hires(bitmap,colors); + } + + File_error = 0; + fclose(file); + } + else + File_error = 1; +} + +int Save_C64_window(byte *saveWhat, byte *loadAddr) +{ + int button; + unsigned int i; + T_Dropdown_button *what, *addr; + char * what_label[] = { + "All", + "Bitmap", + "Screen", + "Color" + }; + char * address_label[] = { + "None", + "$2000", + "$4000", + "$6000", + "$8000", + "$A000", + "$C000", + "$E000" + }; + + Open_window(200,120,"c64 settings"); + Window_set_normal_button(110,100,80,15,"Save",1,1,SDLK_RETURN); + Window_set_normal_button(10,100,80,15,"Cancel",1,1,SDLK_ESCAPE); + + Print_in_window(13,18,"Data:",MC_Dark,MC_Light); + what=Window_set_dropdown_button(10,28,90,15,70,what_label[*saveWhat],1, 0, 1, LEFT_SIDE); + Window_dropdown_clear_items(what); + for (i=0; i2) + { + Warning_message("More than 2 colors in 8x8 pixels"); + // TODO here we should hilite the offending block + printf("\nerror at %dx%d (%d colors)\n",cx*8,cy*8,numcolors); + return 1; + } + for(i=0;i<16;i++) + { + if(cusage[i]) + { + c2=i; + break; + } + } + c1=c2; + for(i=c2+1;i<16;i++) + { + if(cusage[i]) + { + c1=i; + } + } + colors[cx+cy*40]=(c2<<4)|c1; + + for(y=0; y<8; y++) + { + bits=0; + for(x=0; x<8; x++) + { + pixel=Read_pixel_function(x+cx*8,y+cy*8); + if(pixel>15) + { + Warning_message("Color above 15 used"); + // TODO hilite offending block here too? + // or make it smarter with color allocation? + // However, the palette is fixed to the 16 first colors + return 1; + } + bits=bits<<1; + if (pixel==c1) bits|=1; + } + bitmap[pos++]=bits; + //Write_byte(file,bits&255); + } + } + } + + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return 1; + } + + if (loadAddr) + { + Write_byte(file,0); + Write_byte(file,loadAddr); + } + if (saveWhat==0 || saveWhat==1) + Write_bytes(file,bitmap,8000); + if (saveWhat==0 || saveWhat==2) + Write_bytes(file,colors,1000); + + fclose(file); + return 0; +} + +int Save_C64_multi(char *filename, byte saveWhat, byte loadAddr) +{ + /* + BITS COLOR INFORMATION COMES FROM + 00 Background color #0 (screen color) + 01 Upper 4 bits of screen memory + 10 Lower 4 bits of screen memory + 11 Color nybble (nybble = 1/2 byte = 4 bits) + */ + + int cx,cy,x,y,c[4]={0,0,0,0},color,lut[16],bits,pixel,pos=0; + byte bitmap[8000],screen[1000],nybble[1000]; + word numcolors,count; + dword cusage[256]; + byte i,background=0; + FILE *file; + + numcolors=Count_used_colors(cusage); + + count=0; + for(x=0;x<16;x++) + { + //printf("color %d, pixels %d\n",x,cusage[x]); + if(cusage[x]>count) + { + count=cusage[x]; + background=x; + } + } + + for(cy=0; cy<25; cy++) + { + //printf("\ny:%2d ",cy); + for(cx=0; cx<40; cx++) + { + numcolors=Count_used_colors_area(cusage,cx*4,cy*8,4,8); + if(numcolors>4) + { + Warning_message("More than 4 colors in 4x8"); + // TODO hilite offending block + return 1; + } + color=1; + c[0]=background; + for(i=0; i<16; i++) + { + lut[i]=0; + if(cusage[i]) + { + if(i!=background) + { + lut[i]=color; + c[color]=i; + color++; + } + else + { + lut[i]=0; + } + } + } + // add to screen and nybble + screen[cx+cy*40]=c[1]<<4|c[2]; + nybble[cx+cy*40]=c[3]; + //printf("%x%x%x ",c[1],c[2],c[3]); + for(y=0;y<8;y++) + { + bits=0; + for(x=0;x<4;x++) + { + pixel=Read_pixel_function(cx*4+x,cy*8+y); + if(pixel>15) + { + Warning_message("Color above 15 used"); + // TODO hilite as in hires, you should stay to + // the fixed 16 color palette + return 1; + } + bits=bits<<2; + bits|=lut[pixel]; + + } + //Write_byte(file,bits&255); + bitmap[pos++]=bits; + } + } + } + + file = fopen(filename,"wb"); + + if(!file) + { + Warning_message("File open failed"); + File_error = 1; + return 1; + } + + if (loadAddr) + { + Write_byte(file,0); + Write_byte(file,loadAddr); + } + + if (saveWhat==0 || saveWhat==1) + Write_bytes(file,bitmap,8000); + + if (saveWhat==0 || saveWhat==2) + Write_bytes(file,screen,1000); + + if (saveWhat==0 || saveWhat==3) + Write_bytes(file,nybble,1000); + + if (saveWhat==0) + Write_byte(file,background); + + fclose(file); + //printf("\nbg:%d\n",background); + return 0; +} + +void Save_C64(void) +{ + char filename[MAX_PATH_CHARACTERS]; + static byte saveWhat=0, loadAddr=0; + dword numcolors,cusage[256]; + numcolors=Count_used_colors(cusage); + + Get_full_filename(filename,0); + + if (numcolors>16) + { + Warning_message("Error: Max 16 colors"); + File_error = 1; + return; + } + if (((Main_image_width!=320) && (Main_image_width!=160)) || Main_image_height!=200) + { + Warning_message("must be 320x200 or 160x200"); + File_error = 1; + return; + } + + if(!Save_C64_window(&saveWhat,&loadAddr)) + { + File_error = 1; + return; + } + //printf("saveWhat=%d, loadAddr=%d\n",saveWhat,loadAddr); + + if (Main_image_width==320) + File_error = Save_C64_hires(filename,saveWhat,loadAddr); + else + File_error = Save_C64_multi(filename,saveWhat,loadAddr); +} +