add radiance write, float2rad

This commit is contained in:
John Cupitt 2009-03-23 22:47:53 +00:00
parent c1cfe958e1
commit bafa70caec
16 changed files with 571 additions and 93 deletions

View File

@ -5,9 +5,11 @@
- reset dcm:display-range on magick read to help DICOM
- saner im_buildlut() behaviour
- added im_gauss_imask_sep()
- allow open of truncated images, but block pixel access
- allow open and view of truncated images (thanks Joe & Rachel)
- revising rounding on im_affine*() coordinate transforms to make them more
stable
- added Radiance write
- added im_float2rad()
3/3/09 started 7.17.2
- im_magick2vips.c: allow funky bit depths, like 14 (thanks Mikkel)

6
TODO
View File

@ -1,4 +1,8 @@
- radiance writer? the reader is OK, apparently
- rad2floatt/float2rad/radiance read/write all need docs
- same for matio?
- doc strings would be nice, read the SWIG notes on this

View File

@ -501,6 +501,7 @@ int im_Lab2LCh( IMAGE *, IMAGE * );
int im_LCh2Lab( IMAGE *, IMAGE * );
int im_LabQ2XYZ( IMAGE *, IMAGE * );
int im_rad2float( IMAGE *, IMAGE * );
int im_float2rad( IMAGE *, IMAGE * );
int im_LCh2UCS( IMAGE *, IMAGE * );
int im_Lab2LCh( IMAGE *, IMAGE * );
int im_Lab2LabQ( IMAGE *, IMAGE * );

View File

@ -345,6 +345,8 @@ int im_local_array( IMAGE *im, void **out, int n,
gint64 im_file_length( int fd );
int im__write( int fd, const void *buf, size_t count );
FILE *im__file_open_read( const char *filename );
FILE *im__file_open_write( const char *filename );
char *im__file_read( FILE *fp, const char *name, unsigned int *length_out );
char *im__file_read_name( const char *name, unsigned int *length_out );
int im__file_write( void *data, size_t size, size_t nmemb, FILE *stream );

View File

@ -20,6 +20,7 @@ libcolour_la_SOURCES = \
im_UCS2LCh.c \
im_XYZ2Lab.c \
im_XYZ2Yxy.c \
im_float2rad.c \
im_Yxy2XYZ.c \
im_XYZ2disp.c \
im_dE00_fromLab.c \

View File

@ -475,7 +475,7 @@ rad2float_vec( im_object *argv )
return( im_rad2float( argv[0], argv[1] ) );
}
/* Description of im_LabQ2Lab.
/* Description of im_rad2float.
*/
static im_function rad2float_desc = {
"im_rad2float", /* Name */
@ -486,6 +486,25 @@ static im_function rad2float_desc = {
one_in_one_out /* Arg list */
};
/* Call im_float2rad() via arg vector.
*/
static int
float2rad_vec( im_object *argv )
{
return( im_float2rad( argv[0], argv[1] ) );
}
/* Description of im_float2rad
*/
static im_function float2rad_desc = {
"im_float2rad", /* Name */
"convert float to Radiance packed", /* Description */
IM_FN_PIO, /* Flags */
float2rad_vec, /* Dispatch function */
IM_NUMBER( one_in_one_out ), /* Size of arg list */
one_in_one_out /* Arg list */
};
/* Call im_LabQ2LabS() via arg vector.
*/
static int
@ -1011,6 +1030,7 @@ static im_function *colour_list[] = {
&dE_fromdisp_desc,
&disp2Lab_desc,
&disp2XYZ_desc,
&float2rad_desc,
&icc_ac2rc_desc,
&icc_export_desc,
&icc_export_depth_desc,

View File

@ -0,0 +1,208 @@
/* Convert float to Radiance 32bit packed format
* 23/3/09
* - from im_rad2float and Radiance sources
*/
/*
This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
Sections of this file from Greg Ward and Radiance with kind
permission. The Radience copyright notice appears below.
*/
/* ====================================================================
* The Radiance Software License, Version 1.0
*
* Copyright (c) 1990 - 2009 The Regents of the University of California,
* through Lawrence Berkeley National Laboratory. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes Radiance software
* (http://radsite.lbl.gov/)
* developed by the Lawrence Berkeley National Laboratory
* (http://www.lbl.gov/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
* and "The Regents of the University of California" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact radiance@radsite.lbl.gov.
*
* 5. Products derived from this software may not be called "Radiance",
* nor may "Radiance" appear in their name, without prior written
* permission of Lawrence Berkeley National Laboratory.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of Lawrence Berkeley National Laboratory. For more
* information on Lawrence Berkeley National Laboratory, please see
* <http://www.lbl.gov/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <math.h>
#include <vips/vips.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
#endif /*WITH_DMALLOC*/
/* Begin copy-paste from Radiance sources.
*/
#define RED 0
#define GRN 1
#define BLU 2
#define CIEX 0 /* or, if input is XYZ... */
#define CIEY 1
#define CIEZ 2
#define EXP 3 /* exponent same for either format */
#define COLXS 128 /* excess used for exponent */
#define WHT 3 /* used for RGBPRIMS type */
#undef BYTE
#define BYTE unsigned char /* 8-bit unsigned integer */
typedef BYTE COLR[4]; /* red, green, blue (or X,Y,Z), exponent */
typedef float COLORV;
typedef COLORV COLOR[3]; /* red, green, blue (or X,Y,Z) */
#define copycolor(c1,c2) ((c1)[0]=(c2)[0],(c1)[1]=(c2)[1],(c1)[2]=(c2)[2])
static void
setcolr(clr, r, g, b) /* assign a short color value */
register COLR clr;
double r, g, b;
{
double d;
int e;
d = r > g ? r : g;
if (b > d) d = b;
if (d <= 1e-32) {
clr[RED] = clr[GRN] = clr[BLU] = 0;
clr[EXP] = 0;
return;
}
d = frexp(d, &e) * 255.9999 / d;
if (r > 0.0)
clr[RED] = r * d;
else
clr[RED] = 0;
if (g > 0.0)
clr[GRN] = g * d;
else
clr[GRN] = 0;
if (b > 0.0)
clr[BLU] = b * d;
else
clr[BLU] = 0;
clr[EXP] = e + COLXS;
}
/* End copy-paste from Radiance sources.
*/
static void
float2rad( COLOR *inp, COLR *outbuf, int n )
{
while (n-- > 0) {
setcolr( outbuf, inp[RED], inp[GRN], inp[BLU] );
inp++;
outbuf++;
}
}
int
im_float2rad( IMAGE *in, IMAGE *out )
{
/* Must be 3-band float.
*/
if( in->Bands != 3 || in->BandFmt != IM_BANDFMT_FLOAT ||
in->Coding != IM_CODING_NONE ) {
im_error( "im_float2rad", "%s",
_( "not a 3-band float uncoded image" ) );
return( -1 );
}
if( im_cp_desc( out, in ) )
return( -1 );
out->Bands = 4;
out->BandFmt = IM_BANDFMT_UCHAR;
out->Bbits = im_bits_of_fmt( out->BandFmt );
if( im_wrapone( in, out,
(im_wrapone_fn) float2rad, NULL, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -151,7 +151,7 @@ register COLR clr;
*/
void
static void
rad2float( COLR *inp, COLOR *outbuf, int n )
{
colr_color(outbuf[0], inp[0]);

View File

@ -652,17 +652,8 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
/* Make input.
*/
#ifdef BINARY_OPEN
if( !(fp = fopen( filename, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( filename, "r" )) ) {
#endif /*BINARY_OPEN*/
jpeg_destroy_decompress( &cinfo );
im_error( "im_jpeg2vips",
_( "unable to open \"%s\"" ), filename );
if( !(fp = im__file_open_read( filename )) )
return( -1 );
}
eman.fp = fp;
jpeg_stdio_src( &cinfo, fp );

View File

@ -135,13 +135,8 @@ read_new( const char *name, IMAGE *out )
read->row_pointer = NULL;
read->data = NULL;
#ifdef BINARY_OPEN
if( !(read->fp = fopen( name, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(read->fp = fopen( name, "r" )) ) {
#endif /*BINARY_OPEN*/
if( !(read->fp = im__file_open_read( name )) ) {
read_destroy( read );
im_error( "im_png2vips", _( "unable to open \"%s\"" ), name );
return( NULL );
}

View File

@ -395,16 +395,8 @@ ppm2vips_header( const char *filename, IMAGE *out )
int bits;
int ascii;
#ifdef BINARY_OPEN
if( !(fp = fopen( filename, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( filename, "r" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im_ppm2vips_header",
_( "unable to open \"%s\"" ), filename );
if( !(fp = im__file_open_read( filename )) )
return( -1 );
}
if( read_header( fp, out, &bits, &ascii ) ) {
fclose( fp );
return( -1 );
@ -425,15 +417,8 @@ isppmmmap( const char *filename )
int bits;
int ascii;
#ifdef BINARY_OPEN
if( !(fp = fopen( filename, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( filename, "r" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im_ppm2vips_header",
_( "unable to open \"%s\"" ), filename );
if( !(fp = im__file_open_read( filename )) )
return( -1 );
}
if( !(im = im_open( "temp", "p" )) ) {
fclose( fp );
@ -455,21 +440,12 @@ im_ppm2vips( const char *filename, IMAGE *out )
{
FILE *fp;
#ifdef BINARY_OPEN
if( !(fp = fopen( filename, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( filename, "r" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im_ppm2vips",
_( "unable to open \"%s\"" ), filename );
if( !(fp = im__file_open_read( filename )) )
return( -1 );
}
if( parse_ppm( fp, filename, out ) ) {
fclose( fp );
return( -1 );
}
fclose( fp );
return( 0 );

View File

@ -683,15 +683,8 @@ im_vips2jpeg( IMAGE *in, const char *filename )
/* Make output.
*/
#ifdef BINARY_OPEN
if( !(write->eman.fp = fopen( name, "wb" )) ) {
#else /*BINARY_OPEN*/
if( !(write->eman.fp = fopen( name, "w" )) ) {
#endif /*BINARY_OPEN*/
if( !(write->eman.fp = im__file_open_write( name )) ) {
write_destroy( write );
im_error( "im_vips2jpeg",
_( "unable to open \"%s\"" ), name );
return( -1 );
}
jpeg_stdio_dest( &write->cinfo, write->eman.fp );

View File

@ -293,14 +293,8 @@ im_vips2png( IMAGE *in, const char *filename )
/* Make output.
*/
#ifdef BINARY_OPEN
if( !(write->fp = fopen( name, "wb" )) ) {
#else /*BINARY_OPEN*/
if( !(write->fp = fopen( name, "w" )) ) {
#endif /*BINARY_OPEN*/
if( !(write->fp = im__file_open_write( name )) ) {
write_destroy( write );
im_error( "im_vips2png", _( "unable to open \"%s\"" ), name );
return( -1 );
}
png_init_io( write->pPng, write->fp );

View File

@ -83,15 +83,7 @@ write_new( IMAGE *in, const char *name )
write->in = in;
write->tg = im_threadgroup_create( write->in );
write->name = im_strdup( NULL, name );
#ifdef BINARY_OPEN
if( !(write->fp = fopen( name, "wb" )) ) {
#else /*BINARY_OPEN*/
if( !(write->fp = fopen( name, "w" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im_vips2ppm",
_( "unable to open \"%s\" for output" ), name );
}
write->fp = im__file_open_write( name );
if( !write->tg || !write->name || !write->fp ) {
write_destroy( write );

View File

@ -1,4 +1,7 @@
/* Read Radiance (.hdr) files
*
* 23/3/09
* - add radiance write
*/
/*
@ -31,12 +34,6 @@
Remaining issues:
+ the whole image is unpacked to a 3-band float and so will (potentially)
need a fair bit of memory
we could just read RGBE/XYZE and leave it at 4 bytes per pixel, then
unpack on the fly with an operator along the lines of LabQ2Lab
+ it ignores some header fields, like VIEW and DATE
+ it will not rotate/flip as the FORMAT string asks
@ -666,6 +663,103 @@ register FILE *fp;
return(0);
}
static void
fputformat( /* put out a format value */
char *s,
FILE *fp
)
{
fputs(FMTSTR, fp);
fputs(s, fp);
putc('\n', fp);
}
char *
resolu2str(buf, rp) /* convert resolution struct to line */
char *buf;
register RESOLU *rp;
{
if (rp->rt&YMAJOR)
sprintf(buf, "%cY %d %cX %d\n",
rp->rt&YDECR ? '-' : '+', rp->yr,
rp->rt&XDECR ? '-' : '+', rp->xr);
else
sprintf(buf, "%cX %d %cY %d\n",
rp->rt&XDECR ? '-' : '+', rp->xr,
rp->rt&YDECR ? '-' : '+', rp->yr);
return(buf);
}
static void
fputresolu(ord, sl, ns, fp) /* put out picture dimensions */
int ord; /* scanline ordering */
int sl, ns; /* scanline length and number */
FILE *fp;
{
RESOLU rs;
if ((rs.rt = ord) & YMAJOR) {
rs.xr = sl;
rs.yr = ns;
} else {
rs.xr = ns;
rs.yr = sl;
}
fputsresolu(&rs, fp);
}
static int
fwritecolrs(scanline, len, fp) /* write out a colr scanline */
register COLR *scanline;
int len;
register FILE *fp;
{
register int i, j, beg, cnt = 1;
int c2;
if ((len < MINELEN) | (len > MAXELEN)) /* OOBs, write out flat */
return(fwrite((char *)scanline,sizeof(COLR),len,fp) - len);
/* put magic header */
putc(2, fp);
putc(2, fp);
putc(len>>8, fp);
putc(len&255, fp);
/* put components seperately */
for (i = 0; i < 4; i++) {
for (j = 0; j < len; j += cnt) { /* find next run */
for (beg = j; beg < len; beg += cnt) {
for (cnt = 1; cnt < 127 && beg+cnt < len &&
scanline[beg+cnt][i] == scanline[beg][i]; cnt++)
;
if (cnt >= MINRUN)
break; /* long enough */
}
if (beg-j > 1 && beg-j < MINRUN) {
c2 = j+1;
while (scanline[c2++][i] == scanline[j][i])
if (c2 == beg) { /* short run */
putc(128+beg-j, fp);
putc(scanline[j][i], fp);
j = beg;
break;
}
}
while (j < beg) { /* write out non-run */
if ((c2 = beg-j) > 128) c2 = 128;
putc(c2, fp);
while (c2--)
putc(scanline[j++][i], fp);
}
if (cnt >= MINRUN) { /* write out run */
putc(128+cnt, fp);
putc(scanline[beg][i], fp);
} else
cnt = 0;
}
}
return(ferror(fp) ? -1 : 0);
}
@ -673,7 +767,7 @@ register FILE *fp;
/* End copy-paste from Radiance sources.
*/
/* What we track during an radiance-file read.
/* What we track during radiance file read.
*/
typedef struct {
char *filename;
@ -685,6 +779,7 @@ typedef struct {
COLOR colcor;
double aspect;
RGBPRIMS prims;
RESOLU rs;
COLR *buf;
} Read;
@ -700,7 +795,7 @@ israd( const char *filename )
printf( "israd: \"%s\"\n", filename );
#endif /*DEBUG*/
if( !(fin = fopen( filename, "r" )) )
if( !(fin = im__file_open_read( filename )) )
return( 0 );
strcpy( format, PICFMT );
result = checkheader( fin, format, NULL );
@ -746,7 +841,7 @@ read_new( const char *filename, IMAGE *out )
read->prims[3][1] = CIE_y_w;
read->buf = NULL;
if( !(read->fin = fopen( filename, "r" )) ) {
if( !(read->fin = im__file_open_read( filename )) ) {
read_destroy( read );
return( NULL );
}
@ -798,17 +893,16 @@ static const char *colcor_name[3] = {
static int
rad2vips_get_header( Read *read, FILE *fin, IMAGE *out )
{
RESOLU rs;
int i, j;
if( getheader( fin, (gethfunc *) rad2vips_process_line, read ) ||
!fgetsresolu( &rs, fin ) ) {
!fgetsresolu( &read->rs, fin ) ) {
im_error( "rad2vips",
"%s", _( "error reading radiance header" ) );
return( -1 );
}
out->Xsize = scanlen( &rs );
out->Ysize = numscans( &rs );
out->Xsize = scanlen( &read->rs );
out->Ysize = numscans( &read->rs );
out->Bands = 4;
out->BandFmt = IM_BANDFMT_UCHAR;
@ -917,6 +1011,180 @@ rad2vips( const char *filename, IMAGE *out )
return( 0 );
}
/* What we track during an radiance-file write.
*/
typedef struct {
IMAGE *in;
char *filename;
im_threadgroup_t *tg;
FILE *fout;
char format[256];
double expos;
COLOR colcor;
double aspect;
RGBPRIMS prims;
RESOLU rs;
} Write;
static void
write_destroy( Write *write )
{
IM_FREEF( im_threadgroup_free, write->tg );
IM_FREE( write->filename );
IM_FREEF( fclose, write->fout );
im_free( write );
}
static Write *
write_new( IMAGE *in, const char *filename )
{
Write *write;
int i;
if( !(write = IM_NEW( NULL, Write )) )
return( NULL );
write->in = in;
write->filename = im_strdup( NULL, filename );
write->tg = im_threadgroup_create( write->in );
write->fout = im__file_open_write( filename );
strcpy( write->format, COLRFMT );
write->expos = 1.0;
for( i = 0; i < 3; i++ )
write->colcor[i] = 1.0;
write->aspect = 1.0;
write->prims[0][0] = CIE_x_r;
write->prims[0][1] = CIE_y_r;
write->prims[1][0] = CIE_x_g;
write->prims[1][1] = CIE_y_g;
write->prims[2][0] = CIE_x_b;
write->prims[2][1] = CIE_y_b;
write->prims[3][0] = CIE_x_w;
write->prims[3][1] = CIE_y_w;
if( !write->filename || !write->tg || !write->fout ) {
write_destroy( write );
return( NULL );
}
return( write );
}
static int
vips2rad_put_header( Write *write )
{
char *str;
int i, j;
double d;
(void) im_meta_get_double( write->in, "rad-expos", &write->expos );
(void) im_meta_get_double( write->in, "rad-aspect", &write->aspect );
if( im_meta_get_string( write->in, "rad-format", &str ) )
im_strncpy( write->format, str, 256 );
if( write->in->Type == IM_TYPE_RGB )
strcpy( write->format, COLRFMT );
if( write->in->Type == IM_TYPE_XYZ )
strcpy( write->format, CIEFMT );
for( i = 0; i < 3; i++ )
if( im_meta_get_double( write->in, colcor_name[i], &d ) )
write->colcor[i] = d;
for( i = 0; i < 4; i++ )
for( j = 0; j < 2; j++ )
if( im_meta_get_double( write->in,
prims_name[i][j], &d ) )
write->prims[i][j] = d;
/* Make y decreasing for consistency with vips.
*/
write->rs.rt = YDECR | YMAJOR;
write->rs.xr = write->in->Xsize;
write->rs.yr = write->in->Ysize;
fprintf( write->fout, "#?RADIANCE\n" );
fprintf( write->fout, "#generated by libvips\n" );
fputformat( write->format, write->fout );
fputexpos( write->expos, write->fout );
fputcolcor( write->colcor, write->fout );
fputaspect( write->aspect, write->fout );
fputprims( write->prims, write->fout );
fputresolu( &write->rs, write->fout );
return( 0 );
}
static int
vips2rad_put_data_block( REGION *region, Rect *area, void *a, void *b )
{
Write *write = (Write *) a;
int i;
for( i = 0; i < area->height; i++ ) {
PEL *p = (PEL *) IM_REGION_ADDR( region, 0, area->top + i );
if( fwritecolrs( p, area->width, write->fout ) )
return( -1 );
}
return( 0 );
}
static int
vips2rad_put_data( Write *write )
{
if( im_wbuffer( write->tg, vips2rad_put_data_block, write, NULL ) )
return( -1 );
return( 0 );
}
static int
vips2rad( IMAGE *in, const char *filename )
{
Write *write;
#ifdef DEBUG
printf( "vips2rad: writing \"%s\"\n", filename );
#endif /*DEBUG*/
if( im_pincheck( in ) )
return( -1 );
if( in->Coding != IM_CODING_NONE ) {
im_error( "vip2rad", "%s", _( "uncoded only" ) );
return( -1 );
}
if( in->BandFmt == IM_BANDFMT_FLOAT &&
in->Bands == 3 ) {
IMAGE *t;
if( !(t = im_open_local( in, "vips2rad", "p" )) ||
im_float2rad( in, t ) ||
vips2rad( t, filename ) )
return( -1 );
return( 0 );
}
if( in->BandFmt != IM_BANDFMT_UCHAR ||
in->Bands == 4 ) {
im_error( "vip2rad", "%s", _( "4 band uchar only" ) );
return( -1 );
}
if( !(write = write_new( in, filename )) )
return( -1 );
if( vips2rad_put_header( write ) ||
vips2rad_put_data( write ) ) {
write_destroy( write );
return( -1 );
}
write_destroy( write );
return( 0 );
}
static const char *rad_suffs[] = { ".hdr", NULL };
/* rad format adds no new members.
@ -936,7 +1204,7 @@ vips_format_rad_class_init( VipsFormatRadClass *class )
format_class->is_a = israd;
format_class->header = rad2vips_header;
format_class->load = rad2vips;
format_class->save = NULL;
format_class->save = vips2rad;
format_class->suffs = rad_suffs;
}

View File

@ -885,6 +885,44 @@ im__file_read( FILE *fp, const char *name, unsigned int *length_out )
return( str );
}
FILE *
im__file_open_read( const char *filename )
{
FILE *fp;
#ifdef BINARY_OPEN
if( !(fp = fopen( filename, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( filename, "r" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im__file_open_read",
_( "unable to open file \"%s\" for reading" ),
filename );
return( NULL );
}
return( fp );
}
FILE *
im__file_open_write( const char *filename )
{
FILE *fp;
#ifdef BINARY_OPEN
if( !(fp = fopen( filename, "wb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( filename, "w" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im__file_open_write",
_( "unable to open file \"%s\" for writing" ),
filename );
return( NULL );
}
return( fp );
}
/* Load from a filename as a string.
*/
char *
@ -893,15 +931,8 @@ im__file_read_name( const char *name, unsigned int *length_out )
FILE *fp;
char *buffer;
#ifdef BINARY_OPEN
if( !(fp = fopen( name, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( name, "r" )) ) {
#endif /*BINARY_OPEN*/
im_error( "im__file_read_name",
_( "unable to open file \"%s\"" ), name );
if( !(fp = im__file_open_read( name )) )
return( NULL );
}
if( !(buffer = im__file_read( fp, name, length_out )) ) {
fclose( fp );
return( NULL );