/* As above, but map read/write. */ int vips_mapfilerw( VipsImage *im ) { struct stat st; mode_t m; assert( !im->baseaddr ); /* Check the size of the file if it is less than 64 bytes return * make also sure that it is a regular file */ g_assert( im->file_length > 0 ); if( fstat( im->fd, &st ) == -1 ) { vips_error( "vips_mapfilerw", "%s", _( "unable to get file status" ) ); return( -1 ); } m = (mode_t) st.st_mode; if( im->file_length < 64 || !S_ISREG( m ) ) { vips_error( "vips_mapfile", "%s", _( "unable to read data" ) ); return( -1 ); } if( !(im->baseaddr = vips__mmap( im->fd, 1, im->file_length, 0 )) ) return( -1 ); im->length = im->file_length; return( 0 ); }
static int read_image( Read *read, VipsImage *out ) { VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); guint64 length; void *data; int fd; webp_decoder decoder; /* libwebp makes streaming very hard. We have to read to a full memory * buffer, then copy to out. * * mmap the input file, it's slightly quicker. */ t[0] = vips_image_new_buffer(); if( read_header( read, t[0] ) ) return( -1 ); if( vips_image_write_prepare( t[0] ) ) return( -1 ); if( !(fd = vips__open_image_read( read->filename )) ) return( -1 ); if( (length = vips_file_length( fd )) < 0 ) { vips_tracked_close( fd ); return( -1 ); } if( !(data = vips__mmap( fd, FALSE, length, 0 )) ) { vips_tracked_close( fd ); return( -1 ); } if( t[0]->Bands == 3 ) decoder = WebPDecodeRGBInto; else decoder = WebPDecodeRGBAInto; if( !decoder( (uint8_t *) data, length, VIPS_IMAGE_ADDR( t[0], 0, 0 ), VIPS_IMAGE_SIZEOF_IMAGE( t[0] ), VIPS_IMAGE_SIZEOF_LINE( t[0] ) ) ) { vips__munmap( data, length ); vips_tracked_close( fd ); vips_error( "webp2vips", "%s", _( "unable to read pixels" ) ); return( -1 ); } vips__munmap( data, length ); vips_tracked_close( fd ); if( vips_image_write( t[0], out ) ) return( -1 ); return( 0 ); }
/* Map a window into a file. */ static int vips_window_set( VipsWindow *window, int top, int height ) { int pagesize = vips_getpagesize(); void *baseaddr; gint64 start, end, pagestart; size_t length, pagelength; /* Calculate start and length for our window. */ start = window->im->sizeof_header + VIPS_IMAGE_SIZEOF_LINE( window->im ) * top; length = VIPS_IMAGE_SIZEOF_LINE( window->im ) * height; pagestart = start - start % pagesize; end = start + length; pagelength = end - pagestart; /* Make sure we have enough file. */ if( end > window->im->file_length ) { vips_error( "vips_window_set", _( "unable to read data for \"%s\", %s" ), window->im->filename, _( "file has been truncated" ) ); return( -1 ); } if( !(baseaddr = vips__mmap( window->im->fd, 0, pagelength, pagestart )) ) return( -1 ); window->baseaddr = baseaddr; window->length = pagelength; window->data = (VipsPel *) baseaddr + (start - pagestart); window->top = top; window->height = height; /* Sanity check ... make sure the data pointer is readable. */ vips__read_test &= window->data[0]; #ifdef DEBUG_TOTAL g_mutex_lock( vips__global_lock ); total_mmap_usage += window->length; if( total_mmap_usage > max_mmap_usage ) max_mmap_usage = total_mmap_usage; g_mutex_unlock( vips__global_lock ); trace_mmap_usage(); #endif /*DEBUG_TOTAL*/ return( 0 ); }
static Read * read_new( const char *filename, void *data, size_t length ) { Read *read; if( !(read = VIPS_NEW( NULL, Read )) ) return( NULL ); read->filename = g_strdup( filename ); read->data = data; read->length = length; read->fd = 0; read->idec = NULL; if( read->filename ) { /* libwebp makes streaming from a file source very hard. We * have to read to a full memory buffer, then copy to out. * * mmap the input file, it's slightly quicker. */ if( (read->fd = vips__open_image_read( read->filename )) < 0 || (read->length = vips_file_length( read->fd )) < 0 || !(read->data = vips__mmap( read->fd, FALSE, read->length, 0 )) ) { read_free( read ); return( NULL ); } } WebPInitDecoderConfig( &read->config ); if( WebPGetFeatures( read->data, MINIMAL_HEADER, &read->config.input ) != VP8_STATUS_OK ) { read_free( read ); return( NULL ); } if( read->config.input.has_alpha ) read->config.output.colorspace = MODE_RGBA; else read->config.output.colorspace = MODE_RGB; read->config.options.use_threads = TRUE; return( read ); }
int vips_mapfile( VipsImage *im ) { struct stat st; mode_t m; assert( !im->baseaddr ); /* Check the size of the file; if it is less than 64 bytes, then flag * an error, we won't be able to read the vips header without a segv. */ g_assert( im->file_length > 0 ); if( im->file_length < 64 ) { vips_error( "vips_mapfile", "%s", _( "file is less than 64 bytes" ) ); return( -1 ); } if( fstat( im->fd, &st ) == -1 ) { vips_error( "vips_mapfile", "%s", _( "unable to get file status" ) ); return( -1 ); } m = (mode_t) st.st_mode; if( !S_ISREG( m ) ) { vips_error( "vips_mapfile", "%s", _( "not a regular file" ) ); return( -1 ); } if( !(im->baseaddr = vips__mmap( im->fd, 0, im->file_length, 0 )) ) return( -1 ); im->length = im->file_length; return( 0 ); }
static Read * read_new( const char *filename, const void *data, size_t length, int shrink ) { Read *read; if( !(read = VIPS_NEW( NULL, Read )) ) return( NULL ); read->filename = g_strdup( filename ); read->data = data; read->length = length; read->shrink = shrink; read->fd = 0; read->idec = NULL; if( read->filename ) { /* libwebp makes streaming from a file source very hard. We * have to read to a full memory buffer, then copy to out. * * mmap the input file, it's slightly quicker. */ if( (read->fd = vips__open_image_read( read->filename )) < 0 || (read->length = vips_file_length( read->fd )) < 0 || !(read->data = vips__mmap( read->fd, FALSE, read->length, 0 )) ) { read_free( read ); return( NULL ); } } WebPInitDecoderConfig( &read->config ); if( WebPGetFeatures( read->data, MINIMAL_HEADER, &read->config.input ) != VP8_STATUS_OK ) { read_free( read ); return( NULL ); } if( read->config.input.has_alpha ) read->config.output.colorspace = MODE_RGBA; else read->config.output.colorspace = MODE_RGB; read->config.options.use_threads = 1; read->width = read->config.input.width / read->shrink; read->height = read->config.input.height / read->shrink; if( read->width == 0 || read->height == 0 ) { vips_error( "webp", "%s", _( "bad setting for shrink" ) ); return( NULL ); } if( read->shrink > 1 ) { read->config.options.use_scaling = 1; read->config.options.scaled_width = read->width; read->config.options.scaled_height = read->height; } return( read ); }