diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index 6903221b..18d691c4 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -21,6 +21,8 @@ * - use dbuf for buffer output * 4/4/17 * - reduce stack use to help musl + * 22/7/18 + * - update code from radiance ... pasted in from rad5R1 */ /* @@ -150,43 +152,24 @@ #include "pforeign.h" /* Begin copy-paste from Radiance sources. + * + * To update: + * + * 1. Download and unpack latest stable radiance + * 2. ray/src/common has the files we need ... copy in this order: + * colour.h + * resolu.h + * rtio.h + * fputword.c + * colour.c + * resolu.c + * header.c + * 3. trim each one down, removing extern decls + * 4. make all functions static + * 5. reorder to remove forward refs + * 6. remove unused funcs, mostly related to HDR write */ - /* 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 - - /* 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 */ -typedef int gethfunc(char *s, void *p); /* callback to process header lines */ - - #define RED 0 #define GRN 1 #define BLU 2 @@ -197,10 +180,10 @@ typedef int gethfunc(char *s, void *p); /* callback to process header lines */ #define COLXS 128 /* excess used for exponent */ #define WHT 3 /* used for RGBPRIMS type */ -#undef BYTE -#define BYTE unsigned char /* 8-bit unsigned integer */ +#undef uby8 +#define uby8 unsigned char /* 8-bit unsigned integer */ -typedef BYTE COLR[4]; /* red, green, blue (or X,Y,Z), exponent */ +typedef uby8 COLR[4]; /* red, green, blue (or X,Y,Z), exponent */ typedef float COLORV; typedef COLORV COLOR[3]; /* red, green, blue (or X,Y,Z) */ @@ -232,8 +215,8 @@ typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ #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 +#define CIE_x_w (1./3.) /* use true white */ +#define CIE_y_w (1./3.) #else #define CIE_x_r 0.640 /* nominal CRT primaries */ #define CIE_y_r 0.330 @@ -241,8 +224,8 @@ typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ #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 +#define CIE_x_w (1./3.) /* use true white */ +#define CIE_y_w (1./3.) #endif #define STDPRIMS {{CIE_x_r,CIE_y_r},{CIE_x_g,CIE_y_g}, \ @@ -327,12 +310,12 @@ typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ #define PRIMARYSTR "PRIMARIES=" #define LPRIMARYSTR 10 #define isprims(hl) (!strncmp(hl,PRIMARYSTR,LPRIMARYSTR)) -#define primsval(p,hl) sscanf(hl+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]) + &(p)[WHT][CIEX],&(p)[WHT][CIEY]) == 8) #define fputprims(p,fp) fprintf(fp, \ "%s %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",\ PRIMARYSTR, \ @@ -345,11 +328,22 @@ typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ #define COLCORSTR "COLORCORR=" #define LCOLCORSTR 10 #define iscolcor(hl) (!strncmp(hl,COLCORSTR,LCOLCORSTR)) -#define colcorval(cc,hl) sscanf(hl+LCOLCORSTR,"%f %f %f", \ +#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) @@ -358,28 +352,134 @@ typedef float COLORMAT[3][3]; /* color coordinate conversion matrix */ #define cpcolormat(md,ms) memcpy((void *)md,(void *)ms,sizeof(COLORMAT)) +#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 */ + + /* 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 + + /* 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) + + /* identify header lines */ +#define isheadid(s) headidval(NULL,s) +#define isformat(s) formatval(NULL,s) +#define isdate(s) dateval(NULL,s) +#define isgmt(s) gmtval(NULL,s) + +#define LATLONSTR "LATLONG=" +#define LLATLONSTR 8 +#define islatlon(hl) (!strncmp(hl,LATLONSTR,LLATLONSTR)) +#define latlonval(ll,hl) sscanf((hl)+LLATLONSTR, "%f %f", \ + &(ll)[0],&(ll)[1]) +#define fputlatlon(lat,lon,fp) fprintf(fp,"%s %.6f %.6f\n",LATLONSTR,lat,lon) + +typedef int gethfunc(char *s, void *p); /* callback to process header lines */ + +#ifdef getc_unlocked /* avoid horrendous overhead of flockfile */ +#undef getc +#undef putc +#define getc getc_unlocked +#define putc putc_unlocked +#endif +static char resolu_buf[RESOLU_BUFLEN]; /* resolution line buffer */ -#define MAXLINE 512 +static 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); +} -char HDRSTR[] = "#?"; /* information header magic number */ -char FMTSTR[] = "FORMAT="; /* format identifier */ +static 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); +} + +#define MAXLINE 2048 + +static const char FMTSTR[] = "FORMAT="; /* format identifier */ -char TMSTR[] = "CAPDATE="; /* capture date identifier */ static gethfunc mycheck; - static int formatval( /* get format value (return true if format) */ - register char *r, - register char *s + char *r, + const char *s ) { - register char *cp = FMTSTR; + const char *cp = FMTSTR; while (*cp) if (*cp++ != *s++) return(0); while (isspace(*s)) s++; @@ -387,22 +487,24 @@ formatval( /* get format value (return true if format) */ if (r == NULL) return(1); do *r++ = *s++; - while(*s && !isspace(*s)); + while (*s && !isspace(*s)); *r = '\0'; return(1); } -static int -isformat( /* is line a format line? */ - char *s +static void +fputformat( /* put out a format value */ + const char *s, + FILE *fp ) { - return(formatval(NULL, s)); + fputs(FMTSTR, fp); + fputs(s, fp); + putc('\n', fp); } - static int getheader( /* get header from file */ FILE *fp, @@ -410,30 +512,24 @@ getheader( /* get header from file */ void *p ) { + int rtotal = 0; char buf[MAXLINE]; - int n; - /* give up if there are more than 1,000 lines of header, prevents - * us scanning entire files when testing for israd */ - for (n = 0; n < 1000; n++) { + for ( ; ; ) { + int rval = 0; 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[buf[0]=='\r'] == '\n') + return(rtotal); if (buf[MAXLINE-2] != '\n') { ungetc(buf[MAXLINE-2], fp); /* prevent false end */ buf[MAXLINE-2] = '\0'; } - if (f != NULL && (*f)(buf, p) < 0) + if (f != NULL && (rval = (*f)(buf, p)) < 0) return(-1); + rtotal += rval; } - - return(0); } @@ -459,8 +555,8 @@ mycheck( /* check a header line for format info. */ static int globmatch( /* check for match of s against pattern p */ - register char *p, - register char *s + const char *p, + const char *s ) { int setmatch; @@ -474,7 +570,7 @@ globmatch( /* check for match of s against pattern p */ case '*': /* match any string */ while (p[1] == '*') p++; do - if ( (p[1]=='?' || p[1]==*s) && + if ( (p[1]=='?') | (p[1]==*s) && globmatch(p+1,s) ) return(1); while (*s++); @@ -487,11 +583,11 @@ globmatch( /* check for match of s against pattern p */ if (!*p) return(0); if (*p == '-') { - setmatch += p[-1] <= *s && *s <= p[1]; + setmatch += (p[-1] <= *s && *s <= p[1]); if (!*++p) break; } else - setmatch += *p == *s; + setmatch += (*p == *s); } if (!setmatch) return(0); @@ -533,7 +629,7 @@ checkheader( ) { struct check cdat; - register char *cp; + char *cp; cdat.fp = fout; cdat.fs[0] = '\0'; @@ -552,74 +648,6 @@ checkheader( return(strcmp(fmt, cdat.fs) ? -1 : 1); /* literal match */ } - -static char resolu_buf[RESOLU_BUFLEN]; /* resolution line buffer */ - - -static int -str2resolu(RESOLU *rp, char *buf) /* convert resolution line to struct */ -{ - 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); -} - - -#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 */ - -static void -fputformat( /* put out a format value */ - char *s, - FILE *fp -) -{ - fputs(FMTSTR, fp); - fputs(s, fp); - putc('\n', fp); -} - -char * -resolu2str(char *buf, RESOLU *rp) /* convert resolution struct to line */ -{ - 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); -} - /* End copy-paste from Radiance sources. */