support many Radiance readers active at once
we had some globals for the Rad reader state, whcih was fine with the old reader, but with the new sequential one you can have several active at once
This commit is contained in:
parent
f5799c4608
commit
ae6ea3ba87
@ -3,6 +3,7 @@
|
|||||||
- falsecolour was not working for some image types
|
- falsecolour was not working for some image types
|
||||||
- foreign memory buffer images did not have the right dhint, broke
|
- foreign memory buffer images did not have the right dhint, broke
|
||||||
command-line falsecolour on sequential images
|
command-line falsecolour on sequential images
|
||||||
|
- support many Radiance readers active at once
|
||||||
|
|
||||||
19/1/14 started 7.38.1
|
19/1/14 started 7.38.1
|
||||||
- bump soname, thanks benjamin
|
- bump soname, thanks benjamin
|
||||||
|
18
TODO
18
TODO
@ -1,21 +1,3 @@
|
|||||||
- shrink does not auto unpack labq or rad, should it?
|
|
||||||
|
|
||||||
- others .. differences in:
|
|
||||||
|
|
||||||
grep -l CODING_LABQ */*.c
|
|
||||||
conversion/join.c
|
|
||||||
conversion/msb.c
|
|
||||||
inplace/im_draw_mask.c
|
|
||||||
resample/shrink.c
|
|
||||||
|
|
||||||
grep -l CODING_RAD */*.c
|
|
||||||
conversion/embed.c
|
|
||||||
inplace/flood.c
|
|
||||||
inplace/im_draw_image.c
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- need to do mosaicing and inplace, plus im_label_regions in morph
|
- need to do mosaicing and inplace, plus im_label_regions in morph
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ read_jpeg_generate( VipsRegion *or,
|
|||||||
printf( "read_jpeg_generate: line %d, %d rows\n",
|
printf( "read_jpeg_generate: line %d, %d rows\n",
|
||||||
r->top, r->height );
|
r->top, r->height );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
VIPS_GATE_START( "read_jpeg_generate: work" );
|
VIPS_GATE_START( "read_jpeg_generate: work" );
|
||||||
|
|
||||||
/* We're inside a tilecache where tiles are the full image width, so
|
/* We're inside a tilecache where tiles are the full image width, so
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
* - support sequential read
|
* - support sequential read
|
||||||
* 5/11/13
|
* 5/11/13
|
||||||
* - rewritten scanline encode and decode, now much faster
|
* - rewritten scanline encode and decode, now much faster
|
||||||
|
* 23/1/14
|
||||||
|
* - put the reader globals into a struct so we can have many active
|
||||||
|
* readers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -617,38 +620,57 @@ register RESOLU *rp;
|
|||||||
#define BUFFER_SIZE (4096)
|
#define BUFFER_SIZE (4096)
|
||||||
#define BUFFER_MARGIN (256)
|
#define BUFFER_MARGIN (256)
|
||||||
|
|
||||||
static unsigned char buffer[BUFFER_SIZE + BUFFER_MARGIN];
|
/* Read from a FILE with a rolling memory buffer ... this lets us reduce the
|
||||||
static int buffer_length = 0;
|
* number of fgetc() and gives us some very quick readahead.
|
||||||
static int buffer_position = 0;
|
*/
|
||||||
static FILE *buffer_fp = NULL;
|
|
||||||
|
|
||||||
static void
|
typedef struct _Buffer {
|
||||||
buffer_init( FILE *fp )
|
unsigned char text[BUFFER_SIZE + BUFFER_MARGIN];
|
||||||
|
int length;
|
||||||
|
int position;
|
||||||
|
FILE *fp;
|
||||||
|
} Buffer;
|
||||||
|
|
||||||
|
static Buffer *
|
||||||
|
buffer_new( FILE *fp )
|
||||||
{
|
{
|
||||||
buffer_length = 0;
|
Buffer *buffer = g_new0( Buffer, 1 );
|
||||||
buffer_position = 0;
|
|
||||||
buffer_fp = fp;
|
buffer->length = 0;
|
||||||
|
buffer->position = 0;
|
||||||
|
buffer->fp = fp;
|
||||||
|
|
||||||
|
return( buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
buffer_free( Buffer *buffer )
|
||||||
|
{
|
||||||
|
g_free( buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure there are at least @require bytes of readahead available.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
buffer_need( int require )
|
buffer_need( Buffer *buffer, int require )
|
||||||
{
|
{
|
||||||
int remaining;
|
int remaining;
|
||||||
|
|
||||||
g_assert( require < BUFFER_MARGIN );
|
g_assert( require < BUFFER_MARGIN );
|
||||||
|
|
||||||
remaining = buffer_length - buffer_position;
|
remaining = buffer->length - buffer->position;
|
||||||
if( remaining < require ) {
|
if( remaining < require ) {
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
memcpy( buffer, buffer + buffer_position, remaining );
|
memcpy( buffer->text,
|
||||||
buffer_position = 0;
|
buffer->text + buffer->position, remaining );
|
||||||
buffer_length = remaining;
|
buffer->position = 0;
|
||||||
|
buffer->length = remaining;
|
||||||
|
|
||||||
len = fread( buffer + buffer_length, 1, BUFFER_SIZE,
|
len = fread( buffer->text + buffer->length,
|
||||||
buffer_fp );
|
1, BUFFER_SIZE, buffer->fp );
|
||||||
buffer_length += len;
|
buffer->length += len;
|
||||||
remaining = buffer_length - buffer_position;
|
remaining = buffer->length - buffer->position;
|
||||||
|
|
||||||
if( remaining < require ) {
|
if( remaining < require ) {
|
||||||
vips_error( "rad2vips", "%s", _( "end of file" ) );
|
vips_error( "rad2vips", "%s", _( "end of file" ) );
|
||||||
@ -659,26 +681,26 @@ buffer_need( int require )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BUFFER_FETCH (buffer[buffer_position++])
|
#define BUFFER_FETCH(B) ((B)->text[(B)->position++])
|
||||||
#define BUFFER_PEEK (buffer[buffer_position])
|
#define BUFFER_PEEK(B) ((B)->text[(B)->position])
|
||||||
|
|
||||||
/* Read a single scanlne, encoded in the old style.
|
/* Read a single scanlne, encoded in the old style.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
scanline_read_old( COLR *scanline, int width )
|
scanline_read_old( Buffer *buffer, COLR *scanline, int width )
|
||||||
{
|
{
|
||||||
int rshift;
|
int rshift;
|
||||||
|
|
||||||
rshift = 0;
|
rshift = 0;
|
||||||
|
|
||||||
while( width > 0 ) {
|
while( width > 0 ) {
|
||||||
if( buffer_need( 4 ) )
|
if( buffer_need( buffer, 4 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
scanline[0][RED] = BUFFER_FETCH;
|
scanline[0][RED] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][GRN] = BUFFER_FETCH;
|
scanline[0][GRN] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][BLU] = BUFFER_FETCH;
|
scanline[0][BLU] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][EXP] = BUFFER_FETCH;
|
scanline[0][EXP] = BUFFER_FETCH( buffer );
|
||||||
|
|
||||||
if( scanline[0][RED] == 1 &&
|
if( scanline[0][RED] == 1 &&
|
||||||
scanline[0][GRN] == 1 &&
|
scanline[0][GRN] == 1 &&
|
||||||
@ -706,7 +728,7 @@ scanline_read_old( COLR *scanline, int width )
|
|||||||
/* Read a single encoded scanline.
|
/* Read a single encoded scanline.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
scanline_read( COLR *scanline, int width )
|
scanline_read( Buffer *buffer, COLR *scanline, int width )
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
@ -714,21 +736,21 @@ scanline_read( COLR *scanline, int width )
|
|||||||
*/
|
*/
|
||||||
if( width < MINELEN ||
|
if( width < MINELEN ||
|
||||||
width > MAXELEN )
|
width > MAXELEN )
|
||||||
return( scanline_read_old( scanline, width ) );
|
return( scanline_read_old( buffer, scanline, width ) );
|
||||||
|
|
||||||
if( buffer_need( 4 ) )
|
if( buffer_need( buffer, 4 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( BUFFER_PEEK != 2 )
|
if( BUFFER_PEEK( buffer ) != 2 )
|
||||||
return( scanline_read_old( scanline, width ) );
|
return( scanline_read_old( buffer, scanline, width ) );
|
||||||
|
|
||||||
scanline[0][RED] = BUFFER_FETCH;
|
scanline[0][RED] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][GRN] = BUFFER_FETCH;
|
scanline[0][GRN] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][BLU] = BUFFER_FETCH;
|
scanline[0][BLU] = BUFFER_FETCH( buffer );
|
||||||
scanline[0][EXP] = BUFFER_FETCH;
|
scanline[0][EXP] = BUFFER_FETCH( buffer );
|
||||||
if( scanline[0][GRN] != 2 ||
|
if( scanline[0][GRN] != 2 ||
|
||||||
scanline[0][BLU] & 128 )
|
scanline[0][BLU] & 128 )
|
||||||
return( scanline_read_old( scanline + 1, width - 1 ) );
|
return( scanline_read_old( buffer, scanline + 1, width - 1 ) );
|
||||||
|
|
||||||
if( ((scanline[0][BLU] << 8) | scanline[0][EXP]) != width ) {
|
if( ((scanline[0][BLU] << 8) | scanline[0][EXP]) != width ) {
|
||||||
vips_error( "rad2vips", "%s", _( "scanline length mismatch" ) );
|
vips_error( "rad2vips", "%s", _( "scanline length mismatch" ) );
|
||||||
@ -740,10 +762,10 @@ scanline_read( COLR *scanline, int width )
|
|||||||
int code, len;
|
int code, len;
|
||||||
gboolean run;
|
gboolean run;
|
||||||
|
|
||||||
if( buffer_need( 2 ) )
|
if( buffer_need( buffer, 2 ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
code = BUFFER_FETCH;
|
code = BUFFER_FETCH( buffer );
|
||||||
run = code > 128;
|
run = code > 128;
|
||||||
len = run ? code & 127 : code;
|
len = run ? code & 127 : code;
|
||||||
|
|
||||||
@ -755,15 +777,16 @@ scanline_read( COLR *scanline, int width )
|
|||||||
if( run ) {
|
if( run ) {
|
||||||
int val;
|
int val;
|
||||||
|
|
||||||
val = BUFFER_FETCH;
|
val = BUFFER_FETCH( buffer );
|
||||||
while( len-- )
|
while( len-- )
|
||||||
scanline[j++][i] = val;
|
scanline[j++][i] = val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( buffer_need( len ) )
|
if( buffer_need( buffer, len ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
while( len-- )
|
while( len-- )
|
||||||
scanline[j++][i] = BUFFER_FETCH;
|
scanline[j++][i] =
|
||||||
|
BUFFER_FETCH( buffer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,6 +884,7 @@ typedef struct {
|
|||||||
double aspect;
|
double aspect;
|
||||||
RGBPRIMS prims;
|
RGBPRIMS prims;
|
||||||
RESOLU rs;
|
RESOLU rs;
|
||||||
|
Buffer *buffer;
|
||||||
} Read;
|
} Read;
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -888,7 +912,7 @@ read_destroy( VipsObject *object, Read *read )
|
|||||||
{
|
{
|
||||||
VIPS_FREE( read->filename );
|
VIPS_FREE( read->filename );
|
||||||
VIPS_FREEF( fclose, read->fin );
|
VIPS_FREEF( fclose, read->fin );
|
||||||
buffer_init( NULL );
|
VIPS_FREEF( buffer_free, read->buffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
static Read *
|
static Read *
|
||||||
@ -920,9 +944,9 @@ read_new( const char *filename, VipsImage *out )
|
|||||||
g_signal_connect( out, "close",
|
g_signal_connect( out, "close",
|
||||||
G_CALLBACK( read_destroy ), read );
|
G_CALLBACK( read_destroy ), read );
|
||||||
|
|
||||||
if( !(read->fin = vips__file_open_read( filename, NULL, FALSE )) )
|
if( !(read->fin = vips__file_open_read( filename, NULL, FALSE )) ||
|
||||||
|
!(read->buffer = buffer_new( read->fin )) )
|
||||||
return( NULL );
|
return( NULL );
|
||||||
buffer_init( read->fin );
|
|
||||||
|
|
||||||
return( read );
|
return( read );
|
||||||
}
|
}
|
||||||
@ -1037,24 +1061,30 @@ rad2vips_generate( VipsRegion *or,
|
|||||||
void *seq, void *a, void *b, gboolean *stop )
|
void *seq, void *a, void *b, gboolean *stop )
|
||||||
{
|
{
|
||||||
VipsRect *r = &or->valid;
|
VipsRect *r = &or->valid;
|
||||||
|
Read *read = (Read *) a;
|
||||||
|
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf( "rad2vips_get_data\n" );
|
printf( "rad2vips_generate: line %d, %d rows\n",
|
||||||
|
r->top, r->height );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
VIPS_GATE_START( "rad2vips_generate: work" );
|
||||||
|
|
||||||
for( y = 0; y < r->height; y++ ) {
|
for( y = 0; y < r->height; y++ ) {
|
||||||
COLR *buf = (COLR *)
|
COLR *buf = (COLR *)
|
||||||
VIPS_REGION_ADDR( or, 0, r->top + y );
|
VIPS_REGION_ADDR( or, 0, r->top + y );
|
||||||
|
|
||||||
if( scanline_read( buf, or->im->Xsize ) ) {
|
if( scanline_read( read->buffer, buf, or->im->Xsize ) ) {
|
||||||
vips_error( "rad2vips",
|
vips_error( "rad2vips",
|
||||||
_( "read error line %d" ), r->top + y );
|
_( "read error line %d" ), r->top + y );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VIPS_GATE_STOP( "rad2vips_generate: work" );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user