Files
FireBee_Setup/sources/z-tools/trunk/zview/plugins/img/imgldg.c

366 lines
8.2 KiB
C

#include "zview.h"
#include "img.h"
extern int32 plane2packed24( int32 no_words, int32 plane_length, int16 no_planes, void *src, void *dst, COLOR_MAP *palette);
boolean CDECL reader_init( const char *name, IMGINFO info);
void CDECL reader_get_txt( IMGINFO info, txt_data *txtdata);
boolean CDECL reader_read( IMGINFO info, uint8 *buffer);
void CDECL reader_quit( IMGINFO info);
void CDECL init( void);
PROC IMGFunc[] =
{
{ "plugin_init", "", init},
{ "reader_init", "", reader_init},
{ "reader_get_txt", "", reader_get_txt},
{ "reader_read", "", reader_read},
{ "reader_quit", "", reader_quit}
};
LDGLIB img_plugin =
{
0x0200, /* Plugin version */
5, /* Number of plugin's functions */
IMGFunc, /* List of functions */
"IMG", /* File's type Handled */
LDG_NOT_SHARED, /* The flags NOT_SHARED is used here.. even if zview plugins are reentrant
and are shareable, we must use this flags because we don't know if the
user has ldg.prg deamon installed on his computer */
NULL, /* Function called when the plugin is unloaded */
1L /* Howmany file type are supported by this plugin */
};
boolean CDECL reader_init( const char *name, IMGINFO info)
{
IMG_REF *pic = NULL;
IMGHDR *head = NULL;
XIMG_DATA *imginfo = NULL;
int16 handle, line_width;
int8 identify[6];
if ( ( handle = ( int16) Fopen( name, 0)) < 0)
return FALSE;
pic = ( IMG_REF*)malloc( sizeof( IMG_REF));
head = &pic->img;
imginfo = &pic->info;
if( pic == NULL)
{
Fclose( handle);
return FALSE;
}
if ( Fread( handle, sizeof( IMGHDR), head) != sizeof( IMGHDR))
{
free( pic);
return FALSE;
}
if (( head->planes != 1) && ( head->planes != 4) && ( head->planes != 8) && ( head->planes != 24))
{
free( pic);
Fclose( handle);
return FALSE;
}
pic->file_handle = handle;
pic->width = head->w;
pic->height = head->h;
pic->planes = head->planes;
line_width = ((( head->w + 15) & 0xfff0) >> 3 ) * head->planes;
imginfo->pat_len = head->pattern_length;
imginfo->line_len = ( head->w + 7) >> 3;
imginfo->file_length = Fseek( 0L, handle, 2);
imginfo->img_buf_len = MAX( 8192, line_width << 1);
imginfo->img_buf = ( uint8*)malloc( imginfo->img_buf_len + 256L);
if ( imginfo->img_buf == NULL)
{
free( pic);
Fclose( handle);
return FALSE;
}
/* Normally, here, it's the size of the line that we allocate but we prevent buffer
Overflow with some picture saved with french application */
imginfo->line_buffer = ( uint8*)malloc( imginfo->img_buf_len + 256L);
imginfo->img_buf_valid = 0;
if ( imginfo->line_buffer == NULL)
{
free( imginfo->img_buf);
free( pic);
Fclose( handle);
return FALSE;
}
info->real_width = info->width = pic->width;
info->real_height = info->height= pic->height;
info->components = ( pic->planes == 1 ? 1 : 3);
info->planes = pic->planes;
info->orientation = UP_TO_DOWN;
info->colors = 1L << ( uint32)pic->planes;
info->indexed_color = FALSE; /* ( (( pic->planes == 1) || ( pic->planes > 8)) ? 0 : 1); */
info->memory_alloc = TT_RAM;
info->page = 1;
info->delay = 0;
info->num_comments = 0;
info->_priv_ptr = ( void*)pic;
strcpy( info->info, "GEM Bitmap ");
strcpy( info->compression, "RLE");
/* It a extended IMG ?, if not, return */
if(( head->length <= ( sizeof( IMGHDR) >> 1)) || ( info->planes > 8))
return TRUE;
strcat( info->info, "( eXtended)");
Fseek( sizeof( IMGHDR), handle, 0);
Fread( handle, 6, identify);
if( strcmp ( identify, "XIMG") != 0)
{
free( imginfo->line_buffer);
free( imginfo->img_buf);
free( pic);
Fclose( handle);
return FALSE;
}
else
{
RGB1000 palette[256];
register int32 pal_len;
register int16 i;
pal_len = MIN ((( head->length << 1) - 6 - sizeof( IMGHDR)), ( sizeof( RGB1000) << 8));
Fread( handle, pal_len, palette);
for ( i = 0; i < info->colors; i++)
{
register int32 intensity = ( int32)palette[i].blue;
info->palette[i].blue = ( uint8) (((( intensity << 8) - intensity) + 500) / 1000L);
intensity = ( int32)palette[i].green;
info->palette[i].green = ( uint8) (((( intensity << 8) - intensity) + 500) / 1000L);
intensity = ( int32)palette[i].red;
info->palette[i].red = ( uint8) (((( intensity << 8) - intensity) + 500) / 1000L);
}
}
return TRUE;
}
void fill_img_buf( IMG_REF *pic)
{
XIMG_DATA *info = &pic->info;
int32 read = info->img_buf_len;
if ( read > info->rest_length)
read = info->rest_length;
info->img_buf_offset = 0;
info->img_buf_used = Fread( pic->file_handle, read, info->img_buf );
info->rest_length -= info->img_buf_used;
}
void refill_img_buf( IMG_REF *pic, int32 read)
{
XIMG_DATA *info = &pic->info;
info->img_buf_used -= read;
info->img_buf_offset += read;
if ( info->img_buf_offset >= ( info->img_buf_len >> 1))
{
if ( info->img_buf_used > 0)
memcpy( info->img_buf, info->img_buf + info->img_buf_offset, info->img_buf_used);
read = info->img_buf_offset;
if ( read > info->rest_length )
read = info->rest_length;
read = Fread( pic->file_handle, read, info->img_buf + info->img_buf_used );
info->img_buf_used += read;
info->img_buf_offset = 0;
info->rest_length -= read;
}
}
uint8 *unpack_line2( uint8 *img, uint8 *des, int16 pat_len, int16 len)
{
register int16 i, cnt;
while ( len > 0)
{
register uint8 tag = *img++;
if ( tag == 0)
{
cnt = *img++;
for ( i = 0; i < cnt; i++)
{
register int16 j;
for ( j = 0; j < pat_len; j++)
*des++ = img[j];
}
img += pat_len;
cnt *= pat_len;
}
else if ( tag == 0x80 )
{
cnt = *img++;
for ( i = 0; i < cnt; i++)
*des++ = *img++;
}
else if (( tag & 0x80 ) == 0)
{
cnt = tag & 0x7f;
for ( i = 0; i < cnt; i++)
*des++ = 0;
}
else
{
cnt = tag & 0x7f;
for ( i = 0; i < cnt; i++)
*des++ = 0xff;
}
len -= cnt;
}
return( img);
}
uint8 *unpack_line1( uint8 *img, uint8 *des, int16 pat_len, int16 len)
{
if (( img[0] == 0 ) && ( img[1] == 0 ) && ( img[2] == 0xff))
{
if ( img[3] > 1)
{
unpack_line2( img + 4, des, pat_len, len);
img[3] -= 1;
return( img);
}
else
return( unpack_line2( img + 4, des, pat_len, len));
}
else
return( unpack_line2( img, des, pat_len, len));
}
void unpack_line( IMG_REF *pic, uint8 *des)
{
XIMG_DATA *info = &pic->info;
uint8 *img_line;
int32 read;
img_line = info->img_buf + info->img_buf_offset;
read = ( int32) ( unpack_line1( img_line, des, info->pat_len, info->line_len * pic->planes ) - img_line );
refill_img_buf( pic, read);
}
boolean CDECL reader_read( IMGINFO info, uint8 *buffer)
{
int16 even_len;
IMG_REF *pic = ( IMG_REF *)info->_priv_ptr;
XIMG_DATA *img_info = &pic->info;
IMGHDR *head = &pic->img;
if ( img_info->img_buf_valid == 0)
{
Fseek( head->length << 1, pic->file_handle, 0);
img_info->rest_length = img_info->file_length - ( head->length << 1);
fill_img_buf( pic);
img_info->img_buf_valid = 1;
}
if( info->planes > 8)
{
unpack_line( pic, buffer);
return TRUE;
}
even_len = ( img_info->line_len + 1) & ~1;
unpack_line( pic, img_info->line_buffer);
if ( img_info->line_len & 1)
{
uint8 *odd, *even;
int16 i;
odd = img_info->line_buffer + ( img_info->line_len * head->planes);
even = odd + head->planes;
for ( i = 0; i < head->planes; i++)
{
*( --even) = 0;
odd -= img_info->line_len;
even -= img_info->line_len;
memcpy( even, odd, img_info->line_len);
}
}
if( !plane2packed24( even_len >> 1, even_len, head->planes, img_info->line_buffer, buffer, info->palette))
return FALSE;
return TRUE;
}
void CDECL reader_get_txt( IMGINFO info, txt_data *txtdata)
{
return;
}
void CDECL reader_quit( IMGINFO info)
{
IMG_REF *pic = ( IMG_REF *)info->_priv_ptr;
if ( pic)
{
Fclose( pic->file_handle );
free( pic->info.img_buf);
free( pic->info.line_buffer);
free( pic);
}
}
void CDECL init( void)
{
return;
}
int main( void)
{
ldg_init( &img_plugin);
return( 0);
}