diff --git a/ChangeLog b/ChangeLog index 9291d06f..f30b5d75 100644 --- a/ChangeLog +++ b/ChangeLog @@ -40,6 +40,7 @@ - removed yafrnohalo.c - added matio as a dependency - added Matlab save file read +- added Radiance file read 11/9/08 started 7.16.3 - oop typo in manpage for im_project() diff --git a/TODO b/TODO index 6d278e3b..ec2c1f81 100644 --- a/TODO +++ b/TODO @@ -28,14 +28,6 @@ stupid error message (does not say "file not found") -- add HDR support? - - http://www.radiance-online.org/ - - not clear what the file format is? - - there's a mail from Greg Ward with details - diff --git a/libsrc/format/Makefile.am b/libsrc/format/Makefile.am index 82261236..91b25126 100644 --- a/libsrc/format/Makefile.am +++ b/libsrc/format/Makefile.am @@ -1,17 +1,22 @@ noinst_LTLIBRARIES = libformat.la libformat_la_SOURCES = \ + color.h \ + color.c \ + copyright.h \ dbh.h \ format.c \ format_dispatch.c \ + header.c \ im_analyze2vips.c \ im_csv2vips.c \ im_exr2vips.c \ im_jpeg2vips.c \ - im_mat2vips.c \ im_magick2vips.c \ + im_mat2vips.c \ im_png2vips.c \ im_ppm2vips.c \ + im_rad2vips.c \ im_raw2vips.c \ im_tiff2vips.c \ im_tile_cache.c \ @@ -20,6 +25,9 @@ libformat_la_SOURCES = \ im_vips2png.c \ im_vips2ppm.c \ im_vips2tiff.c \ - im_vips2raw.c + im_vips2raw.c \ + resolu.c \ + resolu.h \ + rtio.h INCLUDES = -I${top_srcdir}/include @VIPS_CFLAGS@ @VIPS_INCLUDES@ diff --git a/libsrc/format/color.c b/libsrc/format/color.c new file mode 100644 index 00000000..c459addf --- /dev/null +++ b/libsrc/format/color.c @@ -0,0 +1,315 @@ +#ifndef lint +static const char RCSid[] = "$Id: color.c,v 2.16 2005/02/09 00:00:17 greg Exp $"; +#endif +/* + * color.c - routines for color calculations. + * + * Externals declared in color.h + */ + +#include "copyright.h" + +#include + +#include + +#include + +#include "color.h" + +#ifdef getc_unlocked /* avoid horrendous overhead of flockfile */ +#undef getc +#undef putc +#define getc getc_unlocked +#define putc putc_unlocked +#endif + +#define MINELEN 8 /* minimum scanline length for encoding */ +#define MAXELEN 0x7fff /* maximum scanline length for encoding */ +#define MINRUN 4 /* minimum run length */ + + +char * +tempbuffer(len) /* get a temporary buffer */ +unsigned int len; +{ + static char *tempbuf = NULL; + static unsigned tempbuflen = 0; + + if (len > tempbuflen) { + if (tempbuflen > 0) + tempbuf = (char *)realloc((void *)tempbuf, len); + else + tempbuf = (char *)malloc(len); + tempbuflen = tempbuf==NULL ? 0 : len; + } + return(tempbuf); +} + + +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); +} + + +static int +oldreadcolrs(scanline, len, fp) /* read in an old colr scanline */ +register COLR *scanline; +int len; +register FILE *fp; +{ + int rshift; + register int i; + + rshift = 0; + + while (len > 0) { + scanline[0][RED] = getc(fp); + scanline[0][GRN] = getc(fp); + scanline[0][BLU] = getc(fp); + scanline[0][EXP] = getc(fp); + if (feof(fp) || ferror(fp)) + return(-1); + if (scanline[0][RED] == 1 && + scanline[0][GRN] == 1 && + scanline[0][BLU] == 1) { + for (i = scanline[0][EXP] << rshift; i > 0; i--) { + copycolr(scanline[0], scanline[-1]); + scanline++; + len--; + } + rshift += 8; + } else { + scanline++; + len--; + rshift = 0; + } + } + return(0); +} + + +int +freadcolrs(scanline, len, fp) /* read in an encoded colr scanline */ +register COLR *scanline; +int len; +register FILE *fp; +{ + register int i, j; + int code, val; + /* determine scanline type */ + if ((len < MINELEN) | (len > MAXELEN)) + return(oldreadcolrs(scanline, len, fp)); + if ((i = getc(fp)) == EOF) + return(-1); + if (i != 2) { + ungetc(i, fp); + return(oldreadcolrs(scanline, len, fp)); + } + scanline[0][GRN] = getc(fp); + scanline[0][BLU] = getc(fp); + if ((i = getc(fp)) == EOF) + return(-1); + if (scanline[0][GRN] != 2 || scanline[0][BLU] & 128) { + scanline[0][RED] = 2; + scanline[0][EXP] = i; + return(oldreadcolrs(scanline+1, len-1, fp)); + } + if ((scanline[0][BLU]<<8 | i) != len) + return(-1); /* length mismatch! */ + /* read each component */ + for (i = 0; i < 4; i++) + for (j = 0; j < len; ) { + if ((code = getc(fp)) == EOF) + return(-1); + if (code > 128) { /* run */ + code &= 127; + if ((val = getc(fp)) == EOF) + return -1; + if (j + code > len) + return -1; /* overrun */ + while (code--) + scanline[j++][i] = val; + } else { /* non-run */ + if (j + code > len) + return -1; /* overrun */ + while (code--) { + if ((val = getc(fp)) == EOF) + return -1; + scanline[j++][i] = val; + } + } + } + return(0); +} + + +int +fwritescan(scanline, len, fp) /* write out a scanline */ +register COLOR *scanline; +int len; +FILE *fp; +{ + COLR *clrscan; + int n; + register COLR *sp; + /* get scanline buffer */ + if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL) + return(-1); + clrscan = sp; + /* convert scanline */ + n = len; + while (n-- > 0) { + setcolr(sp[0], scanline[0][RED], + scanline[0][GRN], + scanline[0][BLU]); + scanline++; + sp++; + } + return(fwritecolrs(clrscan, len, fp)); +} + + +int +freadscan(scanline, len, fp) /* read in a scanline */ +register COLOR *scanline; +int len; +FILE *fp; +{ + register COLR *clrscan; + + if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL) + return(-1); + if (freadcolrs(clrscan, len, fp) < 0) + return(-1); + /* convert scanline */ + colr_color(scanline[0], clrscan[0]); + while (--len > 0) { + scanline++; clrscan++; + if (clrscan[0][RED] == clrscan[-1][RED] && + clrscan[0][GRN] == clrscan[-1][GRN] && + clrscan[0][BLU] == clrscan[-1][BLU] && + clrscan[0][EXP] == clrscan[-1][EXP]) + copycolor(scanline[0], scanline[-1]); + else + colr_color(scanline[0], clrscan[0]); + } + return(0); +} + + +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; +} + + +void +colr_color(col, clr) /* convert short to float color */ +register COLOR col; +register COLR clr; +{ + double f; + + if (clr[EXP] == 0) + col[RED] = col[GRN] = col[BLU] = 0.0; + else { + f = ldexp(1.0, (int)clr[EXP]-(COLXS+8)); + col[RED] = (clr[RED] + 0.5)*f; + col[GRN] = (clr[GRN] + 0.5)*f; + col[BLU] = (clr[BLU] + 0.5)*f; + } +} + + +int +bigdiff(c1, c2, md) /* c1 delta c2 > md? */ +register COLOR c1, c2; +double md; +{ + register int i; + + for (i = 0; i < 3; i++) + if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) || + colval(c2,i)-colval(c1,i) > md*colval(c1,i)) + return(1); + return(0); +} diff --git a/libsrc/format/color.h b/libsrc/format/color.h new file mode 100644 index 00000000..1137f426 --- /dev/null +++ b/libsrc/format/color.h @@ -0,0 +1,244 @@ +/* RCSid $Id: color.h,v 2.29 2006/09/05 21:54:32 greg Exp $ */ +/* + * color.h - header for routines using pixel color values. + * + * Must be included after X11 headers, since they declare a BYTE type. + * + * Two color representations are used, one for calculation and + * another for storage. Calculation is done with three floats + * for speed. Stored color values use 4 bytes which contain + * three single byte mantissas and a common exponent. + */ +#ifndef _RAD_COLOR_H_ +#define _RAD_COLOR_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#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) */ + +typedef float RGBPRIMS[4][2]; /* (x,y) chromaticities for RGBW */ +typedef float (*RGBPRIMP)[2]; /* pointer to RGBPRIMS array */ + +typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ + +#define copycolr(c1,c2) (c1[0]=c2[0],c1[1]=c2[1], \ + c1[2]=c2[2],c1[3]=c2[3]) + +#define colval(col,pri) ((col)[pri]) + +#define setcolor(col,r,g,b) ((col)[RED]=(r),(col)[GRN]=(g),(col)[BLU]=(b)) + +#define copycolor(c1,c2) ((c1)[0]=(c2)[0],(c1)[1]=(c2)[1],(c1)[2]=(c2)[2]) + +#define scalecolor(col,sf) ((col)[0]*=(sf),(col)[1]*=(sf),(col)[2]*=(sf)) + +#define addcolor(c1,c2) ((c1)[0]+=(c2)[0],(c1)[1]+=(c2)[1],(c1)[2]+=(c2)[2]) + +#define multcolor(c1,c2) ((c1)[0]*=(c2)[0],(c1)[1]*=(c2)[1],(c1)[2]*=(c2)[2]) + +#ifdef NTSC +#define CIE_x_r 0.670 /* standard NTSC primaries */ +#define CIE_y_r 0.330 +#define CIE_x_g 0.210 +#define CIE_y_g 0.710 +#define CIE_x_b 0.140 +#define CIE_y_b 0.080 +#define CIE_x_w 0.3333 /* use true white */ +#define CIE_y_w 0.3333 +#else +#define CIE_x_r 0.640 /* nominal CRT primaries */ +#define CIE_y_r 0.330 +#define CIE_x_g 0.290 +#define CIE_y_g 0.600 +#define CIE_x_b 0.150 +#define CIE_y_b 0.060 +#define CIE_x_w 0.3333 /* use true white */ +#define CIE_y_w 0.3333 +#endif + +#define STDPRIMS {{CIE_x_r,CIE_y_r},{CIE_x_g,CIE_y_g}, \ + {CIE_x_b,CIE_y_b},{CIE_x_w,CIE_y_w}} + +#define CIE_D ( CIE_x_r*(CIE_y_g - CIE_y_b) + \ + CIE_x_g*(CIE_y_b - CIE_y_r) + \ + CIE_x_b*(CIE_y_r - CIE_y_g) ) +#define CIE_C_rD ( (1./CIE_y_w) * \ + ( CIE_x_w*(CIE_y_g - CIE_y_b) - \ + CIE_y_w*(CIE_x_g - CIE_x_b) + \ + CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g ) ) +#define CIE_C_gD ( (1./CIE_y_w) * \ + ( CIE_x_w*(CIE_y_b - CIE_y_r) - \ + CIE_y_w*(CIE_x_b - CIE_x_r) - \ + CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r ) ) +#define CIE_C_bD ( (1./CIE_y_w) * \ + ( CIE_x_w*(CIE_y_r - CIE_y_g) - \ + CIE_y_w*(CIE_x_r - CIE_x_g) + \ + CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r ) ) + +#define CIE_rf (CIE_y_r*CIE_C_rD/CIE_D) +#define CIE_gf (CIE_y_g*CIE_C_gD/CIE_D) +#define CIE_bf (CIE_y_b*CIE_C_bD/CIE_D) + +/* As of 9-94, CIE_rf=.265074126, CIE_gf=.670114631 and CIE_bf=.064811243 */ + +/***** The following definitions are valid for RGB colors only... *****/ + +#define bright(col) (CIE_rf*(col)[RED]+CIE_gf*(col)[GRN]+CIE_bf*(col)[BLU]) +#define normbright(c) ( ( (long)(CIE_rf*256.+.5)*(c)[RED] + \ + (long)(CIE_gf*256.+.5)*(c)[GRN] + \ + (long)(CIE_bf*256.+.5)*(c)[BLU] ) >> 8 ) + + /* luminous efficacies over visible spectrum */ +#define MAXEFFICACY 683. /* defined maximum at 550 nm */ +#define WHTEFFICACY 179. /* uniform white light */ +#define D65EFFICACY 203. /* standard illuminant D65 */ +#define INCEFFICACY 160. /* illuminant A (incand.) */ +#define SUNEFFICACY 208. /* illuminant B (solar dir.) */ +#define SKYEFFICACY D65EFFICACY /* skylight (should be 110) */ +#define DAYEFFICACY D65EFFICACY /* combined sky and solar */ + +#define luminance(col) (WHTEFFICACY * bright(col)) + +/***** ...end of stuff specific to RGB colors *****/ + +#define intens(col) ( (col)[0] > (col)[1] \ + ? (col)[0] > (col)[2] ? (col)[0] : (col)[2] \ + : (col)[1] > (col)[2] ? (col)[1] : (col)[2] ) + +#define colrval(c,p) ( (c)[EXP] ? \ + ldexp((c)[p]+.5,(int)(c)[EXP]-(COLXS+8)) : \ + 0. ) + +#define WHTCOLOR {1.0,1.0,1.0} +#define BLKCOLOR {0.0,0.0,0.0} +#define WHTCOLR {128,128,128,COLXS+1} +#define BLKCOLR {0,0,0,0} + + /* picture format identifier */ +#define COLRFMT "32-bit_rle_rgbe" +#define CIEFMT "32-bit_rle_xyze" +#define PICFMT "32-bit_rle_???e" /* matches either */ +#define LPICFMT 15 /* max format id len */ + + /* macros for exposures */ +#define EXPOSSTR "EXPOSURE=" +#define LEXPOSSTR 9 +#define isexpos(hl) (!strncmp(hl,EXPOSSTR,LEXPOSSTR)) +#define exposval(hl) atof((hl)+LEXPOSSTR) +#define fputexpos(ex,fp) fprintf(fp,"%s%e\n",EXPOSSTR,ex) + + /* macros for pixel aspect ratios */ +#define ASPECTSTR "PIXASPECT=" +#define LASPECTSTR 10 +#define isaspect(hl) (!strncmp(hl,ASPECTSTR,LASPECTSTR)) +#define aspectval(hl) atof((hl)+LASPECTSTR) +#define fputaspect(pa,fp) fprintf(fp,"%s%f\n",ASPECTSTR,pa) + + /* macros for primary specifications */ +#define PRIMARYSTR "PRIMARIES=" +#define LPRIMARYSTR 10 +#define isprims(hl) (!strncmp(hl,PRIMARYSTR,LPRIMARYSTR)) +#define primsval(p,hl) sscanf(hl+LPRIMARYSTR, \ + "%f %f %f %f %f %f %f %f", \ + &(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 fputprims(p,fp) fprintf(fp, \ + "%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]) + + /* macros for color correction */ +#define COLCORSTR "COLORCORR=" +#define LCOLCORSTR 10 +#define iscolcor(hl) (!strncmp(hl,COLCORSTR,LCOLCORSTR)) +#define colcorval(cc,hl) sscanf(hl+LCOLCORSTR,"%f %f %f", \ + &(cc)[RED],&(cc)[GRN],&(cc)[BLU]) +#define fputcolcor(cc,fp) fprintf(fp,"%s %f %f %f\n",COLCORSTR, \ + (cc)[RED],(cc)[GRN],(cc)[BLU]) + +/* + * Conversions to and from XYZ space generally don't apply WHTEFFICACY. + * If you need Y to be luminance (cd/m^2), this must be applied when + * converting from radiance (watts/sr/m^2). + */ + +extern RGBPRIMS stdprims; /* standard primary chromaticities */ +extern COLORMAT rgb2xyzmat; /* RGB to XYZ conversion matrix */ +extern COLORMAT xyz2rgbmat; /* XYZ to RGB conversion matrix */ +extern COLOR cblack, cwhite; /* black (0,0,0) and white (1,1,1) */ + +#define CGAMUT_LOWER 01 +#define CGAMUT_UPPER 02 +#define CGAMUT (CGAMUT_LOWER|CGAMUT_UPPER) + +#define rgb_cie(xyz,rgb) colortrans(xyz,rgb2xyzmat,rgb) + +#define cpcolormat(md,ms) memcpy((void *)md,(void *)ms,sizeof(COLORMAT)) + + /* defined in color.c */ +extern char *tempbuffer(unsigned int len); +extern int fwritecolrs(COLR *scanline, int len, FILE *fp); +extern int freadcolrs(COLR *scanline, int len, FILE *fp); +extern int fwritescan(COLOR *scanline, int len, FILE *fp); +extern int freadscan(COLOR *scanline, int len, FILE *fp); +extern void setcolr(COLR clr, double r, double g, double b); +extern void colr_color(COLOR col, COLR clr); +extern int bigdiff(COLOR c1, COLOR c2, double md); + /* defined in spec_rgb.c */ +extern void spec_rgb(COLOR col, int s, int e); +extern void spec_cie(COLOR col, int s, int e); +extern void cie_rgb(COLOR rgb, COLOR xyz); +extern int clipgamut(COLOR col, double brt, int gamut, + COLOR lower, COLOR upper); +extern void colortrans(COLOR c2, COLORMAT mat, COLOR c1); +extern void multcolormat(COLORMAT m3, COLORMAT m2, + COLORMAT m1); +extern int colorprimsOK(RGBPRIMS pr); +extern int compxyz2rgbmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2xyzmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2rgbmat(COLORMAT mat, RGBPRIMS pr1, RGBPRIMS pr2); +extern int compxyzWBmat(COLORMAT mat, float wht1[2], + float wht2[2]); +extern int compxyz2rgbWBmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2xyzWBmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2rgbWBmat(COLORMAT mat, RGBPRIMS pr1, RGBPRIMS pr2); + /* defined in colrops.c */ +extern int setcolrcor(double (*f)(double, double), double a2); +extern int setcolrinv(double (*f)(double, double), double a2); +extern int setcolrgam(double g); +extern int colrs_gambs(COLR *scan, int len); +extern int gambs_colrs(COLR *scan, int len); +extern void shiftcolrs(COLR *scan, int len, int adjust); +extern void normcolrs(COLR *scan, int len, int adjust); + + +#ifdef __cplusplus +} +#endif +#endif /* _RAD_COLOR_H_ */ + diff --git a/libsrc/format/colrops.c b/libsrc/format/colrops.c new file mode 100644 index 00000000..e241e34a --- /dev/null +++ b/libsrc/format/colrops.c @@ -0,0 +1,231 @@ +#ifndef lint +static const char RCSid[] = "$Id: colrops.c,v 2.11 2003/07/30 10:11:06 schorsch Exp $"; +#endif +/* + * Integer operations on COLR scanlines + */ + +#include "copyright.h" + +#include +#include + +#include "rtmisc.h" +#include "color.h" + + +#define MAXGSHIFT 31 /* maximum shift for gamma table */ + +static BYTE *g_mant = NULL, *g_nexp = NULL; + +static BYTE (*g_bval)[256] = NULL; + + +int +setcolrcor(f, a2) /* set brightness correction */ +double (*f)(double,double); +double a2; +{ + double mult; + register int i, j; + /* allocate tables */ + if (g_bval == NULL && (g_bval = + (BYTE (*)[256])bmalloc((MAXGSHIFT+1)*256)) == NULL) + return(-1); + /* compute colr -> gamb mapping */ + mult = 1.0/256.0; + for (i = 0; i <= MAXGSHIFT; i++) { + for (j = 0; j < 256; j++) + g_bval[i][j] = 256.0 * (*f)((j+.5)*mult, a2); + mult *= 0.5; + } + return(0); +} + + +int +setcolrinv(f, a2) /* set inverse brightness correction */ +double (*f)(double,double); +double a2; +{ + double mult; + register int i, j; + /* allocate tables */ + if (g_mant == NULL && (g_mant = (BYTE *)bmalloc(256)) == NULL) + return(-1); + if (g_nexp == NULL && (g_nexp = (BYTE *)bmalloc(256)) == NULL) + return(-1); + /* compute gamb -> colr mapping */ + i = 0; + mult = 256.0; + for (j = 256; j--; ) { + while ((g_mant[j] = mult * (*f)((j+.5)/256.0, a2)) < 128) { + i++; + mult *= 2.0; + } + g_nexp[j] = i; + } + return(0); +} + + +int +setcolrgam(g) /* set gamma conversion */ +double g; +{ + if (setcolrcor(pow, 1.0/g) < 0) + return(-1); + return(setcolrinv(pow, g)); +} + + +int +colrs_gambs(scan, len) /* convert scanline of colrs to gamma bytes */ +register COLR *scan; +int len; +{ + register int i, expo; + + if (g_bval == NULL) + return(-1); + while (len-- > 0) { + expo = scan[0][EXP] - COLXS; + if (expo < -MAXGSHIFT) { + if (expo < -MAXGSHIFT-8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 0; + } else { + i = (-MAXGSHIFT-1) - expo; + scan[0][RED] = + g_bval[MAXGSHIFT][((scan[0][RED]>>i)+1)>>1]; + scan[0][GRN] = + g_bval[MAXGSHIFT][((scan[0][GRN]>>i)+1)>>1]; + scan[0][BLU] = + g_bval[MAXGSHIFT][((scan[0][BLU]>>i)+1)>>1]; + } + } else if (expo > 0) { + if (expo > 8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 255; + } else { + i = (scan[0][RED]<<1 | 1) << (expo-1); + scan[0][RED] = i > 255 ? 255 : g_bval[0][i]; + i = (scan[0][GRN]<<1 | 1) << (expo-1); + scan[0][GRN] = i > 255 ? 255 : g_bval[0][i]; + i = (scan[0][BLU]<<1 | 1) << (expo-1); + scan[0][BLU] = i > 255 ? 255 : g_bval[0][i]; + } + } else { + scan[0][RED] = g_bval[-expo][scan[0][RED]]; + scan[0][GRN] = g_bval[-expo][scan[0][GRN]]; + scan[0][BLU] = g_bval[-expo][scan[0][BLU]]; + } + scan[0][EXP] = COLXS; + scan++; + } + return(0); +} + + +int +gambs_colrs(scan, len) /* convert gamma bytes to colr scanline */ +register COLR *scan; +int len; +{ + register int nexpo; + + if ((g_mant == NULL) | (g_nexp == NULL)) + return(-1); + while (len-- > 0) { + nexpo = g_nexp[scan[0][RED]]; + if (g_nexp[scan[0][GRN]] < nexpo) + nexpo = g_nexp[scan[0][GRN]]; + if (g_nexp[scan[0][BLU]] < nexpo) + nexpo = g_nexp[scan[0][BLU]]; + if (nexpo < g_nexp[scan[0][RED]]) + scan[0][RED] = g_mant[scan[0][RED]] + >> (g_nexp[scan[0][RED]]-nexpo); + else + scan[0][RED] = g_mant[scan[0][RED]]; + if (nexpo < g_nexp[scan[0][GRN]]) + scan[0][GRN] = g_mant[scan[0][GRN]] + >> (g_nexp[scan[0][GRN]]-nexpo); + else + scan[0][GRN] = g_mant[scan[0][GRN]]; + if (nexpo < g_nexp[scan[0][BLU]]) + scan[0][BLU] = g_mant[scan[0][BLU]] + >> (g_nexp[scan[0][BLU]]-nexpo); + else + scan[0][BLU] = g_mant[scan[0][BLU]]; + scan[0][EXP] = COLXS - nexpo; + scan++; + } + return(0); +} + + +void +shiftcolrs(scan, len, adjust) /* shift a scanline of colors by 2^adjust */ +register COLR *scan; +register int len; +register int adjust; +{ + int minexp; + + if (adjust == 0) + return; + minexp = adjust < 0 ? -adjust : 0; + while (len-- > 0) { + if (scan[0][EXP] <= minexp) + scan[0][RED] = scan[0][GRN] = scan[0][BLU] = + scan[0][EXP] = 0; + else + scan[0][EXP] += adjust; + scan++; + } +} + + +void +normcolrs(scan, len, adjust) /* normalize a scanline of colrs */ +register COLR *scan; +int len; +int adjust; +{ + register int c; + register int shift; + + while (len-- > 0) { + shift = scan[0][EXP] + adjust - COLXS; + if (shift > 0) { + if (shift > 8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 255; + } else { + shift--; + c = (scan[0][RED]<<1 | 1) << shift; + scan[0][RED] = c > 255 ? 255 : c; + c = (scan[0][GRN]<<1 | 1) << shift; + scan[0][GRN] = c > 255 ? 255 : c; + c = (scan[0][BLU]<<1 | 1) << shift; + scan[0][BLU] = c > 255 ? 255 : c; + } + } else if (shift < 0) { + if (shift < -8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 0; + } else { + shift = -1-shift; + scan[0][RED] = ((scan[0][RED]>>shift)+1)>>1; + scan[0][GRN] = ((scan[0][GRN]>>shift)+1)>>1; + scan[0][BLU] = ((scan[0][BLU]>>shift)+1)>>1; + } + } + scan[0][EXP] = COLXS - adjust; + scan++; + } +} diff --git a/libsrc/format/copyright.h b/libsrc/format/copyright.h new file mode 100644 index 00000000..a59f1365 --- /dev/null +++ b/libsrc/format/copyright.h @@ -0,0 +1,58 @@ +/* RCSid: $Id: copyright.h,v 3.2 2008/12/06 01:08:53 greg Exp $ */ +/* ==================================================================== + * 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 + * . + */ + diff --git a/libsrc/format/format.c b/libsrc/format/format.c index e6ee41cb..3737c0ae 100644 --- a/libsrc/format/format.c +++ b/libsrc/format/format.c @@ -203,6 +203,7 @@ im__format_init( void ) extern GType vips_format_csv_get_type(); extern GType vips_format_ppm_get_type(); extern GType vips_format_analyze_get_type(); + extern GType vips_format_rad_get_type(); vips_format_vips_get_type(); #ifdef HAVE_JPEG @@ -213,10 +214,6 @@ im__format_init( void ) extern GType vips_format_png_get_type(); vips_format_png_get_type(); #endif /*HAVE_PNG*/ -#ifdef HAVE_MATIO - extern GType vips_format_mat_get_type(); - vips_format_mat_get_type(); -#endif /*HAVE_MATIO*/ vips_format_csv_get_type(); vips_format_ppm_get_type(); vips_format_analyze_get_type(); @@ -224,6 +221,11 @@ im__format_init( void ) extern GType vips_format_exr_get_type(); vips_format_exr_get_type(); #endif /*HAVE_OPENEXR*/ +#ifdef HAVE_MATIO + extern GType vips_format_mat_get_type(); + vips_format_mat_get_type(); +#endif /*HAVE_MATIO*/ + vips_format_rad_get_type(); #ifdef HAVE_MAGICK extern GType vips_format_magick_get_type(); vips_format_magick_get_type(); diff --git a/libsrc/format/header.c b/libsrc/format/header.c new file mode 100644 index 00000000..08b5528d --- /dev/null +++ b/libsrc/format/header.c @@ -0,0 +1,340 @@ +#ifndef lint +static const char RCSid[] = "$Id: header.c,v 2.23 2005/02/01 01:28:16 greg Exp $"; +#endif +/* + * header.c - routines for reading and writing information headers. + * + * Externals declared in resolu.h + * + * newheader(t,fp) start new information header identified by string t + * isheadid(s) returns true if s is a header id line + * headidval(r,s) copy header identifier value in s to r + * dateval(t,s) get capture date value + * isdate(s) returns true if s is a date line + * fputdate(t,fp) put out the given capture date and time + * fputnow(fp) put out the current date and time + * printargs(ac,av,fp) print an argument list to fp, followed by '\n' + * isformat(s) returns true if s is of the form "FORMAT=*" + * formatval(r,s) copy the format value in s to r + * fputformat(s,fp) write "FORMAT=%s" to fp + * getheader(fp,f,p) read header from fp, calling f(s,p) on each line + * globmatch(pat, str) check for glob match of str against pat + * checkheader(i,p,o) check header format from i against p and copy to o + * + * To copy header from input to output, use getheader(fin, fputs, fout) + */ + +#include "copyright.h" + +#include + +#include "rtio.h" +#include "resolu.h" + +#define MAXLINE 512 + +char HDRSTR[] = "#?"; /* information header magic number */ + +char FMTSTR[] = "FORMAT="; /* format identifier */ + +char TMSTR[] = "CAPDATE="; /* capture date identifier */ + +static gethfunc mycheck; + + +extern void +newheader( /* identifying line of information header */ + char *s, + register FILE *fp +) +{ + fputs(HDRSTR, fp); + fputs(s, fp); + putc('\n', fp); +} + + +extern int +headidval( /* get header id (return true if is id) */ + register char *r, + register char *s +) +{ + register char *cp = HDRSTR; + + while (*cp) if (*cp++ != *s++) return(0); + if (r == NULL) return(1); + while (*s && !isspace(*s)) *r++ = *s++; + *r = '\0'; + return(1); +} + + +extern int +isheadid( /* check to see if line is header id */ + char *s +) +{ + return(headidval(NULL, s)); +} + + +extern int +dateval( /* get capture date value */ + time_t *tloc, + char *s +) +{ + struct tm tms; + register char *cp = TMSTR; + + while (*cp) if (*cp++ != *s++) return(0); + while (isspace(*s)) s++; + if (!*s) return(0); + if (sscanf(s, "%d:%d:%d %d:%d:%d", + &tms.tm_year, &tms.tm_mon, &tms.tm_mday, + &tms.tm_hour, &tms.tm_min, &tms.tm_sec) != 6) + return(0); + if (tloc == NULL) + return(1); + tms.tm_mon--; + tms.tm_year -= 1900; + tms.tm_isdst = -1; /* ask mktime() to figure out DST */ + *tloc = mktime(&tms); + return(1); +} + + +extern int +isdate( /* is the given line a capture date? */ + char *s +) +{ + return(dateval(NULL, s)); +} + + +extern void +fputdate( /* write out the given time value */ + time_t tv, + FILE *fp +) +{ + struct tm *tm = localtime(&tv); + if (tm == NULL) + return; + fprintf(fp, "%s %04d:%02d:%02d %02d:%02d:%02d\n", TMSTR, + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + + +extern void +fputnow( /* write out the current time */ + FILE *fp +) +{ + time_t tv; + time(&tv); + fputdate(tv, fp); +} + + +extern void +printargs( /* print arguments to a file */ + int ac, + char **av, + FILE *fp +) +{ + while (ac-- > 0) { + fputword(*av++, fp); + fputc(ac ? ' ' : '\n', fp); + } +} + + +extern int +formatval( /* get format value (return true if format) */ + register char *r, + register char *s +) +{ + register char *cp = FMTSTR; + + while (*cp) if (*cp++ != *s++) return(0); + while (isspace(*s)) s++; + if (!*s) return(0); + if (r == NULL) return(1); + do + *r++ = *s++; + while(*s && !isspace(*s)); + *r = '\0'; + return(1); +} + + +extern int +isformat( /* is line a format line? */ + char *s +) +{ + return(formatval(NULL, s)); +} + + +extern void +fputformat( /* put out a format value */ + char *s, + FILE *fp +) +{ + fputs(FMTSTR, fp); + fputs(s, fp); + putc('\n', fp); +} + + +extern int +getheader( /* get header from file */ + FILE *fp, + gethfunc *f, + void *p +) +{ + char buf[MAXLINE]; + + for ( ; ; ) { + buf[MAXLINE-2] = '\n'; + if (fgets(buf, MAXLINE, fp) == NULL) + return(-1); + if (buf[0] == '\n') + return(0); +#ifdef MSDOS + if (buf[0] == '\r' && buf[1] == '\n') + return(0); +#endif + if (buf[MAXLINE-2] != '\n') { + ungetc(buf[MAXLINE-2], fp); /* prevent false end */ + buf[MAXLINE-2] = '\0'; + } + if (f != NULL && (*f)(buf, p) < 0) + return(-1); + } +} + + +struct check { + FILE *fp; + char fs[64]; +}; + + +static int +mycheck( /* check a header line for format info. */ + char *s, + void *cp +) +{ + if (!formatval(((struct check*)cp)->fs, s) + && ((struct check*)cp)->fp != NULL) { + fputs(s, ((struct check*)cp)->fp); + } + return(0); +} + + +extern int +globmatch( /* check for match of s against pattern p */ + register char *p, + register char *s +) +{ + int setmatch; + + do { + switch (*p) { + case '?': /* match any character */ + if (!*s++) + return(0); + break; + case '*': /* match any string */ + while (p[1] == '*') p++; + do + if ( (p[1]=='?' || p[1]==*s) && + globmatch(p+1,s) ) + return(1); + while (*s++); + return(0); + case '[': /* character set */ + setmatch = *s == *++p; + if (!*p) + return(0); + while (*++p != ']') { + if (!*p) + return(0); + if (*p == '-') { + setmatch += p[-1] <= *s && *s <= p[1]; + if (!*++p) + break; + } else + setmatch += *p == *s; + } + if (!setmatch) + return(0); + s++; + break; + case '\\': /* literal next */ + p++; + /* fall through */ + default: /* normal character */ + if (*p != *s) + return(0); + s++; + break; + } + } while (*p++); + return(1); +} + + +/* + * Checkheader(fin,fmt,fout) returns a value of 1 if the input format + * matches the specification in fmt, 0 if no input format was found, + * and -1 if the input format does not match or there is an + * error reading the header. If fmt is empty, then -1 is returned + * if any input format is found (or there is an error), and 0 otherwise. + * If fmt contains any '*' or '?' characters, then checkheader + * does wildcard expansion and copies a matching result into fmt. + * Be sure that fmt is big enough to hold the match in such cases, + * and that it is not a static, read-only string! + * The input header (minus any format lines) is copied to fout + * if fout is not NULL. + */ + +extern int +checkheader( + FILE *fin, + char *fmt, + FILE *fout +) +{ + struct check cdat; + register char *cp; + + cdat.fp = fout; + cdat.fs[0] = '\0'; + if (getheader(fin, mycheck, &cdat) < 0) + return(-1); + if (!cdat.fs[0]) + return(0); + for (cp = fmt; *cp; cp++) /* check for globbing */ + if ((*cp == '?') | (*cp == '*')) { + if (globmatch(fmt, cdat.fs)) { + strcpy(fmt, cdat.fs); + return(1); + } else + return(-1); + } + return(strcmp(fmt, cdat.fs) ? -1 : 1); /* literal match */ +} diff --git a/libsrc/format/im_analyze2vips.c b/libsrc/format/im_analyze2vips.c index 79eeace2..fa79fb56 100644 --- a/libsrc/format/im_analyze2vips.c +++ b/libsrc/format/im_analyze2vips.c @@ -33,8 +33,8 @@ */ /* -#define DEBUG */ +#define DEBUG #ifdef HAVE_CONFIG_H #include @@ -306,8 +306,6 @@ read_header( const char *header ) if( !(d = (struct dsr *) im__file_read_name( header, &len )) ) return( NULL ); if( len != sizeof( struct dsr ) ) { - im_error( "im_analyze2vips", - "%s", _( "header file size incorrect" ) ); im_free( d ); return( NULL ); } @@ -351,8 +349,6 @@ read_header( const char *header ) } if( len != d->hk.sizeof_hdr ) { - im_error( "im_analyze2vips", - "%s", _( "header file size incorrect" ) ); im_free( d ); return( NULL ); } @@ -522,8 +518,11 @@ analyze2vips_header( const char *filename, IMAGE *out ) int fmt; generate_filenames( filename, header, image ); - if( !(d = read_header( header )) ) + if( !(d = read_header( header )) ) { + im_error( "im_analyze2vips", + "%s", _( "header file size incorrect" ) ); return( -1 ); + } #ifdef DEBUG print_dsr( d ); @@ -559,8 +558,11 @@ im_analyze2vips( const char *filename, IMAGE *out ) IM_ARCH_NATIVE : IM_ARCH_BYTE_SWAPPED; generate_filenames( filename, header, image ); - if( !(d = read_header( header )) ) + if( !(d = read_header( header )) ) { + im_error( "im_analyze2vips", + "%s", _( "header file size incorrect" ) ); return( -1 ); + } #ifdef DEBUG print_dsr( d ); diff --git a/libsrc/format/im_mat2vips.c b/libsrc/format/im_mat2vips.c index ca4dccf3..c07b4318 100644 --- a/libsrc/format/im_mat2vips.c +++ b/libsrc/format/im_mat2vips.c @@ -31,12 +31,21 @@ Remaining issues: -* it transposes images, I think, since Matlab seems to use column-major order -* will colour images work? no idea, needs testing -* it will not do complex images -* it will not handle sparse matricies -* it loads the first variable in the file with between 1 and 3 dimensions, is this sensible behaviour? -* load only, no save ++ it transposes images, I think, since Matlab seems to use column-major order + ++ will colour images work? no idea, needs testing + ++ it will not do complex images + ++ it will not handle sparse matricies + ++ it loads the first variable in the file with between 1 and 3 dimensions, + is this sensible behaviour? + ++ load only, no save + ++ could use much less memory --- we use Mat_VarReadDataAll() to read the + whole variable into mem, then copy to a vips buffer, yuk */ diff --git a/libsrc/format/im_png2vips.c b/libsrc/format/im_png2vips.c index 1d2328d1..7660f4ed 100644 --- a/libsrc/format/im_png2vips.c +++ b/libsrc/format/im_png2vips.c @@ -12,6 +12,8 @@ * - from vips_png.c * 8/5/06 * - set RGB16/GREY16 if appropriate + * 28/2/09 + * - small cleanups */ /* diff --git a/libsrc/format/im_rad2vips.c b/libsrc/format/im_rad2vips.c new file mode 100644 index 00000000..b80425d3 --- /dev/null +++ b/libsrc/format/im_rad2vips.c @@ -0,0 +1,335 @@ +/* Read Radiance (.hdr) files + */ + +/* + + 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 reader come from Greg Ward and Radiance with kind + permission. The Radience copyright notice appears in "copyright.h". + + */ + +/* + */ +#define DEBUG + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include + +#include +#include + +#include "rtio.h" +#include "resolu.h" +#include "color.h" + +#ifdef WITH_DMALLOC +#include +#endif /*WITH_DMALLOC*/ + +/* What we track during an radiance-file read. + */ +typedef struct { + char *filename; + IMAGE *out; + + FILE *fin; + char format[256]; + double expos; + COLOR colcor; + double aspect; + RGBPRIMS prims; + + COLOR *buf; +} Read; + +static int +israd( const char *filename ) +{ + FILE *fin; + char format[256]; + int result; + +#ifdef DEBUG + printf( "israd: \"%s\"\n", filename ); +#endif /*DEBUG*/ + + if( !(fin = fopen( filename, "r" )) ) + return( 0 ); + strcpy( format, "*" ); + result = checkheader( fin, format, NULL ); + fclose( fin ); + + return( result ); +} + +static void +read_destroy( Read *read ) +{ + IM_FREE( read->filename ); + IM_FREEF( fclose, read->fin ); + IM_FREE( read->buf ); + + im_free( read ); +} + +static Read * +read_new( const char *filename, IMAGE *out ) +{ + Read *read; + int i; + + if( !(read = IM_NEW( NULL, Read )) ) + return( NULL ); + + read->filename = im_strdup( NULL, filename ); + read->out = out; + read->fin = NULL; + strcpy( read->format, COLRFMT ); + read->expos = 1.0; + for( i = 0; i < 3; i++ ) + read->colcor[i] = 1.0; + read->aspect = 1.0; + read->prims[0][0] = CIE_x_r; + read->prims[0][1] = CIE_y_r; + read->prims[1][0] = CIE_x_g; + read->prims[1][1] = CIE_y_g; + read->prims[2][0] = CIE_x_b; + read->prims[2][1] = CIE_y_b; + read->prims[3][0] = CIE_x_w; + read->prims[3][1] = CIE_y_w; + read->buf = NULL; + + if( !(read->fin = fopen( filename, "r" )) ) { + read_destroy( read ); + return( NULL ); + } + + return( read ); +} + +static int +rad2vips_process_line( char *line, Read *read ) +{ + if( isformat( line ) ) { + if( formatval( line, read->format ) ) + return( -1 ); + } + else if( isexpos( line ) ) { + read->expos *= exposval( line ); + } + else if( iscolcor( line ) ) { + COLOR cc; + int i; + + colcorval( cc, line ); + for( i = 0; i < 3; i++ ) + read->colcor[i] *= cc[i]; + } + else if( isaspect( line ) ) { + read->aspect *= aspectval( line ); + } + else if( isprims( line ) ) { + primsval( read->prims, line ); + } + + return( 0 ); +} + +static const char *prims_name[4][2] = { + { "rad-prims-rx", "rad-prims-ry" }, + { "rad-prims-gx", "rad-prims-gy" }, + { "rad-prims-bx", "rad-prims-by" }, + { "rad-prims-wx", "rad-prims-wy" } +}; + +static const char *colcor_name[3] = { + "rad-colcor-r", + "rad-colcor-g", + "rad-colcor-b" +}; + +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 ) ) { + im_error( "rad2vips", + "%s", _( "error reading radiance header" ) ); + return( -1 ); + } + out->Xsize = scanlen( &rs ); + out->Ysize = numscans( &rs ); + + out->Bands = 3; + out->BandFmt = IM_BANDFMT_FLOAT; + out->Bbits = im_bits_of_fmt( out->BandFmt ); + + out->Coding = IM_CODING_NONE; + out->Xres = 1.0; + out->Yres = read->aspect; + out->Xoffset = 0.0; + out->Yoffset = 0.0; + + if( im_meta_set_string( out, "rad-format", read->format ) ) + return( -1 ); + + if( strcmp( read->format, COLRFMT ) == 0 ) + out->Type = IM_TYPE_RGB; + else if( strcmp( read->format, CIEFMT ) == 0 ) + out->Type = IM_TYPE_XYZ; + else + out->Type = IM_TYPE_MULTIBAND; + + if( im_meta_set_double( out, "rad-expos", read->expos ) ) + return( -1 ); + + for( i = 0; i < 3; i++ ) + if( im_meta_set_double( out, colcor_name[i], read->colcor[i] ) ) + return( -1 ); + + if( im_meta_set_double( out, "rad-aspect", read->aspect ) ) + return( -1 ); + + for( i = 0; i < 4; i++ ) + for( j = 0; j < 2; j++ ) + if( im_meta_set_double( out, + prims_name[i][j], read->prims[i][j] ) ) + return( -1 ); + + return( 0 ); +} + +static int +rad2vips_header( const char *filename, IMAGE *out ) +{ + Read *read; + +#ifdef DEBUG + printf( "rad2vips_header: reading \"%s\"\n", filename ); +#endif /*DEBUG*/ + + if( !(read = read_new( filename, out )) ) + return( -1 ); + if( rad2vips_get_header( read, read->fin, read->out ) ) { + read_destroy( read ); + return( -1 ); + } + read_destroy( read ); + + return( 0 ); +} + +static int +rad2vips_get_data( Read *read, FILE *fin, IMAGE *im ) +{ + int y; + +#ifdef DEBUG + printf( "rad2vips_get_data\n" ); +#endif /*DEBUG*/ + + if( im_outcheck( im ) || + im_setupout( im ) ) + return( -1 ); + if( !(read->buf = IM_ARRAY( NULL, im->Xsize, COLOR )) ) + return( -1 ); + + for( y = 0; y < im->Ysize; y++ ) { + if( freadscan( read->buf, im->Xsize, fin ) ) { + im_error( "rad2vips", "%s", + _( "read error" ) ); + return( -1 ); + } + if( im_writeline( y, im, (void *) read->buf ) ) + return( -1 ); + } + + return( 0 ); +} + +static int +rad2vips( const char *filename, IMAGE *out ) +{ + Read *read; + +#ifdef DEBUG + printf( "rad2vips: reading \"%s\"\n", filename ); +#endif /*DEBUG*/ + + if( !(read = read_new( filename, out )) ) + return( -1 ); + if( rad2vips_get_header( read, read->fin, read->out ) || + rad2vips_get_data( read, read->fin, read->out ) ) { + read_destroy( read ); + return( -1 ); + } + read_destroy( read ); + + return( 0 ); +} + +static const char *rad_suffs[] = { ".hdr", NULL }; + +/* rad format adds no new members. + */ +typedef VipsFormat VipsFormatRad; +typedef VipsFormatClass VipsFormatRadClass; + +static void +vips_format_rad_class_init( VipsFormatRadClass *class ) +{ + VipsObjectClass *object_class = (VipsObjectClass *) class; + VipsFormatClass *format_class = (VipsFormatClass *) class; + + object_class->nickname = "rad"; + object_class->description = _( "Radiance" ); + + format_class->is_a = israd; + format_class->header = rad2vips_header; + format_class->load = rad2vips; + format_class->save = NULL; + format_class->suffs = rad_suffs; +} + +static void +vips_format_rad_init( VipsFormatRad *object ) +{ +} + +G_DEFINE_TYPE( VipsFormatRad, vips_format_rad, VIPS_TYPE_FORMAT ); + diff --git a/libsrc/format/radiance/PictureFormat.pdf b/libsrc/format/radiance/PictureFormat.pdf new file mode 100644 index 00000000..5ffe336e Binary files /dev/null and b/libsrc/format/radiance/PictureFormat.pdf differ diff --git a/libsrc/format/radiance/RadianceRGBE.zip b/libsrc/format/radiance/RadianceRGBE.zip new file mode 100644 index 00000000..60fc2f24 Binary files /dev/null and b/libsrc/format/radiance/RadianceRGBE.zip differ diff --git a/libsrc/format/radiance/color.c b/libsrc/format/radiance/color.c new file mode 100644 index 00000000..c459addf --- /dev/null +++ b/libsrc/format/radiance/color.c @@ -0,0 +1,315 @@ +#ifndef lint +static const char RCSid[] = "$Id: color.c,v 2.16 2005/02/09 00:00:17 greg Exp $"; +#endif +/* + * color.c - routines for color calculations. + * + * Externals declared in color.h + */ + +#include "copyright.h" + +#include + +#include + +#include + +#include "color.h" + +#ifdef getc_unlocked /* avoid horrendous overhead of flockfile */ +#undef getc +#undef putc +#define getc getc_unlocked +#define putc putc_unlocked +#endif + +#define MINELEN 8 /* minimum scanline length for encoding */ +#define MAXELEN 0x7fff /* maximum scanline length for encoding */ +#define MINRUN 4 /* minimum run length */ + + +char * +tempbuffer(len) /* get a temporary buffer */ +unsigned int len; +{ + static char *tempbuf = NULL; + static unsigned tempbuflen = 0; + + if (len > tempbuflen) { + if (tempbuflen > 0) + tempbuf = (char *)realloc((void *)tempbuf, len); + else + tempbuf = (char *)malloc(len); + tempbuflen = tempbuf==NULL ? 0 : len; + } + return(tempbuf); +} + + +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); +} + + +static int +oldreadcolrs(scanline, len, fp) /* read in an old colr scanline */ +register COLR *scanline; +int len; +register FILE *fp; +{ + int rshift; + register int i; + + rshift = 0; + + while (len > 0) { + scanline[0][RED] = getc(fp); + scanline[0][GRN] = getc(fp); + scanline[0][BLU] = getc(fp); + scanline[0][EXP] = getc(fp); + if (feof(fp) || ferror(fp)) + return(-1); + if (scanline[0][RED] == 1 && + scanline[0][GRN] == 1 && + scanline[0][BLU] == 1) { + for (i = scanline[0][EXP] << rshift; i > 0; i--) { + copycolr(scanline[0], scanline[-1]); + scanline++; + len--; + } + rshift += 8; + } else { + scanline++; + len--; + rshift = 0; + } + } + return(0); +} + + +int +freadcolrs(scanline, len, fp) /* read in an encoded colr scanline */ +register COLR *scanline; +int len; +register FILE *fp; +{ + register int i, j; + int code, val; + /* determine scanline type */ + if ((len < MINELEN) | (len > MAXELEN)) + return(oldreadcolrs(scanline, len, fp)); + if ((i = getc(fp)) == EOF) + return(-1); + if (i != 2) { + ungetc(i, fp); + return(oldreadcolrs(scanline, len, fp)); + } + scanline[0][GRN] = getc(fp); + scanline[0][BLU] = getc(fp); + if ((i = getc(fp)) == EOF) + return(-1); + if (scanline[0][GRN] != 2 || scanline[0][BLU] & 128) { + scanline[0][RED] = 2; + scanline[0][EXP] = i; + return(oldreadcolrs(scanline+1, len-1, fp)); + } + if ((scanline[0][BLU]<<8 | i) != len) + return(-1); /* length mismatch! */ + /* read each component */ + for (i = 0; i < 4; i++) + for (j = 0; j < len; ) { + if ((code = getc(fp)) == EOF) + return(-1); + if (code > 128) { /* run */ + code &= 127; + if ((val = getc(fp)) == EOF) + return -1; + if (j + code > len) + return -1; /* overrun */ + while (code--) + scanline[j++][i] = val; + } else { /* non-run */ + if (j + code > len) + return -1; /* overrun */ + while (code--) { + if ((val = getc(fp)) == EOF) + return -1; + scanline[j++][i] = val; + } + } + } + return(0); +} + + +int +fwritescan(scanline, len, fp) /* write out a scanline */ +register COLOR *scanline; +int len; +FILE *fp; +{ + COLR *clrscan; + int n; + register COLR *sp; + /* get scanline buffer */ + if ((sp = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL) + return(-1); + clrscan = sp; + /* convert scanline */ + n = len; + while (n-- > 0) { + setcolr(sp[0], scanline[0][RED], + scanline[0][GRN], + scanline[0][BLU]); + scanline++; + sp++; + } + return(fwritecolrs(clrscan, len, fp)); +} + + +int +freadscan(scanline, len, fp) /* read in a scanline */ +register COLOR *scanline; +int len; +FILE *fp; +{ + register COLR *clrscan; + + if ((clrscan = (COLR *)tempbuffer(len*sizeof(COLR))) == NULL) + return(-1); + if (freadcolrs(clrscan, len, fp) < 0) + return(-1); + /* convert scanline */ + colr_color(scanline[0], clrscan[0]); + while (--len > 0) { + scanline++; clrscan++; + if (clrscan[0][RED] == clrscan[-1][RED] && + clrscan[0][GRN] == clrscan[-1][GRN] && + clrscan[0][BLU] == clrscan[-1][BLU] && + clrscan[0][EXP] == clrscan[-1][EXP]) + copycolor(scanline[0], scanline[-1]); + else + colr_color(scanline[0], clrscan[0]); + } + return(0); +} + + +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; +} + + +void +colr_color(col, clr) /* convert short to float color */ +register COLOR col; +register COLR clr; +{ + double f; + + if (clr[EXP] == 0) + col[RED] = col[GRN] = col[BLU] = 0.0; + else { + f = ldexp(1.0, (int)clr[EXP]-(COLXS+8)); + col[RED] = (clr[RED] + 0.5)*f; + col[GRN] = (clr[GRN] + 0.5)*f; + col[BLU] = (clr[BLU] + 0.5)*f; + } +} + + +int +bigdiff(c1, c2, md) /* c1 delta c2 > md? */ +register COLOR c1, c2; +double md; +{ + register int i; + + for (i = 0; i < 3; i++) + if (colval(c1,i)-colval(c2,i) > md*colval(c2,i) || + colval(c2,i)-colval(c1,i) > md*colval(c1,i)) + return(1); + return(0); +} diff --git a/libsrc/format/radiance/color.h b/libsrc/format/radiance/color.h new file mode 100644 index 00000000..1137f426 --- /dev/null +++ b/libsrc/format/radiance/color.h @@ -0,0 +1,244 @@ +/* RCSid $Id: color.h,v 2.29 2006/09/05 21:54:32 greg Exp $ */ +/* + * color.h - header for routines using pixel color values. + * + * Must be included after X11 headers, since they declare a BYTE type. + * + * Two color representations are used, one for calculation and + * another for storage. Calculation is done with three floats + * for speed. Stored color values use 4 bytes which contain + * three single byte mantissas and a common exponent. + */ +#ifndef _RAD_COLOR_H_ +#define _RAD_COLOR_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#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) */ + +typedef float RGBPRIMS[4][2]; /* (x,y) chromaticities for RGBW */ +typedef float (*RGBPRIMP)[2]; /* pointer to RGBPRIMS array */ + +typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ + +#define copycolr(c1,c2) (c1[0]=c2[0],c1[1]=c2[1], \ + c1[2]=c2[2],c1[3]=c2[3]) + +#define colval(col,pri) ((col)[pri]) + +#define setcolor(col,r,g,b) ((col)[RED]=(r),(col)[GRN]=(g),(col)[BLU]=(b)) + +#define copycolor(c1,c2) ((c1)[0]=(c2)[0],(c1)[1]=(c2)[1],(c1)[2]=(c2)[2]) + +#define scalecolor(col,sf) ((col)[0]*=(sf),(col)[1]*=(sf),(col)[2]*=(sf)) + +#define addcolor(c1,c2) ((c1)[0]+=(c2)[0],(c1)[1]+=(c2)[1],(c1)[2]+=(c2)[2]) + +#define multcolor(c1,c2) ((c1)[0]*=(c2)[0],(c1)[1]*=(c2)[1],(c1)[2]*=(c2)[2]) + +#ifdef NTSC +#define CIE_x_r 0.670 /* standard NTSC primaries */ +#define CIE_y_r 0.330 +#define CIE_x_g 0.210 +#define CIE_y_g 0.710 +#define CIE_x_b 0.140 +#define CIE_y_b 0.080 +#define CIE_x_w 0.3333 /* use true white */ +#define CIE_y_w 0.3333 +#else +#define CIE_x_r 0.640 /* nominal CRT primaries */ +#define CIE_y_r 0.330 +#define CIE_x_g 0.290 +#define CIE_y_g 0.600 +#define CIE_x_b 0.150 +#define CIE_y_b 0.060 +#define CIE_x_w 0.3333 /* use true white */ +#define CIE_y_w 0.3333 +#endif + +#define STDPRIMS {{CIE_x_r,CIE_y_r},{CIE_x_g,CIE_y_g}, \ + {CIE_x_b,CIE_y_b},{CIE_x_w,CIE_y_w}} + +#define CIE_D ( CIE_x_r*(CIE_y_g - CIE_y_b) + \ + CIE_x_g*(CIE_y_b - CIE_y_r) + \ + CIE_x_b*(CIE_y_r - CIE_y_g) ) +#define CIE_C_rD ( (1./CIE_y_w) * \ + ( CIE_x_w*(CIE_y_g - CIE_y_b) - \ + CIE_y_w*(CIE_x_g - CIE_x_b) + \ + CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g ) ) +#define CIE_C_gD ( (1./CIE_y_w) * \ + ( CIE_x_w*(CIE_y_b - CIE_y_r) - \ + CIE_y_w*(CIE_x_b - CIE_x_r) - \ + CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r ) ) +#define CIE_C_bD ( (1./CIE_y_w) * \ + ( CIE_x_w*(CIE_y_r - CIE_y_g) - \ + CIE_y_w*(CIE_x_r - CIE_x_g) + \ + CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r ) ) + +#define CIE_rf (CIE_y_r*CIE_C_rD/CIE_D) +#define CIE_gf (CIE_y_g*CIE_C_gD/CIE_D) +#define CIE_bf (CIE_y_b*CIE_C_bD/CIE_D) + +/* As of 9-94, CIE_rf=.265074126, CIE_gf=.670114631 and CIE_bf=.064811243 */ + +/***** The following definitions are valid for RGB colors only... *****/ + +#define bright(col) (CIE_rf*(col)[RED]+CIE_gf*(col)[GRN]+CIE_bf*(col)[BLU]) +#define normbright(c) ( ( (long)(CIE_rf*256.+.5)*(c)[RED] + \ + (long)(CIE_gf*256.+.5)*(c)[GRN] + \ + (long)(CIE_bf*256.+.5)*(c)[BLU] ) >> 8 ) + + /* luminous efficacies over visible spectrum */ +#define MAXEFFICACY 683. /* defined maximum at 550 nm */ +#define WHTEFFICACY 179. /* uniform white light */ +#define D65EFFICACY 203. /* standard illuminant D65 */ +#define INCEFFICACY 160. /* illuminant A (incand.) */ +#define SUNEFFICACY 208. /* illuminant B (solar dir.) */ +#define SKYEFFICACY D65EFFICACY /* skylight (should be 110) */ +#define DAYEFFICACY D65EFFICACY /* combined sky and solar */ + +#define luminance(col) (WHTEFFICACY * bright(col)) + +/***** ...end of stuff specific to RGB colors *****/ + +#define intens(col) ( (col)[0] > (col)[1] \ + ? (col)[0] > (col)[2] ? (col)[0] : (col)[2] \ + : (col)[1] > (col)[2] ? (col)[1] : (col)[2] ) + +#define colrval(c,p) ( (c)[EXP] ? \ + ldexp((c)[p]+.5,(int)(c)[EXP]-(COLXS+8)) : \ + 0. ) + +#define WHTCOLOR {1.0,1.0,1.0} +#define BLKCOLOR {0.0,0.0,0.0} +#define WHTCOLR {128,128,128,COLXS+1} +#define BLKCOLR {0,0,0,0} + + /* picture format identifier */ +#define COLRFMT "32-bit_rle_rgbe" +#define CIEFMT "32-bit_rle_xyze" +#define PICFMT "32-bit_rle_???e" /* matches either */ +#define LPICFMT 15 /* max format id len */ + + /* macros for exposures */ +#define EXPOSSTR "EXPOSURE=" +#define LEXPOSSTR 9 +#define isexpos(hl) (!strncmp(hl,EXPOSSTR,LEXPOSSTR)) +#define exposval(hl) atof((hl)+LEXPOSSTR) +#define fputexpos(ex,fp) fprintf(fp,"%s%e\n",EXPOSSTR,ex) + + /* macros for pixel aspect ratios */ +#define ASPECTSTR "PIXASPECT=" +#define LASPECTSTR 10 +#define isaspect(hl) (!strncmp(hl,ASPECTSTR,LASPECTSTR)) +#define aspectval(hl) atof((hl)+LASPECTSTR) +#define fputaspect(pa,fp) fprintf(fp,"%s%f\n",ASPECTSTR,pa) + + /* macros for primary specifications */ +#define PRIMARYSTR "PRIMARIES=" +#define LPRIMARYSTR 10 +#define isprims(hl) (!strncmp(hl,PRIMARYSTR,LPRIMARYSTR)) +#define primsval(p,hl) sscanf(hl+LPRIMARYSTR, \ + "%f %f %f %f %f %f %f %f", \ + &(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 fputprims(p,fp) fprintf(fp, \ + "%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]) + + /* macros for color correction */ +#define COLCORSTR "COLORCORR=" +#define LCOLCORSTR 10 +#define iscolcor(hl) (!strncmp(hl,COLCORSTR,LCOLCORSTR)) +#define colcorval(cc,hl) sscanf(hl+LCOLCORSTR,"%f %f %f", \ + &(cc)[RED],&(cc)[GRN],&(cc)[BLU]) +#define fputcolcor(cc,fp) fprintf(fp,"%s %f %f %f\n",COLCORSTR, \ + (cc)[RED],(cc)[GRN],(cc)[BLU]) + +/* + * Conversions to and from XYZ space generally don't apply WHTEFFICACY. + * If you need Y to be luminance (cd/m^2), this must be applied when + * converting from radiance (watts/sr/m^2). + */ + +extern RGBPRIMS stdprims; /* standard primary chromaticities */ +extern COLORMAT rgb2xyzmat; /* RGB to XYZ conversion matrix */ +extern COLORMAT xyz2rgbmat; /* XYZ to RGB conversion matrix */ +extern COLOR cblack, cwhite; /* black (0,0,0) and white (1,1,1) */ + +#define CGAMUT_LOWER 01 +#define CGAMUT_UPPER 02 +#define CGAMUT (CGAMUT_LOWER|CGAMUT_UPPER) + +#define rgb_cie(xyz,rgb) colortrans(xyz,rgb2xyzmat,rgb) + +#define cpcolormat(md,ms) memcpy((void *)md,(void *)ms,sizeof(COLORMAT)) + + /* defined in color.c */ +extern char *tempbuffer(unsigned int len); +extern int fwritecolrs(COLR *scanline, int len, FILE *fp); +extern int freadcolrs(COLR *scanline, int len, FILE *fp); +extern int fwritescan(COLOR *scanline, int len, FILE *fp); +extern int freadscan(COLOR *scanline, int len, FILE *fp); +extern void setcolr(COLR clr, double r, double g, double b); +extern void colr_color(COLOR col, COLR clr); +extern int bigdiff(COLOR c1, COLOR c2, double md); + /* defined in spec_rgb.c */ +extern void spec_rgb(COLOR col, int s, int e); +extern void spec_cie(COLOR col, int s, int e); +extern void cie_rgb(COLOR rgb, COLOR xyz); +extern int clipgamut(COLOR col, double brt, int gamut, + COLOR lower, COLOR upper); +extern void colortrans(COLOR c2, COLORMAT mat, COLOR c1); +extern void multcolormat(COLORMAT m3, COLORMAT m2, + COLORMAT m1); +extern int colorprimsOK(RGBPRIMS pr); +extern int compxyz2rgbmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2xyzmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2rgbmat(COLORMAT mat, RGBPRIMS pr1, RGBPRIMS pr2); +extern int compxyzWBmat(COLORMAT mat, float wht1[2], + float wht2[2]); +extern int compxyz2rgbWBmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2xyzWBmat(COLORMAT mat, RGBPRIMS pr); +extern int comprgb2rgbWBmat(COLORMAT mat, RGBPRIMS pr1, RGBPRIMS pr2); + /* defined in colrops.c */ +extern int setcolrcor(double (*f)(double, double), double a2); +extern int setcolrinv(double (*f)(double, double), double a2); +extern int setcolrgam(double g); +extern int colrs_gambs(COLR *scan, int len); +extern int gambs_colrs(COLR *scan, int len); +extern void shiftcolrs(COLR *scan, int len, int adjust); +extern void normcolrs(COLR *scan, int len, int adjust); + + +#ifdef __cplusplus +} +#endif +#endif /* _RAD_COLOR_H_ */ + diff --git a/libsrc/format/radiance/colrops.c b/libsrc/format/radiance/colrops.c new file mode 100644 index 00000000..e241e34a --- /dev/null +++ b/libsrc/format/radiance/colrops.c @@ -0,0 +1,231 @@ +#ifndef lint +static const char RCSid[] = "$Id: colrops.c,v 2.11 2003/07/30 10:11:06 schorsch Exp $"; +#endif +/* + * Integer operations on COLR scanlines + */ + +#include "copyright.h" + +#include +#include + +#include "rtmisc.h" +#include "color.h" + + +#define MAXGSHIFT 31 /* maximum shift for gamma table */ + +static BYTE *g_mant = NULL, *g_nexp = NULL; + +static BYTE (*g_bval)[256] = NULL; + + +int +setcolrcor(f, a2) /* set brightness correction */ +double (*f)(double,double); +double a2; +{ + double mult; + register int i, j; + /* allocate tables */ + if (g_bval == NULL && (g_bval = + (BYTE (*)[256])bmalloc((MAXGSHIFT+1)*256)) == NULL) + return(-1); + /* compute colr -> gamb mapping */ + mult = 1.0/256.0; + for (i = 0; i <= MAXGSHIFT; i++) { + for (j = 0; j < 256; j++) + g_bval[i][j] = 256.0 * (*f)((j+.5)*mult, a2); + mult *= 0.5; + } + return(0); +} + + +int +setcolrinv(f, a2) /* set inverse brightness correction */ +double (*f)(double,double); +double a2; +{ + double mult; + register int i, j; + /* allocate tables */ + if (g_mant == NULL && (g_mant = (BYTE *)bmalloc(256)) == NULL) + return(-1); + if (g_nexp == NULL && (g_nexp = (BYTE *)bmalloc(256)) == NULL) + return(-1); + /* compute gamb -> colr mapping */ + i = 0; + mult = 256.0; + for (j = 256; j--; ) { + while ((g_mant[j] = mult * (*f)((j+.5)/256.0, a2)) < 128) { + i++; + mult *= 2.0; + } + g_nexp[j] = i; + } + return(0); +} + + +int +setcolrgam(g) /* set gamma conversion */ +double g; +{ + if (setcolrcor(pow, 1.0/g) < 0) + return(-1); + return(setcolrinv(pow, g)); +} + + +int +colrs_gambs(scan, len) /* convert scanline of colrs to gamma bytes */ +register COLR *scan; +int len; +{ + register int i, expo; + + if (g_bval == NULL) + return(-1); + while (len-- > 0) { + expo = scan[0][EXP] - COLXS; + if (expo < -MAXGSHIFT) { + if (expo < -MAXGSHIFT-8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 0; + } else { + i = (-MAXGSHIFT-1) - expo; + scan[0][RED] = + g_bval[MAXGSHIFT][((scan[0][RED]>>i)+1)>>1]; + scan[0][GRN] = + g_bval[MAXGSHIFT][((scan[0][GRN]>>i)+1)>>1]; + scan[0][BLU] = + g_bval[MAXGSHIFT][((scan[0][BLU]>>i)+1)>>1]; + } + } else if (expo > 0) { + if (expo > 8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 255; + } else { + i = (scan[0][RED]<<1 | 1) << (expo-1); + scan[0][RED] = i > 255 ? 255 : g_bval[0][i]; + i = (scan[0][GRN]<<1 | 1) << (expo-1); + scan[0][GRN] = i > 255 ? 255 : g_bval[0][i]; + i = (scan[0][BLU]<<1 | 1) << (expo-1); + scan[0][BLU] = i > 255 ? 255 : g_bval[0][i]; + } + } else { + scan[0][RED] = g_bval[-expo][scan[0][RED]]; + scan[0][GRN] = g_bval[-expo][scan[0][GRN]]; + scan[0][BLU] = g_bval[-expo][scan[0][BLU]]; + } + scan[0][EXP] = COLXS; + scan++; + } + return(0); +} + + +int +gambs_colrs(scan, len) /* convert gamma bytes to colr scanline */ +register COLR *scan; +int len; +{ + register int nexpo; + + if ((g_mant == NULL) | (g_nexp == NULL)) + return(-1); + while (len-- > 0) { + nexpo = g_nexp[scan[0][RED]]; + if (g_nexp[scan[0][GRN]] < nexpo) + nexpo = g_nexp[scan[0][GRN]]; + if (g_nexp[scan[0][BLU]] < nexpo) + nexpo = g_nexp[scan[0][BLU]]; + if (nexpo < g_nexp[scan[0][RED]]) + scan[0][RED] = g_mant[scan[0][RED]] + >> (g_nexp[scan[0][RED]]-nexpo); + else + scan[0][RED] = g_mant[scan[0][RED]]; + if (nexpo < g_nexp[scan[0][GRN]]) + scan[0][GRN] = g_mant[scan[0][GRN]] + >> (g_nexp[scan[0][GRN]]-nexpo); + else + scan[0][GRN] = g_mant[scan[0][GRN]]; + if (nexpo < g_nexp[scan[0][BLU]]) + scan[0][BLU] = g_mant[scan[0][BLU]] + >> (g_nexp[scan[0][BLU]]-nexpo); + else + scan[0][BLU] = g_mant[scan[0][BLU]]; + scan[0][EXP] = COLXS - nexpo; + scan++; + } + return(0); +} + + +void +shiftcolrs(scan, len, adjust) /* shift a scanline of colors by 2^adjust */ +register COLR *scan; +register int len; +register int adjust; +{ + int minexp; + + if (adjust == 0) + return; + minexp = adjust < 0 ? -adjust : 0; + while (len-- > 0) { + if (scan[0][EXP] <= minexp) + scan[0][RED] = scan[0][GRN] = scan[0][BLU] = + scan[0][EXP] = 0; + else + scan[0][EXP] += adjust; + scan++; + } +} + + +void +normcolrs(scan, len, adjust) /* normalize a scanline of colrs */ +register COLR *scan; +int len; +int adjust; +{ + register int c; + register int shift; + + while (len-- > 0) { + shift = scan[0][EXP] + adjust - COLXS; + if (shift > 0) { + if (shift > 8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 255; + } else { + shift--; + c = (scan[0][RED]<<1 | 1) << shift; + scan[0][RED] = c > 255 ? 255 : c; + c = (scan[0][GRN]<<1 | 1) << shift; + scan[0][GRN] = c > 255 ? 255 : c; + c = (scan[0][BLU]<<1 | 1) << shift; + scan[0][BLU] = c > 255 ? 255 : c; + } + } else if (shift < 0) { + if (shift < -8) { + scan[0][RED] = + scan[0][GRN] = + scan[0][BLU] = 0; + } else { + shift = -1-shift; + scan[0][RED] = ((scan[0][RED]>>shift)+1)>>1; + scan[0][GRN] = ((scan[0][GRN]>>shift)+1)>>1; + scan[0][BLU] = ((scan[0][BLU]>>shift)+1)>>1; + } + } + scan[0][EXP] = COLXS - adjust; + scan++; + } +} diff --git a/libsrc/format/radiance/header.c b/libsrc/format/radiance/header.c new file mode 100644 index 00000000..08b5528d --- /dev/null +++ b/libsrc/format/radiance/header.c @@ -0,0 +1,340 @@ +#ifndef lint +static const char RCSid[] = "$Id: header.c,v 2.23 2005/02/01 01:28:16 greg Exp $"; +#endif +/* + * header.c - routines for reading and writing information headers. + * + * Externals declared in resolu.h + * + * newheader(t,fp) start new information header identified by string t + * isheadid(s) returns true if s is a header id line + * headidval(r,s) copy header identifier value in s to r + * dateval(t,s) get capture date value + * isdate(s) returns true if s is a date line + * fputdate(t,fp) put out the given capture date and time + * fputnow(fp) put out the current date and time + * printargs(ac,av,fp) print an argument list to fp, followed by '\n' + * isformat(s) returns true if s is of the form "FORMAT=*" + * formatval(r,s) copy the format value in s to r + * fputformat(s,fp) write "FORMAT=%s" to fp + * getheader(fp,f,p) read header from fp, calling f(s,p) on each line + * globmatch(pat, str) check for glob match of str against pat + * checkheader(i,p,o) check header format from i against p and copy to o + * + * To copy header from input to output, use getheader(fin, fputs, fout) + */ + +#include "copyright.h" + +#include + +#include "rtio.h" +#include "resolu.h" + +#define MAXLINE 512 + +char HDRSTR[] = "#?"; /* information header magic number */ + +char FMTSTR[] = "FORMAT="; /* format identifier */ + +char TMSTR[] = "CAPDATE="; /* capture date identifier */ + +static gethfunc mycheck; + + +extern void +newheader( /* identifying line of information header */ + char *s, + register FILE *fp +) +{ + fputs(HDRSTR, fp); + fputs(s, fp); + putc('\n', fp); +} + + +extern int +headidval( /* get header id (return true if is id) */ + register char *r, + register char *s +) +{ + register char *cp = HDRSTR; + + while (*cp) if (*cp++ != *s++) return(0); + if (r == NULL) return(1); + while (*s && !isspace(*s)) *r++ = *s++; + *r = '\0'; + return(1); +} + + +extern int +isheadid( /* check to see if line is header id */ + char *s +) +{ + return(headidval(NULL, s)); +} + + +extern int +dateval( /* get capture date value */ + time_t *tloc, + char *s +) +{ + struct tm tms; + register char *cp = TMSTR; + + while (*cp) if (*cp++ != *s++) return(0); + while (isspace(*s)) s++; + if (!*s) return(0); + if (sscanf(s, "%d:%d:%d %d:%d:%d", + &tms.tm_year, &tms.tm_mon, &tms.tm_mday, + &tms.tm_hour, &tms.tm_min, &tms.tm_sec) != 6) + return(0); + if (tloc == NULL) + return(1); + tms.tm_mon--; + tms.tm_year -= 1900; + tms.tm_isdst = -1; /* ask mktime() to figure out DST */ + *tloc = mktime(&tms); + return(1); +} + + +extern int +isdate( /* is the given line a capture date? */ + char *s +) +{ + return(dateval(NULL, s)); +} + + +extern void +fputdate( /* write out the given time value */ + time_t tv, + FILE *fp +) +{ + struct tm *tm = localtime(&tv); + if (tm == NULL) + return; + fprintf(fp, "%s %04d:%02d:%02d %02d:%02d:%02d\n", TMSTR, + tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + + +extern void +fputnow( /* write out the current time */ + FILE *fp +) +{ + time_t tv; + time(&tv); + fputdate(tv, fp); +} + + +extern void +printargs( /* print arguments to a file */ + int ac, + char **av, + FILE *fp +) +{ + while (ac-- > 0) { + fputword(*av++, fp); + fputc(ac ? ' ' : '\n', fp); + } +} + + +extern int +formatval( /* get format value (return true if format) */ + register char *r, + register char *s +) +{ + register char *cp = FMTSTR; + + while (*cp) if (*cp++ != *s++) return(0); + while (isspace(*s)) s++; + if (!*s) return(0); + if (r == NULL) return(1); + do + *r++ = *s++; + while(*s && !isspace(*s)); + *r = '\0'; + return(1); +} + + +extern int +isformat( /* is line a format line? */ + char *s +) +{ + return(formatval(NULL, s)); +} + + +extern void +fputformat( /* put out a format value */ + char *s, + FILE *fp +) +{ + fputs(FMTSTR, fp); + fputs(s, fp); + putc('\n', fp); +} + + +extern int +getheader( /* get header from file */ + FILE *fp, + gethfunc *f, + void *p +) +{ + char buf[MAXLINE]; + + for ( ; ; ) { + buf[MAXLINE-2] = '\n'; + if (fgets(buf, MAXLINE, fp) == NULL) + return(-1); + if (buf[0] == '\n') + return(0); +#ifdef MSDOS + if (buf[0] == '\r' && buf[1] == '\n') + return(0); +#endif + if (buf[MAXLINE-2] != '\n') { + ungetc(buf[MAXLINE-2], fp); /* prevent false end */ + buf[MAXLINE-2] = '\0'; + } + if (f != NULL && (*f)(buf, p) < 0) + return(-1); + } +} + + +struct check { + FILE *fp; + char fs[64]; +}; + + +static int +mycheck( /* check a header line for format info. */ + char *s, + void *cp +) +{ + if (!formatval(((struct check*)cp)->fs, s) + && ((struct check*)cp)->fp != NULL) { + fputs(s, ((struct check*)cp)->fp); + } + return(0); +} + + +extern int +globmatch( /* check for match of s against pattern p */ + register char *p, + register char *s +) +{ + int setmatch; + + do { + switch (*p) { + case '?': /* match any character */ + if (!*s++) + return(0); + break; + case '*': /* match any string */ + while (p[1] == '*') p++; + do + if ( (p[1]=='?' || p[1]==*s) && + globmatch(p+1,s) ) + return(1); + while (*s++); + return(0); + case '[': /* character set */ + setmatch = *s == *++p; + if (!*p) + return(0); + while (*++p != ']') { + if (!*p) + return(0); + if (*p == '-') { + setmatch += p[-1] <= *s && *s <= p[1]; + if (!*++p) + break; + } else + setmatch += *p == *s; + } + if (!setmatch) + return(0); + s++; + break; + case '\\': /* literal next */ + p++; + /* fall through */ + default: /* normal character */ + if (*p != *s) + return(0); + s++; + break; + } + } while (*p++); + return(1); +} + + +/* + * Checkheader(fin,fmt,fout) returns a value of 1 if the input format + * matches the specification in fmt, 0 if no input format was found, + * and -1 if the input format does not match or there is an + * error reading the header. If fmt is empty, then -1 is returned + * if any input format is found (or there is an error), and 0 otherwise. + * If fmt contains any '*' or '?' characters, then checkheader + * does wildcard expansion and copies a matching result into fmt. + * Be sure that fmt is big enough to hold the match in such cases, + * and that it is not a static, read-only string! + * The input header (minus any format lines) is copied to fout + * if fout is not NULL. + */ + +extern int +checkheader( + FILE *fin, + char *fmt, + FILE *fout +) +{ + struct check cdat; + register char *cp; + + cdat.fp = fout; + cdat.fs[0] = '\0'; + if (getheader(fin, mycheck, &cdat) < 0) + return(-1); + if (!cdat.fs[0]) + return(0); + for (cp = fmt; *cp; cp++) /* check for globbing */ + if ((*cp == '?') | (*cp == '*')) { + if (globmatch(fmt, cdat.fs)) { + strcpy(fmt, cdat.fs); + return(1); + } else + return(-1); + } + return(strcmp(fmt, cdat.fs) ? -1 : 1); /* literal match */ +} diff --git a/libsrc/format/radiance/ra_skel.c b/libsrc/format/radiance/ra_skel.c new file mode 100644 index 00000000..9c963f7c --- /dev/null +++ b/libsrc/format/radiance/ra_skel.c @@ -0,0 +1,176 @@ +#ifndef lint +static const char RCSid[] = "$Id: ra_skel.c,v 2.13 2006/03/10 19:40:13 schorsch Exp $"; +#endif +/* + * Skeletal 24-bit image conversion program. Replace "skel" + * in this file with a more appropriate image type identifier. + * + * The Rmakefile entry should look something like this: + * ra_skel: ra_skel.o + * cc $(CFLAGS) -o ra_skel ra_skel.o -lrtrad -lm + * ra_skel.o: ../common/color.h ../common/resolu.h + * + * If you like to do things the hard way, you can link directly + * to the object files "color.o colrops.o resolu.o header.o" in + * the common subdirectory instead of using the -lrtrad library. + */ + +#include +#include +#include + +#include "platform.h" +#include "color.h" +#include "resolu.h" + +double gamcor = 2.2; /* gamma correction */ + +int bradj = 0; /* brightness adjustment */ + +char *progname; + +int xmax, ymax; + + +main(argc, argv) +int argc; +char *argv[]; +{ + int reverse = 0; + int i; + + progname = argv[0]; + + for (i = 1; i < argc; i++) + if (argv[i][0] == '-') + switch (argv[i][1]) { + case 'g': /* gamma correction */ + gamcor = atof(argv[++i]); + break; + case 'e': /* exposure adjustment */ + if (argv[i+1][0] != '+' && argv[i+1][0] != '-') + goto userr; + bradj = atoi(argv[++i]); + break; + case 'r': /* reverse conversion */ + reverse = 1; + break; + default: + goto userr; + } + else + break; + + if (i < argc-2) + goto userr; + if (i <= argc-1 && freopen(argv[i], "r", stdin) == NULL) { + fprintf(stderr, "%s: can't open input \"%s\"\n", + progname, argv[i]); + exit(1); + } + if (i == argc-2 && freopen(argv[i+1], "w", stdout) == NULL) { + fprintf(stderr, "%s: can't open output \"%s\"\n", + progname, argv[i+1]); + exit(1); + } + SET_FILE_BINARY(stdin); + SET_FILE_BINARY(stdout); + setcolrgam(gamcor); /* set up gamma correction */ + if (reverse) { + /* get their image resolution */ + read_skel_head(&xmax, &ymax); + /* put our header */ + newheader("RADIANCE", stdout); + printargs(i, argv, stdout); + fputformat(COLRFMT, stdout); + putchar('\n'); + fprtresolu(xmax, ymax, stdout); + /* convert file */ + skel2ra(); + } else { + /* get our header */ + if (checkheader(stdin, COLRFMT, NULL) < 0 || + fgetresolu(&xmax, &ymax, stdin) < 0) + quiterr("bad picture format"); + /* write their header */ + write_skel_head(xmax, ymax); + /* convert file */ + ra2skel(); + } + exit(0); +userr: + fprintf(stderr, + "Usage: %s [-r][-g gamma][-e +/-stops] [input [output]]\n", + progname); + exit(1); +} + + +quiterr(err) /* print message and exit */ +char *err; +{ + if (err != NULL) { + fprintf(stderr, "%s: %s\n", progname, err); + exit(1); + } + exit(0); +} + + +skel2ra() /* convert 24-bit scanlines to Radiance picture */ +{ + COLR *scanout; + register int x; + int y; + /* allocate scanline */ + scanout = (COLR *)malloc(xmax*sizeof(COLR)); + if (scanout == NULL) + quiterr("out of memory in skel2ra"); + /* convert image */ + for (y = ymax-1; y >= 0; y--) { + for (x = 0; x < xmax; x++) { + scanout[x][RED] = getc(stdin); + scanout[x][GRN] = getc(stdin); + scanout[x][BLU] = getc(stdin); + } + if (feof(stdin) | ferror(stdin)) + quiterr("error reading skel image"); + /* undo gamma */ + gambs_colrs(scanout, xmax); + if (bradj) /* adjust exposure */ + shiftcolrs(scanout, xmax, bradj); + if (fwritecolrs(scanout, xmax, stdout) < 0) + quiterr("error writing Radiance picture"); + } + /* free scanline */ + free((void *)scanout); +} + + +ra2skel() /* convert Radiance scanlines to 24-bit */ +{ + COLR *scanin; + register int x; + int y; + /* allocate scanline */ + scanin = (COLR *)malloc(xmax*sizeof(COLR)); + if (scanin == NULL) + quiterr("out of memory in ra2skel"); + /* convert image */ + for (y = ymax-1; y >= 0; y--) { + if (freadcolrs(scanin, xmax, stdin) < 0) + quiterr("error reading Radiance picture"); + if (bradj) /* adjust exposure */ + shiftcolrs(scanin, xmax, bradj); + colrs_gambs(scanin, xmax); /* gamma correction */ + for (x = 0; x < xmax; x++) { + putc(scanin[x][RED], stdout); + putc(scanin[x][GRN], stdout); + putc(scanin[x][BLU], stdout); + } + if (ferror(stdout)) + quiterr("error writing skel file"); + } + /* free scanline */ + free((void *)scanin); +} diff --git a/libsrc/format/radiance/resolu.c b/libsrc/format/radiance/resolu.c new file mode 100644 index 00000000..0c96fadd --- /dev/null +++ b/libsrc/format/radiance/resolu.c @@ -0,0 +1,104 @@ +#ifndef lint +static const char RCSid[] = "$Id: resolu.c,v 2.6 2006/06/07 17:52:03 schorsch Exp $"; +#endif +/* + * Read and write image resolutions. + * + * Externals declared in resolu.h + */ + +#include "copyright.h" + +#include +#include + +#include "resolu.h" + + +char resolu_buf[RESOLU_BUFLEN]; /* resolution line buffer */ + + +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); +} + + +int +fgetresolu(sl, ns, fp) /* get picture dimensions */ +int *sl, *ns; /* scanline length and number */ +FILE *fp; +{ + RESOLU rs; + + if (!fgetsresolu(&rs, fp)) + return(-1); + if (rs.rt & YMAJOR) { + *sl = rs.xr; + *ns = rs.yr; + } else { + *sl = rs.yr; + *ns = rs.xr; + } + return(rs.rt); +} + + +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); +} + + +int +str2resolu(rp, buf) /* convert resolution line to struct */ +register RESOLU *rp; +char *buf; +{ + register char *xndx, *yndx; + register char *cp; + + if (buf == NULL) + return(0); + xndx = yndx = NULL; + for (cp = buf; *cp; cp++) + if (*cp == 'X') + xndx = cp; + else if (*cp == 'Y') + yndx = cp; + if (xndx == NULL || yndx == NULL) + return(0); + rp->rt = 0; + if (xndx > yndx) rp->rt |= YMAJOR; + if (xndx[-1] == '-') rp->rt |= XDECR; + if (yndx[-1] == '-') rp->rt |= YDECR; + if ((rp->xr = atoi(xndx+1)) <= 0) + return(0); + if ((rp->yr = atoi(yndx+1)) <= 0) + return(0); + return(1); +} diff --git a/libsrc/format/radiance/resolu.h b/libsrc/format/radiance/resolu.h new file mode 100644 index 00000000..7767b08c --- /dev/null +++ b/libsrc/format/radiance/resolu.h @@ -0,0 +1,84 @@ +/* RCSid $Id: resolu.h,v 2.10 2005/02/01 01:28:16 greg Exp $ */ +/* + * Definitions for resolution line in image file. + * + * Include after + * + * True image orientation is defined by an xy coordinate system + * whose origin is at the lower left corner of the image, with + * x increasing to the right and y increasing in the upward direction. + * This true orientation is independent of how the pixels are actually + * ordered in the file, which is indicated by the resolution line. + * This line is of the form "{+-}{XY} xyres {+-}{YX} yxres\n". + * A typical line for a 1024x600 image might be "-Y 600 +X 1024\n", + * indicating that the scanlines are in English text order (PIXSTANDARD). + */ +#ifndef _RAD_RESOLU_H_ +#define _RAD_RESOLU_H_ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + /* flags for scanline ordering */ +#define XDECR 1 +#define YDECR 2 +#define YMAJOR 4 + + /* standard scanline ordering */ +#define PIXSTANDARD (YMAJOR|YDECR) +#define PIXSTDFMT "-Y %d +X %d\n" + + /* structure for image dimensions */ +typedef struct { + int rt; /* orientation (from flags above) */ + int xr, yr; /* x and y resolution */ +} RESOLU; + + /* macros to get scanline length and number */ +#define scanlen(rs) ((rs)->rt & YMAJOR ? (rs)->xr : (rs)->yr) +#define numscans(rs) ((rs)->rt & YMAJOR ? (rs)->yr : (rs)->xr) + + /* resolution string buffer and its size */ +#define RESOLU_BUFLEN 32 +extern char resolu_buf[RESOLU_BUFLEN]; + + /* macros for reading/writing resolution struct */ +#define fputsresolu(rs,fp) fputs(resolu2str(resolu_buf,rs),fp) +#define fgetsresolu(rs,fp) str2resolu(rs, \ + fgets(resolu_buf,RESOLU_BUFLEN,fp)) + + /* reading/writing of standard ordering */ +#define fprtresolu(sl,ns,fp) fprintf(fp,PIXSTDFMT,ns,sl) +#define fscnresolu(sl,ns,fp) (fscanf(fp,PIXSTDFMT,ns,sl)==2) + + /* defined in resolu.c */ +extern void fputresolu(int ord, int sl, int ns, FILE *fp); +extern int fgetresolu(int *sl, int *ns, FILE *fp); +extern char * resolu2str(char *buf, RESOLU *rp); +extern int str2resolu(RESOLU *rp, char *buf); + /* defined in header.c */ +extern void newheader(char *t, FILE *fp); +extern int isheadid(char *s); +extern int headidval(char *r, char *s); +extern int dateval(time_t *t, char *s); +extern int isdate(char *s); +extern void fputdate(time_t t, FILE *fp); +extern void fputnow(FILE *fp); +extern void printargs(int ac, char **av, FILE *fp); +extern int isformat(char *s); +extern int formatval(char *r, char *s); +extern void fputformat(char *s, FILE *fp); +typedef int gethfunc(char *s, void *p); /* callback to process header lines */ +extern int getheader(FILE *fp, gethfunc *f, void *p); +extern int globmatch(char *pat, char *str); +extern int checkheader(FILE *fin, char *fmt, FILE *fout); + +#ifdef __cplusplus +} +#endif +#endif /* _RAD_RESOLU_H_ */ + diff --git a/libsrc/format/radiance/rtio.h b/libsrc/format/radiance/rtio.h new file mode 100644 index 00000000..71511c1e --- /dev/null +++ b/libsrc/format/radiance/rtio.h @@ -0,0 +1,86 @@ +/* RCSid $Id: rtio.h,v 3.9 2006/12/23 17:27:45 greg Exp $ */ +/* + * Radiance i/o and string routines + */ + +#ifndef _RAD_RTIO_H_ +#define _RAD_RTIO_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + /* defined in badarg.c */ +extern int badarg(int ac, char **av, char *fl); + /* defined in expandarg.c */ +extern int expandarg(int *acp, char ***avp, int n); + /* defined in fdate.c */ +extern time_t fdate(char *fname); +extern int setfdate(char *fname, long ftim); + /* defined in fgetline.c */ +extern char *fgetline(char *s, int n, FILE *fp); + /* defined in fgetval.c */ +extern int fgetval(FILE *fp, int ty, void *vp); + /* defined in fgetword.c */ +extern char *fgetword(char *s, int n, FILE *fp); + /* defined in fputword.c */ +extern void fputword(char *s, FILE *fp); + /* defined in fropen.c */ +extern FILE *frlibopen(char *fname); + /* defined in getlibpath.c */ +extern char *getrlibpath(void); + /* defined in gethomedir.c */ +extern char *gethomedir(char *uname, char *path, int plen); + /* defined in getpath.c */ +extern char *getpath(char *fname, char *searchpath, int mode); + /* defined in byteswap.c */ +extern void swap16(char *wp, int n); +extern void swap32(char *wp, int n); +extern void swap64(char *wp, int n); + /* defined in portio.c */ +extern void putstr(char *s, FILE *fp); +extern void putint(long i, int siz, FILE *fp); +extern void putflt(double f, FILE *fp); +extern char *getstr(char *s, FILE *fp); +extern long getint(int siz, FILE *fp); +extern double getflt(FILE *fp); + /* defined in rexpr.c */ +extern int ecompile(char *sp, int iflg, int wflag); +extern char *expsave(void); +extern void expset(char *ep); +extern char *eindex(char *sp); + /* defined in savestr.c */ +extern char *savestr(char *str); +extern void freestr(char *s); +extern int shash(char *s); + /* defined in savqstr.c */ +extern char *savqstr(char *s); +extern void freeqstr(char *s); + /* defined in wordfile.c */ +extern int wordfile(char **words, char *fname); +extern int wordstring(char **avl, char *str); + /* defined in words.c */ +extern char *atos(char *rs, int nb, char *s); +extern char *nextword(char *cp, int nb, char *s); +extern char *sskip(char *s); +extern char *sskip2(char *s, int n); +extern char *iskip(char *s); +extern char *fskip(char *s); +extern int isint(char *s); +extern int isintd(char *s, char *ds); +extern int isflt(char *s); +extern int isfltd(char *s, char *ds); + /* defined in lamp.c */ +extern float * matchlamp(char *s); +extern int loadlamps(char *file); +extern void freelamps(void); + +#ifdef __cplusplus +} +#endif +#endif /* _RAD_RTIO_H_ */ + diff --git a/libsrc/format/radiance/test1flt_med.hdr b/libsrc/format/radiance/test1flt_med.hdr new file mode 100644 index 00000000..2b97c730 Binary files /dev/null and b/libsrc/format/radiance/test1flt_med.hdr differ diff --git a/libsrc/format/resolu.c b/libsrc/format/resolu.c new file mode 100644 index 00000000..0c96fadd --- /dev/null +++ b/libsrc/format/resolu.c @@ -0,0 +1,104 @@ +#ifndef lint +static const char RCSid[] = "$Id: resolu.c,v 2.6 2006/06/07 17:52:03 schorsch Exp $"; +#endif +/* + * Read and write image resolutions. + * + * Externals declared in resolu.h + */ + +#include "copyright.h" + +#include +#include + +#include "resolu.h" + + +char resolu_buf[RESOLU_BUFLEN]; /* resolution line buffer */ + + +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); +} + + +int +fgetresolu(sl, ns, fp) /* get picture dimensions */ +int *sl, *ns; /* scanline length and number */ +FILE *fp; +{ + RESOLU rs; + + if (!fgetsresolu(&rs, fp)) + return(-1); + if (rs.rt & YMAJOR) { + *sl = rs.xr; + *ns = rs.yr; + } else { + *sl = rs.yr; + *ns = rs.xr; + } + return(rs.rt); +} + + +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); +} + + +int +str2resolu(rp, buf) /* convert resolution line to struct */ +register RESOLU *rp; +char *buf; +{ + register char *xndx, *yndx; + register char *cp; + + if (buf == NULL) + return(0); + xndx = yndx = NULL; + for (cp = buf; *cp; cp++) + if (*cp == 'X') + xndx = cp; + else if (*cp == 'Y') + yndx = cp; + if (xndx == NULL || yndx == NULL) + return(0); + rp->rt = 0; + if (xndx > yndx) rp->rt |= YMAJOR; + if (xndx[-1] == '-') rp->rt |= XDECR; + if (yndx[-1] == '-') rp->rt |= YDECR; + if ((rp->xr = atoi(xndx+1)) <= 0) + return(0); + if ((rp->yr = atoi(yndx+1)) <= 0) + return(0); + return(1); +} diff --git a/libsrc/format/resolu.h b/libsrc/format/resolu.h new file mode 100644 index 00000000..7767b08c --- /dev/null +++ b/libsrc/format/resolu.h @@ -0,0 +1,84 @@ +/* RCSid $Id: resolu.h,v 2.10 2005/02/01 01:28:16 greg Exp $ */ +/* + * Definitions for resolution line in image file. + * + * Include after + * + * True image orientation is defined by an xy coordinate system + * whose origin is at the lower left corner of the image, with + * x increasing to the right and y increasing in the upward direction. + * This true orientation is independent of how the pixels are actually + * ordered in the file, which is indicated by the resolution line. + * This line is of the form "{+-}{XY} xyres {+-}{YX} yxres\n". + * A typical line for a 1024x600 image might be "-Y 600 +X 1024\n", + * indicating that the scanlines are in English text order (PIXSTANDARD). + */ +#ifndef _RAD_RESOLU_H_ +#define _RAD_RESOLU_H_ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + /* flags for scanline ordering */ +#define XDECR 1 +#define YDECR 2 +#define YMAJOR 4 + + /* standard scanline ordering */ +#define PIXSTANDARD (YMAJOR|YDECR) +#define PIXSTDFMT "-Y %d +X %d\n" + + /* structure for image dimensions */ +typedef struct { + int rt; /* orientation (from flags above) */ + int xr, yr; /* x and y resolution */ +} RESOLU; + + /* macros to get scanline length and number */ +#define scanlen(rs) ((rs)->rt & YMAJOR ? (rs)->xr : (rs)->yr) +#define numscans(rs) ((rs)->rt & YMAJOR ? (rs)->yr : (rs)->xr) + + /* resolution string buffer and its size */ +#define RESOLU_BUFLEN 32 +extern char resolu_buf[RESOLU_BUFLEN]; + + /* macros for reading/writing resolution struct */ +#define fputsresolu(rs,fp) fputs(resolu2str(resolu_buf,rs),fp) +#define fgetsresolu(rs,fp) str2resolu(rs, \ + fgets(resolu_buf,RESOLU_BUFLEN,fp)) + + /* reading/writing of standard ordering */ +#define fprtresolu(sl,ns,fp) fprintf(fp,PIXSTDFMT,ns,sl) +#define fscnresolu(sl,ns,fp) (fscanf(fp,PIXSTDFMT,ns,sl)==2) + + /* defined in resolu.c */ +extern void fputresolu(int ord, int sl, int ns, FILE *fp); +extern int fgetresolu(int *sl, int *ns, FILE *fp); +extern char * resolu2str(char *buf, RESOLU *rp); +extern int str2resolu(RESOLU *rp, char *buf); + /* defined in header.c */ +extern void newheader(char *t, FILE *fp); +extern int isheadid(char *s); +extern int headidval(char *r, char *s); +extern int dateval(time_t *t, char *s); +extern int isdate(char *s); +extern void fputdate(time_t t, FILE *fp); +extern void fputnow(FILE *fp); +extern void printargs(int ac, char **av, FILE *fp); +extern int isformat(char *s); +extern int formatval(char *r, char *s); +extern void fputformat(char *s, FILE *fp); +typedef int gethfunc(char *s, void *p); /* callback to process header lines */ +extern int getheader(FILE *fp, gethfunc *f, void *p); +extern int globmatch(char *pat, char *str); +extern int checkheader(FILE *fin, char *fmt, FILE *fout); + +#ifdef __cplusplus +} +#endif +#endif /* _RAD_RESOLU_H_ */ + diff --git a/libsrc/format/rtio.h b/libsrc/format/rtio.h new file mode 100644 index 00000000..71511c1e --- /dev/null +++ b/libsrc/format/rtio.h @@ -0,0 +1,86 @@ +/* RCSid $Id: rtio.h,v 3.9 2006/12/23 17:27:45 greg Exp $ */ +/* + * Radiance i/o and string routines + */ + +#ifndef _RAD_RTIO_H_ +#define _RAD_RTIO_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + /* defined in badarg.c */ +extern int badarg(int ac, char **av, char *fl); + /* defined in expandarg.c */ +extern int expandarg(int *acp, char ***avp, int n); + /* defined in fdate.c */ +extern time_t fdate(char *fname); +extern int setfdate(char *fname, long ftim); + /* defined in fgetline.c */ +extern char *fgetline(char *s, int n, FILE *fp); + /* defined in fgetval.c */ +extern int fgetval(FILE *fp, int ty, void *vp); + /* defined in fgetword.c */ +extern char *fgetword(char *s, int n, FILE *fp); + /* defined in fputword.c */ +extern void fputword(char *s, FILE *fp); + /* defined in fropen.c */ +extern FILE *frlibopen(char *fname); + /* defined in getlibpath.c */ +extern char *getrlibpath(void); + /* defined in gethomedir.c */ +extern char *gethomedir(char *uname, char *path, int plen); + /* defined in getpath.c */ +extern char *getpath(char *fname, char *searchpath, int mode); + /* defined in byteswap.c */ +extern void swap16(char *wp, int n); +extern void swap32(char *wp, int n); +extern void swap64(char *wp, int n); + /* defined in portio.c */ +extern void putstr(char *s, FILE *fp); +extern void putint(long i, int siz, FILE *fp); +extern void putflt(double f, FILE *fp); +extern char *getstr(char *s, FILE *fp); +extern long getint(int siz, FILE *fp); +extern double getflt(FILE *fp); + /* defined in rexpr.c */ +extern int ecompile(char *sp, int iflg, int wflag); +extern char *expsave(void); +extern void expset(char *ep); +extern char *eindex(char *sp); + /* defined in savestr.c */ +extern char *savestr(char *str); +extern void freestr(char *s); +extern int shash(char *s); + /* defined in savqstr.c */ +extern char *savqstr(char *s); +extern void freeqstr(char *s); + /* defined in wordfile.c */ +extern int wordfile(char **words, char *fname); +extern int wordstring(char **avl, char *str); + /* defined in words.c */ +extern char *atos(char *rs, int nb, char *s); +extern char *nextword(char *cp, int nb, char *s); +extern char *sskip(char *s); +extern char *sskip2(char *s, int n); +extern char *iskip(char *s); +extern char *fskip(char *s); +extern int isint(char *s); +extern int isintd(char *s, char *ds); +extern int isflt(char *s); +extern int isfltd(char *s, char *ds); + /* defined in lamp.c */ +extern float * matchlamp(char *s); +extern int loadlamps(char *file); +extern void freelamps(void); + +#ifdef __cplusplus +} +#endif +#endif /* _RAD_RTIO_H_ */ +