Files
FireBee_Setup/sources/z-tools/trunk/zview/pic_load.c

353 lines
9.6 KiB
C

#include "general.h"
#include "pic_load.h"
#include "prefs.h"
#include "progress.h"
#include "plugins.h"
#include "mfdb.h"
#include "ztext.h"
#include "chrono.h"
#include "txt_data.h"
#include "zvdi//color.h"
#include "zvdi//raster.h"
#include "zvdi//vdi.h"
#include <math.h>
boolean decoder_init_done = FALSE;
void ( *raster) ( DECDATA, void *dst);
void ( *raster_cmap) ( DECDATA, void *);
void ( *raster_true) ( DECDATA, void *);
void ( *cnvpal_color) ( IMGINFO, DECDATA);
void ( *raster_gray) ( DECDATA, void *);
void CDECL ( *decoder_quit) ( IMGINFO);
boolean CDECL ( *decoder_init) ( const char *, IMGINFO);
boolean CDECL ( *decoder_read) ( IMGINFO, uint8 *);
void CDECL ( *decoder_get_txt) ( IMGINFO, txt_data *);
extern int16 smooth_resize( MFDB *source_image, MFDB *resized_image, int resize_algo);
static int16 setup ( IMAGE *img, IMGINFO info, DECDATA data)
{
int16 i, n_planes = ( ( info->planes == 1 && info->components == 1) ? 1: app.nplanes);
uint16 display_w, display_h;
double precise_x, precise_y, factor;
size_t src_line_size;
if( img->view_mode && ( info->width > thumbnail[thumbnail_size][0] || info->height > thumbnail[thumbnail_size][1]) && ( !smooth_thumbnail || n_planes < 16))
{
factor = MAX( ( ( double)info->height / ( double)thumbnail[thumbnail_size][1]), ( ( double)info->width / ( double)thumbnail[thumbnail_size][0]));
precise_x = ( double)info->width / factor;
precise_y = ( double)info->height / factor;
display_w = ( uint16)( precise_x > 0 ? precise_x : 16);
display_h = ( uint16)( precise_y > 0 ? precise_y : 16);
data->IncXfx = ((( uint32)info->width << 16) + ( display_w >> 1)) / display_w;
data->IncYfx = ((( uint32)info->height << 16) + ( display_h >> 1)) / display_h;
}
else
{
display_w = info->width;
display_h = info->height;
data->IncXfx = 0x10000uL;
data->IncYfx = 0x10000uL;
}
if( img->view_mode)
/* if we are in preview mode, we decompress only one image */
img->page = 1;
else
img->page = info->page;
if( ( img->image = ( MFDB *)gmalloc( sizeof( MFDB) * img->page)) == NULL)
return( 0);
for ( i = 0 ; i < img->page ; i++)
{
if ( !init_mfdb( &img->image[i], display_w, display_h, n_planes))
return( 0);
}
if( info->num_comments)
{
/* we initialise the txt_data struct... */
if( !init_txt_data( img, info->num_comments, info->max_comments_length))
return ( 0);
decoder_get_txt( info, img->comments);
}
else
img->comments = NULL;
// we assume that the pixel size is minimum 8 bits because some GNU libraries return 1 and 4 bits format like 8 bits ones.
// We add also a little more memory for avoid buffer overflow for plugin badly coded.
src_line_size = ( info->width + 64) * info->components;
data->RowBuf = ( uint8*)gmalloc( src_line_size);
if( !data->RowBuf)
return ( 0);
if(( info->planes == 1 && info->components == 1) || app.nplanes > 8)
data->DthBuf = NULL;
else
{
size_t size = ( display_w + 15) * 3;
if( ( data->DthBuf = gmalloc( size)) == NULL)
return ( 0);
memset( data->DthBuf, 0, size);
}
data->DthWidth = display_w;
data->PixMask = ( 1 << info->planes) - 1;
data->LnSize = img->image[0].fd_wdwidth * n_planes;
if ( info->planes == 1 && info->components == 1)
{
cnvpal_mono( info, data);
raster = raster_mono;
}
else
{
if ( info->indexed_color)
{
( *cnvpal_color)( info, data);
raster = raster_cmap;
}
else
raster = ( info->components >= 3 ? raster_true : raster_gray);
}
img->img_w = info->real_width;
img->img_h = info->real_height;
img->colors = info->colors;
img->bits = info->planes;
strcpy( img->info, info->info);
strcpy( img->compression, info->compression);
return( 1);
}
/*==================================================================================*
* read_img: *
* Read a image and fit the MFDB within IMAGE structur with the data. *
*----------------------------------------------------------------------------------*
* img: The struct. with the MFDB to be fitted. *
* info: The struct. with the line and dither buffer *
*----------------------------------------------------------------------------------*
* returns: - *
*==================================================================================*/
static inline void read_img ( IMAGE *img, IMGINFO info, DECDATA data)
{
uint16 *dst;
int16 y_dst, i, y, progress_counter = 0, img_h = info->height;
int32 line_size = data->LnSize, line_to_decode = img_h * img->page;
uint8 *buf = data->RowBuf;
for ( i = 0; i < img->page; i++)
{
uint32 scale = ( data->IncYfx + 1) >> 1;
y_dst = img->image[0].fd_h;
dst = img->image[i].fd_addr;
if( info->orientation == DOWN_TO_UP)
{
dst += data->LnSize * ( y_dst - 1);
line_size = -data->LnSize;
}
info->page_wanted = i;
for( y = 1; y <= img_h; y++)
{
if( !decoder_read( info, buf))
return;
while(( scale >> 16) < y)
{
( *raster)( data, dst);
dst += line_size;
scale += data->IncYfx;
if (!--y_dst) break;
}
if( img->progress_bar)
{
progress_counter++;
win_progress(( int16)((( int32)progress_counter * 150L) / line_to_decode));
}
}
img->delay[i] = info->delay;
}
}
/*==================================================================================*
* quit_img: *
* Close the image's file and free the line/dither/info buffer. *
*----------------------------------------------------------------------------------*
* info: The struct. to liberate *
*----------------------------------------------------------------------------------*
* returns: - *
*==================================================================================*/
void quit_img( IMGINFO info, DECDATA data)
{
if( decoder_init_done == TRUE)
decoder_quit( info);
if( data->DthBuf != NULL)
gfree( data->DthBuf);
if( data->RowBuf != NULL)
gfree( data->RowBuf);
gfree( data);
gfree( info);
decoder_init_done = FALSE;
}
boolean get_pic_info( const char *file, char *extention, IMGINFO info)
{
int16 i, j, c = 0;
char plugin[3];
/* We check if a plug-ins can do the job */
for( i = 0; i < plugins_nbr; i++, c = 0)
{
for( j = 0; j < codecs[i]->user_ext; j++)
{
plugin[0] = codecs[i]->infos[c++];
plugin[1] = codecs[i]->infos[c++];
plugin[2] = codecs[i]->infos[c++];
if( strncmp( extention, plugin, 3) == 0)
{
if ( !( decoder_init = ldg_find( "reader_init", codecs[i]))
|| !( decoder_read = ldg_find( "reader_read", codecs[i]))
|| !( decoder_quit = ldg_find( "reader_quit", codecs[i]))
|| !( decoder_get_txt = ldg_find( "reader_get_txt", codecs[i])))
{
errshow( codecs[i]->infos, ldg_error());
return FALSE;
}
// decoder_get_page_size = ldg_find( "reader_get_page_size", codecs[i]);
return decoder_init( file, info);
}
}
}
/* I wish that it will never append ! */
return FALSE;
}
/*==================================================================================*
* pic_load: *
* read a supported picture and fill a IMAGE structure. *
*----------------------------------------------------------------------------------*
* file: The file that will be read. *
* img: The IMAGE struct. that will be filled. *
*----------------------------------------------------------------------------------*
* returns: '0' if error or picture not supported *
*==================================================================================*/
int16 pic_load( const char *file, char *extention, IMAGE *img)
{
IMGINFO info;
DECDATA data;
info = ( img_info *) gmalloc( sizeof( img_info));
if ( !info)
{
errshow( "", ENOMEM);
return( 0);
}
data = ( dec_data *) gmalloc( sizeof( dec_data));
if ( !data)
{
errshow( "", ENOMEM);
gfree( info);
return ( 0);
}
if( img->progress_bar)
win_progress_begin( "Please Wait...");
/* We initialise some variables needed by the codecs */
info->background_color = 0xFFFFFF;
info->thumbnail = img->view_mode;
chrono_on();
if(( decoder_init_done = get_pic_info( file, extention, info)) == FALSE)
{
gfree( data);
gfree( info);
win_progress_end();
return ( 0);
}
if( !setup ( img, info, data))
{
errshow( "", ENOMEM);
quit_img( info, data);
delete_mfdb( img->image, img->page);
win_progress_end();
return ( 0);
}
read_img ( img, info, data);
quit_img( info, data);
win_progress_end();
if( img->view_mode && ( img->image[0].fd_w > thumbnail[thumbnail_size][0] || img->image[0].fd_h > thumbnail[thumbnail_size][1]) && smooth_thumbnail && img->image[0].fd_nplanes >= 16)
{
MFDB resized_image;
double precise_x, precise_y, factor;
uint16 display_w, display_h;
factor = MAX((( double)img->image[0].fd_h / ( double)thumbnail[thumbnail_size][1]), (( double)img->image[0].fd_w / ( double)thumbnail[thumbnail_size][0]));
precise_x = ( double)img->image[0].fd_w / factor;
precise_y = ( double)img->image[0].fd_h / factor;
display_w = ( uint16)( precise_x > 0 ? precise_x : 16);
display_h = ( uint16)( precise_y > 0 ? precise_y : 16);
init_mfdb( &resized_image, display_w, display_h, img->image[0].fd_nplanes);
smooth_resize( &img->image[0], &resized_image, smooth_thumbnail);
gfree( img->image[0].fd_addr);
img->image[0].fd_addr = resized_image.fd_addr;
img->image[0].fd_w = resized_image.fd_w;
img->image[0].fd_h = resized_image.fd_h;
img->image[0].fd_wdwidth = resized_image.fd_wdwidth;
}
chrono_off( img->working_time);
return ( 1);
}