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); }