add radiance write, float2rad
This commit is contained in:
parent
c1cfe958e1
commit
bafa70caec
|
@ -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
6
TODO
|
@ -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
|
||||
|
||||
|
|
|
@ -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 * );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
}
|
|
@ -151,7 +151,7 @@ register COLR clr;
|
|||
*/
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
rad2float( COLR *inp, COLOR *outbuf, int n )
|
||||
{
|
||||
colr_color(outbuf[0], inp[0]);
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue