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); +} +