Stefan D�hla schrieb:
For instance X-Rite DTP41 and DTP51, or GretagMacbeth Spectrolino/Spectroscan. Code examples see Argyll source code.b.t.w.: does someone know about spectrophotometers or colorimeters that have a complete interfacing description (maybe even source code)?
Avantes also provides a freely available Linux SDK for its Spectrocam. I've written the attached small program to make semi-automatic monitor measurements with Spectrocam under Linux (sorry, no nice user interface, just a quick and dirty hack - and black calibration is still missing).
-Gerhard
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <unistd.h>
#include <specstar.h>
static char *device = "/dev/ttyS0";
static void
initialize(void)
{
SpcErrors ok;
HANDLE serial_handle;
serial_handle = SpectroCam_Open_Serial(device);
if (serial_handle == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Cannot open %s\n", device);
exit(1);
}
if (SpectroCam_Init(0, serial_handle, 1, &ok) == NULL) {
fprintf(stderr, "SpectroCam_Init failed: %s\n",
SpectroCam_ErrorString(ok));
exit(1);
}
}
static SpcErrors
measure_integration(MONITOR_CALIBRATION *moni)
{
SpcErrors ok = ERR_OK;
SPC_MEASURE_OPTIONS M;
DATA_MEASURED dm;
double FreqTime;
word I;
FreqTime = moni->FreqTime = 1000.0 / moni->ScreenFrequency;
M.UseDefaults = FALSE;
M.Flash = M.Flashes = 0;
M.Store = 1;
M.Data = &dm;
M.AvrCnt = 1;
M.Deconvolution = 0; //SPC_DECONVOLUTION_NONE;
M.SpectrumMode = 0; //SM_ALLPIXELS;
M.Illuminant = ILLUMINANT_D65;
M.Observer = OBSERVER_2;
M.MeasureMode = SPC_MM_EMISSION_LENS;
NextIT(NULL, 0); // reset integration routine
M.Integration = moni->IntegrationTime;
while(1) {
ok = SpectroCam_ExecuteRequest(SPC_REQUEST_MEASURE,(int)&M);
if(ok != ERR_OK && ok != ERR_OVERFLOW)
goto done;
I = NextIT(&dm, FreqTime);
printf("Time: %3d => %3.2fmSec Level: %.1f\n",
M.Integration, IT2mSec(M.Integration), dm.MaxRaw);
if((word)M.Integration == I)
break;
M.Integration = (word)I;
}
moni->IntegrationTime = M.Integration;
done:
if(ok != ERR_OK) {
printf("Spectrocam returned: %s\n", SpectroCam_ErrorString(ok));
SpectroCam_Exit();
exit(1);
}
return ok;
}
static void
measure_moni(const char *datafile)
{
int N = 1000;
int i;
SpcErrors ok;
FILE *f, *data;
char line[256];
DATA_MEASURED dm;
SPC_MEASURE_OPTIONS M;
MONITOR_CALIBRATION Moni;
double Ywhite;
if ((data = fopen(datafile, "r")) == NULL) {
perror(datafile);
SpectroCam_Exit();
exit(1);
}
f = popen("wish", "w");
fprintf(f, "frame .f -width 480 -height 640 -background #ffffff\n");
fprintf(f, "pack .f\n");
fflush(f);
printf("place on white area and press return>");
fflush(stdout);
gets(line);
Moni.IntegrationTime = 1;
Moni.ScreenFrequency = 1000;
measure_integration(&Moni);
#if 1
printf("Measuring frequency...\n");
ok = SpectroCam_ExecuteRequest(SPC_REQUEST_FREQUENCY,(int)&Moni);
if(ok != ERR_OK) {
printf("Spectrocam returned: %s\n", SpectroCam_ErrorString(ok));
SpectroCam_Exit();
exit(1);
}
printf("Frequency measured: %.1f Hz\n", Moni.ScreenFrequency);
#endif
for (i = 0; i < N; i++) {
int rgb[3];
fscanf(data, "%d", &rgb[0]);
fscanf(data, "%d", &rgb[1]);
fscanf(data, "%d", &rgb[2]);
fprintf(f, ".f configure -background #%02x%02x%02x\n",
rgb[0], rgb[1], rgb[2]);
fflush(f);
usleep(200000);
M.MeasureMode = SPC_MM_EMISSION_LENS;
M.UseDefaults = FALSE;
M.SpectrumMode = SM_FASTSPECTRUM;
M.Store = 1;
M.Measured = 0;
M.Illuminant = ILLUMINANT_D50; // don't care is not used
M.Observer = OBSERVER_2;
M.Type = 0; // average/continuous/long
M.Function = 0; // normal/fast/multiple
M.Deconvolution = SPC_DECONVOLUTION_20NM;
M.Timeout = 0;
M.Flashes = 0;
M.Flash = FALSE;
M.Freq = 0;
M.Integration = Moni.IntegrationTime; // mSec2IT(Time_in_milliseconds);
M.AvrCnt = 4;
M.Data = &dm;
ok = SpectroCam_ExecuteRequest(SPC_REQUEST_MEASURE,(int)&M);
#if 0
if (ok == ERR_OVERFLOW)
continue;
#endif
if(ok != ERR_OK) {
printf("Spectrocam returned: %s\n", SpectroCam_ErrorString(ok));
SpectroCam_Exit();
exit(1);
}
if (i == 0) {
Ywhite = dm.Cie.XYZ.Y / 100.0;
printf("Luminance=%f\n", dm.Cie.XYZ.Y);
}
dm.Cie.XYZ.X /= Ywhite;
dm.Cie.XYZ.Y /= Ywhite;
dm.Cie.XYZ.Z /= Ywhite;
if (i == 0)
printf("DMIN ");
else
printf("A%d ", i);
printf("%f %f %f %f %f %f %f\n",
rgb[0]/2.55, rgb[1]/2.55, rgb[2]/2.55,
dm.Cie.XYZ.X, dm.Cie.XYZ.Y, dm.Cie.XYZ.Z,
SpectroCam_ColorTemperature(dm.Cie.xyuv.u, dm.Cie.xyuv.v));
fflush(stdout);
}
fprintf(f,"exit\n");
}
int
main(int ac, char **av)
{
SpcErrors ok;
char line[256];
MONITOR_CALIBRATION Moni;
Moni.ScreenFrequency = 100;
initialize();
measure_moni(av[1]);
SpectroCam_Exit();
exit(0);
}
