Merge remote-tracking branch 'origin/7.38'

Conflicts:
	ChangeLog
	configure.ac
	libvips/conversion/falsecolour.c
	libvips/resample/affine.c
This commit is contained in:
John Cupitt 2014-01-23 15:25:09 +00:00
commit 13a6ed1457
6 changed files with 113 additions and 56 deletions

View File

@ -1,4 +1,12 @@
21/1/14 started 7.39.0
- fancy auto-decode for all operations
22/1/14 started 7.38.2
- auto RAD decode for affine
- falsecolour was not working for some image types
- foreign memory buffer images did not have the right dhint, broke
command-line falsecolour on sequential images
- support many Radiance readers active at once
19/1/14 started 7.38.1
- bump soname, thanks benjamin

View File

@ -14,6 +14,8 @@
* - force input to mono 8-bit for the user
* 1/8/13
* - redone as a class
* 23/1/14
* - oops, was not auto-getting and casting the first band
*/
/*
@ -342,11 +344,14 @@ vips_falsecolour_build( VipsObject *object )
VIPS_FORMAT_UCHAR )) )
return( -1 );
/* Force to mono 8-bit.
/* Force to mono 8-bit. Don't use vips_colourspace() to go to B_W, we
* want to work for images which aren't in a recognised space, like
* MULTIBAND.
*/
if( vips_colourspace( falsecolour->in, &t[1],
VIPS_INTERPRETATION_B_W, NULL ) ||
vips_maplut( t[1], &t[3], t[0], NULL ) ||
if( vips_check_uncoded( class->nickname, falsecolour->in ) ||
vips_extract_band( falsecolour->in, &t[1], 0, NULL ) ||
vips_cast( t[1], &t[2], VIPS_FORMAT_UCHAR, NULL ) ||
vips_maplut( t[2], &t[3], t[0], NULL ) ||
vips_image_write( t[3], conversion->out ) )
return( -1 );

View File

@ -150,6 +150,10 @@ typedef struct _ReadJpeg {
/* Set if we need to finish the decompress.
*/
gboolean decompressing;
/* Track the y pos during a read with this.
*/
int y_pos;
} ReadJpeg;
static int
@ -222,6 +226,8 @@ readjpeg_new( VipsImage *out, int shrink, gboolean fail, gboolean readbehind )
jpeg->eman.pub.output_message = vips__new_output_message;
jpeg->eman.fp = NULL;
jpeg->y_pos = 0;
/* jpeg_create_decompress() can fail on some sanity checks. Don't
* readjpeg_free() since we don't want to jpeg_destroy_decompress().
*/
@ -888,7 +894,7 @@ read_jpeg_generate( VipsRegion *or,
printf( "read_jpeg_generate: line %d, %d rows\n",
r->top, r->height );
#endif /*DEBUG*/
VIPS_GATE_START( "read_jpeg_generate: work" );
/* We're inside a tilecache where tiles are the full image width, so
@ -907,6 +913,11 @@ read_jpeg_generate( VipsRegion *or,
*/
g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) );
/* And check that y_pos is correct. It should be, since we are inside
* a vips_sequential().
*/
g_assert( r->top == jpeg->y_pos );
/* Here for longjmp() from vips__new_error_exit().
*/
if( setjmp( jpeg->eman.jmp ) )
@ -926,6 +937,8 @@ read_jpeg_generate( VipsRegion *or,
for( x = 0; x < sz; x++ )
row_pointer[0][x] = 255 - row_pointer[0][x];
}
jpeg->y_pos += 1;
}
VIPS_GATE_STOP( "read_jpeg_generate: work" );

View File

@ -12,6 +12,9 @@
* - support sequential read
* 5/11/13
* - 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_MARGIN (256)
static unsigned char buffer[BUFFER_SIZE + BUFFER_MARGIN];
static int buffer_length = 0;
static int buffer_position = 0;
static FILE *buffer_fp = NULL;
/* Read from a FILE with a rolling memory buffer ... this lets us reduce the
* number of fgetc() and gives us some very quick readahead.
*/
static void
buffer_init( FILE *fp )
typedef struct _Buffer {
unsigned char text[BUFFER_SIZE + BUFFER_MARGIN];
int length;
int position;
FILE *fp;
} Buffer;
static Buffer *
buffer_new( FILE *fp )
{
buffer_length = 0;
buffer_position = 0;
buffer_fp = fp;
Buffer *buffer = g_new0( Buffer, 1 );
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
buffer_need( int require )
buffer_need( Buffer *buffer, int require )
{
int remaining;
g_assert( require < BUFFER_MARGIN );
remaining = buffer_length - buffer_position;
remaining = buffer->length - buffer->position;
if( remaining < require ) {
size_t len;
memcpy( buffer, buffer + buffer_position, remaining );
buffer_position = 0;
buffer_length = remaining;
memcpy( buffer->text,
buffer->text + buffer->position, remaining );
buffer->position = 0;
buffer->length = remaining;
len = fread( buffer + buffer_length, 1, BUFFER_SIZE,
buffer_fp );
buffer_length += len;
remaining = buffer_length - buffer_position;
len = fread( buffer->text + buffer->length,
1, BUFFER_SIZE, buffer->fp );
buffer->length += len;
remaining = buffer->length - buffer->position;
if( remaining < require ) {
vips_error( "rad2vips", "%s", _( "end of file" ) );
@ -659,26 +681,26 @@ buffer_need( int require )
return( 0 );
}
#define BUFFER_FETCH (buffer[buffer_position++])
#define BUFFER_PEEK (buffer[buffer_position])
#define BUFFER_FETCH(B) ((B)->text[(B)->position++])
#define BUFFER_PEEK(B) ((B)->text[(B)->position])
/* Read a single scanlne, encoded in the old style.
*/
static int
scanline_read_old( COLR *scanline, int width )
scanline_read_old( Buffer *buffer, COLR *scanline, int width )
{
int rshift;
rshift = 0;
while( width > 0 ) {
if( buffer_need( 4 ) )
if( buffer_need( buffer, 4 ) )
return( -1 );
scanline[0][RED] = BUFFER_FETCH;
scanline[0][GRN] = BUFFER_FETCH;
scanline[0][BLU] = BUFFER_FETCH;
scanline[0][EXP] = BUFFER_FETCH;
scanline[0][RED] = BUFFER_FETCH( buffer );
scanline[0][GRN] = BUFFER_FETCH( buffer );
scanline[0][BLU] = BUFFER_FETCH( buffer );
scanline[0][EXP] = BUFFER_FETCH( buffer );
if( scanline[0][RED] == 1 &&
scanline[0][GRN] == 1 &&
@ -706,7 +728,7 @@ scanline_read_old( COLR *scanline, int width )
/* Read a single encoded scanline.
*/
static int
scanline_read( COLR *scanline, int width )
scanline_read( Buffer *buffer, COLR *scanline, int width )
{
int i, j;
@ -714,21 +736,21 @@ scanline_read( COLR *scanline, int width )
*/
if( width < MINELEN ||
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 );
if( BUFFER_PEEK != 2 )
return( scanline_read_old( scanline, width ) );
if( BUFFER_PEEK( buffer ) != 2 )
return( scanline_read_old( buffer, scanline, width ) );
scanline[0][RED] = BUFFER_FETCH;
scanline[0][GRN] = BUFFER_FETCH;
scanline[0][BLU] = BUFFER_FETCH;
scanline[0][EXP] = BUFFER_FETCH;
scanline[0][RED] = BUFFER_FETCH( buffer );
scanline[0][GRN] = BUFFER_FETCH( buffer );
scanline[0][BLU] = BUFFER_FETCH( buffer );
scanline[0][EXP] = BUFFER_FETCH( buffer );
if( scanline[0][GRN] != 2 ||
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 ) {
vips_error( "rad2vips", "%s", _( "scanline length mismatch" ) );
@ -740,10 +762,10 @@ scanline_read( COLR *scanline, int width )
int code, len;
gboolean run;
if( buffer_need( 2 ) )
if( buffer_need( buffer, 2 ) )
return( -1 );
code = BUFFER_FETCH;
code = BUFFER_FETCH( buffer );
run = code > 128;
len = run ? code & 127 : code;
@ -755,15 +777,16 @@ scanline_read( COLR *scanline, int width )
if( run ) {
int val;
val = BUFFER_FETCH;
val = BUFFER_FETCH( buffer );
while( len-- )
scanline[j++][i] = val;
}
else {
if( buffer_need( len ) )
if( buffer_need( buffer, len ) )
return( -1 );
while( len-- )
scanline[j++][i] = BUFFER_FETCH;
scanline[j++][i] =
BUFFER_FETCH( buffer );
}
}
@ -861,6 +884,7 @@ typedef struct {
double aspect;
RGBPRIMS prims;
RESOLU rs;
Buffer *buffer;
} Read;
int
@ -888,7 +912,7 @@ read_destroy( VipsObject *object, Read *read )
{
VIPS_FREE( read->filename );
VIPS_FREEF( fclose, read->fin );
buffer_init( NULL );
VIPS_FREEF( buffer_free, read->buffer );
}
static Read *
@ -920,9 +944,9 @@ read_new( const char *filename, VipsImage *out )
g_signal_connect( out, "close",
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 );
buffer_init( read->fin );
return( read );
}
@ -1037,24 +1061,30 @@ rad2vips_generate( VipsRegion *or,
void *seq, void *a, void *b, gboolean *stop )
{
VipsRect *r = &or->valid;
Read *read = (Read *) a;
int y;
#ifdef DEBUG
printf( "rad2vips_get_data\n" );
printf( "rad2vips_generate: line %d, %d rows\n",
r->top, r->height );
#endif /*DEBUG*/
VIPS_GATE_START( "rad2vips_generate: work" );
for( y = 0; y < r->height; y++ ) {
COLR *buf = (COLR *)
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",
_( "read error line %d" ), r->top + y );
return( -1 );
}
}
VIPS_GATE_STOP( "rad2vips_generate: work" );
return( 0 );
}

View File

@ -937,6 +937,7 @@ vips_image_build( VipsObject *object )
image->Type = VIPS_INTERPRETATION_MULTIBAND;
image->dtype = VIPS_IMAGE_SETBUF_FOREIGN;
image->dhint = VIPS_DEMAND_STYLE_ANY;
break;

View File

@ -79,6 +79,8 @@
* 14/12/12
* - redone as a class
* - added input space translation
* 22/1/14
* - auto RAD decode
*/
/*
@ -412,7 +414,7 @@ vips_affine_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_affine_parent_class )->build( object ) )
return( -1 );
if( vips_check_coding_noneorlabq( class->nickname, resample->in ) )
if( vips_check_coding_known( class->nickname, resample->in ) )
return( -1 );
if( vips_check_vector_length( class->nickname,
affine->matrix->n, 4 ) )
@ -483,21 +485,19 @@ vips_affine_build( VipsObject *object )
return( -1 );
}
/* Unpack labq for processing.
*/
if( vips__image_decode( in, &t[0] ) )
return( -1 );
in = t[0];
/* Add new pixels around the input so we can interpolate at the edges.
*/
if( vips_embed( in, &t[1],
if( vips_embed( in, &t[2],
window_offset, window_offset,
in->Xsize + window_size, in->Ysize + window_size,
"extend", VIPS_EXTEND_COPY,
NULL ) )
return( -1 );
in = t[1];
in = t[2];
/* Normally SMALLTILE ... except if this is a size up/down affine.
*/