Support of .ICO file loading
only loading the biggest icon see http://pulkomandy.tk/projects/GrafX2/ticket/69
This commit is contained in:
parent
c2c36849b5
commit
c2486ed629
@ -137,6 +137,7 @@ enum FILE_FORMATS
|
|||||||
FORMAT_CM5,
|
FORMAT_CM5,
|
||||||
FORMAT_PPH,
|
FORMAT_PPH,
|
||||||
FORMAT_XPM,
|
FORMAT_XPM,
|
||||||
|
FORMAT_ICO,
|
||||||
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image
|
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
*/
|
*/
|
||||||
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
||||||
|
|
||||||
|
Copyright 2018 Thomas Bernard
|
||||||
Copyright 2011 Pawel Góralski
|
Copyright 2011 Pawel Góralski
|
||||||
Copyright 2009 Petter Lindquist
|
Copyright 2009 Petter Lindquist
|
||||||
Copyright 2008 Yves Rizoud
|
Copyright 2008 Yves Rizoud
|
||||||
@ -1897,6 +1898,192 @@ void Save_BMP(T_IO_Context * context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////// ICO ////////////////////////////////////
|
||||||
|
typedef struct {
|
||||||
|
byte width; //Specifies image width in pixels. Value 0 means image width is 256 pixels.
|
||||||
|
byte height; //Specifies image height in pixels. Value 0 means image height is 256 pixels.
|
||||||
|
byte ncolors; //0 for image without palette
|
||||||
|
byte reserved;
|
||||||
|
word planes; // (hotspot X for CUR files)
|
||||||
|
word bpp; // (hotspot Y for CUR files)
|
||||||
|
dword bytecount;
|
||||||
|
dword offset;
|
||||||
|
} T_ICO_ImageEntry;
|
||||||
|
|
||||||
|
void Test_ICO(T_IO_Context * context)
|
||||||
|
{
|
||||||
|
char filename[MAX_PATH_CHARACTERS];
|
||||||
|
FILE *file;
|
||||||
|
struct {
|
||||||
|
word Reserved;
|
||||||
|
word Type; // Specifies image type: 1 for icon (.ICO) image, 2 for cursor (.CUR) image. Other values are invalid.
|
||||||
|
word Count; // Specifies number of images in the file.
|
||||||
|
} header;
|
||||||
|
|
||||||
|
File_error=1;
|
||||||
|
Get_full_filename(filename, context->File_name, context->File_directory);
|
||||||
|
printf("Test_ICO(%p) %s\n", context, filename);
|
||||||
|
|
||||||
|
if ((file=fopen(filename, "rb")))
|
||||||
|
{
|
||||||
|
if (Read_word_le(file,&(header.Reserved))
|
||||||
|
&& Read_word_le(file,&(header.Type))
|
||||||
|
&& Read_word_le(file,&(header.Count)))
|
||||||
|
{
|
||||||
|
printf("type=%d count=%d\n", header.Type, header.Count);
|
||||||
|
if (header.Reserved == 0 && header.Type <= 2 && header.Count > 0)
|
||||||
|
File_error=0;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load_ICO(T_IO_Context * context)
|
||||||
|
{
|
||||||
|
char filename[MAX_PATH_CHARACTERS];
|
||||||
|
FILE *file;
|
||||||
|
struct {
|
||||||
|
word Reserved;
|
||||||
|
word Type; // Specifies image type: 1 for icon (.ICO) image, 2 for cursor (.CUR) image. Other values are invalid.
|
||||||
|
word Count; // Specifies number of images in the file.
|
||||||
|
} header;
|
||||||
|
T_ICO_ImageEntry * images;
|
||||||
|
T_ICO_ImageEntry * entry;
|
||||||
|
unsigned int i;
|
||||||
|
word width, max_width = 0;
|
||||||
|
word max_bpp = 0;
|
||||||
|
word min_bpp = 0xffff;
|
||||||
|
dword mask[3]; // R G B
|
||||||
|
|
||||||
|
File_error=0;
|
||||||
|
Get_full_filename(filename, context->File_name, context->File_directory);
|
||||||
|
printf("Load_ICO(%p)\n", context);
|
||||||
|
if ((file=fopen(filename, "rb")))
|
||||||
|
{
|
||||||
|
if (Read_word_le(file,&(header.Reserved))
|
||||||
|
&& Read_word_le(file,&(header.Type))
|
||||||
|
&& Read_word_le(file,&(header.Count)))
|
||||||
|
{
|
||||||
|
printf("type=%d count=%d\n", header.Type, header.Count);
|
||||||
|
images = malloc(sizeof(T_ICO_ImageEntry) * header.Count);
|
||||||
|
if (images == NULL)
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
File_error=1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < header.Count; i++) {
|
||||||
|
entry = images + i;
|
||||||
|
if (!Read_byte(file,&entry->width)
|
||||||
|
|| !Read_byte(file,&entry->height)
|
||||||
|
|| !Read_byte(file,&entry->ncolors)
|
||||||
|
|| !Read_byte(file,&entry->reserved)
|
||||||
|
|| !Read_word_le(file,&entry->planes)
|
||||||
|
|| !Read_word_le(file,&entry->bpp)
|
||||||
|
|| !Read_dword_le(file,&entry->bytecount)
|
||||||
|
|| !Read_dword_le(file,&entry->offset))
|
||||||
|
{
|
||||||
|
free(images);
|
||||||
|
fclose(file);
|
||||||
|
File_error=1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
width = entry->width;
|
||||||
|
if (width == 0) width = 256;
|
||||||
|
if (width > max_width) max_width = width;
|
||||||
|
printf("%2d: %3dx%3d %dcolors planes=%d bpp=%d\n", i, entry->width, entry->height, entry->ncolors, entry->planes, entry->bpp);
|
||||||
|
}
|
||||||
|
// select the picture with the maximum width and 256 colors or less
|
||||||
|
printf("max width = %d\n", max_width);
|
||||||
|
for (i = 0; i < header.Count; i++)
|
||||||
|
{
|
||||||
|
if (images[i].width == (max_width & 0xff))
|
||||||
|
{
|
||||||
|
if (images[i].bpp == 8)
|
||||||
|
break;
|
||||||
|
if (images[i].bpp < 8 && images[i].bpp > max_bpp)
|
||||||
|
max_bpp = images[i].bpp;
|
||||||
|
if (images[i].bpp < min_bpp)
|
||||||
|
min_bpp = images[i].bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("i=%d max_bpp=%d min_bpp=%d\n", i, max_bpp, min_bpp);
|
||||||
|
if (i >= header.Count)
|
||||||
|
{
|
||||||
|
// 256 color not found, select another one
|
||||||
|
for (i = 0; i < header.Count; i++)
|
||||||
|
{
|
||||||
|
if (images[i].width == (max_width & 0xff))
|
||||||
|
{
|
||||||
|
if ((max_bpp != 0 && images[i].bpp == max_bpp)
|
||||||
|
|| (images[i].bpp == min_bpp))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= header.Count)
|
||||||
|
{
|
||||||
|
File_error=2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T_BMP_Header bmpheader;
|
||||||
|
|
||||||
|
entry = images + i;
|
||||||
|
fseek(file, entry->offset, SEEK_SET);
|
||||||
|
// TODO : detect PNG icons
|
||||||
|
if (Read_dword_le(file,&(bmpheader.Size_2)) // 40
|
||||||
|
&& Read_dword_le(file,&(bmpheader.Width))
|
||||||
|
&& Read_dword_le(file,(dword *)&(bmpheader.Height))
|
||||||
|
&& Read_word_le(file,&(bmpheader.Planes))
|
||||||
|
&& Read_word_le(file,&(bmpheader.Nb_bits))
|
||||||
|
&& Read_dword_le(file,&(bmpheader.Compression))
|
||||||
|
&& Read_dword_le(file,&(bmpheader.Size_3))
|
||||||
|
&& Read_dword_le(file,&(bmpheader.XPM))
|
||||||
|
&& Read_dword_le(file,&(bmpheader.YPM))
|
||||||
|
&& Read_dword_le(file,&(bmpheader.Nb_Clr))
|
||||||
|
&& Read_dword_le(file,&(bmpheader.Clr_Imprt)) )
|
||||||
|
{
|
||||||
|
word nb_colors = 0;
|
||||||
|
if (bmpheader.Nb_Clr != 0)
|
||||||
|
nb_colors=bmpheader.Nb_Clr;
|
||||||
|
else
|
||||||
|
nb_colors=1<<bmpheader.Nb_bits;
|
||||||
|
printf("size=%d width=%d height=%d planes=%d nbbits=%d nb_colors=%d\n", bmpheader.Size_2, bmpheader.Width, bmpheader.Height, bmpheader.Planes, bmpheader.Nb_bits, nb_colors);
|
||||||
|
// bmpheader.Width != entry.width...
|
||||||
|
// Image 16/24/32 bits
|
||||||
|
if (bmpheader.Nb_bits == 16)
|
||||||
|
{
|
||||||
|
mask[0] = 0x00007C00;
|
||||||
|
mask[1] = 0x000003E0;
|
||||||
|
mask[2] = 0x0000001F;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask[0] = 0x00FF0000;
|
||||||
|
mask[1] = 0x0000FF00;
|
||||||
|
mask[2] = 0x000000FF;
|
||||||
|
}
|
||||||
|
Pre_load(context, bmpheader.Width,bmpheader.Height/2,0/*file_size*/,FORMAT_ICO,PIXEL_SIMPLE,(entry->bpp > 8));
|
||||||
|
if (entry->bpp <= 8)
|
||||||
|
Load_BMP_Palette(context, file, nb_colors, 0);
|
||||||
|
if (File_error == 0)
|
||||||
|
{
|
||||||
|
Load_BMP_Pixels(context, file, bmpheader.Compression, bmpheader.Nb_bits, (bmpheader.Height < 0) ? 1 : 0, mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(images);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
} else {
|
||||||
|
File_error=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////// GIF ////////////////////////////////////
|
//////////////////////////////////// GIF ////////////////////////////////////
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|||||||
@ -145,6 +145,10 @@ void Save_PPH(T_IO_Context *);
|
|||||||
// Loading is done through SDL_Image
|
// Loading is done through SDL_Image
|
||||||
void Save_XPM(T_IO_Context*);
|
void Save_XPM(T_IO_Context*);
|
||||||
|
|
||||||
|
// -- ICO (Windows ICO)
|
||||||
|
void Test_ICO(T_IO_Context *);
|
||||||
|
void Load_ICO(T_IO_Context *);
|
||||||
|
|
||||||
// -- PNG -------------------------------------------------------------------
|
// -- PNG -------------------------------------------------------------------
|
||||||
#ifndef __no_pnglib__
|
#ifndef __no_pnglib__
|
||||||
void Test_PNG(T_IO_Context *);
|
void Test_PNG(T_IO_Context *);
|
||||||
@ -184,6 +188,7 @@ T_Format File_formats[] = {
|
|||||||
{FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"},
|
{FORMAT_CM5, " cm5", Test_CM5, Load_CM5, Save_CM5, 0, 0, 1, "cm5", "cm5"},
|
||||||
{FORMAT_PPH, " pph", Test_PPH, Load_PPH, Save_PPH, 0, 0, 1, "pph", "pph"},
|
{FORMAT_PPH, " pph", Test_PPH, Load_PPH, Save_PPH, 0, 0, 1, "pph", "pph"},
|
||||||
{FORMAT_XPM, " xpm", NULL, NULL, Save_XPM, 0, 0, 0, "xpm", "xpm"},
|
{FORMAT_XPM, " xpm", NULL, NULL, Save_XPM, 0, 0, 0, "xpm", "xpm"},
|
||||||
|
{FORMAT_ICO, " ico", Test_ICO, Load_ICO, NULL, 0, 0, 0, "ico", "ico;cur"},
|
||||||
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
|
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user