Files
2026-08-20 20:28:40 +01:00

261 lines
6.8 KiB
C

/*
* Author: Graeme W. Gill
* Date: 2007/3/21
* Version: 1.00
*
* Copyright 2007 Graeme W. Gill
* All rights reserved.
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
* see the License.txt file for licencing details.
*
*/
/*
* This is some utility code to subsample the 1 and 5nm spectral
* data in xspect to wider spacings using ANSI-CGATS the recommended
* triangular filter.
*/
#include <stdio.h>
#include <math.h>
#include "aconfig.h"
#include "cgats.h"
#include "xspect.h"
#include "numlib.h"
#include "ui.h"
void usage(void) {
fprintf(stderr,"Downsample spectral data\n");
fprintf(stderr,"Author: Graeme W. Gill\n");
fprintf(stderr,"usage: specsubsamp -options\n");
fprintf(stderr," -i illum Choose illuminant for print/transparency spectral data:\n");
fprintf(stderr," A, C, D50, D50M2, D65, F5, F8, F10 or file.sp\n");
fprintf(stderr," -o observ Choose CIE Observer for spectral data:\n");
fprintf(stderr," 1931_2, 1964_10, 2015_2, 2015_10, S&B 1955_2, shaw, J&V 1978_2 or file.cmf\n");
fprintf(stderr," -w st,en,sp Output start, end and spacing nm\n");
fprintf(stderr," -5 Comment output wavelegths every 5\n");
exit(1);
}
int
main(
int argc,
char *argv[]
) {
int fa,nfa; /* argument we're looking at */
int verb = 0;
icxIllumeType illum = icxIT_D50; /* Spectral defaults */
xspect cust_illum; /* Custom illumination spectrum */
icxObserverType obType = icxOT_CIE_1931_2;
xspect custObserver[3]; /* If obType = icxOT_custom */
int obs = 0; /* If nz output observer */
double wl_short = 380.0, wl_long = 730.0, wl_width = 10.0;
int wl_n = 0;
int evy5 = 0;
error_program = argv[0];
/* Process the arguments */
for(fa = 1;fa < argc;fa++) {
nfa = fa; /* skip to nfa if next argument is used */
if (argv[fa][0] == '-') { /* Look for any flags */
char *na = NULL; /* next argument after flag, null if none */
if (argv[fa][2] != '\000')
na = &argv[fa][2]; /* next is directly after flag */
else {
if ((fa+1) < argc) {
if (argv[fa+1][0] != '-') {
nfa = fa + 1;
na = argv[nfa]; /* next is seperate non-flag argument */
}
}
}
/* Spectral Illuminant type */
if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
fa = nfa;
if (na == NULL) usage();
if (strcmp(na, "A") == 0) {
illum = icxIT_A;
} else if (strcmp(na, "C") == 0) {
illum = icxIT_C;
} else if (strcmp(na, "D50") == 0) {
illum = icxIT_D50;
} else if (strcmp(na, "D50M2") == 0) {
illum = icxIT_D50M2;
} else if (strcmp(na, "D65") == 0) {
illum = icxIT_D65;
} else if (strcmp(na, "F5") == 0) {
illum = icxIT_F5;
} else if (strcmp(na, "F8") == 0) {
illum = icxIT_F8;
} else if (strcmp(na, "F10") == 0) {
illum = icxIT_F10;
} else { /* Assume it's a filename */
inst_meas_type mt;
illum = icxIT_custom;
if (read_xspect(&cust_illum, &mt, NULL, na) != 0)
usage();
if (mt != inst_mrt_none
&& mt != inst_mrt_emission
&& mt != inst_mrt_ambient
&& mt != inst_mrt_emission_flash
&& mt != inst_mrt_ambient_flash)
error("Custom illuminant '%s' is wrong measurement type",na);
}
}
/* Spectral Observer type */
else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
fa = nfa;
if (na == NULL) usage();
if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */
obs = 1;
obType = icxOT_CIE_1931_2;
} else if (strcmp(na, "1964_10") == 0) { /* Classic 10 degree */
obs = 1;
obType = icxOT_CIE_1964_10;
} else if (strcmp(na, "2015_2") == 0) { /* Latest 2 degree */
obs = 1;
obType = icxOT_CIE_2015_2;
} else if (strcmp(na, "2015_10") == 0) { /* Latest 10 degree */
obs = 1;
obType = icxOT_CIE_2015_10;
} else if (strcmp(na, "1955_2") == 0) { /* Stiles and Burch 1955 2 degree */
obs = 1;
obType = icxOT_Stiles_Burch_2;
} else if (strcmp(na, "1978_2") == 0) { /* Judd and Voss 1978 2 degree */
obs = 1;
obType = icxOT_Judd_Voss_2;
} else if (strcmp(na, "shaw") == 0) { /* Shaw and Fairchilds 1997 2 degree */
obs = 1;
obType = icxOT_Shaw_Fairchild_2;
} else { /* Assume it's a filename */
obs = 1;
obType = icxOT_custom;
if (read_cmf(custObserver, na) != 0)
usage();
}
}
else if (argv[fa][1] == 'w' || argv[fa][1] == 'W') {
fa = nfa;
if (na == NULL) usage();
if (sscanf(na, " %lf,%lf,%lf ",&wl_short,&wl_long,&wl_width) != 3)
if (wl_short > wl_long)
usage();
}
else if (argv[fa][1] == '5') {
evy5 = 1;
}
/* Verbosity */
else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
verb = 1;
} else {
usage();
}
}
else
break;
}
wl_n = (int)((wl_long - wl_short)/wl_width + 1.5);
if ((fabs(wl_short + (wl_n - 1.0) * wl_width) - wl_long) > 0.001)
error("Not an integer number of output samples");
if (obs) {
int i, j, k;
xspect *sp[3];
if (obType == icxOT_custom) {
sp[0] = &custObserver[0];
sp[1] = &custObserver[1];
sp[2] = &custObserver[2];
} else {
if (standardObserver(sp, obType) != 0)
error ("standardObserver returned error");
}
printf("/* %f - %f, %f spacing, %d samples */\n",wl_short,wl_long,wl_width,wl_n);
printf("{\n");
for (k = 0; k < 3; k++) {
printf(" {\n");
for (i = 0; i < wl_n; i++) {
double cwl, swl, sw, tw, outv;
int ns;
cwl = XSPECT_WL(wl_short, wl_long, wl_n, i);
ns = (int)(wl_width/0.1 + 0.5);
tw = outv = 0.0;
for (j = -ns; j <= ns; j++) {
swl = cwl + (j * wl_width)/ns;
sw = (ns - abs(j))/(double)ns;
tw += sw;
outv += sw * value_xspect(sp[k], swl);
}
outv /= tw;
if (!evy5 || i % 5 == 0)
printf(" /* %3.1f */ %1.10f%s\n",cwl,outv, i < (wl_n-1) ? "," : "");
else
printf(" %1.10f%s\n",outv, i < (wl_n-1) ? "," : "");
}
printf(" }%s\n",k < (3-1) ? "," : "");
}
printf("}\n");
} else {
int i, j;
xspect sp;
if (illum == icxIT_custom)
sp = cust_illum;
else {
if (standardIlluminant(&sp, illum, 0) != 0)
error ("standardIlluminant returned error");
}
printf("/* %f - %f, %f spacing, %d samples */\n",wl_short,wl_long,wl_width,wl_n);
printf("{\n");
for (i = 0; i < wl_n; i++) {
double cwl, swl, sw, tw, outv;
int ns;
cwl = XSPECT_WL(wl_short, wl_long, wl_n, i);
//printf("~1 output %f\n",cwl);
ns = (int)(wl_width/0.1 + 0.5);
tw = outv = 0.0;
for (j = -ns; j <= ns; j++) {
swl = cwl + (j * wl_width)/ns;
sw = (ns - abs(j))/(double)ns;
tw += sw;
//printf("~1 sample %f weight %f\n",swl,sw);
outv += sw * value_xspect(&sp, swl);
}
outv /= tw;
if (!evy5 || i % 5 == 0)
printf(" /* %3.1f */ %1.10f%s\n",cwl,outv, i < (wl_n-1) ? "," : "");
else
printf(" %1.10f%s\n",outv, i < (wl_n-1) ? "," : "");
}
printf("}\n");
}
return 0;
}