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_HGR, ///< Apple II HGR and DHGR
|
||||
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_CLIPBOARD ///< To load/save from/to Clipboard
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
*/
|
||||
/* 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)
|
||||
|
||||
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 *);
|
||||
#endif
|
||||
|
||||
// -- HP-48 Grob ------------------------------------------------------------
|
||||
void Test_GRB(T_IO_Context *, FILE *);
|
||||
void Load_GRB(T_IO_Context *);
|
||||
|
||||
/// @}
|
||||
#endif
|
||||
|
||||
@ -119,6 +119,7 @@ const T_Format File_formats[] = {
|
||||
"gpx;"
|
||||
"cpc;scr;win;"
|
||||
"hgr;dhgr;"
|
||||
"grb;grob;"
|
||||
"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_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
|
||||
@ -156,6 +157,7 @@ const T_Format File_formats[] = {
|
||||
#ifndef __no_tifflib__
|
||||
{FORMAT_TIFF," tiff",Test_TIFF,Load_TIFF,Save_TIFF,0, 1, 1, "tif", "tif;tiff"},
|
||||
#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"},
|
||||
};
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
*/
|
||||
/* Grafx2 - The Ultimate 256-color bitmap paint program
|
||||
|
||||
Copyright 2018 Thomas Bernard
|
||||
Copyright 2018-2019 Thomas Bernard
|
||||
Copyright 2011 Pawel Góralski
|
||||
Copyright 2009 Petter Lindquist
|
||||
Copyright 2008 Yves Rizoud
|
||||
@ -2256,10 +2256,10 @@ NeoChrome Format :
|
||||
Dali *.SD0 (ST low resolution)
|
||||
*.SD1 (ST medium resolution)
|
||||
*.SD2 (ST high resolution)
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
1 long file id? [always 0]
|
||||
16 words palette
|
||||
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))
|
||||
goto error;
|
||||
|
||||
|
||||
ptr = buffer;
|
||||
for (x_pos = 0; x_pos < width; )
|
||||
{
|
||||
@ -7252,7 +7252,7 @@ void Save_HGR(T_IO_Context * context)
|
||||
}
|
||||
if (context->Width == 560)
|
||||
is_dhgr = 1;
|
||||
|
||||
|
||||
file = Open_file_write(context);
|
||||
if (file == NULL)
|
||||
return;
|
||||
@ -7322,3 +7322,140 @@ void Save_HGR(T_IO_Context * context)
|
||||
free(vram[1]);
|
||||
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