add support for reading HP-48 Grob format
This commit is contained in:
parent
911ad97646
commit
0cea439da9
@ -155,6 +155,7 @@ enum FILE_FORMATS
|
|||||||
FORMAT_MOTO, ///< Thomson MO/TO computers pictures
|
FORMAT_MOTO, ///< Thomson MO/TO computers pictures
|
||||||
FORMAT_HGR, ///< Apple II HGR and DHGR
|
FORMAT_HGR, ///< Apple II HGR and DHGR
|
||||||
FORMAT_TIFF, ///< Tagged Image File Format
|
FORMAT_TIFF, ///< Tagged Image File Format
|
||||||
|
FORMAT_GRB, ///< HP-48 Grob
|
||||||
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image (or recoil)
|
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image (or recoil)
|
||||||
FORMAT_CLIPBOARD ///< To load/save from/to Clipboard
|
FORMAT_CLIPBOARD ///< To load/save from/to Clipboard
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
*/
|
*/
|
||||||
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
||||||
|
|
||||||
Copyright 2018 Thomas Bernard
|
Copyright 2018-2019 Thomas Bernard
|
||||||
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
|
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
|
||||||
|
|
||||||
Grafx2 is free software; you can redistribute it and/or
|
Grafx2 is free software; you can redistribute it and/or
|
||||||
@ -175,5 +175,9 @@ void Load_TIFF_from_memory(T_IO_Context *, const void *, unsigned long);
|
|||||||
void Save_TIFF_to_memory(T_IO_Context *, void * *, unsigned long *);
|
void Save_TIFF_to_memory(T_IO_Context *, void * *, unsigned long *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// -- HP-48 Grob ------------------------------------------------------------
|
||||||
|
void Test_GRB(T_IO_Context *, FILE *);
|
||||||
|
void Load_GRB(T_IO_Context *);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -119,6 +119,7 @@ const T_Format File_formats[] = {
|
|||||||
"gpx;"
|
"gpx;"
|
||||||
"cpc;scr;win;"
|
"cpc;scr;win;"
|
||||||
"hgr;dhgr;"
|
"hgr;dhgr;"
|
||||||
|
"grb;grob;"
|
||||||
"tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin;map"},
|
"tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico;ic2;cur;cm5;pph;info;flc;bin;map"},
|
||||||
{FORMAT_ALL_PALETTES, "(pal)", NULL, NULL, NULL, 1, 0, 0, "", "kcf;pal;gpl"},
|
{FORMAT_ALL_PALETTES, "(pal)", NULL, NULL, NULL, 1, 0, 0, "", "kcf;pal;gpl"},
|
||||||
{FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
|
{FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
|
||||||
@ -156,6 +157,7 @@ const T_Format File_formats[] = {
|
|||||||
#ifndef __no_tifflib__
|
#ifndef __no_tifflib__
|
||||||
{FORMAT_TIFF," tiff",Test_TIFF,Load_TIFF,Save_TIFF,0, 1, 1, "tif", "tif;tiff"},
|
{FORMAT_TIFF," tiff",Test_TIFF,Load_TIFF,Save_TIFF,0, 1, 1, "tif", "tif;tiff"},
|
||||||
#endif
|
#endif
|
||||||
|
{FORMAT_GRB, " grb", Test_GRB, Load_GRB, NULL, 0, 0, 0, "grb", "grb;grob"},
|
||||||
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff"},
|
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 0, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
*/
|
*/
|
||||||
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
||||||
|
|
||||||
Copyright 2018 Thomas Bernard
|
Copyright 2018-2019 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
|
||||||
@ -2256,10 +2256,10 @@ NeoChrome Format :
|
|||||||
Dali *.SD0 (ST low resolution)
|
Dali *.SD0 (ST low resolution)
|
||||||
*.SD1 (ST medium resolution)
|
*.SD1 (ST medium resolution)
|
||||||
*.SD2 (ST high resolution)
|
*.SD2 (ST high resolution)
|
||||||
|
|
||||||
Files do not seem to have any resolution or bit plane info stored in them. The file
|
Files do not seem to have any resolution or bit plane info stored in them. The file
|
||||||
extension seems to be the only way to determine the contents.
|
extension seems to be the only way to determine the contents.
|
||||||
|
|
||||||
1 long file id? [always 0]
|
1 long file id? [always 0]
|
||||||
16 words palette
|
16 words palette
|
||||||
92 bytes reserved? [usually 0]
|
92 bytes reserved? [usually 0]
|
||||||
@ -2404,7 +2404,7 @@ void Load_NEO(T_IO_Context * context)
|
|||||||
{
|
{
|
||||||
if (!Read_bytes(file, buffer, (resolution==2) ? 80 : 160))
|
if (!Read_bytes(file, buffer, (resolution==2) ? 80 : 160))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ptr = buffer;
|
ptr = buffer;
|
||||||
for (x_pos = 0; x_pos < width; )
|
for (x_pos = 0; x_pos < width; )
|
||||||
{
|
{
|
||||||
@ -7252,7 +7252,7 @@ void Save_HGR(T_IO_Context * context)
|
|||||||
}
|
}
|
||||||
if (context->Width == 560)
|
if (context->Width == 560)
|
||||||
is_dhgr = 1;
|
is_dhgr = 1;
|
||||||
|
|
||||||
file = Open_file_write(context);
|
file = Open_file_write(context);
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
@ -7322,3 +7322,140 @@ void Save_HGR(T_IO_Context * context)
|
|||||||
free(vram[1]);
|
free(vram[1]);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////// HP-48 Grob Files ////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HP48 addresses are 20bits (5 nibbles)
|
||||||
|
* offset is in nibble (half byte)
|
||||||
|
*/
|
||||||
|
static dword Read_HP48Address(const byte * buffer, int offset)
|
||||||
|
{
|
||||||
|
dword data = 0;
|
||||||
|
int i = 4;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
byte nibble;
|
||||||
|
nibble = buffer[(offset + i) >> 1];
|
||||||
|
if ((offset + i) & 1)
|
||||||
|
nibble >>= 4;
|
||||||
|
nibble &= 15;
|
||||||
|
data = (data << 4) | nibble;
|
||||||
|
}
|
||||||
|
while (i-- > 0);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for a HP-48 Grob file
|
||||||
|
*/
|
||||||
|
void Test_GRB(T_IO_Context * context, FILE * file)
|
||||||
|
{
|
||||||
|
byte buffer[18];
|
||||||
|
unsigned long file_size;
|
||||||
|
dword prologue, size, width, height;
|
||||||
|
|
||||||
|
(void)context;
|
||||||
|
File_error = 1;
|
||||||
|
file_size = File_length_file(file);
|
||||||
|
if (!Read_bytes(file, buffer, 18))
|
||||||
|
return;
|
||||||
|
if(memcmp(buffer, "HPHP48-R", 8) != 0)
|
||||||
|
return;
|
||||||
|
prologue = Read_HP48Address(buffer+8, 0);
|
||||||
|
size = Read_HP48Address(buffer+8, 5);
|
||||||
|
GFX2_Log(GFX2_DEBUG, "HP48 File detected. %lu bytes prologue %05x %u nibbles\n",
|
||||||
|
file_size, prologue, size);
|
||||||
|
if (prologue != 0x02b1e)
|
||||||
|
return;
|
||||||
|
height = Read_HP48Address(buffer+8, 10);
|
||||||
|
width = Read_HP48Address(buffer+8, 15);
|
||||||
|
GFX2_Log(GFX2_DEBUG, " Grob dimensions : %ux%u\n", width, height);
|
||||||
|
if ((file_size - 8) < ((size + 5) / 2))
|
||||||
|
return;
|
||||||
|
if (file_size < (18 + ((width + 7) >> 3) * height))
|
||||||
|
return;
|
||||||
|
File_error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load_GRB(T_IO_Context * context)
|
||||||
|
{
|
||||||
|
byte buffer[18];
|
||||||
|
byte * bitplane[4];
|
||||||
|
unsigned long file_size;
|
||||||
|
dword prologue, size, width, height;
|
||||||
|
byte bp, bpp;
|
||||||
|
FILE * file;
|
||||||
|
unsigned x, y;
|
||||||
|
|
||||||
|
File_error = 1;
|
||||||
|
file = Open_file_read(context);
|
||||||
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
file_size = File_length_file(file);
|
||||||
|
if (!Read_bytes(file, buffer, 18))
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prologue = Read_HP48Address(buffer+8, 0);
|
||||||
|
size = Read_HP48Address(buffer+8, 5);
|
||||||
|
height = Read_HP48Address(buffer+8, 10);
|
||||||
|
width = Read_HP48Address(buffer+8, 15);
|
||||||
|
if (height >= 256)
|
||||||
|
bpp = 4;
|
||||||
|
else if (height >= 192)
|
||||||
|
bpp = 3;
|
||||||
|
else if (height >= 128)
|
||||||
|
bpp = 2;
|
||||||
|
else
|
||||||
|
bpp = 1;
|
||||||
|
|
||||||
|
File_error = 0;
|
||||||
|
Pre_load(context, width, height/bpp, file_size, FORMAT_GRB, PIXEL_SIMPLE, bpp);
|
||||||
|
if (File_error == 0)
|
||||||
|
{
|
||||||
|
dword bytes_per_plane = ((width + 7) >> 3) * (height/bpp);
|
||||||
|
dword offset = 0;
|
||||||
|
|
||||||
|
if (Config.Clear_palette)
|
||||||
|
memset(context->Palette, 0, sizeof(T_Palette));
|
||||||
|
for (x = 0; x < ((unsigned)1 << bpp); x++)
|
||||||
|
{
|
||||||
|
context->Palette[x].R = context->Palette[x].G = (x * 255) / ((1 << bpp) - 1);
|
||||||
|
context->Palette[x].B = 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all bit planes
|
||||||
|
for (bp = 0; bp < bpp; bp++)
|
||||||
|
{
|
||||||
|
bitplane[bp] = GFX2_malloc(bytes_per_plane);
|
||||||
|
if (bitplane[bp])
|
||||||
|
{
|
||||||
|
if (!Read_bytes(file, bitplane[bp], bytes_per_plane))
|
||||||
|
File_error = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// set pixels
|
||||||
|
for (y = 0; y < (height/bpp) && File_error == 0; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
byte b = 0;
|
||||||
|
for (bp = 0; bp < bpp; bp++)
|
||||||
|
b |= ((bitplane[bp][offset] >> (x & 7)) & 1) << bp;
|
||||||
|
// invert because 1 is a black pixel on HP-48 LCD display
|
||||||
|
Set_pixel(context, x, y, b ^ ((1 << bpp) - 1));
|
||||||
|
if ((x & 7) == 7)
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
if ((x & 7) != 7)
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
// Free bit planes
|
||||||
|
for (bp = 0; bp < bpp; bp++)
|
||||||
|
free(bitplane[bp]);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user