Merge pull request #451 from Sterblue/master
Add buffer write support for HDR Radiance
This commit is contained in:
commit
fa8a91ea72
@ -131,6 +131,7 @@ static VImage magickload_buffer( VipsBlob * buffer , VOption *options = 0 );
|
|||||||
static VImage fitsload( char * filename , VOption *options = 0 );
|
static VImage fitsload( char * filename , VOption *options = 0 );
|
||||||
static VImage openexrload( char * filename , VOption *options = 0 );
|
static VImage openexrload( char * filename , VOption *options = 0 );
|
||||||
void radsave( char * filename , VOption *options = 0 );
|
void radsave( char * filename , VOption *options = 0 );
|
||||||
|
VipsBlob * radsave_buffer( VOption *options = 0 );
|
||||||
void ppmsave( char * filename , VOption *options = 0 );
|
void ppmsave( char * filename , VOption *options = 0 );
|
||||||
void csvsave( char * filename , VOption *options = 0 );
|
void csvsave( char * filename , VOption *options = 0 );
|
||||||
void matrixsave( char * filename , VOption *options = 0 );
|
void matrixsave( char * filename , VOption *options = 0 );
|
||||||
|
@ -1656,6 +1656,18 @@ void VImage::radsave( char * filename , VOption *options )
|
|||||||
set( "filename", filename ) );
|
set( "filename", filename ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VipsBlob * VImage::radsave_buffer( VOption *options )
|
||||||
|
{
|
||||||
|
VipsBlob * buffer;
|
||||||
|
|
||||||
|
call( "radsave_buffer" ,
|
||||||
|
(options ? options : VImage::option()) ->
|
||||||
|
set( "in", *this ) ->
|
||||||
|
set( "buffer", &buffer ) );
|
||||||
|
|
||||||
|
return( buffer );
|
||||||
|
}
|
||||||
|
|
||||||
void VImage::ppmsave( char * filename , VOption *options )
|
void VImage::ppmsave( char * filename , VOption *options )
|
||||||
{
|
{
|
||||||
call( "ppmsave" ,
|
call( "ppmsave" ,
|
||||||
|
@ -1618,7 +1618,8 @@ void
|
|||||||
vips_foreign_operation_init( void )
|
vips_foreign_operation_init( void )
|
||||||
{
|
{
|
||||||
extern GType vips_foreign_load_rad_get_type( void );
|
extern GType vips_foreign_load_rad_get_type( void );
|
||||||
extern GType vips_foreign_save_rad_get_type( void );
|
extern GType vips_foreign_save_rad_file_get_type( void );
|
||||||
|
extern GType vips_foreign_save_rad_buffer_get_type( void );
|
||||||
extern GType vips_foreign_load_mat_get_type( void );
|
extern GType vips_foreign_load_mat_get_type( void );
|
||||||
extern GType vips_foreign_load_ppm_get_type( void );
|
extern GType vips_foreign_load_ppm_get_type( void );
|
||||||
extern GType vips_foreign_save_ppm_get_type( void );
|
extern GType vips_foreign_save_ppm_get_type( void );
|
||||||
@ -1688,7 +1689,8 @@ vips_foreign_operation_init( void )
|
|||||||
|
|
||||||
#ifdef HAVE_RADIANCE
|
#ifdef HAVE_RADIANCE
|
||||||
vips_foreign_load_rad_get_type();
|
vips_foreign_load_rad_get_type();
|
||||||
vips_foreign_save_rad_get_type();
|
vips_foreign_save_rad_file_get_type();
|
||||||
|
vips_foreign_save_rad_buffer_get_type();
|
||||||
#endif /*HAVE_RADIANCE*/
|
#endif /*HAVE_RADIANCE*/
|
||||||
|
|
||||||
#ifdef HAVE_POPPLER
|
#ifdef HAVE_POPPLER
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
* 23/1/14
|
* 23/1/14
|
||||||
* - put the reader globals into a struct so we can have many active
|
* - put the reader globals into a struct so we can have many active
|
||||||
* readers
|
* readers
|
||||||
|
* 23/5/16
|
||||||
|
* - Add buffer save functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -132,12 +134,14 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/internal.h>
|
#include <vips/internal.h>
|
||||||
|
#include <vips/debug.h>
|
||||||
|
|
||||||
#include "radiance.h"
|
#include "radiance.h"
|
||||||
|
|
||||||
@ -810,29 +814,16 @@ scanline_read( Buffer *buffer, COLR *scanline, int width )
|
|||||||
*/
|
*/
|
||||||
#define MAX_LINE (2 * MAXELEN * sizeof( COLR ))
|
#define MAX_LINE (2 * MAXELEN * sizeof( COLR ))
|
||||||
|
|
||||||
/* Write a single scanline.
|
/* write an RLE scanline. Write magic header.
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
scanline_write( COLR *scanline, int width, FILE *fp )
|
rle_scanline_write( COLR *scanline, int width, unsigned char *buffer, int *buffer_pos )
|
||||||
{
|
{
|
||||||
unsigned char buffer[MAX_LINE];
|
|
||||||
int buffer_pos = 0;
|
|
||||||
|
|
||||||
#define PUTC( CH ) { \
|
#define PUTC( CH ) { \
|
||||||
buffer[buffer_pos++] = (CH); \
|
buffer[(*buffer_pos)++] = (CH); \
|
||||||
g_assert( buffer_pos <= MAX_LINE ); \
|
g_assert( *buffer_pos <= MAX_LINE ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, j, beg, cnt;
|
int i, j, beg, cnt;
|
||||||
|
|
||||||
if( width < MINELEN ||
|
|
||||||
width > MAXELEN )
|
|
||||||
/* Write as a flat scanline.
|
|
||||||
*/
|
|
||||||
return( fwrite( scanline, sizeof( COLR ), width, fp ) - width );
|
|
||||||
|
|
||||||
/* An RLE scanline. Write magic header.
|
|
||||||
*/
|
|
||||||
PUTC( 2 );
|
PUTC( 2 );
|
||||||
PUTC( 2 );
|
PUTC( 2 );
|
||||||
PUTC( width >> 8 );
|
PUTC( width >> 8 );
|
||||||
@ -885,6 +876,25 @@ scanline_write( COLR *scanline, int width, FILE *fp )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a single scanline.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
scanline_write( COLR *scanline, int width, FILE *fp )
|
||||||
|
{
|
||||||
|
unsigned char buffer[MAX_LINE];
|
||||||
|
int buffer_pos = 0;
|
||||||
|
|
||||||
|
if( width < MINELEN ||
|
||||||
|
width > MAXELEN )
|
||||||
|
/* Write as a flat scanline.
|
||||||
|
*/
|
||||||
|
return( fwrite( scanline, sizeof( COLR ), width, fp ) - width );
|
||||||
|
|
||||||
|
/* An RLE scanline.
|
||||||
|
*/
|
||||||
|
rle_scanline_write( scanline, width, buffer, &buffer_pos );
|
||||||
|
|
||||||
return( fwrite( buffer, 1, buffer_pos, fp ) - buffer_pos );
|
return( fwrite( buffer, 1, buffer_pos, fp ) - buffer_pos );
|
||||||
}
|
}
|
||||||
@ -1151,7 +1161,7 @@ vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* What we track during a radiance file write.
|
/* What we track during a radiance write.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VipsImage *in;
|
VipsImage *in;
|
||||||
@ -1167,7 +1177,7 @@ typedef struct {
|
|||||||
} Write;
|
} Write;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_destroy( Write *write )
|
write_destroy_file( Write *write )
|
||||||
{
|
{
|
||||||
VIPS_FREE( write->filename );
|
VIPS_FREE( write->filename );
|
||||||
VIPS_FREEF( fclose, write->fout );
|
VIPS_FREEF( fclose, write->fout );
|
||||||
@ -1175,8 +1185,14 @@ write_destroy( Write *write )
|
|||||||
vips_free( write );
|
vips_free( write );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_destroy( Write *write )
|
||||||
|
{
|
||||||
|
vips_free( write );
|
||||||
|
}
|
||||||
|
|
||||||
static Write *
|
static Write *
|
||||||
write_new( VipsImage *in, const char *filename )
|
write_new( VipsImage *in)
|
||||||
{
|
{
|
||||||
Write *write;
|
Write *write;
|
||||||
int i;
|
int i;
|
||||||
@ -1185,8 +1201,6 @@ write_new( VipsImage *in, const char *filename )
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
|
|
||||||
write->in = in;
|
write->in = in;
|
||||||
write->filename = vips_strdup( NULL, filename );
|
|
||||||
write->fout = vips__file_open_write( filename, FALSE );
|
|
||||||
strcpy( write->format, COLRFMT );
|
strcpy( write->format, COLRFMT );
|
||||||
write->expos = 1.0;
|
write->expos = 1.0;
|
||||||
for( i = 0; i < 3; i++ )
|
for( i = 0; i < 3; i++ )
|
||||||
@ -1201,16 +1215,11 @@ write_new( VipsImage *in, const char *filename )
|
|||||||
write->prims[3][0] = CIE_x_w;
|
write->prims[3][0] = CIE_x_w;
|
||||||
write->prims[3][1] = CIE_y_w;
|
write->prims[3][1] = CIE_y_w;
|
||||||
|
|
||||||
if( !write->filename || !write->fout ) {
|
|
||||||
write_destroy( write );
|
|
||||||
return( NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( write );
|
return( write );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
vips2rad_put_header( Write *write )
|
vips2rad_make_header( Write *write )
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -1240,6 +1249,12 @@ vips2rad_put_header( Write *write )
|
|||||||
write->rs.rt = YDECR | YMAJOR;
|
write->rs.rt = YDECR | YMAJOR;
|
||||||
write->rs.xr = write->in->Xsize;
|
write->rs.xr = write->in->Xsize;
|
||||||
write->rs.yr = write->in->Ysize;
|
write->rs.yr = write->in->Ysize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips2rad_put_header( Write *write )
|
||||||
|
{
|
||||||
|
vips2rad_make_header(write);
|
||||||
|
|
||||||
fprintf( write->fout, "#?RADIANCE\n" );
|
fprintf( write->fout, "#?RADIANCE\n" );
|
||||||
|
|
||||||
@ -1292,15 +1307,224 @@ vips__rad_save( VipsImage *in, const char *filename )
|
|||||||
if( vips_image_pio_input( in ) ||
|
if( vips_image_pio_input( in ) ||
|
||||||
vips_check_coding_rad( "vips2rad", in ) )
|
vips_check_coding_rad( "vips2rad", in ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( !(write = write_new( in, filename )) )
|
if( !(write = write_new( in )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( vips2rad_put_header( write ) ||
|
|
||||||
|
write->filename = vips_strdup( NULL, filename );
|
||||||
|
write->fout = vips__file_open_write( filename, FALSE );
|
||||||
|
|
||||||
|
if( !write->filename || !write->fout ||
|
||||||
|
vips2rad_put_header( write ) ||
|
||||||
vips2rad_put_data( write ) ) {
|
vips2rad_put_data( write ) ) {
|
||||||
|
write_destroy_file( write );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
write_destroy_file( write );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _WriteBuf {
|
||||||
|
char *buf;
|
||||||
|
size_t len;
|
||||||
|
size_t alloc;
|
||||||
|
} WriteBuf;
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_buf_free( WriteBuf *wbuf )
|
||||||
|
{
|
||||||
|
VIPS_FREE( wbuf->buf );
|
||||||
|
VIPS_FREE( wbuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
static WriteBuf *
|
||||||
|
write_buf_new( void )
|
||||||
|
{
|
||||||
|
WriteBuf *wbuf;
|
||||||
|
|
||||||
|
if( !(wbuf = VIPS_NEW( NULL, WriteBuf )) )
|
||||||
|
return( NULL );
|
||||||
|
|
||||||
|
wbuf->buf = NULL;
|
||||||
|
wbuf->len = 0;
|
||||||
|
wbuf->alloc = 0;
|
||||||
|
|
||||||
|
return( wbuf );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_buf_grow( WriteBuf *wbuf, size_t grow_len )
|
||||||
|
{
|
||||||
|
size_t new_len = wbuf->len + grow_len;
|
||||||
|
|
||||||
|
if( new_len > wbuf->alloc ) {
|
||||||
|
size_t proposed_alloc = (16 + wbuf->alloc) * 3 / 2;
|
||||||
|
|
||||||
|
wbuf->alloc = VIPS_MAX( proposed_alloc, new_len );
|
||||||
|
|
||||||
|
/* There's no vips_realloc(), so we call g_realloc() directly.
|
||||||
|
* This is safe, since vips_malloc() / vips_free() are wrappers
|
||||||
|
* over g_malloc() / g_free().
|
||||||
|
*
|
||||||
|
* FIXME: add vips_realloc().
|
||||||
|
*/
|
||||||
|
wbuf->buf = g_realloc( wbuf->buf, wbuf->alloc );
|
||||||
|
|
||||||
|
VIPS_DEBUG_MSG( "write_buf_grow: grown to %zd bytes\n",
|
||||||
|
wbuf->alloc );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bprintf( WriteBuf *wbuf, const char *fmt, ... )
|
||||||
|
{
|
||||||
|
int length = 0;
|
||||||
|
char *write_start = NULL;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
/* Determine required size */
|
||||||
|
va_start(ap, fmt);
|
||||||
|
length = vsnprintf(write_start, length, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
write_buf_grow( wbuf, length + 1 );
|
||||||
|
|
||||||
|
write_start = wbuf->buf + wbuf->len;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
length = vsnprintf(write_start, length + 1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
wbuf->len += length;
|
||||||
|
|
||||||
|
g_assert( wbuf->len <= wbuf->alloc );
|
||||||
|
}
|
||||||
|
|
||||||
|
#define bputformat(s,wb) bprintf(wb, "%s%s\n", FMTSTR, s)
|
||||||
|
|
||||||
|
#define bputexpos(ex,wb) bprintf(wb,"%s%e\n",EXPOSSTR,ex)
|
||||||
|
|
||||||
|
#define bputcolcor(cc,wb) bprintf(wb,"%s %f %f %f\n",COLCORSTR, \
|
||||||
|
(cc)[RED],(cc)[GRN],(cc)[BLU])
|
||||||
|
|
||||||
|
#define bputaspect(pa,wb) bprintf(wb,"%s%f\n",ASPECTSTR,pa)
|
||||||
|
|
||||||
|
#define bputprims(p,wb) bprintf(wb, \
|
||||||
|
"%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",\
|
||||||
|
PRIMARYSTR, \
|
||||||
|
(p)[RED][CIEX],(p)[RED][CIEY], \
|
||||||
|
(p)[GRN][CIEX],(p)[GRN][CIEY], \
|
||||||
|
(p)[BLU][CIEX],(p)[BLU][CIEY], \
|
||||||
|
(p)[WHT][CIEX],(p)[WHT][CIEY])
|
||||||
|
|
||||||
|
#define bputsresolu(rs,wb) bprintf(wb,"%s",resolu2str(resolu_buf,rs))
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips2rad_put_header_buf( WriteBuf *wbuf, Write *write )
|
||||||
|
{
|
||||||
|
vips2rad_make_header(write);
|
||||||
|
|
||||||
|
bprintf( wbuf, "#?RADIANCE\n" );
|
||||||
|
|
||||||
|
bputformat( write->format, wbuf );
|
||||||
|
bputexpos( write->expos, wbuf );
|
||||||
|
bputcolcor( write->colcor, wbuf );
|
||||||
|
bprintf( wbuf, "SOFTWARE=vips %s\n", vips_version_string() );
|
||||||
|
bputaspect( write->aspect, wbuf );
|
||||||
|
bputprims( write->prims, wbuf );
|
||||||
|
bprintf( wbuf, "\n" );
|
||||||
|
bputsresolu( &write->rs, wbuf );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write a single scanline to buffer.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
scanline_write_buf( COLR *scanline, int width, WriteBuf *wbuf )
|
||||||
|
{
|
||||||
|
int buffer_pos = 0;
|
||||||
|
|
||||||
|
write_buf_grow( wbuf, MAX_LINE );
|
||||||
|
unsigned char *buffer = (unsigned char *) wbuf->buf + wbuf->len;
|
||||||
|
|
||||||
|
if( width < MINELEN ||
|
||||||
|
width > MAXELEN ) {
|
||||||
|
/* Write as a flat scanline.
|
||||||
|
*/
|
||||||
|
memcpy( buffer, scanline, sizeof( COLR ) * width );
|
||||||
|
wbuf->len += sizeof( COLR ) * width;
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An RLE scanline.
|
||||||
|
*/
|
||||||
|
rle_scanline_write( scanline, width, buffer, &buffer_pos );
|
||||||
|
|
||||||
|
wbuf->len += buffer_pos;
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips2rad_put_data_block_buf( VipsRegion *region, VipsRect *area, void *a )
|
||||||
|
{
|
||||||
|
WriteBuf *wbuf = (WriteBuf *) a;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < area->height; i++ ) {
|
||||||
|
VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i );
|
||||||
|
|
||||||
|
if( scanline_write_buf( (COLR *) p, area->width, wbuf ) )
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips2rad_put_data_buf( WriteBuf *wbuf, Write *write )
|
||||||
|
{
|
||||||
|
if( vips_sink_disc( write->in, vips2rad_put_data_block_buf, wbuf ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vips__rad_save_buf( VipsImage *in, void **obuf, size_t *olen )
|
||||||
|
{
|
||||||
|
Write *write;
|
||||||
|
WriteBuf *wbuf;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "vips2rad: writing to buffer\n" );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
if( vips_image_pio_input( in ) ||
|
||||||
|
vips_check_coding_rad( "vips2rad", in ) )
|
||||||
|
return( -1 );
|
||||||
|
if( !(wbuf = write_buf_new()) )
|
||||||
|
return( -1 );
|
||||||
|
if( !(write = write_new( in )) ) {
|
||||||
|
write_buf_free( wbuf );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vips2rad_put_header_buf( wbuf, write ) ||
|
||||||
|
vips2rad_put_data_buf( wbuf, write ) ) {
|
||||||
write_destroy( write );
|
write_destroy( write );
|
||||||
|
write_buf_free( wbuf );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
write_destroy( write );
|
write_destroy( write );
|
||||||
|
|
||||||
|
*obuf = wbuf->buf;
|
||||||
|
wbuf->buf = NULL;
|
||||||
|
if( olen )
|
||||||
|
*olen = wbuf->len;
|
||||||
|
|
||||||
|
write_buf_free( wbuf );
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ int vips__rad_header( const char *filename, VipsImage *out );
|
|||||||
int vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind );
|
int vips__rad_load( const char *filename, VipsImage *out, gboolean readbehind );
|
||||||
|
|
||||||
int vips__rad_save( VipsImage *in, const char *filename );
|
int vips__rad_save( VipsImage *in, const char *filename );
|
||||||
|
int vips__rad_save_buf( VipsImage *in, void **obuf, size_t *olen );
|
||||||
|
|
||||||
extern const char *vips__rad_suffs[];
|
extern const char *vips__rad_suffs[];
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
*
|
*
|
||||||
* 2/12/11
|
* 2/12/11
|
||||||
* - wrap a class around the rad writer
|
* - wrap a class around the rad writer
|
||||||
|
* 23/5/16
|
||||||
|
* - split into file and buffer save classes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,22 +64,6 @@ typedef VipsForeignSaveClass VipsForeignSaveRadClass;
|
|||||||
G_DEFINE_TYPE( VipsForeignSaveRad, vips_foreign_save_rad,
|
G_DEFINE_TYPE( VipsForeignSaveRad, vips_foreign_save_rad,
|
||||||
VIPS_TYPE_FOREIGN_SAVE );
|
VIPS_TYPE_FOREIGN_SAVE );
|
||||||
|
|
||||||
static int
|
|
||||||
vips_foreign_save_rad_build( VipsObject *object )
|
|
||||||
{
|
|
||||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
|
||||||
VipsForeignSaveRad *rad = (VipsForeignSaveRad *) object;
|
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_rad_parent_class )->
|
|
||||||
build( object ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( vips__rad_save( save->ready, rad->filename ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Save a bit of typing.
|
/* Save a bit of typing.
|
||||||
*/
|
*/
|
||||||
#define UC VIPS_FORMAT_UCHAR
|
#define UC VIPS_FORMAT_UCHAR
|
||||||
@ -107,9 +93,8 @@ vips_foreign_save_rad_class_init( VipsForeignSaveRadClass *class )
|
|||||||
gobject_class->set_property = vips_object_set_property;
|
gobject_class->set_property = vips_object_set_property;
|
||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
object_class->nickname = "radsave";
|
object_class->nickname = "radsave_base";
|
||||||
object_class->description = _( "save image to Radiance file" );
|
object_class->description = _( "save Radiance" );
|
||||||
object_class->build = vips_foreign_save_rad_build;
|
|
||||||
|
|
||||||
foreign_class->suffs = vips__rad_suffs;
|
foreign_class->suffs = vips__rad_suffs;
|
||||||
|
|
||||||
@ -118,12 +103,6 @@ vips_foreign_save_rad_class_init( VipsForeignSaveRadClass *class )
|
|||||||
save_class->coding[VIPS_CODING_NONE] = FALSE;
|
save_class->coding[VIPS_CODING_NONE] = FALSE;
|
||||||
save_class->coding[VIPS_CODING_RAD] = TRUE;
|
save_class->coding[VIPS_CODING_RAD] = TRUE;
|
||||||
|
|
||||||
VIPS_ARG_STRING( class, "filename", 1,
|
|
||||||
_( "Filename" ),
|
|
||||||
_( "Filename to save to" ),
|
|
||||||
VIPS_ARGUMENT_REQUIRED_INPUT,
|
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveRad, filename ),
|
|
||||||
NULL );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -131,6 +110,120 @@ vips_foreign_save_rad_init( VipsForeignSaveRad *rad )
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSaveRadFile {
|
||||||
|
VipsForeignSaveRad parent_object;
|
||||||
|
|
||||||
|
char *filename;
|
||||||
|
} VipsForeignSaveRadFile;
|
||||||
|
|
||||||
|
typedef VipsForeignSaveRadClass VipsForeignSaveRadFileClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSaveRadFile, vips_foreign_save_rad_file,
|
||||||
|
vips_foreign_save_rad_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_rad_file_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||||
|
VipsForeignSaveRadFile *rad_file = (VipsForeignSaveRadFile *) object;
|
||||||
|
|
||||||
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_rad_file_parent_class )->
|
||||||
|
build( object ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
if( vips__rad_save( save->ready, rad_file->filename ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_rad_file_class_init( VipsForeignSaveRadFileClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
|
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
object_class->nickname = "radsave";
|
||||||
|
object_class->description = _( "save image to Radiance file" );
|
||||||
|
object_class->build = vips_foreign_save_rad_file_build;
|
||||||
|
|
||||||
|
VIPS_ARG_STRING( class, "filename", 1,
|
||||||
|
_( "Filename" ),
|
||||||
|
_( "Filename to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveRadFile, filename ),
|
||||||
|
NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_rad_file_init( VipsForeignSaveRadFile *file )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _VipsForeignSaveRadBuffer {
|
||||||
|
VipsForeignSaveRad parent_object;
|
||||||
|
|
||||||
|
VipsArea *buf;
|
||||||
|
} VipsForeignSaveRadBuffer;
|
||||||
|
|
||||||
|
typedef VipsForeignSaveRadClass VipsForeignSaveRadBufferClass;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE( VipsForeignSaveRadBuffer, vips_foreign_save_rad_buffer,
|
||||||
|
vips_foreign_save_rad_get_type() );
|
||||||
|
|
||||||
|
static int
|
||||||
|
vips_foreign_save_rad_buffer_build( VipsObject *object )
|
||||||
|
{
|
||||||
|
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||||
|
|
||||||
|
void *obuf;
|
||||||
|
size_t olen;
|
||||||
|
VipsBlob *blob;
|
||||||
|
|
||||||
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_rad_buffer_parent_class )->
|
||||||
|
build( object ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
if( vips__rad_save_buf( save->ready, &obuf, &olen ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
blob = vips_blob_new( (VipsCallbackFn) vips_free, obuf, olen );
|
||||||
|
g_object_set( object, "buffer", blob, NULL );
|
||||||
|
vips_area_unref( VIPS_AREA( blob ) );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_rad_buffer_class_init( VipsForeignSaveRadBufferClass *class )
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
|
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
|
object_class->nickname = "radsave_buffer";
|
||||||
|
object_class->description = _( "save image to Radiance buffer" );
|
||||||
|
object_class->build = vips_foreign_save_rad_buffer_build;
|
||||||
|
|
||||||
|
VIPS_ARG_BOXED( class, "buffer", 1,
|
||||||
|
_( "Buffer" ),
|
||||||
|
_( "Buffer to save to" ),
|
||||||
|
VIPS_ARGUMENT_REQUIRED_OUTPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveRadBuffer, buf ),
|
||||||
|
VIPS_TYPE_BLOB );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_foreign_save_rad_buffer_init( VipsForeignSaveRadBuffer *buffer )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /*HAVE_RADIANCE*/
|
#endif /*HAVE_RADIANCE*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,3 +252,49 @@ vips_radsave( VipsImage *in, const char *filename, ... )
|
|||||||
|
|
||||||
return( result );
|
return( result );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vips_radsave_buffer:
|
||||||
|
* @in: image to save
|
||||||
|
* @buf: return output buffer here
|
||||||
|
* @len: return output length here
|
||||||
|
* @...: %NULL-terminated list of optional named arguments
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* As vips_radsave(), but save to a memory buffer.
|
||||||
|
*
|
||||||
|
* The address of the buffer is returned in @obuf, the length of the buffer in
|
||||||
|
* @olen. You are responsible for freeing the buffer with g_free() when you
|
||||||
|
* are done with it.
|
||||||
|
*
|
||||||
|
* See also: vips_radsave(), vips_image_write_to_file().
|
||||||
|
*
|
||||||
|
* Returns: 0 on success, -1 on error.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips_radsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
VipsArea *area;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
area = NULL;
|
||||||
|
|
||||||
|
va_start( ap, len );
|
||||||
|
result = vips_call_split( "radsave_buffer", ap, in, &area );
|
||||||
|
va_end( ap );
|
||||||
|
|
||||||
|
if( !result &&
|
||||||
|
area ) {
|
||||||
|
if( buf ) {
|
||||||
|
*buf = area->data;
|
||||||
|
area->free_fn = NULL;
|
||||||
|
}
|
||||||
|
if( len )
|
||||||
|
*len = area->length;
|
||||||
|
|
||||||
|
vips_area_unref( area );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( result );
|
||||||
|
}
|
@ -510,6 +510,8 @@ int vips_radload( const char *filename, VipsImage **out, ... )
|
|||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
int vips_radsave( VipsImage *in, const char *filename, ... )
|
int vips_radsave( VipsImage *in, const char *filename, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
int vips_radsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
|
||||||
|
__attribute__((sentinel));
|
||||||
|
|
||||||
int vips_pdfload( const char *filename, VipsImage **out, ... )
|
int vips_pdfload( const char *filename, VipsImage **out, ... )
|
||||||
__attribute__((sentinel));
|
__attribute__((sentinel));
|
||||||
|
Loading…
Reference in New Issue
Block a user