PNG loading. Don't try saving yet, it's pkm-saving code

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@569 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2009-01-29 17:01:02 +00:00
parent 8ba5bc178a
commit 0575684810
5 changed files with 345 additions and 11 deletions

View File

@ -38,7 +38,7 @@ ifdef COMSPEC
BIN = grafx2.exe BIN = grafx2.exe
CFGBIN = gfxcfg.exe CFGBIN = gfxcfg.exe
COPT = -W -Wall -Wdeclaration-after-statement -O -g -ggdb `sdl-config --cflags` $(TTFCOPT) COPT = -W -Wall -Wdeclaration-after-statement -O -g -ggdb `sdl-config --cflags` $(TTFCOPT)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng
CC = gcc CC = gcc
OBJDIR = obj/win32 OBJDIR = obj/win32
# Resources (icon) # Resources (icon)

View File

@ -89,9 +89,9 @@
// Les différents formats de fichiers: // Les différents formats de fichiers:
#define NB_FORMATS_CONNUS 12 // Nombre de formats connus (devrait être la valeur maximale de NB_FORMATS_LOAD et NB_FORMATS_SAVE, mais plus généralement: Card({NB_FORMATS_LOAD} UNION {NB_FORMATS_SAVE})) #define NB_FORMATS_CONNUS 13 // Nombre de formats connus (devrait être la valeur maximale de NB_FORMATS_LOAD et NB_FORMATS_SAVE, mais plus généralement: Card({NB_FORMATS_LOAD} UNION {NB_FORMATS_SAVE}))
#define NB_FORMATS_LOAD 12 // Nombre de formats que l'on sait charger #define NB_FORMATS_LOAD 13 // Nombre de formats que l'on sait charger
#define NB_FORMATS_SAVE 12 // Nombre de formats que l'on sait sauver #define NB_FORMATS_SAVE 13 // Nombre de formats que l'on sait sauver
enum FORMATS_RECONNUS enum FORMATS_RECONNUS
{ {
@ -106,7 +106,8 @@ enum FORMATS_RECONNUS
FORMAT_PC1, // | l'on doit aller piocher ces FORMAT_PC1, // | l'on doit aller piocher ces
FORMAT_CEL, // | données. FORMAT_CEL, // | données.
FORMAT_KCF, // | FORMAT_KCF, // |
FORMAT_PAL // | FORMAT_PAL, // |
FORMAT_PNG // |
}; };
#define FORMAT_PAR_DEFAUT FORMAT_GIF // Format par défaut (ah bon? oh!) #define FORMAT_PAR_DEFAUT FORMAT_GIF // Format par défaut (ah bon? oh!)

View File

@ -675,7 +675,8 @@ void Rien_du_tout(void);
"pc1", // PC1 "pc1", // PC1
"cel", // CEL "cel", // CEL
"kcf", // KCF "kcf", // KCF
"pal" // PAL "pal", // PAL
"png", // PNG
}; };
// Fonction à appeler pour vérifier la signature du fichier // Fonction à appeler pour vérifier la signature du fichier
@ -692,7 +693,8 @@ void Rien_du_tout(void);
Test_PC1, // PC1 Test_PC1, // PC1
Test_CEL, // CEL Test_CEL, // CEL
Test_KCF, // KCF Test_KCF, // KCF
Test_PAL // PAL Test_PAL, // PAL
Test_PNG // PNG
}; };
// Fonction à appeler pour charger l'image // Fonction à appeler pour charger l'image
@ -709,7 +711,8 @@ void Rien_du_tout(void);
Load_PC1, // PC1 Load_PC1, // PC1
Load_CEL, // CEL Load_CEL, // CEL
Load_KCF, // KCF Load_KCF, // KCF
Load_PAL // PAL Load_PAL, // PAL
Load_PNG // PNG
}; };
// Fonction à appeler pour sauvegarder l'image // Fonction à appeler pour sauvegarder l'image
@ -726,7 +729,8 @@ void Rien_du_tout(void);
Save_PC1, // PC1 Save_PC1, // PC1
Save_CEL, // CEL Save_CEL, // CEL
Save_KCF, // KCF Save_KCF, // KCF
Save_PAL // PAL Save_PAL, // PAL
Save_PNG // PNG
}; };
// indique si l'on doit considérer que l'image n'est plus modifiée // indique si l'on doit considérer que l'image n'est plus modifiée
@ -743,7 +747,8 @@ void Rien_du_tout(void);
1, // PC1 1, // PC1
1, // CEL 1, // CEL
0, // KCF 0, // KCF
0 // PAL 0, // PAL
1 // PNG
}; };
// Le format de fichier autorise un commentaire // Le format de fichier autorise un commentaire
@ -760,7 +765,8 @@ void Rien_du_tout(void);
0, // PC1 0, // PC1
0, // CEL 0, // CEL
0, // KCF 0, // KCF
0 // PAL 0, // PAL
0 // PNG
}; };
#else #else
extern char Format_Extension[NB_FORMATS_CONNUS][4]; extern char Format_Extension[NB_FORMATS_CONNUS][4];

View File

@ -29,6 +29,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h> #include <limits.h>
#include <png.h>
#include "const.h" #include "const.h"
#include "struct.h" #include "struct.h"
@ -5346,3 +5347,324 @@ void Load_TGA(char * nom,Bitmap24B * dest,int * larg,int * haut)
} }
fclose(fichier); fclose(fichier);
} }
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// PNG ////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// -- Tester si un fichier est au format PNG --------------------------------
void Test_PNG(void)
{
FILE *Fichier; // Fichier du fichier
char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
char PNG_header[8];
Nom_fichier_complet(Nom_du_fichier,0);
Erreur_fichier=1;
// Ouverture du fichier
if ((Fichier=fopen(Nom_du_fichier, "rb")))
{
// Lecture du header du fichier
if (read_bytes(Fichier,PNG_header,8))
{
if ( !png_sig_cmp(PNG_header, 0, 8))
Erreur_fichier=0;
}
fclose(Fichier);
}
}
png_bytep * row_pointers;
// -- Lire un fichier au format PNG -----------------------------------------
void Load_PNG(void)
{
FILE *Fichier; // Fichier du fichier
char Nom_du_fichier[TAILLE_CHEMIN_FICHIER]; // Nom complet du fichier
char PNG_header[8];
dword Taille_image;
long Taille_du_fichier;
struct stat Informations_Fichier;
png_structp png_ptr;
png_infop info_ptr;
Nom_fichier_complet(Nom_du_fichier,0);
Erreur_fichier=0;
if ((Fichier=fopen(Nom_du_fichier, "rb")))
{
stat(Nom_du_fichier,&Informations_Fichier);
Taille_du_fichier=Informations_Fichier.st_size;
if (read_bytes(Fichier,PNG_header,8))
{
if ( !png_sig_cmp(PNG_header, 0, 8))
{
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr)
{
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr)
{
png_byte color_type;
png_byte bit_depth;
if (!setjmp(png_jmpbuf(png_ptr)))
{
png_init_io(png_ptr, Fichier);
png_set_sig_bytes(png_ptr, 8);
png_read_info(png_ptr, info_ptr);
color_type = info_ptr->color_type;
bit_depth = info_ptr->bit_depth;
if (bit_depth <= 8 && (color_type == PNG_COLOR_TYPE_PALETTE || PNG_COLOR_TYPE_GRAY))
{
Initialiser_preview(info_ptr->width,info_ptr->height,Taille_du_fichier,FORMAT_PNG);
if (Erreur_fichier==0)
{
int x,y;
png_colorp palette;
int num_palette;
if (color_type == PNG_COLOR_TYPE_GRAY)
{
if (bit_depth < 8)
png_set_gray_1_2_4_to_8(png_ptr);
// palette de niveaux de gris
for (x=0;x<num_palette;x++)
{
Principal_Palette[x].R=x;
Principal_Palette[x].V=x;
Principal_Palette[x].B=x;
}
}
else
{
// conversion des fichiers de moins de 256 couleurs
if (bit_depth < 8)
{
png_set_packing(png_ptr);
if (Config.Clear_palette)
memset(Principal_Palette,0,sizeof(T_Palette));
}
png_get_PLTE(png_ptr, info_ptr, &palette,
&num_palette);
for (x=0;x<num_palette;x++)
{
Principal_Palette[x].R=palette[x].red;
Principal_Palette[x].V=palette[x].green;
Principal_Palette[x].B=palette[x].blue;
}
//free(palette);
}
Set_palette(Principal_Palette);
Remapper_fileselect();
//
Principal_Largeur_image=info_ptr->width;
Principal_Hauteur_image=info_ptr->height;
Taille_image=(dword)(Principal_Largeur_image*Principal_Hauteur_image);
Principal_Commentaire[0]='\0'; // On efface le commentaire
png_set_interlace_handling(png_ptr);
png_read_update_info(png_ptr, info_ptr);
/* read file */
if (!setjmp(png_jmpbuf(png_ptr)))
{
row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * Principal_Hauteur_image);
for (y=0; y<Principal_Hauteur_image; y++)
row_pointers[y] = (png_byte*) malloc(info_ptr->rowbytes);
png_read_image(png_ptr, row_pointers);
for (y=0; y<Principal_Hauteur_image; y++)
for (x=0; x<Principal_Largeur_image; x++)
Pixel_de_chargement(x, y, row_pointers[y][x]);
}
else
Erreur_fichier=2;
/* cleanup heap allocation */
for (y=0; y<Principal_Hauteur_image; y++)
free(row_pointers[y]);
free(row_pointers);
}
else
Erreur_fichier=2;
}
}
}
}
}
/*Close_lecture();*/
}
else // Lecture header impossible: Erreur ne modifiant pas l'image
Erreur_fichier=1;
fclose(Fichier);
}
else // Ouv. fichier impossible: Erreur ne modifiant pas l'image
Erreur_fichier=1;
}
void Save_PNG(void)
{
char Nom_du_fichier[TAILLE_CHEMIN_FICHIER];
FILE *Fichier;
T_Header_PKM Head;
dword Compteur_de_pixels;
dword Taille_image;
word Compteur_de_repetitions;
byte Derniere_couleur;
byte Valeur_pixel;
byte Taille_commentaire;
// Construction du header
memcpy(Head.Ident,"PKM",3);
Head.Methode=0;
Trouver_recon(&Head.Recon1,&Head.Recon2);
Head.Largeur=Principal_Largeur_image;
Head.Hauteur=Principal_Hauteur_image;
memcpy(Head.Palette,Principal_Palette,sizeof(T_Palette));
Palette_256_to_64(Head.Palette);
// Calcul de la taille du Post-Header
Head.Jump=9; // 6 pour les dimensions de l'ecran + 3 pour la back-color
Taille_commentaire=strlen(Principal_Commentaire);
if (Taille_commentaire)
Head.Jump+=Taille_commentaire+2;
Nom_fichier_complet(Nom_du_fichier,0);
Erreur_fichier=0;
// Ouverture du fichier
if ((Fichier=fopen(Nom_du_fichier,"wb")))
{
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Head.Largeur = SDL_Swap16(Head.Largeur);
Head.Hauteur = SDL_Swap16(Head.Hauteur);
Head.Jump = SDL_Swap16(Head.Jump);
#endif
// Ecriture du header
if (write_bytes(Fichier,&Head,sizeof(T_Header_PKM)))
{
Init_ecriture();
// Ecriture du commentaire
// (Compteur_de_pixels est utilisé ici comme simple indice de comptage)
if (Taille_commentaire)
{
Ecrire_octet(Fichier,0);
Ecrire_octet(Fichier,Taille_commentaire);
for (Compteur_de_pixels=0; Compteur_de_pixels<Taille_commentaire; Compteur_de_pixels++)
Ecrire_octet(Fichier,Principal_Commentaire[Compteur_de_pixels]);
}
// Ecriture des dimensions de l'écran
Ecrire_octet(Fichier,1);
Ecrire_octet(Fichier,4);
Ecrire_octet(Fichier,Largeur_ecran&0xFF);
Ecrire_octet(Fichier,Largeur_ecran>>8);
Ecrire_octet(Fichier,Hauteur_ecran&0xFF);
Ecrire_octet(Fichier,Hauteur_ecran>>8);
// Ecriture de la back-color
Ecrire_octet(Fichier,2);
Ecrire_octet(Fichier,1);
Ecrire_octet(Fichier,Back_color);
// Routine de compression PKM de l'image
Taille_image=(dword)(Principal_Largeur_image*Principal_Hauteur_image);
Compteur_de_pixels=0;
Valeur_pixel=Lit_pixel_de_sauvegarde(0,0);
while ( (Compteur_de_pixels<Taille_image) && (!Erreur_fichier) )
{
Compteur_de_pixels++;
Compteur_de_repetitions=1;
Derniere_couleur=Valeur_pixel;
if(Compteur_de_pixels<Taille_image)
{
Valeur_pixel=Lit_pixel_de_sauvegarde(Compteur_de_pixels % Principal_Largeur_image,Compteur_de_pixels / Principal_Largeur_image);
}
while ( (Valeur_pixel==Derniere_couleur)
&& (Compteur_de_pixels<Taille_image)
&& (Compteur_de_repetitions<65535) )
{
Compteur_de_pixels++;
Compteur_de_repetitions++;
if(Compteur_de_pixels>=Taille_image) break;
Valeur_pixel=Lit_pixel_de_sauvegarde(Compteur_de_pixels % Principal_Largeur_image,Compteur_de_pixels / Principal_Largeur_image);
}
if ( (Derniere_couleur!=Head.Recon1) && (Derniere_couleur!=Head.Recon2) )
{
if (Compteur_de_repetitions==1)
Ecrire_octet(Fichier,Derniere_couleur);
else
if (Compteur_de_repetitions==2)
{
Ecrire_octet(Fichier,Derniere_couleur);
Ecrire_octet(Fichier,Derniere_couleur);
}
else
if ( (Compteur_de_repetitions>2) && (Compteur_de_repetitions<256) )
{ // RECON1/couleur/nombre
Ecrire_octet(Fichier,Head.Recon1);
Ecrire_octet(Fichier,Derniere_couleur);
Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
}
else
if (Compteur_de_repetitions>=256)
{ // RECON2/couleur/hi(nombre)/lo(nombre)
Ecrire_octet(Fichier,Head.Recon2);
Ecrire_octet(Fichier,Derniere_couleur);
Ecrire_octet(Fichier,Compteur_de_repetitions>>8);
Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
}
}
else
{
if (Compteur_de_repetitions<256)
{
Ecrire_octet(Fichier,Head.Recon1);
Ecrire_octet(Fichier,Derniere_couleur);
Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
}
else
{
Ecrire_octet(Fichier,Head.Recon2);
Ecrire_octet(Fichier,Derniere_couleur);
Ecrire_octet(Fichier,Compteur_de_repetitions>>8);
Ecrire_octet(Fichier,Compteur_de_repetitions&0xFF);
}
}
}
Close_ecriture(Fichier);
}
else
Erreur_fichier=1;
fclose(Fichier);
}
else
{
Erreur_fichier=1;
fclose(Fichier);
}
// 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 (Erreur_fichier)
remove(Nom_du_fichier);
}

View File

@ -90,3 +90,8 @@ void Save_PI1(void);
void Test_PC1(void); void Test_PC1(void);
void Load_PC1(void); void Load_PC1(void);
void Save_PC1(void); void Save_PC1(void);
// -- PNG -------------------------------------------------------------------
void Test_PNG(void);
void Load_PNG(void);
void Save_PNG(void);