summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-09-01 15:43:52 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-09-01 15:43:52 +0200
commitc07d0c2d2f6f7b0eb6e92cc6204bf05037957e82 (patch)
tree41791cbe367cf023b98043fee56f9346b2592b49
parentd7f89e6fe63b8697fab5a901cfce457b375638b3 (diff)
Imported Upstream version 1.6.3upstream/1.6.3
-rw-r--r--Jambase57
-rw-r--r--Jamfile5
-rw-r--r--Jamtop18
-rw-r--r--Readme.txt19
-rw-r--r--cgats/cgats.c68
-rw-r--r--cgats/cgats.h2
-rw-r--r--cgats/pars.c30
-rw-r--r--doc/ArgyllDoc.html4308
-rw-r--r--doc/ChangesSummary.html191
-rw-r--r--doc/ColorHug.jpgbin0 -> 28768 bytes
-rw-r--r--doc/ColorManagement.html22
-rw-r--r--doc/Environment.html16
-rw-r--r--doc/File_Formats.html18
-rw-r--r--doc/Installing_Linux.html27
-rw-r--r--doc/Installing_MSWindows.html57
-rw-r--r--doc/Installing_OSX.html570
-rw-r--r--doc/JETI_1211.jpgbin0 -> 29663 bytes
-rw-r--r--doc/Performance.html242
-rw-r--r--doc/Scenarios.html5489
-rw-r--r--doc/afiles7
-rw-r--r--doc/cal_format.html162
-rw-r--r--doc/ccxxmake.html91
-rw-r--r--doc/cht_format.html1192
-rw-r--r--doc/collink.html1945
-rw-r--r--doc/colprof.html662
-rw-r--r--doc/colverify.html (renamed from doc/verify.html)49
-rw-r--r--doc/dispcal.html754
-rw-r--r--doc/dispprofloc.html305
-rw-r--r--doc/dispread.html369
-rw-r--r--doc/dispwin.html133
-rw-r--r--doc/fakeread.html612
-rw-r--r--doc/i1proHiRes.html177
-rw-r--r--doc/i1proHiRes.jpgbin0 -> 26870 bytes
-rw-r--r--doc/i1proHiRes.zipbin0 -> 319734 bytes
-rw-r--r--doc/iccgamut.html335
-rw-r--r--doc/illumread.html272
-rw-r--r--doc/instruments.html3361
-rw-r--r--doc/oeminst.html2
-rw-r--r--doc/printtarg.html55
-rw-r--r--doc/profcheck.html4
-rw-r--r--doc/refine.html42
-rw-r--r--doc/scanin.html520
-rw-r--r--doc/spec2cie.html10
-rw-r--r--doc/spotread.html148
-rw-r--r--doc/targen.html1540
-rw-r--r--doc/tiffgamut.html348
-rw-r--r--doc/txt2ti3.html204
-rw-r--r--doc/xicclu.html1323
-rw-r--r--gamut/gammap.c43
-rw-r--r--gamut/gammap.h2
-rw-r--r--gamut/gamut.c20
-rw-r--r--gamut/gamut.h2
-rw-r--r--gamut/maptest.c3
-rw-r--r--gamut/nearsmth.c1
-rw-r--r--h/aconfig.h4
-rw-r--r--h/counters.h2
-rw-r--r--icc/ClayRGB1998.icmbin580 -> 584 bytes
-rw-r--r--icc/EBU3213_PAL.icmbin0 -> 9120 bytes
-rw-r--r--icc/Jamfile18
-rw-r--r--icc/License.txt2
-rw-r--r--icc/ProPhoto.icmbin0 -> 2892 bytes
-rw-r--r--icc/ProPhotoLin.icmbin0 -> 2900 bytes
-rw-r--r--icc/Readme.txt8
-rw-r--r--icc/Rec2020.icmbin0 -> 9064 bytes
-rw-r--r--icc/Rec709.icmbin0 -> 2920 bytes
-rw-r--r--icc/SMPTE431_P3.icmbin0 -> 872 bytes
-rw-r--r--icc/SMPTE_RP145_NTSC.icmbin0 -> 9100 bytes
-rw-r--r--icc/afiles9
-rw-r--r--icc/icc.c1186
-rw-r--r--icc/icc.h429
-rw-r--r--icc/iccdump.c3
-rw-r--r--icc/icclu.c31
-rw-r--r--icc/icctest.c9
-rw-r--r--icc/lab2lab.icmbin500 -> 500 bytes
-rw-r--r--icc/log.txt8
-rw-r--r--icc/lutest.c139
-rw-r--r--icc/makezip.ksh6
-rw-r--r--icc/mcheck.c2
-rw-r--r--icc/mkDispProf.c331
-rw-r--r--icc/sRGB.icmbin3212 -> 3212 bytes
-rw-r--r--imdi/cctiff.c497
-rw-r--r--link/collink.c1752
-rw-r--r--log.txt306
-rw-r--r--makepackagebin.sh4
-rw-r--r--numlib/numsup.c333
-rw-r--r--numlib/numsup.h70
-rw-r--r--plot/plot.c237
-rw-r--r--profile/F1.sp106
-rw-r--r--profile/F5.sp106
-rw-r--r--profile/F8.sp106
-rw-r--r--profile/Jamfile6
-rw-r--r--profile/afiles5
-rw-r--r--profile/colprof.c96
-rw-r--r--profile/colverify.c (renamed from profile/verify.c)401
-rw-r--r--profile/prof.h2
-rw-r--r--profile/profcheck.c2
-rw-r--r--profile/profin.c9
-rw-r--r--profile/profout.c156
-rw-r--r--profile/txt2ti3.c6
-rw-r--r--ref/ClayRGB1998.icmbin580 -> 584 bytes
-rw-r--r--ref/ColorCheckerDC.ti2264
-rw-r--r--ref/EBU3213_PAL.icmbin0 -> 9120 bytes
-rw-r--r--ref/F1.sp106
-rw-r--r--ref/F5.sp106
-rw-r--r--ref/F8.sp106
-rw-r--r--ref/ProPhoto.icmbin0 -> 2892 bytes
-rw-r--r--ref/ProPhotoLin.icmbin0 -> 2900 bytes
-rw-r--r--ref/ReadMe.txt4
-rw-r--r--ref/Rec2020.icmbin0 -> 9064 bytes
-rw-r--r--ref/Rec709.icmbin0 -> 2920 bytes
-rw-r--r--ref/SMPTE431_P3.icmbin0 -> 872 bytes
-rw-r--r--ref/SMPTE_RP145_NTSC.icmbin0 -> 9100 bytes
-rw-r--r--ref/afiles11
-rw-r--r--ref/lab2lab.icmbin500 -> 500 bytes
-rw-r--r--ref/linear.cal514
-rw-r--r--ref/sRGB.icmbin3212 -> 3212 bytes
-rw-r--r--ref/strange.cal514
-rw-r--r--rspl/Jamfile8
-rw-r--r--rspl/afiles2
-rw-r--r--rspl/c1.c3
-rw-r--r--rspl/cw1.c308
-rw-r--r--rspl/cw3.c325
-rw-r--r--rspl/rev.c34
-rw-r--r--rspl/rspl.c2
-rw-r--r--rspl/scat.c270
-rw-r--r--scanin/ColorCheckerDC.ti2264
-rw-r--r--scanin/Jamfile2
-rw-r--r--scanin/afiles1
-rw-r--r--scanin/scanin.c8
-rw-r--r--spectro/Jamfile43
-rw-r--r--spectro/Makefile.OSX4
-rw-r--r--spectro/Makefile.SA11
-rw-r--r--spectro/Makefile.UNIX2
-rw-r--r--spectro/afiles6
-rw-r--r--spectro/average.c2
-rw-r--r--spectro/ccxxmake.c49
-rw-r--r--spectro/chartread.c28
-rw-r--r--spectro/colorhug.c60
-rw-r--r--spectro/conv.c61
-rw-r--r--spectro/conv.h6
-rw-r--r--spectro/dispcal.c625
-rw-r--r--spectro/dispread.c114
-rw-r--r--spectro/dispsup.c572
-rw-r--r--spectro/dispsup.h41
-rw-r--r--spectro/dispwin.c999
-rw-r--r--spectro/dispwin.h67
-rw-r--r--spectro/dtp20.c13
-rw-r--r--spectro/dtp22.c16
-rw-r--r--spectro/dtp41.c14
-rw-r--r--spectro/dtp51.c22
-rw-r--r--spectro/dtp92.c101
-rw-r--r--spectro/fakeread.c362
-rw-r--r--spectro/hcfr.c9
-rw-r--r--spectro/hidio.c433
-rw-r--r--spectro/hidio.h9
-rw-r--r--spectro/huey.c20
-rw-r--r--spectro/i1d3.c732
-rw-r--r--spectro/i1d3.h13
-rw-r--r--spectro/i1disp.c35
-rw-r--r--spectro/i1pro.c33
-rw-r--r--spectro/i1pro_imp.c1703
-rw-r--r--spectro/i1pro_imp.h39
-rw-r--r--spectro/icoms.c134
-rw-r--r--spectro/icoms.h81
-rw-r--r--spectro/icoms_nt.c280
-rw-r--r--spectro/icoms_ux.c146
-rw-r--r--spectro/ifiles4
-rw-r--r--spectro/illumread.c115
-rw-r--r--spectro/inst.c222
-rw-r--r--spectro/inst.h114
-rw-r--r--spectro/instappsup.c13
-rw-r--r--spectro/instlib.ksh4
-rw-r--r--spectro/insttypeinst.h1
-rw-r--r--spectro/insttypes.c19
-rw-r--r--spectro/insttypes.h6
-rw-r--r--spectro/linear.cal514
-rw-r--r--spectro/madvrwin.c589
-rw-r--r--spectro/madvrwin.h37
-rw-r--r--spectro/munki.c36
-rw-r--r--spectro/munki_imp.c1263
-rw-r--r--spectro/munki_imp.h45
-rw-r--r--spectro/oemarch.c562
-rw-r--r--spectro/oemarch.h4
-rw-r--r--spectro/oeminst.c6
-rw-r--r--spectro/spec2cie.c1
-rw-r--r--spectro/specbos.c1674
-rw-r--r--spectro/specbos.h160
-rw-r--r--spectro/spotread.c206
-rw-r--r--spectro/spyd2.c199
-rw-r--r--spectro/spyd2.h4
-rw-r--r--spectro/spyd2PLD.h2
-rw-r--r--spectro/spyd2setup.h2
-rw-r--r--spectro/ss_imp.c2
-rw-r--r--spectro/strange.cal514
-rw-r--r--spectro/synthread.c3
-rw-r--r--spectro/usbio.c159
-rw-r--r--spectro/usbio.h65
-rw-r--r--spectro/usbio_bsd.c764
-rw-r--r--spectro/usbio_lusb.c897
-rw-r--r--spectro/usbio_lx.c107
-rw-r--r--spectro/usbio_nt.c39
-rw-r--r--spectro/usbio_ox.c26
-rw-r--r--spectro/webwin.c99
-rw-r--r--spectro/webwin.h7
-rw-r--r--target/ofps.c6
-rw-r--r--target/printtarg.c242
-rw-r--r--target/targen.c747
-rw-r--r--target/targen.h1
-rw-r--r--ttbd.txt33
-rw-r--r--tweak/refine.c3
-rw-r--r--ucmm/ucmm.c24
-rw-r--r--usb/55-Argyll.rules2
-rw-r--r--usb/ArgyllCMS.catbin165 -> 3299 bytes
-rw-r--r--usb/ArgyllCMS.inf426
-rw-r--r--usb/ArgyllCMS.inf.d68
-rw-r--r--usb/ArgyllCMS.inf.t222
-rw-r--r--usb/ArgyllCMS_x64.catbin165 -> 3283 bytes
-rw-r--r--usb/Jamfile8
-rw-r--r--usb/Readme.txt3
-rw-r--r--usb/afiles1
-rw-r--r--usb/makecat.bat13
-rw-r--r--xicc/cam02.c94
-rw-r--r--xicc/cam02.h41
-rw-r--r--xicc/cam02plot.c6
-rw-r--r--xicc/cam02ref.h60
-rw-r--r--xicc/cam02test.c24
-rw-r--r--xicc/ccss.c14
-rw-r--r--xicc/iccgamut.c52
-rw-r--r--xicc/monctest.c5
-rw-r--r--xicc/moncurve.c13
-rw-r--r--xicc/mpp.h2
-rw-r--r--xicc/mpplu.c4
-rw-r--r--xicc/revfix.c18
-rw-r--r--xicc/specplot.c6
-rw-r--r--xicc/tiffgamut.c65
-rw-r--r--xicc/tiffgmts.c41
-rw-r--r--xicc/transplot.c68
-rw-r--r--xicc/xcal.c98
-rw-r--r--xicc/xcal.h7
-rw-r--r--xicc/xcam.c13
-rw-r--r--xicc/xcam.h3
-rw-r--r--xicc/xcolorantslu.c2
-rw-r--r--xicc/xfit.c261
-rw-r--r--xicc/xfit.h5
-rw-r--r--xicc/xicc.c466
-rw-r--r--xicc/xicc.h52
-rw-r--r--xicc/xicclu.c774
-rw-r--r--xicc/xlut.c73
-rw-r--r--xicc/xlutfix.c9
-rw-r--r--xicc/xmatrix.c205
-rw-r--r--xicc/xmono.c2
-rw-r--r--xicc/xspect.c2452
-rw-r--r--xicc/xspect.h78
-rw-r--r--ziparch.sh12
254 files changed, 41700 insertions, 15564 deletions
diff --git a/Jambase b/Jambase
index 6ee19eb..d96c40b 100644
--- a/Jambase
+++ b/Jambase
@@ -67,6 +67,8 @@
# make custom file, program dependent & args not
# GenFileNND target : program args : extra_dependecies ;
# make custom file, program & args not dependent
+# GenFileNNDnc target : program args : extra_dependecies ;
+# Same as GenFileNND but don't clean the target.
# CatToFile dest : strings ; save the arguments to the file
# GuiBin image ; Mark executable as GUI applications
# (Needs to go before other declarations of image)
@@ -510,7 +512,7 @@ if $(NT)
}
else if $(MSVCNT) || $(MSVCDIR) || $(MSVCDir) || $(VCINSTALLDIR)
{
- # Visual C++ 8.0/9.0 uses VCINSTALLDIR
+ # Visual C++ 8.0/9.0/10.0 uses VCINSTALLDIR
# We assume VC++ Express + XP32 SDK has been setup
# Visual C++ 6.0 uses MSVCDIR
@@ -523,17 +525,20 @@ if $(NT)
MSVCNT ?= $(MSVCDIR) ;
}
- if $(COMPILER) = MSVCPP10 {
+ if [ MATCH 11\\.(.*) : $(VisualStudioVersion) ] {
+ ECHO "Compiler is VC++11 32 bit" ;
+ MSVCVER = 11 ;
+ } else if [ MATCH (.*)VC\\+\\+10(.*) : $(MSVCNT) ] {
ECHO "Compiler is VC++10 32 bit" ;
MSVCVER = 10 ;
- } else if $(COMPILER) = MSVCPP9 {
+ } else if [ MATCH (.*)VC\\+\\+9(.*) : $(MSVCNT) ] {
ECHO "Compiler is VC++9 32 bit" ;
MSVCVER = 9 ;
- } else if $(COMPILER) = MSVCPP8 {
+ } else if [ MATCH (.*)VC\\+\\+8(.*) : $(MSVCNT) ] {
ECHO "Compiler is VC++8 32 bit" ;
MSVCVER = 8 ;
} else {
- ECHO "Compiler is VC++ 32 bit" ;
+ ECHO "Compiler is VC++6 32 bit" ;
MSVCVER = 6 ;
}
@@ -2541,6 +2546,32 @@ rule GenFileNND1
MakeLocate $(<) ;
}
+# GenFileNNDnc target : program args : extra_dependecies ;
+# Same as GenFileNND but don't clean the target.
+# None of > is assumed to be a file.
+# $(3) are optional extra dependecies
+# SRCDIR and DSTDIR are ignored.
+rule GenFileNNDnc
+{
+#Echo "GenFileNNDnc got '$(<)' and '$(>)' and src targets '$(3)' " ;
+ # Normalize target names and set Grist LOCATE and SOURCE
+ local _t = [ NormIDstTargets $(<) ] ;
+ local _a = $(>) ;
+ _a = $(_a:J=" ") ; # Split up by space delimeter ?
+ local _d = [ NormSrcTargets $(3) ] ;
+
+#Echo "GenFileNNDnc normed '$(_t)' plus '$(_a)' and src targets '$(_d)'" ;
+
+ Depends files : $(_t) ;
+ Depends $(_t) : $(_d) ;
+
+ NotTargets $(_a) ;
+ NoCare $(_a) ;
+ NotFile $(_a) ; # Supresses "independent target", but may mark a directory wrongly
+
+ GenFileNND1 $(_t) : $(_a) ;
+}
+
# Concatenate all the argument to the file
# Each argument to a separate line
# If no arguments, create empty file
@@ -3064,22 +3095,22 @@ rule ShLibraryFromObjects
#Echo "ShLibraryFromObjects SHLINKOBJS = '" $(SHLINKOBJS) "' and P_SHLINKOBJS ='" $(P_SHLINKOBJS) "'" ;
if $(SHLINKOBJS) || $(P_SHLINKOBJS) {
local _o = [ NormSrcTargets $(SHLINKOBJS:S=$(SUFOBJ)) ] $(P_SHLINKOBJS:S=$(SUFOBJ)) ;
- Depends $(_t) : $(_o) ;
- SHLINKOBJS on $(_t) += $(_o) ;
+ Depends $(_sl) : $(_o) ;
+ SHLINKOBJS on $(_sl) += $(_o) ;
}
#Echo "ShLibraryFromObjects SHLINKLIBS = '" $(SHLINKLIBS) "' and P_SHLINKLIBS ='" $(P_SHLINKLIBS) "'" ;
if $(SHLINKLIBS) || $(P_SHLINKLIBS) {
local _l = [ NormSrcTargets $(SHLINKLIBS:S=$(SUFLIB)) ] $(P_SHLINKLIBS:S=$(SUFLIB)) ;
- Depends $(_t) : $(_l) ;
- SHLINKLIBS on $(_t) += $(_l) ;
+ Depends $(_sl) : $(_l) ;
+ SHLINKLIBS on $(_sl) += $(_l) ;
}
#Echo "ShLibraryFromObjects SHLINKSHLIBS = '" $(SHLINKSHLIBS) "' and P_SHLINKSHLIBS ='" $(P_SHLINKSHLIBS) "'" ;
if $(SHLINKSHLIBS) || $(P_SHLINKSHLIBS) {
local _l = [ NormSrcTargets $(SHLINKSHLIBS:S=$(SUFSHLIB)) ] $(P_SHLINKSHLIBS:S=$(SUFSHLIB)) ;
- Depends $(_t) : $(_l) ;
- SHLINKSHLIBS on $(_t) += $(_l) ;
+ Depends $(_sl) : $(_l) ;
+ SHLINKSHLIBS on $(_sl) += $(_l) ;
}
if $(SHLINKDEFFILE) { # Windows special option
@@ -4098,7 +4129,7 @@ if $(OS) = MACOSX { # OS X version of ld
# Link .o and .a into a .dylib
# gcc -dynamiclib -Wl,-headerpad_max_install_names,-undefined,dynamic_lookup,-compatibility_version,1.0,-current_version,1.0,-install_name,/usr/local/lib/libfoo.1.dylib -o libfoo.1.dylib $(OBJ)
# -Wl,-install_name,@executable_path ???
- actions ShLink_
+ actions ShLink_ bind SHLINKOBJS SHLINKLIBS SHLINKSHLIBS
{
$(LINK) -dynamiclib -Wl,-undefined,dynamic_lookup,-install_name,$(SHLINKSEARCHEXEPATH)$(<[1]:BS) $(LINKOUTFLAG)$(<[1]) $(>) $(SHLINKOBJS) $(SHLINKLIBS) $(SHLINKSHLIBS) $(SHLINKFLAGS) $(SHSTDLIBS)
}
@@ -4111,7 +4142,7 @@ if $(OS) = MACOSX { # OS X version of ld
# or set /etc/ld.so.conf.d/*.conf
# To set .so search path (after flag): -Wl,-soname=$(<[1]:BS)
# Old: $(LINK) -shared -Wl,-soname=$(SHLINKSEARCHEXEPATH)$(<[1]:BS) $(SHLINKFLAGS) $(LINKOUTFLAG)$(<[1]) $(>) $(SHLINKOBJS) $(SHLINKLIBS) $(SHLINKSHLIBS) $(SHSTDLIBS)
- actions ShLink_
+ actions ShLink_ bind SHLINKOBJS SHLINKLIBS SHLINKSHLIBS
{
$(LINK) -shared -Wl,-soname=$(SHLINKSEARCHEXEPATH)$(<[1]:BS) $(LINKOUTFLAG)$(<[1]) $(>) $(SHLINKOBJS) $(SHLINKLIBS) $(SHLINKSHLIBS) $(SHLINKFLAGS) $(SHSTDLIBS)
}
diff --git a/Jamfile b/Jamfile
index 1e38a48..5cb66cb 100644
--- a/Jamfile
+++ b/Jamfile
@@ -39,7 +39,7 @@ if ! $(HAVE_JPEG) {
SubInclude jpg ;
}
-if ! $(USE_NATIVE_USB) {
+if $(USE_LIBUSB) = true {
if $(USE_LIBUSB1) = true {
SubInclude libusb1 ;
@@ -62,6 +62,3 @@ if $(UNIX) && $(OS) != MACOSX {
SubInclude ucmm ;
}
-if $(OS) = FREEBSD || $(OS) = OPENBSD {
- SubInclude libusb ;
-}
diff --git a/Jamtop b/Jamtop
index 1809c9d..3ba306b 100644
--- a/Jamtop
+++ b/Jamtop
@@ -27,20 +27,20 @@ DEFINES += ARGYLLCMS ;
# enable serial instruments & support
USE_SERIAL = true ;
+# enable fast serial instruments & support
+USE_FAST_SERIAL = true ; # (Implicit in USE_SERIAL too)
+
# enable USB instruments & support
USE_USB = true ;
-# Use native USB drivers, else use libusb
-USE_NATIVE_USB = true ;
+# enable dummy Demo Instrument, if code is available
+USE_DEMOINST = true ;
-# Use libusb1 rather than libusb0 & libusb0-win32
-USE_LIBUSB1 = true ;
+# Use libusb (deprecated)
+USE_LIBUSB = false ;
-# Except that FreeBSD doesn't have a spectro/usbio_bsd.c yet
-if $(OS) = FREEBSD || $(OS) = OPENBSD {
- USE_NATIVE_USB = false ; # Use libusb
- USE_LIBUSB1 = false ; # Use libusb 0.1
-}
+# Use libusb1 rather than libusb0 & libusb0-win32 (deprecated)
+USE_LIBUSB1 = true ;
# Make the USB V1 library static
LIBUSB_IS_DLL = false ;
diff --git a/Readme.txt b/Readme.txt
index f1b9cb5..f111a1d 100644
--- a/Readme.txt
+++ b/Readme.txt
@@ -1,8 +1,8 @@
-Argyll CMS README file - Version 1.5.0
+Argyll CMS README file - Version 1.6.3
--------------------------------------
-Date: 8th March 2013
+Date: 26th January 2014
Author: Graeme Gill
Introduction
@@ -10,12 +10,13 @@ Introduction
ArgyllCMS is an ICC compatible color management system, available as Open Source.
It supports accurate ICC profile creation for scanners, cameras and film
recorders, and calibration and profiling of displays and RGB & CMYK printers.
-Spectral sample data is supported, allowing a selection of illuminants observer
-types, and paper fluorescent whitener additive compensation. Profiles can also
-incorporate source specific gamut mappings for perceptual and saturation intents.
-Gamut mapping and profile linking uses the CIECAM02 appearance model, a unique
-gamut mapping algorithm, and a wide selection of rendering intents. Device Link
-can be created with a wide variety of advanced options. It also includes code for
+Device Link can be created with a wide variety of advanced options, including
+specialized Video calibration standards and 3dLuts. Spectral sample data is
+supported, allowing a selection of illuminants observer types, and paper
+fluorescent whitener additive compensation. Profiles can also incorporate source
+specific gamut mappings for perceptual and saturation intents. Gamut mapping and
+profile linking uses the CIECAM02 appearance model, a unique gamut mapping algorithm,
+and a wide selection of rendering intents. It also includes code for
the fastest portable 8 bit raster color conversion engine available anywhere, as
well as support for fast, fully accurate 16 bit conversion. Device color gamuts
can also be viewed and compared using a VRML viewer. Comprehensive documentation
@@ -23,7 +24,7 @@ is provided for each major tool, and a general guide to using the tools for typi
color management tasks is also available. A mailing list provides support for
more advanced usage.
-This is Version 1.5.1, a bug fix update to V1.5.0 released on 1st March 2013.
+This is Version 1.6.3, a bug fix update to V1.6.2 released on 18th November 2013.
The first public release of icclib was in November 1998,
and of Argyll was in October 2000. Code development commenced in 1995. See
Changes Summary for an overview of changes since the last release. Changes
diff --git a/cgats/cgats.c b/cgats/cgats.c
index baf9992..84ff2c9 100644
--- a/cgats/cgats.c
+++ b/cgats/cgats.c
@@ -14,6 +14,34 @@
* see the License.txt file in this directory for licensing details.
*/
+/*
+
+ Should add a function to promote a field type, ie.
+ promote integer to float, to avoid misrecognition
+ problems.
+
+
+ To make this more portable for independent use,
+ should save/set/restore LC_NUMERIC locale before
+ printf/scanf from file. e.g.
+
+ include <locale.h>
+ char *old_locale, *saved_locale;
+
+ old_locale = setlocale (LC_NUMERIC, NULL);
+ saved_locale = strdup (old_locale);
+ if (saved_locale == NULL)
+ error ("Out of memory");
+ setlocale (LC_NUMERIC, "C");
+
+ .... read or write ...
+
+ setlocale (LC_NUMERIC, saved_locale);
+ free (saved_locale);
+
+ Also apply to pars.c
+ */
+
#define _CGATS_C_ /* Turn on implimentation code */
#include <stdio.h>
@@ -23,8 +51,8 @@
#undef DEBUG /* Debug only in slected places */
#ifdef DEBUG
-# define DBGA g_log, 0 /* First argument to DBGF() */
-# define DBGF(xx) a1logd xx
+# define DBGA stderr
+# define DBGF(xx) fprintf xx
#else
# define DBGF(xx)
#endif
@@ -40,7 +68,7 @@ extern void error(const char *fmt, ...), warning(const char *fmt, ...);
#include "pars.h"
#include "cgats.h"
-#define REAL_SIGDIG 5 /* Number of significant digits in real representation */
+#define REAL_SIGDIG 6 /* Number of significant digits in real representation */
static int cgats_read(cgats *p, cgatsFile *fp);
static int find_kword(cgats *p, int table, const char *ksym);
@@ -374,6 +402,14 @@ cgats_read(cgats *p, cgatsFile *fp) {
if (tp == NULL)
break; /* EOF */
+ /* This seems unlikely and will cause err() to barf */
+ if (strlen(tp) > CGATS_ERRM_LENGTH/2) {
+ tp[CGATS_ERRM_LENGTH/2] = '\000';
+ err(p,-1,"Read line got symbol '%s' that's too long\n",tp);
+ pp->del(pp);
+ return p->errc;
+ }
+
switch(rstate) {
case R_IDENT: /* Expecting file identifier */
case R_KWORDS: { /* Expecting keyword, field def or data */
@@ -938,16 +974,19 @@ add_field(cgats *p, int table, const char *fsym, data_type ftype) {
p->errc = 0;
p->err[0] = '\000';
- if (table < 0 || table >= p->ntables)
+ if (table < 0 || table >= p->ntables) {
return err(p,-1,"cgats.add_field(), table parameter out of range");
+ }
t = &p->t[table];
- if (t->nsets != 0)
+ if (t->nsets != 0) {
return err(p,-1,"cgats.add_field(), attempt to add field to non-empty table");
+ }
/* Check the field name is reasonable */
- if (cs_has_ws(fsym))
+ if (cs_has_ws(fsym)) {
return err(p,-1,"cgats.add_kword(), field name '%s'is illegal",fsym);
+ }
if (ftype == none_t)
ftype = cs_t; /* Fudge - unknown type yet, used for reads */
@@ -956,22 +995,27 @@ add_field(cgats *p, int table, const char *fsym, data_type ftype) {
st = standard_field(fsym);
if (st == nqcs_t && ftype == cs_t) /* Fudge - standard type to non-quoted if normal */
ftype = nqcs_t;
- if (st != none_t && st != ftype)
+ if (st != none_t && st != ftype) {
return err(p,-1,"cgats.add_field(): unexpected data type for standard field name");
+ }
}
t->nfields++;
if (t->nfields > t->nfieldsa) {
- /* Allocate fields in groups of 4 */
- t->nfieldsa += 4;
- if ((t->fsym = (char **)al->realloc(al, t->fsym, t->nfieldsa * sizeof(char *))) == NULL)
+ /* Allocate fields in groups of 32 */
+ t->nfieldsa += 32;
+ if ((t->fsym = (char **)al->realloc(al, t->fsym, t->nfieldsa * sizeof(char *))) == NULL) {
return err(p,-2,"cgats.add_field(), realloc failed!");
+ }
if ((t->ftype = (data_type *)al->realloc(al, t->ftype, t->nfieldsa * sizeof(data_type)))
- == NULL)
+ == NULL) {
return err(p,-2,"cgats.add_field(), realloc failed!");
+ }
}
- if ((t->fsym[t->nfields-1] = (char *)alloc_copy_data_type(al, cs_t, (void *)fsym)) == NULL)
+ if ((t->fsym[t->nfields-1] = (char *)alloc_copy_data_type(al, cs_t, (void *)fsym)) == NULL) {
return err(p,-2,"cgats.alloc_copy_data_type() malloc fail");
+ }
+
t->ftype[t->nfields-1] = ftype;
return t->nfields-1;
diff --git a/cgats/cgats.h b/cgats/cgats.h
index 2a6b1fd..7537a48 100644
--- a/cgats/cgats.h
+++ b/cgats/cgats.h
@@ -20,7 +20,7 @@
#define CGATSLIB_VERSION 0x020005
#define CGATSLIB_VERSION_STR "2.05"
-#define CGATS_ERRM_LENGTH 200
+#define CGATS_ERRM_LENGTH 2000
#ifdef __cplusplus
extern "C" {
diff --git a/cgats/pars.c b/cgats/pars.c
index 606957c..a0e694c 100644
--- a/cgats/pars.c
+++ b/cgats/pars.c
@@ -41,6 +41,8 @@ extern void error(const char *fmt, ...), warning(const char *fmt, ...);
#include "pars.h"
+#undef DEBUG /* Print each token returned */
+
static void del_parse(parse *p);
static int read_line(parse *p);
static void reset_del(parse *p);
@@ -420,6 +422,9 @@ read_line(parse *p) {
if ((c = p->fp->getch(p->fp)) == EOF) {
if (p->bo == 0) { /* If there is nothing in the buffer */
p->line = 0;
+#ifdef DEBUG
+ printf("pars: read_line() got EOF\n");
+#endif
return 0;
}
c = 0; /* Finish the line */
@@ -443,16 +448,16 @@ read_line(parse *p) {
}
if (c == '\r') {
- p->line++; /* Increment line number */
+ p->line++; /* Increment line number */
p->ltflag = 1; /* Remember to allow 1 of '\n' before next line */
if (p->q == 0)
- c = 0; /* Finish the line */
+ c = 0; /* Finish the line */
} else if (p->q == 0 && (p->delf[c] & PARS_COMM) != 0) { /* Hit a comment */
- p->line++; /* Increment line number */
+ p->line++; /* Increment line number */
p->ltflag = 2; /* Remember to flush all chars up to end of line */
- c = 0; /* Finish the line */
+ c = 0; /* Finish the line */
} else if (c == '\n') {
- p->line++; /* Increment line number */
+ p->line++; /* Increment line number */
if (p->q == 0)
c = 0; /* Finish the the line */
}
@@ -477,6 +482,9 @@ read_line(parse *p) {
} while (c != 0); /* Null means we've done the end of the line */
p->to = 0; /* Reset token pointer to the start of the line buffer */
p->q = 0; /* Reset quoted flag */
+#ifdef DEBUG
+ printf("pars: read_line() got buffer '%s'\n",p->b);
+#endif
return 1;
}
@@ -525,8 +533,12 @@ get_token(parse *p) {
p->errc = 0; /* Reset error status */
p->err[0] = '\000';
- if (p->b == NULL)
+ if (p->b == NULL) {
+#ifdef DEBUG
+ printf("pars: read_token() NULL buffe\n");
+#endif
return NULL;
+ }
p->token++; /* Increment token number */
p->q = 0;
do {
@@ -566,8 +578,14 @@ get_token(parse *p) {
p->q = 0;
if (tbo <= 1) {
p->token = 0;
+#ifdef DEBUG
+ printf("pars: read_token() got nothing useful\n");
+#endif
return NULL; /* Haven't read anything useful */
}
+#ifdef DEBUG
+ printf("pars: read_token() returning '%s'\n",p->tb);
+#endif
return p->tb;
}
diff --git a/doc/ArgyllDoc.html b/doc/ArgyllDoc.html
index 498e974..98e730d 100644
--- a/doc/ArgyllDoc.html
+++ b/doc/ArgyllDoc.html
@@ -1,119 +1,140 @@
-<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
-<html>
- <head>
- <meta http-equiv="Content-Type" content="text/html;
- charset=ISO-8859-1">
- <meta name="author" content="Graeme Gill">
- <meta name="description" content="Root of Argyll CMS documentation">
- <meta name="GENERATOR" content="Mozilla/4.73 [en] (WinNT; I)
- [Netscape]">
- <title>Argyll Documentation Top</title>
- </head>
- <body>
- <h1> Argyll CMS documentation index (V1.5.1)<br>
- </h1>
- Date:&nbsp;&nbsp; 8th March 2013<br>
- Author: Graeme Gill
- <h2><u><a name="Intro"></a>Introduction</u></h2>
- ArgyllCMS is an ICC compatible color management system, available as
- Open Source. It supports accurate ICC profile creation for scanners,
- cameras and film recorders, and calibration and profiling of
- displays and RGB &amp; CMYK printers. Spectral sample data is
- supported, allowing a selection of illuminants observer types, and
- paper fluorescent whitener additive compensation. Profiles can also
- incorporate source specific gamut mappings for perceptual and
- saturation intents. Gamut mapping and profile linking uses the
- CIECAM02 appearance model, a unique gamut mapping algorithm, and a
- wide selection of rendering intents. Device Link can be created with
- a wide variety of advanced options. It also includes code for the
- fastest portable 8 bit raster color conversion engine available
- anywhere, as well as support for fast, fully accurate 16 bit
- conversion. Device color gamuts can also be viewed and compared
- using a VRML viewer. Comprehensive documentation is provided for
- each major tool, and a general guide to using the tools for typical
- color management tasks is also available. A mailing list provides
- support for more advanced usage.<br>
- <p>This is Version 1.5.1, a bug fix and feature update to V1.5.0
- released on 1st March 2013. The first public release of icclib was
- in November 1998, and of Argyll was in October 2000. Code
- development commenced in 1995. See <a href="ChangesSummary.html">Changes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Summary</a> for an overview of changes since the last release.
- Changes between revisions is detailed in the <b>log.txt</b> file
- that accompanies the source code. </p>
- <p>The latest source code is available from <a
- href="http://www.argyllcms.com/">here</a>.<br>
- </p>
- <h2><a href="ColorManagement.html">An Introduction to Color
- Management</a></h2>
- A <a href="ColorManagement.html">concise discussion</a> of what
- color management is, and why we need it, together with a brief
- overview of the ICC profile format.<br>
- <h2 style="text-decoration: underline;">Operating Environments</h2>
- <h2> </h2>
- <p>Argyll is known to compile and run in at least the following
- environments: </p>
- 1) MSWindows XP system using Microsoft VC++ 6.0 compiler<br>
- 2) MSWindows XP system using Microsoft VC++ 8.0 Express compiler +
- Platform SDK Feb. 2003<br>
- 3) MSWindows XP system using Microsoft VC++ 9.0 Express compiler +
- Platform SDK Feb. 2003<br>
- 4) MSWindows XP system using the MingW port of the GCC compiler<br>
- 5) Linux on Fedora Core 8, 32 bit using gcc <br>
- 6) Linux on Fedora Core 8, 64 bit using gcc<br>
- 7) Apple OS X 10.3 PPC using GCC<br>
- 8) Apple OS X 10.4, 10.5, 10.6 Intel using GCC<br>
- 9) Apple OS X10.7 Intel using&nbsp; Clang<br>
- 10) PCBSD 9.1 (FreeBSD) [You need to copy the libusb sub directory
- from ArgyllCMS V1.4.0]<br>
- <br>
- Additionally it is also known to run on:<br>
- <br>
- &nbsp;MSWindows 2000, Vista &amp; Windows 7 32 bit.<br>
- &nbsp;MSWindows Vista 64bit, Windows 7 64bit &amp; Windows 8 64 bit.<br>
- &nbsp;Linux Ubuntu 7.10<br>
- &nbsp;Linux Kubuntu 7.10<br>
- &nbsp;Linux Mandriva 2008.0<br>
- &nbsp;Linux OpenSuSE 10.3<br>
- &nbsp;Linux Whitebox 4.2/2<br>
- <p>but may well compile and run correctly in many more than this,
- including OS X 10.8. </p>
- This is a <span style="font-weight: bold;">command line terminal</span>
- only environment. Those unfamiliar with command line environments
- should consult an appropriate tutorial for their environment if they
- are interested in using this software. See the listing of <a
- href="#cltutes">tutorials</a> below.<span style="font-weight:
- bold;"></span><br>
- <br>
- The following color measuring instruments are directly supported:<br>
- <br>
- X-Rite:<br>
+<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;
+ charset=windows-1252">
+ <meta name="author" content="Graeme Gill">
+ <meta name="description" content="Root of Argyll CMS documentation">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en] (WinNT; I)
+ [Netscape]">
+ <title>Argyll Documentation Top</title>
+ </head>
+ <body>
+ <h1> Argyll CMS documentation index (V1.6.3)<br>
+ </h1>
+ Date:&nbsp;&nbsp; 26th January 2014<br>
+ Author: Graeme Gill
+ <h2><u><a name="Intro"></a>Introduction</u></h2>
+ ArgyllCMS is an ICC compatible color management system, available as
+ Open Source. It supports accurate ICC profile creation for scanners,
+ cameras and film recorders, and calibration and profiling of
+ displays and RGB &amp; CMYK printers. Device Link can be created
+ with a wide variety of advanced options, including specialized Video
+ calibration standards&nbsp; and 3dLuts. Spectral sample data is
+ supported, allowing a selection of illuminants observer types, and
+ paper fluorescent whitener additive compensation. Profiles can also
+ incorporate source specific gamut mappings for perceptual and
+ saturation intents. Gamut mapping and profile linking uses the
+ CIECAM02 appearance model, a unique gamut mapping algorithm, and a
+ wide selection of rendering intents. It also includes code for the
+ fastest portable 8 bit raster color conversion engine available
+ anywhere, as well as support for fast, fully accurate 16 bit
+ conversion. Device color gamuts can also be viewed and compared
+ using a VRML viewer. Comprehensive documentation is provided for
+ each major tool, and a general guide to using the tools for typical
+ color management tasks is also available. A mailing list provides
+ support for more advanced usage.<br>
+ <p>This is Version 1.6.3, a bug fix update to V1.6.2 released on 8th
+ November 2013. The first public release of icclib was in November
+ 1998, and of Argyll was in October 2000. Code development
+ commenced in 1995. See <a href="ChangesSummary.html">Changes
+ Summary</a> for an overview of changes since the last release.
+ Changes between revisions is detailed in the <b>log.txt</b> file
+ that accompanies the source code. </p>
+ <p>The latest source code is available from <a
+ href="http://www.argyllcms.com/">here</a>.<br>
+ </p>
+ <h2><a href="ColorManagement.html">An Introduction to Color
+ Management</a></h2>
+ <p>A great introduction for non technical people is Steve Upton's <a
+ href="http://www.colorwiki.com/wiki/The_Color_of_Toast">The
+ Color of Toast</a>.<br>
+ </p>
+ I present here a more technical but <a href="ColorManagement.html">concise
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ discussion</a> of what color management is, and why we need it,
+ together with a brief overview of the ICC profile format.<br>
+ <br>
+ <h2 style="text-decoration: underline;">Operating Environments</h2>
+ <h2> </h2>
+ <p>Argyll is known to compile and run in at least the following
+ environments: </p>
+ 1) MSWindows XP system using Microsoft VC++ 6.0 compiler<br>
+ 2) MSWindows XP system using Microsoft VC++ 8.0 Express compiler +
+ Platform SDK Feb. 2003<br>
+ 3) MSWindows XP system using Microsoft VC++ 9.0 Express compiler +
+ Platform SDK Feb. 2003<br>
+ 4) MSWindows XP system using Microsoft VC++ 10.0 Express compiler +
+ Platform SDK Feb. 2003<br>
+ 5) MSWindows XP system using Microsoft VC++ 11.0 Express compiler<br>
+ 6) MSWindows XP system using the MingW port of the GCC compiler<br>
+ 7) Linux on Fedora Core 8, 32 bit using gcc <br>
+ 8) Linux on Fedora Core 8, 64 bit using gcc<br>
+ 9) Apple OS X 10.3 PPC using GCC<br>
+ 10) Apple OS X 10.4, 10.5, 10.6 Intel using GCC<br>
+ 11) Apple OS X10.7 Intel using&nbsp; Clang<br>
+ <br>
+ Additionally it is also known to run on:<br>
+ <br>
+ &nbsp;MSWindows 2000, Vista &amp; Windows 7 32 bit.<br>
+ &nbsp;MSWindows Vista 64bit, Windows 7, 8, 8.1 64 bit.<br>
+ &nbsp;Linux Ubuntu 7.10<br>
+ &nbsp;Linux Kubuntu 7.10<br>
+ &nbsp;Linux Mandriva 2008.0<br>
+ &nbsp;Linux OpenSuSE 10.3<br>
+ &nbsp;Linux Whitebox 4.2/2<br>
+ <p>but may well compile and run correctly in many more than this,
+ including OS X 10.8. </p>
+ This is a <span style="font-weight: bold;">command line terminal</span>
+ only environment. Those unfamiliar with command line environments
+ should consult an appropriate tutorial for their environment if they
+ are interested in using this software. See the listing of <a
+ href="#cltutes">tutorials</a> below.<span style="font-weight:
+ bold;"></span><br>
+ <br>
+ The following color measuring instruments are directly supported:<br>
+ <br>
+ JETI:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#specbos">specbos 1211
+ &amp; 1201</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - Tele-Spectro-Radiometer<br>
+ <br>
+ X-Rite:<br>
&nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP20">DTP20 "Pulse"</a>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -156,8 +177,29 @@
- - "swipe" type reflective spectrometer, that can be used untethered.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP22">DTP22 Digital
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - "swipe" type reflective spectrometer, that can be used untethered.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP22">DTP22 Digital
Swatchbook</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -199,7 +241,28 @@
- - spot type reflective spectrometer.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - spot type reflective spectrometer.<br>
&nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP41">DTP41</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -241,9 +304,30 @@
- - spot and strip reading reflective spectrometer.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP41">DTP41T</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - spot and strip reading reflective spectrometer.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP41">DTP41T</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -285,7 +369,28 @@
- - spot and strip reading reflective/transmissive spectrometer.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - spot and strip reading reflective/transmissive spectrometer.<br>
&nbsp;&nbsp;&nbsp; <a href="instruments.html#dtp51">DTP51</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -327,7 +432,28 @@
- - strip reading reflective colorimeter.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - strip reading reflective colorimeter.<br>
&nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP92">DTP92</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -369,68 +495,89 @@
- - CRT display colorimeter.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP94">DTP94</a> <font
- size="-1">"Optix XR"</font> or "Optix XR2" or "Optix Pro"- display
- colorimeter.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#ColorMunki"><span
- style="text-decoration: underline;">ColorMunki</span></a> Design
- or Photo&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
- spot and "swipe" reflective/emissive spectrometer (UV cut only).<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d"><span
- style="text-decoration: underline;">ColorMunki</span></a> Create
- or Smile&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
- colorimeter. (Similar to an Eye-One Display 2)<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#Huey">Lenovo W</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -
- built in laptop Huey display colorimeter.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d3">Eye-One Display
- 3</a> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; - Xrite i1 DisplayPro and ColorMunki
- Display <br>
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [ The OEM
- i1Display Pro, NEC SpectraSensor Pro and<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp;&nbsp; Quato Silver Haze 3 OEM i1d3 are also
- reported to work.]<br>
- &nbsp; &nbsp; <a href="instruments.html#i1p2">Eye-One Pro2</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; - spot and
- "swipe" reflective/emissive spectrometer.<br>
- <br>
- Gretag-Macbeth (now X-Rite):<br>
- &nbsp; &nbsp; <a href="instruments.html#sl">Spectrolino</a> &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot
- reflective/emissive spectrometer.<br>
- &nbsp; &nbsp; <a href="instruments.html#ss">SpectroScan</a> &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot
- reflective/emissive, XY table reflective spectrometer&nbsp; .<br>
- &nbsp; &nbsp; <a href="instruments.html#ss">SpectroScanT</a> &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot
- reflective/emissive/transmissive, XY table reflective spectrometer.<br>
- &nbsp; &nbsp; <a href="instruments.html#i1p">Eye-One Pro</a> "EFI
- ES-1000" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe"
- reflective/emissive spectrometer.<br>
- &nbsp; &nbsp; <a href="instruments.html#i1m">Eye-One Monitor</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe" emissive
- spectrometer.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">Eye-One Display 1
- or 2&nbsp; or LT</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
- display colorimeter.<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">HP DreamColor or
- APS</a>&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - CRT display colorimeter.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#DTP94">DTP94</a> <font
+ size="-1">"Optix XR"</font> or "Optix XR2" or "Optix Pro"- display
+ colorimeter.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#ColorMunki"><span
+ style="text-decoration: underline;">ColorMunki</span></a> Design
+ or Photo&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
+ spot and "swipe" reflective/emissive spectrometer (UV cut only).<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d"><span
+ style="text-decoration: underline;">ColorMunki</span></a> Create
+ or Smile&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
+ colorimeter. (Similar to an Eye-One Display 2)<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#Huey">Lenovo W</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -
+ built in laptop Huey display colorimeter.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d3">Eye-One Display
+ 3</a> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; - Xrite i1 DisplayPro and ColorMunki
+ Display <br>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [ The OEM
+ i1Display Pro, NEC SpectraSensor Pro,<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;&nbsp; Quato Silver Haze 3 OEM and HP
+ DreamColor&nbsp; i1d3 are also reported to work.]<br>
+ &nbsp; &nbsp; <a href="instruments.html#i1p2">Eye-One Pro2</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; - spot and
+ "swipe" reflective/emissive spectrometer.<br>
+ <br>
+ Gretag-Macbeth (now X-Rite):<br>
+ &nbsp; &nbsp; <a href="instruments.html#sl">Spectrolino</a> &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot
+ reflective/emissive spectrometer.<br>
+ &nbsp; &nbsp; <a href="instruments.html#ss">SpectroScan</a> &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot
+ reflective/emissive, XY table reflective spectrometer&nbsp; .<br>
+ &nbsp; &nbsp; <a href="instruments.html#ss">SpectroScanT</a> &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot
+ reflective/emissive/transmissive, XY table reflective spectrometer.<br>
+ &nbsp; &nbsp; <a href="instruments.html#i1p">Eye-One Pro</a> "EFI
+ ES-1000" &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe"
+ reflective/emissive spectrometer.<br>
+ &nbsp; &nbsp; <a href="instruments.html#i1m">Eye-One Monitor</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe" emissive
+ spectrometer.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">Eye-One Display 1
+ or 2&nbsp; or LT</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
+ display colorimeter.<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">HP DreamColor or
+ APS</a>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -472,8 +619,29 @@
- - display colorimeter. (Treated as a Eye-One Display 2)<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">CalMAN X2</a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - display colorimeter. (Treated as a Eye-One Display 2)<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">CalMAN X2</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -515,17 +683,38 @@
- - display colorimeter. (Treated as a Eye-One Display 2)<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#Huey">Huey</a> &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter.<br>
- <br>
- Sequel imaging (Now X-Rite):<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#mox">MonacoOPTIX</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
- colorimeter (Treated as an Eye-One Display 1)<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - display colorimeter. (Treated as a Eye-One Display 2)<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#Huey">Huey</a> &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter.<br>
+ <br>
+ Sequel imaging (Now X-Rite):<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#mox">MonacoOPTIX</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
+ colorimeter (Treated as an Eye-One Display 1)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -567,9 +756,30 @@
- [The Sequel Chroma 4 may also work.]<br>
- <br>
- Lacie Blue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [The Sequel Chroma 4 may also work.]<br>
+ <br>
+ Lacie Blue
Eye:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -611,14 +821,35 @@
- - see <a href="instruments.html#i1d">Eye-One Display</a><br>
- <br>
- DataColor ColorVision:<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#spyd2">Spyder 2</a>
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
- that the user must <a href="oeminst.html">supply</a> firmware)<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - see <a href="instruments.html#i1d">Eye-One Display</a><br>
+ <br>
+ DataColor ColorVision:<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#spyd2">Spyder 2</a>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
+ that the user must <a href="oeminst.html">supply</a> firmware)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -660,22 +891,53 @@
- [The Spyder 1 has also been reported as working, but this has not
- been confirmed.]<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#spyd3">Spyder 3</a>
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter.<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#spyd4">Spyder 4</a>
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
- that the user must <a href="oeminst.html">supply</a> calibration
- data)<br>
- <br>
- Other:<br>
- &nbsp;&nbsp;&nbsp; <span class="titre"><a
- href="instruments.html#HCFR">Colorim&egrave;tre HCFR</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [The Spyder 1 has also been reported as working, but this has not
+ been confirmed.]<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#spyd3">Spyder 3</a>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter.<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="instruments.html#spyd4">Spyder 4</a>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
+ that the user must <a href="oeminst.html">supply</a> calibration
+ data)<br>
+ <br>
+ Other:<br>
+ &nbsp;&nbsp;&nbsp; <span class="titre"><a
+ href="instruments.html#HCFR">Colorimètre HCFR</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
@@ -716,8 +978,6 @@
- - display colorimeter</span><br>
- &nbsp;&nbsp;&nbsp; <a href="http://www.hughski.com/">ColorHug</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -728,6 +988,9 @@
+
+ - display colorimeter</span><br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#ColorHug">ColorHug</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -743,104 +1006,133 @@
- - display colorimeter. Experimental only, does not work on all
- platforms.<br>
- <span style="font-weight: bold;"></span><span class="titre"><br>
- See </span><a href="instruments.html">Operation of particular
- instruments</a> for more instrument specific detail.<br>
- <br>
- Other instruments can be supported indirectly, since patch result
- files created by other packages can be imported into Argyll.<br>
- <br>
- Please <span style="font-weight: bold;">note</span> the <a
- href="Installing.html">installation instructions</a> for each
- platform - they contain important information for getting your
- instruments working.<br>
- <p>If you've decided to buy a color instrument because Argyll
- supports it, please let the dealer and manufacturer know that "<span
- style="font-weight: bold;">You bought it because Argyll CMS
- supports it</span>" - thanks.<br>
- </p>
- <p><span style="font-weight: bold;">Please note that instruments are
- being driven by ArgyllCMS drivers, and that any problems or
- queries regarding instrument<br>
- operation </span><span style="font-weight: bold;">should be
- directed to the Argyll's author(s) or the Argyll mailing list,
- and not to any</span> <span style="font-weight: bold;">other
- party.</span> </p>
- <p>There is a <a href="file:///D:/src/argyll/doc/ccmxs.html">list
- of contributed</a> <span style="font-weight: bold;">ccmx</span>
- (Colorimeter Correction Matrix) files for some display/colorimeter
- combinations.</p>
- <h2><span style="text-decoration: underline; color: rgb(51, 0, 51);"><a
- name="Copyright"></a>Copyright and Licensing:</span><br>
- </h2>
- <p>Most of the source code and provided executable files are
- copyrighted works, licensed under the <span style="font-weight:
- bold;">Affero GNU Version 3 license</span>, and therefore they
- (or works derived from them) can't be copied, sold or made
- available to users interacting with them remotely through a
- computer network, without providing the source code. Nothing other
- than your agreement and compliance with the Affero GNU License
- grants you permission to use, modify or distribute Argyll source
- code, executables or its derivative works. You could be sued for
- copyright infringement if you use or distribute Argyll without a
- valid license. The <span style="font-weight: bold;">Affero GNU</span>
- license <span style="font-weight: bold;">prohibits</span>
- extending these tools<span style="font-weight: bold;"></span>
- (i.e. by combining them with other programs or scripts that make
- use of, depend on, or work with the Argyll code) and distributing
- them, unless the all the elements of the extensions are also made
- available under a GPL compatible license. It is permissible to
- provide Argyll tools with other non GPL components if the elements
- of the package are not related, such that the packaging is mere
- aggregation. For all the gory details, please read the
- accompanying <a href="License.txt">license</a>. </p>
- Note that unlike many commercial ICC profiling tools, the profiles
- created using Argyll, are not subject to any claims or restrictions
- of Argyll's author(s), but are assumed to be the copyright property
- of the person who gathers the characterization data, and causes the
- profiles to be created.
- <p>The Argyll CMS is Copyright 1995 - 2013 Graeme W. Gill, and is
- made available under the terms of the Affero GNU General Public
- License Version 3, as detailed in the <a href="License.txt">License.txt</a>
- file. Documentation is licensed under the terms of the GNU Free
- Documentation License, Version 1.3. The author asserts his moral
- rights over this material in relationship to the attribution and
- integrity of these works. In particular, if these works are
- modified in a way that materially changes their functionality,
- then the modified works should be renamed in a way that clearly
- distinguishes them from "Argyll" or "ArgyllCMS" so that the
- effects of such changes do not reflect on the original works
- integrity or the original authors reputation. A subset of files
- (those that are related to the color instrument drivers, and are
- collected together into the instlib.zip archive by the
- spectro/instlib.ksh script + xicc/ccmx.h and xicc/ccmx.c) are
- licensed under the General Public License Version 2 or later, as
- detailed in the <a href="License2.txt">License2.txt</a> file.<br>
- </p>
- <p>Portions of the ColorHug instrument library
- (spectro/colorhug.[ch]) are Copyright 2011, Richard Hughes, and is
- licensed under the General Public License Version 2 or later, as
- detailed in the <a href="License2.txt">License2.txt</a> file.</p>
- <p>The tool spectro/spec2cie.c is Copyright 2005 Gerhard Fuernkranz,
- and is made available under the terms of the GNU General Public
- License Version 2 or later, and is licensed here under the Version
- 3 license, as detailed in the <a href="License3.txt">License3.txt</a>
- file.<br>
- </p>
- <p>The Win32 USB library libusb-win32 kernel drivers are included in
- this distribution in the usb/driver and usb/bin directories, and
- are copyright Stephan Meyer and Travis Robinson, and are licensed
- under the GNU Version 2 or later (the drivers, services,
- installer). See&nbsp; usb/driver/License.txt,
- libusbw/COPYING_LGPL.txt and libusbw/COPYING_GPL.txt for details.
- Additional terms noted on the <a
- href="http://sourceforge.net/apps/trac/libusb-win32/wiki">website</a>
- are "This license combination explicitly allows the use of this
- library in commercial, non-Open-Source applications."<br>
- </p>
- <p>The icc library in<span style="font-weight: bold;"> icc</span>/,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - display colorimeter<br>
+ <span style="font-weight: bold;"></span><span class="titre"><br>
+ See </span><a href="instruments.html">Operation of particular
+ instruments</a> for more instrument specific detail.<br>
+ <br>
+ Other instruments can be supported indirectly, since patch result
+ files created by other packages can be imported into Argyll.<br>
+ <br>
+ Please <span style="font-weight: bold;">note</span> the <b><a
+ href="Installing.html">installation instructions</a></b> for
+ each platform - they contain important information for getting your
+ instruments working.<br>
+ <p>If you've decided to buy a color instrument because Argyll
+ supports it, please let the dealer and manufacturer know that "<span
+ style="font-weight: bold;">You bought it because Argyll CMS
+ supports it</span>" - thanks.<br>
+ </p>
+ <p><span style="font-weight: bold;">Please note that instruments are
+ being driven by ArgyllCMS drivers, and that any problems or
+ queries regarding instrument<br>
+ operation </span><span style="font-weight: bold;">should be
+ directed to the Argyll's author(s) or the Argyll mailing list,
+ and not to any</span> <span style="font-weight: bold;">other
+ party.</span> </p>
+ <p>There is a <a href="ccmxs.html">list of contributed</a> <span
+ style="font-weight: bold;">ccmx</span> (Colorimeter Correction
+ Matrix) files for some display/colorimeter combinations.</p>
+ <h2><span style="text-decoration: underline; color: rgb(51, 0, 51);"><a
+ name="Copyright"></a>Copyright and Licensing:</span><br>
+ </h2>
+ <p>Most of the source code and provided executable files are
+ copyrighted works, licensed under the <span style="font-weight:
+ bold;">Affero GNU Version 3 license</span>, and therefore they
+ (or works derived from them) can't be copied, sold or made
+ available to users interacting with them remotely through a
+ computer network, without providing the source code. Nothing other
+ than your agreement and compliance with the Affero GNU License
+ grants you permission to use, modify or distribute Argyll source
+ code, executables or its derivative works. You could be sued for
+ copyright infringement if you use or distribute Argyll without a
+ valid license. The <span style="font-weight: bold;">Affero GNU</span>
+ license <span style="font-weight: bold;">prohibits</span>
+ extending these tools<span style="font-weight: bold;"></span>
+ (i.e. by combining them with other programs or scripts that make
+ use of, depend on, or work with the Argyll code) and distributing
+ them, unless the all the elements of the extensions are also made
+ available under a GPL compatible license. It is permissible to
+ provide Argyll tools with other non GPL components if the elements
+ of the package are not related, such that the packaging is mere
+ aggregation. For all the gory details, please read the
+ accompanying <a href="License.txt">license</a>. </p>
+ Note that unlike many commercial ICC profiling tools, the profiles
+ created using Argyll, are not subject to any claims or restrictions
+ of Argyll's author(s), but are assumed to be the copyright property
+ of the person who gathers the characterization data, and causes the
+ profiles to be created.
+ <p>The Argyll CMS is Copyright 1995 - 2013 Graeme W. Gill, and is
+ made available under the terms of the Affero GNU General Public
+ License Version 3, as detailed in the <a href="License.txt">License.txt</a>
+ file. Documentation is licensed under the terms of the GNU Free
+ Documentation License, Version 1.3. The author asserts his moral
+ rights over this material in relationship to the attribution and
+ integrity of these works. In particular, if these works are
+ modified in a way that materially changes their functionality,
+ then the modified works should be renamed in a way that clearly
+ distinguishes them from "Argyll" or "ArgyllCMS" so that the
+ effects of such changes do not reflect on the original works
+ integrity or the original authors reputation. A subset of files
+ (those that are related to the color instrument drivers, and are
+ collected together into the instlib.zip archive by the
+ spectro/instlib.ksh script + xicc/ccmx.h and xicc/ccmx.c) are
+ licensed under the General Public License Version 2 or later, as
+ detailed in the <a href="License2.txt">License2.txt</a> file.<br>
+ </p>
+ <p>Portions of the ColorHug instrument library
+ (spectro/colorhug.[ch]) are Copyright 2011, Richard Hughes, and is
+ licensed under the General Public License Version 2 or later, as
+ detailed in the <a href="License2.txt">License2.txt</a> file.</p>
+ <p>The tool spectro/spec2cie.c is Copyright 2005 Gerhard Fuernkranz,
+ and is made available under the terms of the GNU General Public
+ License Version 2 or later, and is licensed here under the Version
+ 3 license, as detailed in the <a href="License3.txt">License3.txt</a>
+ file.<br>
+ </p>
+ <p>The Win32 USB library libusb-win32 kernel drivers are included in
+ this distribution in the usb/driver and usb/bin directories, and
+ are copyright Stephan Meyer and Travis Robinson, and are licensed
+ under the GNU Version 2 or later (the drivers, services,
+ installer). See&nbsp; usb/driver/License.txt,
+ libusbw/COPYING_LGPL.txt and libusbw/COPYING_GPL.txt for details.
+ Additional terms noted on the <a
+ href="http://sourceforge.net/apps/trac/libusb-win32/wiki">website</a>
+ are "This license combination explicitly allows the use of this
+ library in commercial, non-Open-Source applications."<br>
+ </p>
+ <p>The icc library in<span style="font-weight: bold;"> icc</span>/,
the CGATS library in <span style="font-weight: bold;">cgats</span>/,
@@ -882,6 +1174,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
the jcnf library in <span style="font-weight: bold;">jcnf</span>/,
@@ -922,72 +1235,93 @@
- the files <span style="font-weight: bold;">spectro/xdg_bds.*</span>,
- <span style="font-weight: bold;">spectro/aglob.*</span> and the
- ucmm library in <span style="font-weight: bold;">ucmm</span>/ are
- Copyright 1995 - 2011 Graeme W. Gill, and available according to
- the "MIT" license granted in the icc/License.txt and
- cgats/License.txt files, and the licenses at the top of
- ucmm/ucmm.c and jcnf/jcnf.c.<br>
- </p>
- <p>The yajl library in <span style="font-weight: bold;">jcnf/yajl</span>
- is Copyright 2007-2009, Lloyd Hilaiel and is licensed according to
- the Berkeley-style License granted in the jcnf/yajl/COPYING files.
- The yajl library has been repackaged and modified slightly for
- convenience.<br>
- </p>
- <p> The TIFF library included in this distribution for convenience,
- has its own copyright and license detailed in tiff/COPYRIGHT (an
- "MIT"/"BSD" like license).<br>
- </p>
- <p>The Independent JPEG Group's JPEG library included in this
- distribution for convenience, has its own copyright and license
- detailed in jpg/README (an "MIT"/"BSD" like license). Executables
- that include JPEG format support are based in part on the work of
- the Independent JPEG Group. </p>
- <p>xicc/iccjpeg.h and xicc/iccjpeg.c are from <a
- href="http://www.littlecms.com/">lcms</a> and they are Copyright
- (c) 1998-2010 Marti Maria Saguer and is licensed under an
- "MIT"/"BSD" like license. See the top of the iccjpeg.c file for
- the detailed copyright and licensing conditions.<br>
- </p>
- <p>The mongoose web server software is Copyright (c) 2004-2011
- Sergey Lyubka, and is licensed under an "MIT" license. </p>
- <h2><span style="text-decoration: underline; color: rgb(51, 0, 51);"><a
- name="ProjType"></a>What sort of project is this ? (re:
- contributions)<br>
- </span></h2>
- This is essentially my private project, that I've made available
- under GNU licensing conditions. Because I license my code under
- other licenses as well, there is a limit to what I will accept in
- the way of code contributions back into this project. For me to
- accept contributions into the distribution, it either has to a
- non-core (side) project, or has to be offered to me with copyright
- conditions that are compatible with my other uses (i.e.. a "BSD"
- like license, or assigning or licensing the copyright to me), or has
- to be so trivial (say a one line bug fix), that it can't be the
- subject of copyright. <br>
- <br>
- Of course there is nothing to stop someone setting up a real free
- software, community project based on the GNU licensed code made
- available here, that would be able to take GNU licensed
- contributions from everyone and would essentially be a "fork" of
- this code base.<br>
- <br>
- <h1><u><a href="Compiling.html">Compiling</a></u></h1>
- How to <a href="Compiling.html">build the software</a> from the
- source if you want to.<br>
- <span style="font-weight: bold;">Note</span> that you don't need to
- do this if you are using one of the binary installations.<br>
- <h1 style="color: rgb(51, 204, 0);"><u><a href="Installing.html">Installing</a></u></h1>
- Important notes on <a href="Installing.html">installing the binary
- software</a> on various platforms.<br>
- <br>
- <h2 style="color: rgb(51, 0, 51);"><u><u><a name="GUIs"></a>Graphic
- User Interfaces<br>
- </u></u></h2>
- ArgyllCMS does not directly support a graphic user interface, but
- several people have written <span style="font-weight: bold;">GUI</span>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ the files <span style="font-weight: bold;">spectro/xdg_bds.*</span>,
+ <span style="font-weight: bold;">spectro/aglob.*</span> and the
+ ucmm library in <span style="font-weight: bold;">ucmm</span>/ are
+ Copyright 1995 - 2011 Graeme W. Gill, and available according to
+ the "MIT" license granted in the icc/License.txt and
+ cgats/License.txt files, and the licenses at the top of
+ ucmm/ucmm.c and jcnf/jcnf.c.<br>
+ </p>
+ <p>The yajl library in <span style="font-weight: bold;">jcnf/yajl</span>
+ is Copyright 2007-2009, Lloyd Hilaiel and is licensed according to
+ the Berkeley-style License granted in the jcnf/yajl/COPYING files.
+ The yajl library has been repackaged and modified slightly for
+ convenience.<br>
+ </p>
+ <p> The TIFF library included in this distribution for convenience,
+ has its own copyright and license detailed in tiff/COPYRIGHT (an
+ "MIT"/"BSD" like license).<br>
+ </p>
+ <p>The Independent JPEG Group's JPEG library included in this
+ distribution for convenience, has its own copyright and license
+ detailed in jpg/README (an "MIT"/"BSD" like license). Executables
+ that include JPEG format support are based in part on the work of
+ the Independent JPEG Group. </p>
+ <p>xicc/iccjpeg.h and xicc/iccjpeg.c are from <a
+ href="http://www.littlecms.com/">lcms</a> and they are Copyright
+ (c) 1998-2010 Marti Maria Saguer and is licensed under an
+ "MIT"/"BSD" like license. See the top of the iccjpeg.c file for
+ the detailed copyright and licensing conditions.<br>
+ </p>
+ <p>The mongoose web server software is Copyright (c) 2004-2011
+ Sergey Lyubka, and is licensed under an "MIT" license. </p>
+ <h2><span style="text-decoration: underline; color: rgb(51, 0, 51);"><a
+ name="ProjType"></a>What sort of project is this ? (re:
+ contributions)<br>
+ </span></h2>
+ This is essentially my private project, that I've made available
+ under GNU licensing conditions. Because I license my code under
+ other licenses as well, there is a limit to what I will accept in
+ the way of code contributions back into this project. For me to
+ accept contributions into the distribution, it either has to a
+ non-core (side) project, or has to be offered to me with copyright
+ conditions that are compatible with my other uses (i.e.. a "BSD"
+ like license, or assigning or licensing the copyright to me), or has
+ to be so trivial (say a one line bug fix), that it can't be the
+ subject of copyright. <br>
+ <br>
+ Of course there is nothing to stop someone setting up a real free
+ software, community project based on the GNU licensed code made
+ available here, that would be able to take GNU licensed
+ contributions from everyone and would essentially be a "fork" of
+ this code base.<br>
+ <br>
+ <h1><u><a href="Compiling.html">Compiling</a></u></h1>
+ How to <a href="Compiling.html">build the software</a> from the
+ source if you want to.<br>
+ <span style="font-weight: bold;">Note</span> that you don't need to
+ do this if you are using one of the binary installations.<br>
+ <h1 style="color: rgb(51, 204, 0);"><u><a href="Installing.html">Installing</a></u></h1>
+ Important notes on <a href="Installing.html">installing the binary
+ software</a> on various platforms.<br>
+ <br>
+ <h2 style="color: rgb(51, 0, 51);"><u><u><a name="GUIs"></a>Graphic
+ User Interfaces<br>
+ </u></u></h2>
+ ArgyllCMS does not directly support a graphic user interface, but
+ several people have written <span style="font-weight: bold;">GUI</span>
based front ends for it. A popular <span style="font-weight: bold;"></span>front
end
that
@@ -1034,17 +1368,38 @@ calibration
- and profiling is <a href="http://hoech.net/dispcalGUI/">dispcalGUI</a>
- by Florian H&ouml;ch. Others can be found with a suitable <a
-href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;aq=f&amp;aqi=g1&amp;aql=&amp;oq=">search</a>.<br>
- <h2 style="color: rgb(51, 0, 51);"><u><a name="CmdLine"></a>Main
- Tools and the command line<br>
- </u></h2>
- These are all command line ("DOS" shell) tools, and each tool
- require appropriate options to be set, followed by filename
- arguments. Sometimes the filenames will have to include the usual
- extensions, sometimes they are implicit. To get a brief listing of
- the possible arguments and <span style="font-weight: bold;">usage</span>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and profiling is <a href="http://hoech.net/dispcalGUI/">dispcalGUI</a>
+ by Florian Höch. Others can be found with a suitable <a
+href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;aq=f&amp;aqi=g1&amp;aql=&amp;oq=">search</a>.<br>
+ <h2 style="color: rgb(51, 0, 51);"><u><a name="CmdLine"></a>Main
+ Tools and the command line<br>
+ </u></h2>
+ These are all command line ("DOS" shell) tools, and each tool
+ require appropriate options to be set, followed by filename
+ arguments. Sometimes the filenames will have to include the usual
+ extensions, sometimes they are implicit. To get a brief listing of
+ the possible arguments and <span style="font-weight: bold;">usage</span>
of any of the tools, run it with just an "-?" argument, i.e. <b>targen
@@ -1084,22 +1439,43 @@ href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;a
- -? </b>(or some other unrecognized flag, if the "?" character is
- treated specially in your shell, i.e. try "--" on OS X zsh).<br>
- <br>
- Note that in general the arguments consist of possible flags or
- options followed by file name arguments. All arguments need to be
- separated by whitespace.&nbsp; (If you need to specify a string with
- embedded white space, double quote the string). A flag consists of a
- dash attached to a single letter, the letter identifying the flag,
- and is usually case sensitive. An option is a flag that has an
- associated parameter or parameters. The parameter can be separated
- from the flag by white space, or may come directly after the flag.
- So if a tool has a usage that looks like this:<br>
- <br>
- &nbsp; tool -?<br>
- &nbsp; usage: tool [options] infile outfile<br>
- &nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -? </b>(or some other unrecognized flag, if the "?" character is
+ treated specially in your shell, i.e. try "--" on OS X zsh).<br>
+ <br>
+ Note that in general the arguments consist of possible flags or
+ options followed by file name arguments. All arguments need to be
+ separated by whitespace.&nbsp; (If you need to specify a string with
+ embedded white space, double quote the string). A flag consists of a
+ dash attached to a single letter, the letter identifying the flag,
+ and is usually case sensitive. An option is a flag that has an
+ associated parameter or parameters. The parameter can be separated
+ from the flag by white space, or may come directly after the flag.
+ So if a tool has a usage that looks like this:<br>
+ <br>
+ &nbsp; tool -?<br>
+ &nbsp; usage: tool [options] infile outfile<br>
+ &nbsp;&nbsp;
-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1141,8 +1517,29 @@ href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;a
- Verbose mode<br>
- &nbsp;&nbsp; -d
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Verbose mode<br>
+ &nbsp;&nbsp; -d
n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1184,8 +1581,29 @@ href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;a
- Choose a depth 0-4<br>
- &nbsp;&nbsp; -r
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Choose a depth 0-4<br>
+ &nbsp;&nbsp; -r
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1227,11 +1645,32 @@ href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;a
- Use a random depth<br>
- &nbsp;&nbsp; -f
- [nn]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Use full range. nn optional range 0 - 100.<br>
- &nbsp;&nbsp; -M
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use a random depth<br>
+ &nbsp;&nbsp; -f
+ [nn]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Use full range. nn optional range 0 - 100.<br>
+ &nbsp;&nbsp; -M
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1273,8 +1712,29 @@ href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;a
- Manual<br>
- &nbsp;&nbsp; infile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Manual<br>
+ &nbsp;&nbsp; infile
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1316,153 +1776,177 @@ href="http://www.google.com/search?hl=en&amp;source=hp&amp;q=argyllcms+GUI&amp;a
- Input file<br>
- &nbsp;&nbsp; outfile
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Output file<br>
- <br>
- then there are&nbsp; 5 flags/options, and two filename arguments.
- Notice that square braces [] denote optional items. The first
- flag/option is a flag. The second is an option that has a numerical
- argument in the range 0 to 4. The third is a flag. the fourth is an
- option with an optional argument. The fourth is a flag.&nbsp; The
- flags and options can generally be in any order, but must be before
- the file name arguments. (For a few special tools you actually
- specify a sequence of flags and files where the flags apply just to
- the following file.) So example invocations may look like:<br>
- <br>
- &nbsp; tool -v testin testout<br>
- &nbsp; tool -d3 -M testin1 testout2<br>
- &nbsp; tool -f infile outfile<br>
- &nbsp; tool -f 45 infile outfile<br>
- &nbsp; tool -d 3 -f67 infile outfile<br>
- <p>In order to make use of the tools, it is necessary to keep track
- of where various files are, and what they are called. There are
- many possible ways of doing this. One way is to put each source
- profile and all its associated files (test charts, spectrometer
- values etc.) in one set of directories for each source profile
- type. Similarly the device profiles could be stored in a hierarchy
- of directories ordered by device type, media, resolution, device
- mode etc. Naturally you will want to set your $PATH so that you
- can run the tools from whichever directory you are in, as well as
- specify any necessary directory paths for file arguments so that
- the tools are able to open them.<br>
- </p>
- <p>Note that there are two ways the Argyll tools deal with filename
- extensions. In one you supply the extension (ie. you supply the
- whole file name), so the extension is up to you. In the other
- (used where one name is used for input and output files, or where
- there are multiple output files), the program adds the extension.
- In the documentation this should be indicated by calling it a
- "base name".<br>
- </p>
- <p><a name="cltutes"></a>For more information on using a command
- line environments, consult an appropriate tutorial:</p>
- <p>MS Windows :<br>
- &nbsp;&nbsp; &lt;<a
- href="http://www.bleepingcomputer.com/tutorials/tutorial76.html">http://www.bleepingcomputer.com/tutorials/tutorial76.html</a>&gt;<br>
- &nbsp;&nbsp; &lt;<a
- href="http://www.pcstats.com/articleview.cfm?articleid=1723&amp;page=1">http://www.pcstats.com/articleview.cfm?articleid=1723&amp;page=1</a>&gt;<br>
- &nbsp;&nbsp; &lt;<a
- href="http://www.voidspace.org.uk/python/articles/command_line.shtml">http://www.voidspace.org.uk/python/articles/command_line.shtml</a>&gt;<br>
- <br>
- &nbsp;&nbsp;&nbsp; To find more: &lt;<a
-href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial&gt;</a><br>
- <br>
- OS X:<br>
- &nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.osxfaq.com/Tutorials/LearningCenter/">http://www.osxfaq.com/Tutorials/LearningCenter/</a>&gt;<br>
- &nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.atomiclearning.com/macosxterminalx.shtml">http://www.atomiclearning.com/macosxterminalx.shtml</a>&gt;<br>
- &nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.oreillynet.com/pub/a/mac/2001/12/14/terminal_one.html">http://www.oreillynet.com/pub/a/mac/2001/12/14/terminal_one.html</a>&gt;<br>
- <br>
- &nbsp;&nbsp;&nbsp; To find more: &lt;<a
- href="http://www.google.com/search?hl=en&amp;q=OS+X+shell+tutorial">http://www.google.com/search?hl=en&amp;q=OS+X+shell+tutorial</a>&gt;<br>
- <br>
- Linux:<br>
- &nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.linuxcommand.org/index.php">http://www.linuxcommand.org/index.php</a>&gt;<br>
- &nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.tuxfiles.org/linuxhelp/shell.html">http://www.tuxfiles.org/linuxhelp/shell.html</a>&gt;<br>
- &nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.ee.surrey.ac.uk/Teaching/Unix/">http://www.ee.surrey.ac.uk/Teaching/Unix/</a>&gt;<br>
- <br>
- &nbsp;&nbsp;&nbsp; To find more: &lt;<a
- href="http://www.google.com/search?q=linux+command+line+shell+tutorial">http://www.google.com/search?q=linux+command+line+shell+tutorial</a>&gt;</p>
- <p><br>
- <span style="font-weight: bold;">Note</span> that since OS X is
- based on UNIX, there is much in common between the OS X and Linux
- command line environments, and many of the UNIX tutorials may be
- useful:<br>
- </p>
- <p>&nbsp;&nbsp;&nbsp; &lt;<a
- href="http://www.rain.org/%7Emkummel/unix.html">http://www.rain.org/~mkummel/unix.html</a>&gt;<br>
- <br>
- </p>
- <h2><u><a href="Scenarios.html">Tutorial: Typical usage scenarios
- and examples</a></u></h2>
- A <a href="Scenarios.html">guided tour</a> of the major tools,
- applied to typical CMS jobs, such as calibrating displays, creating
- device profiles, calibrating printers, linking profiles, and
- converting color spaces of raster files. <br>
- <br>
- Although it is is a couple of years old now, this <a
- href="http://www.argyllcms.com/doc/FCMS2010_ArgyllTute.pdf">tutorial</a>
- may also be of interest.<br>
- &nbsp; <br>
- <h3 style="color: rgb(0, 0, 0);"><u><a name="Topics"></a>Topical
- Discussions</u></h3>
- Discussions about particular topics:<br>
- <br>
- <a href="FWA.html">About Fluorescent Whitening Agent compensation</a><br>
- <br>
- <a href="instruments.html">Operation of particular instruments</a><br>
- <br>
- <a href="iccgamutmapping.html">About ICC profiles and Gamut Mapping</a><br>
- <br>
- <a href="monitorcontrols.html">About display monitor settings and
- targets</a><br>
- <br>
- <a href="gamma.html">About display "Gamma"</a><br>
- <br>
- <a href="calvschar.html">What's the difference between Calibration
- and Characterization ?</a><br>
- <br>
- <a href="WideGamutColmters.html">Why doesn't my Colorimeter work
- well on my Wide Gamut display ?</a><br>
- <span style="font-family: monospace;"></span><br>
- <a href="CrushedDisplyBlacks.html">My blacks get crushed on my
- display - why ? How do I fix it ?</a><br>
- <br>
- <a href="i1proDriver.html">How can I have confidence in the i1pro
- Driver ?</a><br>
- <br>
- <a href="evalInputTargets.html">Evaluating input targets</a><br>
- <br>
- <h2><b><u><font><b><u><font size="+2"><a name="Flow"></a>Flow
- diagram of Major Tools:</font></u></b></font></u></b></h2>
- <br>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a
- href="ArgyllFlow.jpg"><img alt="Thumbnail of Flow Diagram"
- src="ArgyllFlowThumb.jpg" style="border: 2px solid ; width:
- 150px; height: 202px;"></a><br>
- <br>
- <h2><b><u><font size="+2"><a name="CatList"></a>Main Tools by
- category:</font></u></b></h2>
- <h3>Calibrating devices<br>
- </h3>
- <small><a style="font-family: monospace;" href="dispcal.html">dispcal</a><span
- style="font-family: monospace;">
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></small>Adjust,
- calibrate and profile a display<small><big>.<br>
- </big></small><small><a style="font-family: monospace;"
- href="printcal.html">printcal</a><span style="font-family:
- monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create a
- printer calibration .cal file from a .ti3 data file<small><big>.</big></small><br>
- <h3>Creating test targets for profiling or print calibration<br>
- </h3>
- <small><a style="font-family: monospace;" href="targen.html">targen</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Input file<br>
+ &nbsp;&nbsp; outfile
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Output file<br>
+ <br>
+ then there are&nbsp; 5 flags/options, and two filename arguments.
+ Notice that square braces [] denote optional items. The first
+ flag/option is a flag. The second is an option that has a numerical
+ argument in the range 0 to 4. The third is a flag. the fourth is an
+ option with an optional argument. The fourth is a flag.&nbsp; The
+ flags and options can generally be in any order, but must be before
+ the file name arguments. (For a few special tools you actually
+ specify a sequence of flags and files where the flags apply just to
+ the following file.) So example invocations may look like:<br>
+ <br>
+ &nbsp; tool -v testin testout<br>
+ &nbsp; tool -d3 -M testin1 testout2<br>
+ &nbsp; tool -f infile outfile<br>
+ &nbsp; tool -f 45 infile outfile<br>
+ &nbsp; tool -d 3 -f67 infile outfile<br>
+ <p>In order to make use of the tools, it is necessary to keep track
+ of where various files are, and what they are called. There are
+ many possible ways of doing this. One way is to put each source
+ profile and all its associated files (test charts, spectrometer
+ values etc.) in one set of directories for each source profile
+ type. Similarly the device profiles could be stored in a hierarchy
+ of directories ordered by device type, media, resolution, device
+ mode etc. Naturally you will want to set your $PATH so that you
+ can run the tools from whichever directory you are in, as well as
+ specify any necessary directory paths for file arguments so that
+ the tools are able to open them.<br>
+ </p>
+ <p>Note that there are two ways the Argyll tools deal with filename
+ extensions. In one you supply the extension (ie. you supply the
+ whole file name), so the extension is up to you. In the other
+ (used where one name is used for input and output files, or where
+ there are multiple output files), the program adds the extension.
+ In the documentation this should be indicated by calling it a
+ "base name".<br>
+ </p>
+ <p><a name="cltutes"></a>For more information on using a command
+ line environments, consult an appropriate tutorial:</p>
+ <p>MS Windows :<br>
+ &nbsp;&nbsp; &lt;<a
+ href="http://www.bleepingcomputer.com/tutorials/tutorial76.html">http://www.bleepingcomputer.com/tutorials/tutorial76.html</a>&gt;<br>
+ &nbsp;&nbsp; &lt;<a
+ href="http://www.pcstats.com/articleview.cfm?articleid=1723&amp;page=1">http://www.pcstats.com/articleview.cfm?articleid=1723&amp;page=1</a>&gt;<br>
+ &nbsp;&nbsp; &lt;<a
+ href="http://www.voidspace.org.uk/python/articles/command_line.shtml">http://www.voidspace.org.uk/python/articles/command_line.shtml</a>&gt;<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; To find more: &lt;<a
+href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial&gt;</a><br>
+ <br>
+ OS X:<br>
+ &nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.osxfaq.com/Tutorials/LearningCenter/">http://www.osxfaq.com/Tutorials/LearningCenter/</a>&gt;<br>
+ &nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.atomiclearning.com/macosxterminalx.shtml">http://www.atomiclearning.com/macosxterminalx.shtml</a>&gt;<br>
+ &nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.oreillynet.com/pub/a/mac/2001/12/14/terminal_one.html">http://www.oreillynet.com/pub/a/mac/2001/12/14/terminal_one.html</a>&gt;<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; To find more: &lt;<a
+ href="http://www.google.com/search?hl=en&amp;q=OS+X+shell+tutorial">http://www.google.com/search?hl=en&amp;q=OS+X+shell+tutorial</a>&gt;<br>
+ <br>
+ Linux:<br>
+ &nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.linuxcommand.org/index.php">http://www.linuxcommand.org/index.php</a>&gt;<br>
+ &nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.tuxfiles.org/linuxhelp/shell.html">http://www.tuxfiles.org/linuxhelp/shell.html</a>&gt;<br>
+ &nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.ee.surrey.ac.uk/Teaching/Unix/">http://www.ee.surrey.ac.uk/Teaching/Unix/</a>&gt;<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; To find more: &lt;<a
+ href="http://www.google.com/search?q=linux+command+line+shell+tutorial">http://www.google.com/search?q=linux+command+line+shell+tutorial</a>&gt;</p>
+ <p><br>
+ <span style="font-weight: bold;">Note</span> that since OS X is
+ based on UNIX, there is much in common between the OS X and Linux
+ command line environments, and many of the UNIX tutorials may be
+ useful:<br>
+ </p>
+ <p>&nbsp;&nbsp;&nbsp; &lt;<a
+ href="http://www.rain.org/%7Emkummel/unix.html">http://www.rain.org/~mkummel/unix.html</a>&gt;<br>
+ <br>
+ </p>
+ <h2><u><a href="Scenarios.html">Tutorial: Typical usage scenarios
+ and examples</a></u></h2>
+ A <a href="Scenarios.html">guided tour</a> of the major tools,
+ applied to typical CMS jobs, such as calibrating displays, creating
+ device profiles, calibrating printers, linking profiles, and
+ converting color spaces of raster files. <br>
+ <br>
+ Although it is is a couple of years old now, this <a
+ href="http://www.argyllcms.com/doc/FCMS2010_ArgyllTute.pdf">tutorial</a>
+ may also be of interest.<br>
+ &nbsp; <br>
+ <h3 style="color: rgb(0, 0, 0);"><u><a name="Topics"></a>Topical
+ Discussions</u></h3>
+ Discussions about particular topics:<br>
+ <br>
+ <a href="FWA.html">About Fluorescent Whitening Agent compensation</a><br>
+ <br>
+ <a href="instruments.html">Operation of particular instruments</a><br>
+ <br>
+ <a href="iccgamutmapping.html">About ICC profiles and Gamut Mapping</a><br>
+ <br>
+ <a href="monitorcontrols.html">About display monitor settings and
+ targets</a><br>
+ <br>
+ <a href="gamma.html">About display "Gamma"</a><br>
+ <br>
+ <a href="calvschar.html">What's the difference between Calibration
+ and Characterization ?</a><br>
+ <br>
+ <a href="WideGamutColmters.html">Why doesn't my Colorimeter work
+ well on my Wide Gamut display ?</a><br>
+ <span style="font-family: monospace;"></span><br>
+ <a href="CrushedDisplyBlacks.html">My blacks get crushed on my
+ display - why ? How do I fix it ?</a><br>
+ <br>
+ <a href="i1proDriver.html">How can I have confidence in the i1pro
+ Driver ?</a><br>
+ <br>
+ <a href="i1proHiRes.html">Does the i1pro High Resolution mode
+ improve accuracy ?</a><br>
+ <br>
+ <a href="evalInputTargets.html">Evaluating input targets</a><br>
+ <br>
+ <h2><b><u><font><b><u><font size="+2"><a name="Flow"></a>Flow
+ diagram of Major Tools:</font></u></b></font></u></b></h2>
+ <br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a
+ href="ArgyllFlow.jpg"><img alt="Thumbnail of Flow Diagram"
+ src="ArgyllFlowThumb.jpg" style="border: 2px solid ; width:
+ 150px; height: 202px;"></a><br>
+ <br>
+ <h2><b><u><font size="+2"><a name="CatList"></a>Main Tools by
+ category:</font></u></b></h2>
+ <h3>Calibrating devices<br>
+ </h3>
+ <small><a style="font-family: monospace;" href="dispcal.html">dispcal</a><span
+ style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></small>Adjust,
+ calibrate and profile a display<small><big>.<br>
+ </big></small><small><a style="font-family: monospace;"
+ href="printcal.html">printcal</a><span style="font-family:
+ monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create a
+ printer calibration .cal file from a .ti3 data file<small><big>.</big></small><br>
+ <h3>Creating test targets for profiling or print calibration<br>
+ </h3>
+ <small><a style="font-family: monospace;" href="targen.html">targen</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1504,9 +1988,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span><big>Generate a profiling test target values .ti1 file. </big><br
- style="font-family: monospace;">
- <a style="font-family: monospace;" href="filmtarg.html">filmtarg</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span><big>Generate a profiling test target values .ti1 file. </big><br
+ style="font-family: monospace;">
+ <a style="font-family: monospace;" href="filmtarg.html">filmtarg</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Create
@@ -1548,9 +2053,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- film recorder TIFF files from Argyll .ti1 file. </big><br
- style="font-family: monospace;">
- <a style="font-family: monospace;" href="printtarg.html">printtarg</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ film recorder TIFF files from Argyll .ti1 file. </big><br
+ style="font-family: monospace;">
+ <a style="font-family: monospace;" href="printtarg.html">printtarg</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Create
@@ -1592,11 +2118,32 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a PS, EPS or TIFF file containing test patch values, ready for
- printing.</big></small>
- <h3>Obtaining test results for profiling or print calibration<br>
- </h3>
- <small><a style="font-family: monospace;" href="chartread.html">chartread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a PS, EPS or TIFF file containing test patch values, ready for
+ printing.</big></small>
+ <h3>Obtaining test results for profiling or print calibration<br>
+ </h3>
+ <small><a style="font-family: monospace;" href="chartread.html">chartread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Read
@@ -1638,10 +2185,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a test chart using an instrument to create a .ti3 data file.</big><span
- style="font-family: monospace;"> </span><br style="font-family:
- monospace;">
- <a style="font-family: monospace;" href="dispread.html">dispread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a test chart using an instrument to create a .ti3 data file.</big><span
+ style="font-family: monospace;"> </span><br style="font-family:
+ monospace;">
+ <a style="font-family: monospace;" href="dispread.html">dispread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Test
@@ -1683,9 +2251,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- and read colorimetric values from a display </big><br
- style="font-family: monospace;">
- <a style="font-family: monospace;" href="filmread.html">filmread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and read colorimetric values from a display </big><br
+ style="font-family: monospace;">
+ <a style="font-family: monospace;" href="filmread.html">filmread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Read
@@ -1727,9 +2316,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- film colorimetric values using a SpectroScanT (Deprecated ?)</big><br
- style="font-family: monospace;">
- <a style="font-family: monospace;" href="scanin.html">scanin</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ film colorimetric values using a SpectroScanT (Deprecated ?)</big><br
+ style="font-family: monospace;">
+ <a style="font-family: monospace;" href="scanin.html">scanin</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1771,14 +2381,35 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span><big>Convert a TIFF&nbsp; image of a test chart into .ti3
- device values. <br>
- </big></small><small><a style="font-family: monospace;"
- href="illumread.html">illumread</a><span style="font-family:
- monospace;"> &nbsp;&nbsp;&nbsp; </span></small>Use an
- instrument to measure an illuminant spectrum, and estimate its UV
- content.<br style="font-family: monospace;">
- <small><a style="font-family: monospace;" href="fakeread.html">fakeread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span><big>Convert a TIFF&nbsp; image of a test chart into .ti3
+ device values. <br>
+ </big></small><small><a style="font-family: monospace;"
+ href="illumread.html">illumread</a><span style="font-family:
+ monospace;"> &nbsp;&nbsp;&nbsp; </span></small>Use an
+ instrument to measure an illuminant spectrum, and estimate its UV
+ content.<br style="font-family: monospace;">
+ <small><a style="font-family: monospace;" href="fakeread.html">fakeread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Fake
@@ -1820,13 +2451,34 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- the reading of a device using an ICC or MPP profile. <br>
- </big></small><small><a style="font-family: monospace;"
- href="synthread.html">synthread</a><span style="font-family:
- monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Fake the
- reading of a device using a synthetic device model. </big></small><br
- style="font-family: monospace;">
- <small><a style="font-family: monospace;" href="cb2ti3.html">cb2ti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ the reading of a device using an ICC or MPP profile. <br>
+ </big></small><small><a style="font-family: monospace;"
+ href="synthread.html">synthread</a><span style="font-family:
+ monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Fake the
+ reading of a device using a synthetic device model. </big></small><br
+ style="font-family: monospace;">
+ <small><a style="font-family: monospace;" href="cb2ti3.html">cb2ti3</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1868,10 +2520,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span><big>Convert Colorblind format CMY/RGB test chart into
- Argyll .ti3 CGATS format. </big><br style="font-family:
- monospace;">
- <a style="font-family: monospace;" href="kodak2ti3.html">kodak2ti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span><big>Convert Colorblind format CMY/RGB test chart into
+ Argyll .ti3 CGATS format. </big><br style="font-family:
+ monospace;">
+ <a style="font-family: monospace;" href="kodak2ti3.html">kodak2ti3</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Convert
@@ -1913,9 +2586,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Kodak Colorflow format CMYK test chart into Argyll .ti3 CGATS
- format. </big><br style="font-family: monospace;">
- <a style="font-family: monospace;" href="txt2ti3.html">txt2ti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Kodak Colorflow format CMYK test chart into Argyll .ti3 CGATS
+ format. </big><br style="font-family: monospace;">
+ <a style="font-family: monospace;" href="txt2ti3.html">txt2ti3</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1957,10 +2651,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span><big>Convert Gretag/Logo/X-Rite or other format RGB or CMYK
- test chart results into Argyll .ti3 CGATS format. </big><br
- style="font-family: monospace;">
- <a style="font-family: monospace;" href="fakeCMY.html">fakeCMY</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span><big>Convert Gretag/Logo/X-Rite or other format RGB or CMYK
+ test chart results into Argyll .ti3 CGATS format. </big><br
+ style="font-family: monospace;">
+ <a style="font-family: monospace;" href="fakeCMY.html">fakeCMY</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2002,10 +2717,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span><big>Create a fake Argyll .ti3 CMY data file from a CMYK
- profile, as a basis of creating a CMY to CMYK separation<br>
- </big></small><small><a style="font-family: monospace;"
- href="average.html">average</a><span style="font-family:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span><big>Create a fake Argyll .ti3 CMY data file from a CMYK
+ profile, as a basis of creating a CMY to CMYK separation<br>
+ </big></small><small><a style="font-family: monospace;"
+ href="average.html">average</a><span style="font-family:
monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Average
@@ -2046,9 +2782,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- / Merge two measurement data files</big></small><br>
- <h3>Creating Device Profiles</h3>
- <small><a style="font-family: monospace;" href="colprof.html">colprof</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ / Merge two measurement data files</big></small><br>
+ <h3>Creating Device Profiles</h3>
+ <small><a style="font-family: monospace;" href="colprof.html">colprof</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2090,8 +2847,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Create an ICC profile from the .ti3 test data. <br>
- <small><a style="font-family: monospace;" href="mppprof.html">mppprof</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Create an ICC profile from the .ti3 test data. <br>
+ <small><a style="font-family: monospace;" href="mppprof.html">mppprof</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2133,9 +2911,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Create a Model Printer Profile (MPP) from the .ti3
- test data. <br>
- <small><a style="font-family: monospace;" href="revfix.html">revfix</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Create a Model Printer Profile (MPP) from the .ti3
+ test data. <br>
+ <small><a style="font-family: monospace;" href="revfix.html">revfix</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2177,10 +2976,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Regenerate a device profiles B2A table data by
- inverting the A2B table.
- <h3>Creating Device Link Profiles</h3>
- <small><a style="font-family: monospace;" href="collink.html">collink</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Regenerate a device profiles B2A table data by
+ inverting the A2B table.
+ <h3>Creating Device Link Profiles</h3>
+ <small><a style="font-family: monospace;" href="collink.html">collink</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2222,11 +3042,32 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Link two device ICC profiles to create a device
- link profile.
- <h3>Converting colors or applying print calibration<br>
- </h3>
- <small><a style="font-family: monospace;" href="cctiff.html">cctiff</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Link two device ICC profiles to create a device
+ link profile.
+ <h3>Converting colors or applying print calibration<br>
+ </h3>
+ <small><a style="font-family: monospace;" href="cctiff.html">cctiff</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2268,10 +3109,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Color convert a TIFF or JPEG file using a sequence
- of ICC device, device link, abstract profiles and calibration files.
- <br>
- <small><a style="font-family: monospace;" href="applycal.html">applycal</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Color convert a TIFF or JPEG file using a sequence
+ of ICC device, device link, abstract profiles and calibration files.
+ <br>
+ <small><a style="font-family: monospace;" href="applycal.html">applycal</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Apply
@@ -2312,8 +3174,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- calibration curves to an ICC profile.<br>
- <small><a style="font-family: monospace;" href="icclu.html">icclu&nbsp;</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ calibration curves to an ICC profile.<br>
+ <small><a style="font-family: monospace;" href="icclu.html">icclu&nbsp;</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2355,9 +3238,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Lookup individual color values through any ICC
- profile table. <br>
- <small><a style="font-family: monospace;" href="xicclu.html">xicclu</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Lookup individual color values through any ICC
+ profile table. <br>
+ <small><a style="font-family: monospace;" href="xicclu.html">xicclu</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2399,9 +3303,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Lookup individual color values forward or inverted
- though an ICC profile table. <br>
- <small><a style="font-family: monospace;" href="mpplu.html">mpplu</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Lookup individual color values forward or inverted
+ though an ICC profile or CAL table. <br>
+ <small><a style="font-family: monospace;" href="mpplu.html">mpplu</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2443,9 +3368,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Lookup individual color values though an MPP
- profile. Also create MPP gamut files/views.<br>
- <small><a style="font-family: monospace;" href="greytiff.html">greytiff</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Lookup individual color values though an MPP
+ profile. Also create MPP gamut files/views.<br>
+ <small><a style="font-family: monospace;" href="greytiff.html">greytiff</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Convert
@@ -2487,17 +3433,38 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a TIFF file to monochrome using an ICC device profile <br>
- <h3>Color Tweaking tools<br>
- </h3>
- <small><a style="font-family: monospace;" href="refine.html">refine</a><span
- style="font-family: monospace;">
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Creates an
- abstract profile from two chart readings, useful for refining
- proofing profiles. <a href="mppprof.html"><br>
- </a>
- <h3>Creating gamut views</h3>
- <small><a style="font-family: monospace;" href="iccgamut.html">iccgamut</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a TIFF file to monochrome using an ICC device profile <br>
+ <h3>Color Tweaking tools<br>
+ </h3>
+ <small><a style="font-family: monospace;" href="refine.html">refine</a><span
+ style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Creates an
+ abstract profile from two chart readings, useful for refining
+ proofing profiles. <a href="mppprof.html"><br>
+ </a>
+ <h3>Creating gamut views</h3>
+ <small><a style="font-family: monospace;" href="iccgamut.html">iccgamut</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -2539,8 +3506,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a gamut file or VRML file of the color gamut of an ICC profile. <br>
- <small><a style="font-family: monospace;" href="tiffgamut.html">tiffgamut</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a gamut file or VRML file of the color gamut of an ICC profile. <br>
+ <small><a style="font-family: monospace;" href="tiffgamut.html">tiffgamut</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -2582,9 +3570,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a gamut file or VRML file of the color gamut of a TIFF or JPEG
- image. <br>
- <small><a style="font-family: monospace;" href="viewgam.html">viewgam</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a gamut file or VRML file of the color gamut of a TIFF or JPEG
+ image. <br>
+ <small><a style="font-family: monospace;" href="viewgam.html">viewgam</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2626,11 +3635,32 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Convert one or more gamuts into a VRML 3D
- visualization file. Compute an intersection.<br>
- <h3>Diagnostic and test tools<br>
- </h3>
- <small><a style="font-family: monospace;" href="iccdump.html">iccdump</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Convert one or more gamuts into a VRML 3D
+ visualization file. Compute an intersection.<br>
+ <h3>Diagnostic and test tools<br>
+ </h3>
+ <small><a style="font-family: monospace;" href="iccdump.html">iccdump</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2672,8 +3702,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Dump the contents of an ICC profile as text. <br>
- <small><a style="font-family: monospace;" href="profcheck.html">profcheck</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Dump the contents of an ICC profile as text. <br>
+ <small><a style="font-family: monospace;" href="profcheck.html">profcheck</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Check
@@ -2715,7 +3766,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an ICC profile against .ti3 test chart data. <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an ICC profile against .ti3 test chart data. <br>
<small style="font-family: monospace;"><a href="invprofcheck.html">invprofcheck</a>&nbsp;
@@ -2757,8 +3829,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </small>Check ICC forward against inverse lookup. <br>
- <small><a style="font-family: monospace;" href="splitti3.html">splitsti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </small>Check ICC forward against inverse lookup. <br>
+ <small><a style="font-family: monospace;" href="splitti3.html">splitsti3</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span></small>Split
@@ -2799,12 +3892,33 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a CGATS file (ie. a .ti3) into two parts randomly to verify
- profiling. <br>
- <small style="font-family: monospace;"><a href="timage.html">timage</a>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </small>Create TIFF test
- images. <br>
- <small><a style="font-family: monospace;" href="mppcheck.html">mppcheck</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a CGATS file (ie. a .ti3) into two parts randomly to verify
+ profiling. <br>
+ <small style="font-family: monospace;"><a href="timage.html">timage</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </small>Create TIFF test
+ images. <br>
+ <small><a style="font-family: monospace;" href="mppcheck.html">mppcheck</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Check
@@ -2846,8 +3960,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an MPP profile against .ti3 test chart data. <br>
- <small><a style="font-family: monospace;" href="spotread.html">spotread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an MPP profile against .ti3 test chart data. <br>
+ <small><a style="font-family: monospace;" href="spotread.html">spotread</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Use
@@ -2888,13 +4023,37 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an instrument to read a single spot color value. <br>
- <small><a style="font-family: monospace;" href="verify.html">verify</a><span
- style="font-family: monospace;">
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Verify
- matching of CIE in two CGATS/.ti3 files (also view differences as
- VRML)<br>
- <small><a style="font-family: monospace;" href="synthcal.html">synthcal</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an instrument to read a single spot color value. <br>
+ <small><a style="font-family: monospace;" href="colverify.html">colverify</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span></small>Verify
+
+
+
+
+ matching of CIE in two CGATS/.ti3 files (also view differences as
+ VRML)<br>
+ <small><a style="font-family: monospace;" href="synthcal.html">synthcal</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -2935,10 +4094,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a synthetic input, display or output calibration (<a
- href="File_Formats.html#.cal">.cal</a>)file.
- <h3>Other Tools</h3>
- <small><a style="font-family: monospace;" href="ccxxmake.html">ccxxmake</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a synthetic input, display or output calibration (<a
+ href="File_Formats.html#.cal">.cal</a>)file.
+ <h3>Other Tools</h3>
+ <small><a style="font-family: monospace;" href="ccxxmake.html">ccxxmake</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Use
@@ -2979,11 +4159,32 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a Spectrometer to create a Colorimeter Correction Matrix
- (CCMX)&nbsp; or a Colorimeter Calibration Spectral Set (CCSS)&nbsp;
- for a particular display.<br>
- <small><a style="font-family: monospace;" href="extracticc.html">extracticc</a><span
- style="font-family: monospace;"></span></small><small><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a Spectrometer to create a Colorimeter Correction Matrix
+ (CCMX)&nbsp; or a Colorimeter Calibration Spectral Set (CCSS)&nbsp;
+ for a particular display.<br>
+ <small><a style="font-family: monospace;" href="extracticc.html">extracticc</a><span
+ style="font-family: monospace;"></span></small><small><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp; </span>Extract
@@ -3025,14 +4226,35 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an embedded ICC profile from a TIFF or JPEG file.<br>
- </small><small><a style="font-family: monospace;"
- href="extractttag.html">extractttag</a><span style="font-family:
- monospace;"></span></small><small><span style="font-family:
- monospace;">&nbsp;&nbsp; </span>Extract a text tag (ie. CGATS
- .ti3 data or CAL) from an ICC profile.</small><br>
- <small><a style="font-family: monospace;" href="dispwin.html">dispwin</a><span
- style="font-family: monospace;"></span></small><small><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an embedded ICC profile from a TIFF or JPEG file.<br>
+ </small><small><a style="font-family: monospace;"
+ href="extractttag.html">extractttag</a><span style="font-family:
+ monospace;"></span></small><small><span style="font-family:
+ monospace;">&nbsp;&nbsp; </span>Extract a text tag (ie. CGATS
+ .ti3 data or CAL) from an ICC profile.</small><br>
+ <small><a style="font-family: monospace;" href="dispwin.html">dispwin</a><span
+ style="font-family: monospace;"></span></small><small><span
style="font-family: monospace;">&nbsp;&nbsp; &nbsp; &nbsp; </span></small>Install
@@ -3074,15 +4296,36 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- or uninstall display profile, set display calibration from profile
- or .cal file, test displace and dispwin access to a display.<br>
- <small><a style=" font-family: monospace;" href="oeminst.html">oeminst</a><span
- style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- </span></small>Install Instrument manufacturers files for the
- Spyder 2, EDR or CCSS calibration files for i1d3 or Spyder 4,&nbsp;
- CCMX files for colorimeters.<br>
- <small><a style="font-family: monospace;" href="specplot.html">specplot</a><span
- style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ or uninstall display profile, set display calibration from profile
+ or .cal file, test displace and dispwin access to a display.<br>
+ <small><a style=" font-family: monospace;" href="oeminst.html">oeminst</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></small>Install Instrument manufacturers files for the
+ Spyder 2, EDR or CCSS calibration files for i1d3 or Spyder 4,&nbsp;
+ CCMX files for colorimeters.<br>
+ <small><a style="font-family: monospace;" href="specplot.html">specplot</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span><span
style="text-decoration: underline; font-family: monospace;"></span></small>&nbsp;
@@ -3124,9 +4367,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Plot a spectrum (.sp, .cmf, .ccss) and calculate CCT and VCT.<br>
- <small><a style="font-family: monospace;" href="spec2cie.html">spec2cie</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Plot a spectrum (.sp, .cmf, .ccss) and calculate CCT and VCT.<br>
+ <small><a style="font-family: monospace;" href="spec2cie.html">spec2cie</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
style="text-decoration: underline; font-family: monospace;"></span></small>Convert
@@ -3168,13 +4432,34 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- spectral .ti3 readings into CIE XYZ or L*a*b* readings. Apply FWA,
- plot spectrums.<small><a style="font-family: monospace;"
- href="oeminst.html"></a></small><br>
- &nbsp;
- <h2><b><u><font size="+2"><a name="AlphList"></a>Main Tools
- Alphabetic Listing:</font></u></b></h2>
- <small><a style="font-family: monospace;" href="applycal.html">applycal</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ spectral .ti3 readings into CIE XYZ or L*a*b* readings. Apply FWA,
+ plot spectrums.<small><a style="font-family: monospace;"
+ href="oeminst.html"></a></small><br>
+ &nbsp;
+ <h2><b><u><font size="+2"><a name="AlphList"></a>Main Tools
+ Alphabetic Listing:</font></u></b></h2>
+ <small><a style="font-family: monospace;" href="applycal.html">applycal</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Apply
@@ -3215,8 +4500,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- calibration curves to an ICC profile.<br>
- <small><a style="font-family: monospace;" href="average.html">average</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ calibration curves to an ICC profile.<br>
+ <small><a style="font-family: monospace;" href="average.html">average</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3258,8 +4564,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span><big>Average / Merge two measurement data files</big></small><br>
- <small><a style="font-family: monospace;" href="cb2ti3.html">cb2ti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span><big>Average / Merge two measurement data files</big></small><br>
+ <small><a style="font-family: monospace;" href="cb2ti3.html">cb2ti3</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3301,9 +4628,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Convert Colorblind format CMY/RGB test chart into
- Argyll .ti3 CGATS format. <br>
- <small><a style="font-family: monospace;" href="cctiff.html">cctiff</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Convert Colorblind format CMY/RGB test chart into
+ Argyll .ti3 CGATS format. <br>
+ <small><a style="font-family: monospace;" href="cctiff.html">cctiff</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3345,9 +4693,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Color convert a TIFF or JPEG file using a sequence
- of ICC device, device link, abstract profiles and calibration files.<br>
- <small><a style="font-family: monospace;" href="ccxxmake.html">ccxxmake</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Color convert a TIFF or JPEG file using a sequence
+ of ICC device, device link, abstract profiles and calibration files.<br>
+ <small><a style="font-family: monospace;" href="ccxxmake.html">ccxxmake</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Use
@@ -3388,10 +4757,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a Spectrometer to create a Colorimeter Correction Matrix
- (CCMX)&nbsp; or a Colorimeter Calibration Spectral Set (CCSS)&nbsp;
- for a particular display.<br>
- <small><a style="font-family: monospace;" href="chartread.html">chartread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a Spectrometer to create a Colorimeter Correction Matrix
+ (CCMX)&nbsp; or a Colorimeter Calibration Spectral Set (CCSS)&nbsp;
+ for a particular display.<br>
+ <small><a style="font-family: monospace;" href="chartread.html">chartread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Read
@@ -3433,8 +4823,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a test chart using an instrument to create a .ti3 data file. <br>
- <small><a style="font-family: monospace;" href="collink.html">collink</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a test chart using an instrument to create a .ti3 data file. <br>
+ <small><a style="font-family: monospace;" href="collink.html">collink</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3476,9 +4887,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Link two device ICC profiles to create a device
- link profile. <br>
- <small><a style="font-family: monospace;" href="colprof.html">colprof</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Link two device ICC profiles to create a device
+ link profile. <br>
+ <small><a style="font-family: monospace;" href="colprof.html">colprof</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3520,11 +4952,98 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Create an ICC profile from the .ti3 test data. <br>
- <small style="font-family: monospace;"><a href="dispcal.html">dispcal</a>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </small>Adjust, calibrate and
- profile a display<small><big>.</big></small><br>
- <small><a style="font-family: monospace;" href="dispread.html">dispread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Create an ICC profile from the .ti3 test data.<br>
+ <font size="-1"><a style="font-family: monospace;"
+ href="file:///D:/src/argyll/doc/colverify.html">colverify</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span></font>Verify
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ matching of CIE in two CGATS/.ti3 files (also view differences as
+ VRML)<br>
+ <small style="font-family: monospace;"><a href="dispcal.html">dispcal</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </small>Adjust, calibrate and
+ profile a display<small><big>.</big></small><br>
+ <small><a style="font-family: monospace;" href="dispread.html">dispread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Test
@@ -3566,9 +5085,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- and read colorimetric values from a display <br>
- <small><a style="font-family: monospace;" href="dispwin.html">dispwin</a><span
- style="font-family: monospace;"></span></small><small><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and read colorimetric values from a display <br>
+ <small><a style="font-family: monospace;" href="dispwin.html">dispwin</a><span
+ style="font-family: monospace;"></span></small><small><span
style="font-family: monospace;">&nbsp;&nbsp; &nbsp; &nbsp; </span></small>Install
@@ -3610,10 +5150,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- or uninstall display profile, set display calibration from profile
- or .cal file, test displace and dispwin access to a display.<br>
- <small><a style="font-family: monospace;" href="extracticc.html">extracticc</a><span
- style="font-family: monospace;"></span></small><small><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ or uninstall display profile, set display calibration from profile
+ or .cal file, test displace and dispwin access to a display.<br>
+ <small><a style="font-family: monospace;" href="extracticc.html">extracticc</a><span
+ style="font-family: monospace;"></span></small><small><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp; </span>Extract
@@ -3655,13 +5216,34 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an embedded ICC profile from a TIFF or JPEG file.<br>
- </small><small><a style="font-family: monospace;"
- href="extractttag.html">extractttag</a><span style="font-family:
- monospace;"></span></small><small><span style="font-family:
- monospace;">&nbsp;&nbsp; </span>Extract a text tag (ie. CGATS
- .ti3 data or CAL) from an ICC profile.</small><br>
- <small><a style="font-family: monospace;" href="fakeCMY.html">fakeCMY</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an embedded ICC profile from a TIFF or JPEG file.<br>
+ </small><small><a style="font-family: monospace;"
+ href="extractttag.html">extractttag</a><span style="font-family:
+ monospace;"></span></small><small><span style="font-family:
+ monospace;">&nbsp;&nbsp; </span>Extract a text tag (ie. CGATS
+ .ti3 data or CAL) from an ICC profile.</small><br>
+ <small><a style="font-family: monospace;" href="fakeCMY.html">fakeCMY</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3703,9 +5285,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Create a fake Argyll .ti3 CMY data file from a CMYK
- profile, as a basis of creating a CMY to CMYK separation <br>
- <small><a style="font-family: monospace;" href="fakeread.html">fakeread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Create a fake Argyll .ti3 CMY data file from a CMYK
+ profile, as a basis of creating a CMY to CMYK separation <br>
+ <small><a style="font-family: monospace;" href="fakeread.html">fakeread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Fake
@@ -3747,8 +5350,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- the reading of a device using an ICC or MPP profile. <br>
- <small><a style="font-family: monospace;" href="filmread.html">filmread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ the reading of a device using an ICC or MPP profile. <br>
+ <small><a style="font-family: monospace;" href="filmread.html">filmread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Read
@@ -3790,8 +5414,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- film colorimetric values using a SpectroScanT (Deprecated ?)<br>
- <small><a style="font-family: monospace;" href="filmtarg.html">filmtarg</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ film colorimetric values using a SpectroScanT (Deprecated ?)<br>
+ <small><a style="font-family: monospace;" href="filmtarg.html">filmtarg</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -3833,8 +5478,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- film recorder TIFF files from Argyll .ti1 file. <br>
- <small><a style="font-family: monospace;" href="greytiff.html">greytiff</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ film recorder TIFF files from Argyll .ti1 file. <br>
+ <small><a style="font-family: monospace;" href="greytiff.html">greytiff</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Convert
@@ -3876,9 +5542,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a TIFF file to monochrome using an ICC device profile <small><a
- style="font-family: monospace;" href="oeminst.html"></a></small><br>
- <small><a style="font-family: monospace;" href="iccdump.html">iccdump</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a TIFF file to monochrome using an ICC device profile <small><a
+ style="font-family: monospace;" href="oeminst.html"></a></small><br>
+ <small><a style="font-family: monospace;" href="iccdump.html">iccdump</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -3920,8 +5607,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Dump the contents of an ICC profile as text. <br>
- <small><a style="font-family: monospace;" href="iccgamut.html">iccgamut</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Dump the contents of an ICC profile as text. <br>
+ <small><a style="font-family: monospace;" href="iccgamut.html">iccgamut</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -3963,8 +5671,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a gamut file or VRML file of the color gamut of an ICC profile. <br>
- <small><a style="font-family: monospace;" href="icclu.html">icclu&nbsp;</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a gamut file or VRML file of the color gamut of an ICC profile. <br>
+ <small><a style="font-family: monospace;" href="icclu.html">icclu&nbsp;</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4006,9 +5735,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Lookup individual color values through any ICC
- profile table. <br>
- <small><a style="font-family: monospace;" href="illumread.html">illumread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Lookup individual color values through any ICC
+ profile table. <br>
+ <small><a style="font-family: monospace;" href="illumread.html">illumread</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span></small>Use
@@ -4049,12 +5799,33 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an instrument to measure an illuminant spectrum, and estimate its UV
- content.<br>
- <small><a style="font-family: monospace;" href="invprofcheck.html">invprofcheck</a><span
- style="font-family: monospace;">&nbsp; </span></small>Check ICC
- forward against inverse lookup. <br>
- <small><a style="font-family: monospace;" href="kodak2ti3.html">kodak2ti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an instrument to measure an illuminant spectrum, and estimate its UV
+ content.<br>
+ <small><a style="font-family: monospace;" href="invprofcheck.html">invprofcheck</a><span
+ style="font-family: monospace;">&nbsp; </span></small>Check ICC
+ forward against inverse lookup. <br>
+ <small><a style="font-family: monospace;" href="kodak2ti3.html">kodak2ti3</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Convert
@@ -4096,9 +5867,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Kodak Colorflow format CMYK test chart into Argyll .ti3 CGATS
- format. <br>
- <small><a style="font-family: monospace;" href="mppcheck.html">mppcheck</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Kodak Colorflow format CMYK test chart into Argyll .ti3 CGATS
+ format. <br>
+ <small><a style="font-family: monospace;" href="mppcheck.html">mppcheck</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Check
@@ -4140,8 +5932,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an MPP profile against .ti3 test chart data. <br>
- <small><a style="font-family: monospace;" href="mpplu.html">mpplu</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an MPP profile against .ti3 test chart data. <br>
+ <small><a style="font-family: monospace;" href="mpplu.html">mpplu</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4183,9 +5996,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Lookup individual color values though an MPP
- profile. Also create MPP gamut files/views. <br>
- <small><a style="font-family: monospace;" href="mppprof.html">mppprof</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Lookup individual color values though an MPP
+ profile. Also create MPP gamut files/views. <br>
+ <small><a style="font-family: monospace;" href="mppprof.html">mppprof</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4227,15 +6061,35 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Create a Model Printer Profile (MPP) from the .ti3
- test data. <br>
- <small><a style=" font-family: monospace;"
- href="file:///D:/src/argyll/doc/oeminst.html">oeminst</a><span
- style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- </span></small>Install Instrument manufacturers files for the
- Spyder 2, EDR or CCSS calibration files for i1d3 or Spyder 4,&nbsp;
- CCMX files for colorimeters.<br>
- <small><a style="font-family: monospace;" href="printcal.html">printcal</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Create a Model Printer Profile (MPP) from the .ti3
+ test data. <br>
+ <small><a style=" font-family: monospace;" href="oeminst.html">oeminst</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></small>Install Instrument manufacturers files for the
+ Spyder 2, EDR or CCSS calibration files for i1d3 or Spyder 4,&nbsp;
+ CCMX files for colorimeters.<br>
+ <small><a style="font-family: monospace;" href="printcal.html">printcal</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -4276,8 +6130,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a printer calibration .cal file from a .ti3 data file<small><big>.</big></small><br>
- <small><a style="font-family: monospace;" href="printtarg.html">printtarg</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a printer calibration .cal file from a .ti3 data file<small><big>.</big></small><br>
+ <small><a style="font-family: monospace;" href="printtarg.html">printtarg</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small><small><big>Create
@@ -4319,9 +6194,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a PS, EPS or TIFF file containing test patch values, ready for
- printing.</big></small><br>
- <small><a style="font-family: monospace;" href="profcheck.html">profcheck</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a PS, EPS or TIFF file containing test patch values, ready for
+ printing.</big></small><br>
+ <small><a style="font-family: monospace;" href="profcheck.html">profcheck</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Check
@@ -4363,13 +6259,34 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an ICC profile against .ti3 test chart data. <br>
- <small><a style="font-family: monospace;" href="refine.html">refine</a><span
- style="font-family: monospace;">
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Creates an
- abstract profile from two chart readings, useful for refining
- proofing profiles. <br>
- <small><a style="font-family: monospace;" href="revfix.html">revfix</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an ICC profile against .ti3 test chart data. <br>
+ <small><a style="font-family: monospace;" href="refine.html">refine</a><span
+ style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Creates an
+ abstract profile from two chart readings, useful for refining
+ proofing profiles. <br>
+ <small><a style="font-family: monospace;" href="revfix.html">revfix</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4411,9 +6328,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Regenerate a device profiles B2A table data by
- inverting the A2B table. <br>
- <small><a style="font-family: monospace;" href="scanin.html">scanin</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Regenerate a device profiles B2A table data by
+ inverting the A2B table. <br>
+ <small><a style="font-family: monospace;" href="scanin.html">scanin</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4455,10 +6393,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Convert a TIFF&nbsp; image of a test chart into
- .ti3 device values. <br>
- <small><a style="font-family: monospace;" href="spec2cie.html">spec2cie</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Convert a TIFF&nbsp; image of a test chart into
+ .ti3 device values. <br>
+ <small><a style="font-family: monospace;" href="spec2cie.html">spec2cie</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span
style="text-decoration: underline; font-family: monospace;"></span></small>Convert
@@ -4500,10 +6459,31 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- spectral .ti3 readings into CIE XYZ or L*a*b* readings. Apply FWA,
- plot spectrums.<br>
- <small><a style="font-family: monospace;" href="specplot.html">specplot</a><span
- style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ spectral .ti3 readings into CIE XYZ or L*a*b* readings. Apply FWA,
+ plot spectrums.<br>
+ <small><a style="font-family: monospace;" href="specplot.html">specplot</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span><span
style="text-decoration: underline; font-family: monospace;"></span></small>&nbsp;
@@ -4545,8 +6525,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Plot a spectrum (.sp, .cmf, .ccss) and calculate CCT and VCT.<br>
- <small><a style="font-family: monospace;" href="splitti3.html">splitsti3</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Plot a spectrum (.sp, .cmf, .ccss) and calculate CCT and VCT.<br>
+ <small><a style="font-family: monospace;" href="splitti3.html">splitsti3</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; </span></small>Split
@@ -4587,9 +6588,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a CGATS file (ie. a .ti3) into two parts randomly to verify
- profiling. <br>
- <small><a style="font-family: monospace;" href="spotread.html">spotread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a CGATS file (ie. a .ti3) into two parts randomly to verify
+ profiling. <br>
+ <small><a style="font-family: monospace;" href="spotread.html">spotread</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Use
@@ -4630,9 +6652,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- an instrument to read a single spot color value. <small><a
- style="font-family: monospace;" href="oeminst.html"></a></small><br>
- <small><a style="font-family: monospace;" href="synthcal.html">synthcal</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ an instrument to read a single spot color value. <small><a
+ style="font-family: monospace;" href="oeminst.html"></a></small><br>
+ <small><a style="font-family: monospace;" href="synthcal.html">synthcal</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -4673,9 +6716,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a synthetic input, display or output calibration (<a
- href="File_Formats.html#.cal">.cal</a>)file.<br>
- <small><a style="font-family: monospace;" href="synthread.html">synthread</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ a synthetic input, display or output calibration (<a
+ href="File_Formats.html#.cal">.cal</a>)file.<br>
+ <small><a style="font-family: monospace;" href="synthread.html">synthread</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><big>Fake
@@ -4717,8 +6781,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- the reading of a device using a synthetic device model. </big></small><br>
- <small><a style="font-family: monospace;" href="targen.html">targen</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ the reading of a device using a synthetic device model. </big></small><br>
+ <small><a style="font-family: monospace;" href="targen.html">targen</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4760,9 +6845,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Generate a profiling test target values .ti1 file.
- <br>
- <small><a style="font-family: monospace;" href="tiffgamut.html">tiffgamut</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Generate a profiling test target values .ti1 file.
+ <br>
+ <small><a style="font-family: monospace;" href="tiffgamut.html">tiffgamut</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create
@@ -4804,14 +6910,6 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- a gamut file or VRML file of the color gamut of a TIFF or JPEG
- image. <br>
- <small><a style="font-family: monospace;" href="timage.html">timage</a><span
- style="font-family: monospace;">
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create TIFF
- test images. <br>
- <small><a style="font-family: monospace;" href="txt2ti3.html">txt2ti3</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4832,6 +6930,15 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
+
+ a gamut file or VRML file of the color gamut of a TIFF or JPEG
+ image. <br>
+ <small><a style="font-family: monospace;" href="timage.html">timage</a><span
+ style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></small>Create TIFF
+ test images. <br>
+ <small><a style="font-family: monospace;" href="txt2ti3.html">txt2ti3</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4852,12 +6959,6 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small><small><big>Convert Gretag/Logo/X-Rite or other
- format RGB or CMYK test chart results into Argyll .ti3 CGATS
- format.</big></small> <br>
- <font size="-1"><a style="font-family: monospace;"
- href="verify.html">verify</a><span style="font-family:
- monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font>Verify
@@ -4898,10 +6999,12 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- matching of CIE in two CGATS/.ti3 files (also view differences as
- VRML)<br>
- <font size="-1"><a style="font-family: monospace;"
- href="viewgam.html">viewgam</a><span style="font-family:
+
+ </span></small><small><big>Convert Gretag/Logo/X-Rite or other
+ format RGB or CMYK test chart results into Argyll .ti3 CGATS
+ format.</big></small> <br>
+ <font size="-1"><a style="font-family: monospace;"
+ href="viewgam.html">viewgam</a><span style="font-family:
monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></font>Convert
@@ -4942,9 +7045,30 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- one or more gamuts into a VRML 3D visualization file. Compute an
- intersection.<br>
- <small><a style="font-family: monospace;" href="xicclu.html">xicclu</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ one or more gamuts into a VRML 3D visualization file. Compute an
+ intersection.<br>
+ <small><a style="font-family: monospace;" href="xicclu.html">xicclu</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -4986,36 +7110,57 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- </span></small>Lookup individual color values forward or inverted
- though an ICC profile table. <br>
- <br>
- <h2><u><a href="Environment.html">Environment Variables<br>
- </a></u></h2>
- <span style="text-decoration: underline;"><span style="font-weight:
- bold;"></span></span> Performance/memory tuning hints, plus
- tweaks for scipting.<br>
- <h2><u><a href="Performance.html">Performance Tuning<br>
- </a></u></h2>
- <span style="text-decoration: underline;"><span style="font-weight:
- bold;"></span></span> Performance hints. <br>
- <h2><u><a href="Overview.html">Overview</a></u></h2>
- Overview of the software and its aims and functionality.<br>
- <h2><u><a href="Limitations.html">Limitations</a></u></h2>
- Limitations of the current functionality.<br>
- <h2><u><a href="Organisation.html">Organization</a></u></h2>
- How directories are organized, what they contain.
- <h2><u><a href="Source.html">Source</a></u></h2>
- Any detailed documentation on how the software works, or what
- algorithms it is based on. (Very incomplete.)
- <h2><u><a href="MinorTools.html">Minor Tools</a></u></h2>
- A very brief description of minor tools and test harnesses. <br>
- <br>
- <br>
- <h2><u><a name="FFormats"></a><a href="File_Formats.html">File
- formats that Argyll uses</a></u></h2>
- Argyll uses a number of file formats for its operation, some that
- are external standards, and some that are unique to Argyll. <br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></small>Lookup individual color values forward or inverted
+ though an ICC profile or CAL table. <br>
+ <br>
+ <h2><u><a href="Environment.html">Environment Variables<br>
+ </a></u></h2>
+ <span style="text-decoration: underline;"><span style="font-weight:
+ bold;"></span></span> Performance/memory tuning hints, plus
+ tweaks for scipting.<br>
+ <h2><u><a href="Performance.html">Performance Tuning<br>
+ </a></u></h2>
+ <span style="text-decoration: underline;"><span style="font-weight:
+ bold;"></span></span> Performance hints. <br>
+ <h2><u><a href="Overview.html">Overview</a></u></h2>
+ Overview of the software and its aims and functionality.<br>
+ <h2><u><a href="Limitations.html">Limitations</a></u></h2>
+ Limitations of the current functionality.<br>
+ <h2><u><a href="Organisation.html">Organization</a></u></h2>
+ How directories are organized, what they contain.
+ <h2><u><a href="Source.html">Source</a></u></h2>
+ Any detailed documentation on how the software works, or what
+ algorithms it is based on. (Very incomplete.)
+ <h2><u><a href="MinorTools.html">Minor Tools</a></u></h2>
+ A very brief description of minor tools and test harnesses. <br>
+ <br>
+ <br>
+ <h2><u><a name="FFormats"></a><a href="File_Formats.html">File
+ formats that Argyll uses</a></u></h2>
+ Argyll uses a number of file formats for its operation, some that
+ are external standards, and some that are unique to Argyll. <br>
+ <br>
<a href="File_Formats.html#.ti1">.ti1</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5057,7 +7202,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Device test values <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Device test values <br>
<a href="File_Formats.html#.ti2">.ti2</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5099,7 +7265,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Device test values &amp; chart layout <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Device test values &amp; chart layout <br>
<a href="File_Formats.html#.ti3">.ti3</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5141,11 +7328,32 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Device test values &amp; CIE tristimulus/spectral results&nbsp; <a
- href="ti3_format.html">Format details.</a><br>
- <a href="File_Formats.html#.cal">.cal</a>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Device
- calibration information. <a href="cal_format.html">Format details.</a><br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Device test values &amp; CIE tristimulus/spectral results&nbsp; <a
+ href="ti3_format.html">Format details.</a><br>
+ <a href="File_Formats.html#.cal">.cal</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Device
+ calibration information. <a href="cal_format.html">Format details.</a><br>
<a href="File_Formats.html#.cht">.cht</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5187,8 +7395,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Test chart recognition template. <a href="cht_format.html">Format
- details.</a> <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Test chart recognition template. <a href="cht_format.html">Format
+ details.</a> <br>
<a href="File_Formats.html#.gam">.gam</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5230,7 +7459,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- 3D gamut surface description <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 3D gamut surface description <br>
<a href="File_Formats.html#.sp">.sp</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5272,12 +7522,36 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Illuminant spectral description <br>
- <a href="File_Formats.html#.ccmx">.ccmx</a>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Colorimeter Correction Matrix <br>
- <a href="File_Formats.html#.ccmx">.ccss</a>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Colorimeter Calibration
- Spectral Set <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Illuminant spectral description <br>
+ <a href="File_Formats.html#.cmf">.cmf</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Color Matching
+ Functions<br>
+ <a href="File_Formats.html#.ccmx">.ccmx</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Colorimeter Correction Matrix <br>
+ <a href="File_Formats.html#.ccmx">.ccss</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Colorimeter Calibration
+ Spectral Set <br>
<a href="File_Formats.html#CGATS">CGATS</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5319,7 +7593,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Standard text based data exchange format <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Standard text based data exchange format <br>
<a href="File_Formats.html#ICC">ICC</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5361,7 +7656,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- International Color Consortium profile format <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ International Color Consortium profile format <br>
<a href="File_Formats.html#MPP">MPP</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5403,7 +7719,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Model device profile format <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Model device profile format <br>
<a href="File_Formats.html#TIFF">TIFF</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5445,7 +7782,28 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Tag Image File Format raster files. <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Tag Image File Format raster files. <br>
<a href="File_Formats.html#JPEG">JPEG</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5487,8 +7845,29 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Joint Photographic Experts Group, JPEG File Interchange Format
- raster files. <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Joint Photographic Experts Group, JPEG File Interchange Format
+ raster files. <br>
<a href="File_Formats.html#VRML">VRML</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -5530,41 +7909,62 @@ href="http://www.google.com/search?hl=en&amp;q=windows+command+prompt+tutorial">
- Virtual Reality Modelling Language 3D file format. <br>
- <br>
- <a href="ucmm.html">ucmm</a> &nbsp; &nbsp;&nbsp;&nbsp; Unix micro
- Color Management Module convention and configuration file format and
- <span style="color: rgb(204, 0, 0); font-weight: bold;">Profile
- Locations</span>.<br>
- &nbsp;
- <h2><u>Errors, Corrections and Omissions:</u></h2>
- <script language="JavaScript">
-<!--
-// Comment
-var v1 = ".com"
-var v2 = "argyllcms"
-var v3 = "Graeme"
-var v4 = "@"
-var v5 = "mailto:"
-var v6 = v5 + v3 + v4 + v2 + v1
-document.write("<a href=" + v6 + ">" + "Let me know" + "</a>")
-//-->
-</script> If you notice any errors, corrections needed or omissions in
- the current documentation, please contact the author.<br>
- &nbsp; <br>
- &nbsp;
- </body>
-</html>
+
+
+
+
+
+
+
+
+ Virtual Reality Modelling Language 3D file format. <br>
+ <br>
+ <a href="ucmm.html">ucmm</a> &nbsp; &nbsp;&nbsp;&nbsp; Unix micro
+ Color Management Module convention and configuration file format and
+ <span style="color: rgb(204, 0, 0); font-weight: bold;">Profile
+ Locations</span>.<br>
+ &nbsp;
+ <h2><u>Errors, Corrections and Omissions:</u></h2>
+ <script language="JavaScript">
+
+<!--
+
+// Comment
+
+var v1 = ".com"
+
+var v2 = "argyllcms"
+
+var v3 = "Graeme"
+
+var v4 = "@"
+
+var v5 = "mailto:"
+
+var v6 = v5 + v3 + v4 + v2 + v1
+
+document.write("<a href=" + v6 + ">" + "Let me know" + "</a>")
+
+//-->
+
+
+
+</script> If you notice any errors, corrections needed or omissions in
+ the current documentation, please contact the author.<br>
+ &nbsp; <br>
+ &nbsp;
+ </body>
+</html>
diff --git a/doc/ChangesSummary.html b/doc/ChangesSummary.html
index 94e3aa3..82d083f 100644
--- a/doc/ChangesSummary.html
+++ b/doc/ChangesSummary.html
@@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
- charset=ISO-8859-1">
+ charset=windows-1252">
<meta name="author" content="Graeme Gill">
<meta name="description" content="Root of Argyll CMS documentation">
<meta name="GENERATOR" content="Mozilla/4.73 [en] (WinNT; I)
@@ -16,6 +16,187 @@
<h1> Summary of Argyll CMS Changes since last release</h1>
<h3>For a <span style="text-decoration: underline;">complete</span>
and more detailed list of changes, please see the log.txt file.</h3>
+ <h1>[V1.6.2 -&gt; V1.6.3] 26th January 2014</h1>
+ <ul>
+ <li>Added ProPhoto.icm and ProPhotoLin.icm to ref profiles.</li>
+ <li>Fix bug in xicclu -py conversion.</li>
+ <li>Added code to minimize ICC rounding error on matrix profile
+ white point accuracy. Re-generated all reference profiles with
+ this change.</li>
+ <li>Changed i1d3 driver to completely ignore any EEPROM checksum
+ errors for non "A-01" rev. instruments.</li>
+ <li>Made transplot handle RGB-&gt;RGB device link.</li>
+ <li>Removed colprof -y option. Use "profcheck -v2" instead, as it
+ is more developed.</li>
+ <li>Fixed bug in dispcal - it was not using the final measurement
+ pass to update the calibration curves.</li>
+ <li>Fixed bug in spotread, dispcal &amp; dispread for CCSS capable
+ instruments where refresh display types was being ignored if a
+ custom observer was used, and/or the custom observer as being
+ ignored, and/or a&nbsp; CCMX was being ignored. Changed instlib
+ semantics for inst_opt_set_ccss_obs :- this is now set
+ immediately, and applied also to any subsequent set_disptype()
+ or col_cal_spec_set().</li>
+ <li>Renamed verify to colverify to avoid clash with MSWin program
+ of the same name. Made it print the patch location for -v2 if it
+ is present in the file.</li>
+ <li>Changed targen to ensure that -V and -p options effects are
+ reflected in the resulting expected CIE values of the .ti1 file.</li>
+ <li>Changed targen so that -V parameter also affects single
+ channel, grey wedge, grid &amp; body centered grid point
+ distribution.</li>
+ <li>Changed colprof to deal with variable grid distribution in a
+ more neuanced way, to reduce overshoot artifacts when the -V
+ parameter is used.</li>
+ <li>Changed colprof to used a power_like function for the grid
+ distribution shape from the -V parameter, so as to avoid issues
+ with a power curve infinte slope near zero.</li>
+ <li>Changed colprof to used a scaled down value of the targen -V
+ parameter as the default for its -V parameter. Documentation now
+ recommends more moderate values for -V.</li>
+ <li>Added a special case to collink for RGB video input encoding
+ to (attempt) to fine tune the black point to compensate for it
+ (probably) not falling on a cLUT grid point. &amp; out encoding</li>
+ <li>Tweaked dispcal to try and improve accuracy of black point
+ calibration.</li>
+ <li>Switch dispread to use NoClamp readings, so that average black
+ point value is not biased.</li>
+ <li>Fixed bug introduced into 1.6.2 oeminst that prevents .ccss
+ files being installed.<br>
+ </li>
+ </ul>
+ <h1>[V1.6.1 -&gt; V1.6.2] 18th November 2013</h1>
+ <ul>
+ <li> Added "dark region emphasis" -V parameter to targen and
+ colprof,&nbsp; in an attempt to improve the accuracy of display
+ profiles intended for use with video. This should improve the
+ subsequent black point accuracy of the profile.</li>
+ <li>Fixed bug and tweaked dispcal black point optimization to err
+ on the black side. Added -v3 for even more debugging
+ information.</li>
+ <li>Changed i1d3 driver to be more forgiving of EEProm checksum
+ calculation, so that it works with the latest release "A-02"
+ rev.&nbsp; i1 display pro &amp; colormunki display instruments,
+ as well as improving its robustness in the face of errors.</li>
+ <li>Fixed race condition bug in OS X HID driver. This fixes
+ occassional problem with i1d3, and also solves problem with the
+ ColorHug on OS X. </li>
+ <li>Fixed problem with TV encoded output and dispread -E -k/-K.</li>
+ <li>Fixed minor bug in DE94 in icclib.</li>
+ <li>Fixed major bug in illumread - result was being corrupted.</li>
+ <li>Fixed "edges don't match" bug in printarg when -iCM -h -s/-S
+ used.</li>
+ <li>Fix bug in -H flag in ccxxmake, chartread, dispcal, dispread,
+ illumread &amp; spotread so that it works once again.</li>
+ <li> <br>
+ </li>
+ </ul>
+ <h1>[V1.6.0 -&gt; V1.6.1] 30th September 2013</h1>
+ <ul>
+ <li>Fix bug in "average -m"<br>
+ </li>
+ <li>Fix oeminst to work with a wider range of i1d3 install files.</li>
+ <li>Fix ColorMunki reflective measurement accuracy, particularly
+ for reflective readings. This has been poor since V1.5</li>
+ <li>Fix bug in using DTP94 on Apple OS X introduced in V1.5</li>
+ <li>Fix MadVR connect code to look for appropriate 32 bit or 64
+ bit .dll.</li>
+ <li>Improve MSWin system driver installation by creating valid
+ ArgyllCMS.cat file to match ArgyllCMS.inf. This eliminates the
+ need to "Disable Driver Signature Enforcement", as well as
+ allowing installation on MSWin&nbsp; 8.1.<br>
+ </li>
+ </ul>
+ <h1>[V1.5.1 -&gt; V1.6.0] 16th August 2013</h1>
+ <ul>
+ <li>Added support for <b>JETI</b> specbos 1211 and 1201 (Thanks
+ to JETI for their support!)</li>
+ <li>Added Video profiling &amp; 3dLut creation support for eeColor
+ and MadVR. See video section in tutorial for pointers to
+ relevant changes to tools. This includes support for MadTPG +
+ various Video standard ICC profiles + verification workflow.<br>
+ </li>
+ <li>Linux profile installation will use <b>colord</b> if
+ libcolordcompat.so is present on system.</li>
+ <li>Fix <b>ColorHug</b> driver so that it is backwards compatible
+ with FW 1.1.8</li>
+ <li>Made sure that MSWin test colors are not color managed. This
+ may affect Vista, Win7 and Win8.</li>
+ <li>Changed spectro/dispwin.c so that null transform color
+ matching is used for displaying test patches on OS X &gt;= 10.6.
+ This should fix calibrating/profiling secondary displays on &gt;
+ OS X 10.6. Note that the 32 bit 10.4 binary will still have
+ problems on &gt; OS X 10.6.</li>
+ <li>Changed <b>instlib API</b> ambient XYZ and spectral units to
+ Lux. In previous versions of instlib they were Lux/pi.</li>
+ <li>For those instruments that support it, made ambient readings
+ honor refresh mode measurements, to improve repeatability when
+ measuring regularly flickering light sources. (specbos, i1d3,
+ i1disp).</li>
+ <li>Changed spotread -ew mode to be Bradford chromatic transform
+ rather than XYZ scaling, to better match Argyll ICC abs. vs.
+ rel.</li>
+ <li>Added support to xicclu to lookup colors though CAL files,
+ both forward and backwards. Will also plot CAL file contents
+ using -g.</li>
+ <li>Added -Y R:rate option to spotread, dispcal, dispread &amp;
+ ccxxmake to allow setting a chosen display refresh rate. This
+ can be used with the Colormunki display, as well as situations
+ in which refresh rate measurement is not reliable.</li>
+ <li>By default printtarg will create PS and EPS files with a CUPS
+ job ticket to disable color management. Use the -U flag to
+ disable this.</li>
+ <li>Added display update delay calibration support to i1pro and
+ ColorMunki (just like i1disp3), to improve measurement times.</li>
+ <li>Changed dispcal &amp; dispread so that they wait up to 0.5
+ seconds when reading dark patches after light ones to allow for
+ display fall time. Added&nbsp; patch order optimization for
+ display patch sets in targen to minimize the extra time.</li>
+ <li>Changed dispwin daemon loader mode option from -E to -X. Added
+ -E option to encode test patch colors in Video 16-235 range.</li>
+ <li>Changed dispcal verify option from -E to -z. Added -E option
+ to encode test patch colors in Video 16-235 range.</li>
+ <li>Added -E option to to dispread to encode test patch colors in
+ Video 16-235 range.</li>
+ <li>Changed CIECAM02 Flare model to distinguish between Flare from
+ the image itself, and Glare from ambient light. This allows
+ scaling Glare with ambient automatically. Changed enumerated
+ viewing conditions for new Flare/Glare settings, changed all to
+ Flareless to improve dark image behavior, while retaining Glare
+ modelling. Tweaked brightness and ambient values.</li>
+ <li>Improved i1pro hi-res mode to improve accuracy.</li>
+ <li>Added Body Centered Cubic grid option to targen.</li>
+ <li>Added -Yn flag to dispcal and dispread, which skips asking the
+ user to place the instrument on the measuring spot.</li>
+ <li>Improve robustness of i1d3 display update measurement code.</li>
+ <li>Added support for applying calibration curves in collink.</li>
+ <li>Changed spotread so that it won't fall back to emissive spot
+ mode if an ambient reading is requested.</li>
+ <li>Turned off B2A table clip map smoothing, as it seems to
+ introduce reversals for some data sets, and provides little
+ benefit.</li>
+ <li>Fixed crash in ucmm/ucmm.c when loading certain profiles using
+ dispwin (thanks to Torok Edwin).</li>
+ <li>Fixed gamut mapping intent "rl" to really use relative L*a*b*</li>
+ <li>Fix bug in cicam02 in V1.5.0 that causes some mapping problems
+ in the red for collink -ir or -ila.&nbsp;</li>
+ <li>Changed cctiff so that it does lossless JPEG copy when there
+ is no color transformation. This makes it more useful for
+ embedding a profile.</li>
+ <li>Fix xicclu so that it works with device links.</li>
+ <li>Fixed bug in shaper/matrix profile curves that caused random
+ bumpy black behaviour (shaper curve optimization local minimum
+ problem).</li>
+ <li>Don't add colorant tag to .tiff files in cctiff unless it is a
+ non-standard space, as Photoshop will barf on such files.</li>
+ <li>Fix bug with Spyder not being able to break out of dispcal
+ adjustment loop.</li>
+ <li>Fix bug in xicc/xicclu, -K flag not being recognised.</li>
+ <li>Fix bug in xicc/xmatrix.c introduced in V1.5 that prevents
+ matrix only profiles from being created.</li>
+ <li>libusb 1.0 is now deprecated in favor of native USB drivers.<br>
+ </li>
+ </ul>
<h1>[V1.5.0 -&gt; V1.5.1] 8th March 2013</h1>
<ul>
<li>Fix spectro/instlib.ksh and standalone instlib build.</li>
@@ -689,6 +870,10 @@
+
+
+
+
</span>for systems with &gt; 3Gig Ram.</li>
<li>Add support for the Eye-One Monitor spectrometer.</li>
<li>Added -L option to <span style="font-weight: bold;">printtarg</span>
@@ -718,6 +903,10 @@
+
+
+
+
and memory usage issues.</li>
<li>Fixed issues with Eye-One Pro Rev B timeouts.</li>
<li>Added new option to collink -fk, that forces 000K input to K
diff --git a/doc/ColorHug.jpg b/doc/ColorHug.jpg
new file mode 100644
index 0000000..6c5d16a
--- /dev/null
+++ b/doc/ColorHug.jpg
Binary files differ
diff --git a/doc/ColorManagement.html b/doc/ColorManagement.html
index fa7b656..50505cd 100644
--- a/doc/ColorManagement.html
+++ b/doc/ColorManagement.html
@@ -96,11 +96,11 @@
down by the International Commission on Illumination (CIE) in 1931
with the establishment of the CIE 1931 <span style="font-weight:
bold;">XYZ</span> color space. This provides a means of predicting
- what light spectra will match in color for a Standard Observer, who
- represents the typical response of the Human eye under given viewing
- conditions. Such a color space is said to be <span
- style="font-weight: bold;">Device Independent</span> since it is
- not related to a particular technological capture or reproduction
+ what light spectra will be a color match to the Standard Observer.
+ The Standard Observer represents the typical response of the Human
+ eye under given viewing conditions. Such a color space is said to be
+ <span style="font-weight: bold;">Device Independent</span> since it
+ is not related to a particular technological capture or reproduction
device. There are also closely related color-spaces which are direct
transformations of the XYZ space, such as the <span
style="font-weight: bold;">L* a* b*</span> space which is a more
@@ -150,8 +150,8 @@
<br>
&nbsp;&nbsp;&nbsp; A Device Link profile provides a transformation
from one Device space to another. It is typically the result of
- linking two device profiles, ie. Device A -&gt; PCS -&gt; Device B,
- resulting in a direct Device A -&gt; Device B transformation.<br>
+ linking two device profiles, ie. Device 1 -&gt; PCS -&gt; Device 2,
+ resulting in a direct Device 1 -&gt; Device 2 transformation.<br>
<br>
<span style="font-weight: bold;">Abstract</span><br>
<br>
@@ -234,11 +234,11 @@
common white point (D50), to facilitate ease of matching colors
amongst devices with different white points. Other viewing condition
effects (ie. image luminance level, viewing surround luminance and
- flare) can be modeled using (for example) using CIECAM02 to modify
- XYZ values.<br>
+ flare/glare) can be modeled using (for example) using CIECAM02 to
+ modify XYZ values.<br>
<br>
Another limitation relates to spectral assumptions. CIE XYZ uses a
- standard observer to convert spectral light values into XYZ values,
+ Standard Observer to convert spectral light values into XYZ values,
but in practice every observer may have slightly different spectral
sensitivities due to biological differences, including aging.
(People with color deficient vision may have radically different
@@ -252,7 +252,7 @@
of reflective prints from the light source used to view them, by
characterizing a prints color by it's reflectance. This is very
convenient, since a print will probably be taken into many different
- lighting situations, but if the color is reduced to XYZ reflectance
+ lighting situations, but if the color is reduced to XYZ reflectance,
the effect of the detailed interaction between the spectra of the
light source and print will lead to inaccuracies.<br>
<br>
diff --git a/doc/Environment.html b/doc/Environment.html
index a319513..66dbbe2 100644
--- a/doc/Environment.html
+++ b/doc/Environment.html
@@ -62,14 +62,17 @@
<div style="margin-left: 40px;"><span style="font-weight: bold;"><span
style="font-weight: bold;"><span style="font-weight: bold;"></span></span></span>Normally
+
a delay of 200 msec is allowed between changing a patch color on a
display, and reading the color with an instrument, although some
- instruments (ie. i1d3) will automatically measure and set an
- appropriate delay during instrument calibration. In rare
- situations this delay may not be sufficient (ie. some TV's with
- extensive image processing features turned on), and a larger delay
- can be set using the <span style="font-weight: bold;"><span
- style="font-weight: bold;"><span style="font-weight: bold;"></span></span></span>ARGYLL_MIN_DISPLAY_UPDATE_DELAY_MS
+ instruments (ie. i1d3, i1pro, ColorMunki) will automatically
+ measure and set an appropriate delay during instrument
+ calibration. In rare situations this delay may not be sufficient
+ (ie. some TV's with extensive image processing features turned
+ on), and a larger delay can be set using the <span
+ style="font-weight: bold;"><span style="font-weight: bold;"><span
+ style="font-weight: bold;"></span></span></span>ARGYLL_MIN_DISPLAY_UPDATE_DELAY_MS
+
environment variable, ie. ARGYLL_MIN_DISPLAY_UPDATE_DELAY_MS=400
would set a 400 msec minimum delay.<br>
@@ -101,6 +104,7 @@
<div style="margin-left: 40px;">Argyll tries to follow the <a
href="http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG
+
Base Directory Specification</a>, and uses the <span
style="font-weight: bold;">XDG_CACHE_HOME</span> environment
variable to place per instrument calibration information (Eye-One
diff --git a/doc/File_Formats.html b/doc/File_Formats.html
index d6e38c5..aa0f4f4 100644
--- a/doc/File_Formats.html
+++ b/doc/File_Formats.html
@@ -3,7 +3,7 @@
<head>
<title>Argyll File Formats</title>
<meta http-equiv="content-type" content="text/html;
- charset=ISO-8859-1">
+ charset=windows-1252">
<meta name="author" content="Graeme Gill">
</head>
<body>
@@ -19,6 +19,7 @@
<a href="#.cht">.cht</a> <br>
<a href="#.gam">.gam</a> <br>
<a href="#.sp">.sp</a><br>
+ <a href="File_Formats.html#.cmf">.cmf</a><br>
<a href="#CGATS">CGATS</a><br>
<a href="#ICC">ICC</a><br>
<a href="#MPP">MPP</a><br>
@@ -89,11 +90,17 @@
<h2><a name=".sp"></a>.sp</h2>
Spectral illuminant description. This is an ASCII text, <a
href="File_Formats.html#CGATS">CGATS</a>, Argyll specific format,
- used to hold a spectral description of an illuminant. Typically it
- is used to record a custom illuminant, for use in
- computing&nbsp;Fluorescent Whitening Agent compensation for
+ used to hold one or more spectral descriptions of an illuminant or
+ color. Typically it is used to record a custom illuminant, for use
+ in computing&nbsp;Fluorescent Whitening Agent compensation for
reflective samples, as well as computing CIE tristimulus values from
spectral samples.<br>
+ <h2><a name=".cmf"></a>.cmf</h2>
+ Color Matching Functions. This is an ASCII text, <a
+ href="file:///D:/src/argyll/doc/File_Formats.html#CGATS">CGATS</a>,
+ Argyll specific format, used to hold three spectral response curves
+ that define a tristimulus observer. The format is the same as a .sp
+ file.<i></i>
<h2><a name=".ccmx"></a>.ccmx</h2>
Colorimeter Correction Matrix. This is an ASCII text, <a
href="File_Formats.html#CGATS">CGATS</a>, Argyll specific format,
@@ -112,7 +119,8 @@
tuned for a particular display. The file contains a description of
the display, the display technology type, the type of spectrometer
used for taking the readings. See <a href="oeminst.html">oeminst</a>
- and <a href="ccxxmake.html">ccxxmake</a> for more information.<br>
+ and <a href="ccxxmake.html">ccxxmake</a> for more information. The
+ format is similar to a .sp file.<br>
<h3><a name="CGATS"></a>CGATS</h3>
CGATS.5 Data Exchange Format, from the Annex J, of the ANSI
CGATS.5-1993 standard.<br>
diff --git a/doc/Installing_Linux.html b/doc/Installing_Linux.html
index ad2cacc..608ff7d 100644
--- a/doc/Installing_Linux.html
+++ b/doc/Installing_Linux.html
@@ -44,11 +44,15 @@
+
+
the <span style="font-weight: bold;">/etc/rc.local</span> startup
script. You may also have to run <span style="font-weight: bold;">xset
+
+
b 100 1000 100</span> in your local setup, if you are running in
an X11 environment. You can check that the system bell is operating
by doing an "echo ^G", where ^G is ctrl-G.<br>
@@ -159,10 +163,19 @@
href="#serial">Serial instrument access:</a></h5>
&nbsp;&nbsp; <a href="#serial">All</a><br>
<br>
- <span style="font-weight: bold;">NOTE:</span> That <span
- style="font-weight: bold;">libmtp</span> has been known to
- interfere with device access, particularly the Spyder 3. You
- probably want to disable this library (look in udev).<br>
+ <span style="font-weight: bold;">NOTE:</span> That <b>mtp-probe</b>
+ /&nbsp; <span style="font-weight: bold;">libmtp</span> been known
+ to interfere with device access, particularly the Spyder 3 and
+ DTP94. Recent versions of the libmtp should ignore any instrument
+ marked as COLOR_MEASUREMENT_DEVICE by the
+ /etc/udev/rules.d/55-Argyll.rules file, but for older systems you
+ probably need to disable libmtp (look in the udev configuration).<br>
+ <br>
+ The <b>JETI</b> specbos <span style="font-weight: bold;">1211</span><span
+ style="font-weight: bold;"> </span>and <b>1201</b> makes use of
+ the <a href="http://www.ftdichip.com/Drivers/VCP.htm">FTDI Virtual
+ COM Port Drivers</a> (VCP), that should come with any recent
+ version of Linux.<br>
<br>
<span style="font-weight: bold;"></span>
<hr style="width: 100%; height: 2px;">
@@ -206,6 +219,8 @@
+
+
<b>/sbin/udevcontrol reload_rules</b> or&nbsp; <span
style="font-weight: bold;">/sbin/udevstart</span> or reboot to get
the new file noticed.<br>
@@ -387,6 +402,8 @@ instruments
+
+
access using hotplug:<br>
</span></h5>
Under <span style="font-weight: bold;">much older versions of Linux</span>,
@@ -542,6 +559,8 @@ instruments
+
+
access:</span><br>
</h5>
If you have a serial instrument then you may find that by default
diff --git a/doc/Installing_MSWindows.html b/doc/Installing_MSWindows.html
index 9079db0..c08e16d 100644
--- a/doc/Installing_MSWindows.html
+++ b/doc/Installing_MSWindows.html
@@ -2,9 +2,9 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
- charset=ISO-8859-1">
+ charset=windows-1252">
<meta http-equiv="content-type" content="text/html;
- charset=ISO-8859-1">
+ charset=windows-1252">
<meta name="GENERATOR" content="Mozilla/4.73 [en] (WinNT; I)
[Netscape]">
<title>Argyll Installation on Microsoft Windows</title>
@@ -60,9 +60,9 @@
<br>
&nbsp;So if the current value of PATH is
"%SystemRoot%\system32;%SystemRoot%" and you unpacked Argyll version
- 1.5.1 in <span style="font-weight: bold;">d:\bin\</span>, then you
+ 1.6.3 in <span style="font-weight: bold;">d:\bin\</span>, then you
would modify PATH to be
- "%SystemRoot%\system32;%SystemRoot%;d:\bin\Argyll_V1.5.1\bin", -
+ "%SystemRoot%\system32;%SystemRoot%;d:\bin\Argyll_V1.6.3\bin", -
i.e. you append the path to the Argyll binaries to your PATH,
separated by the ';' character. The change will take effect when you
start a new command shell, which you start from Start
@@ -112,25 +112,31 @@
have to disable all of them. Reboot after changing settings.<br>
<br>
<hr style="width: 100%; height: 2px;">
- <h3><span style="color: rgb(51, 153, 153);">Serial Instruments:</span><br>
+ <h3><u><font color="#009900">Serial Instruments:</font></u><br>
</h3>
If you are using a serial connected instrument, then there is
nothing special to do to enable this.<br>
- <h3><span style="color: rgb(51, 153, 153);">USB Instruments:</span></h3>
+ <h3><font color="#ff6600"><u>USB Instruments:</u></font></h3>
If you are using a USB connected instrument, then suitable <span
- style="font-weight: bold;">USB drivers</span> may need to be
- installed.<br>
+ style="font-weight: bold;">USB system drivers</span> may need to
+ be installed.<br>
<span style="font-weight: bold;"><br>
- </span>Note that the <span style="font-weight: bold;">Huey</span>
- and <span style="font-weight: bold;">i1 Display Pro</span> and <span
- style="font-weight: bold;">ColorMunki Display</span> colorimeter
- appears as an HID (USB Human Interface Device Class) device, and
- hence will be assigned to the default MSWindows HID driver. You
- therefore <span style="font-weight: bold; text-decoration:
- underline;">don't need</span> to install an Argyll <span
- style="font-weight: bold;">usb</span> driver for these
- instruments, although it is possible to select the libusb0.sys
- driver as an alternative to the default HID driver.<br>
+ </span>Note that the <span style="font-weight: bold;">Huey</span>,
+ <span style="font-weight: bold;">i1 Display Pro</span>, <span
+ style="font-weight: bold;">ColorMunki Display</span> and <b>ColorHug</b>
+ colorimeter appears as an HID (USB Human Interface Device Class)
+ device, and hence will be assigned to the default MSWindows HID
+ driver. You therefore <span style="font-weight: bold;
+ text-decoration: underline;">don't need</span> to install an
+ Argyll <span style="font-weight: bold;">usb</span> system driver
+ for these instruments, although it is possible to select the
+ libusb0.sys driver as an alternative to the default HID driver.<br>
+ <br>
+ If you are using the <b>JETI</b> specbos <span style="font-weight:
+ bold;">1211</span><span style="font-weight: bold;"> </span>or <b>1201</b>,
+ then you may need to install the <a
+ href="http://www.ftdichip.com/Drivers/VCP.htm">FTDI Virtual COM
+ Port Drivers</a> (VCP), if they are not already on your system.<br>
<br>
Jump to your operating system version:<br>
<br>
@@ -158,13 +164,7 @@
<br>
<span style="text-decoration: underline;">To install the Argyll
driver for the first instrument:</span><br>
- &nbsp;&nbsp;&nbsp; Settings -&gt; Power -&gt; <span
- style="font-weight: bold;">Hold Shift Key down and click</span>
- "Restart" -&gt; Troubleshoot -&gt; Advanced Options -&gt; Startup
- Settings -&gt; Restart -&gt;<br>
- &nbsp;&nbsp;&nbsp; (After Reboot) -&gt; "Disable Driver Signature
- Enforcement" (number 7 on the list)<br>
- &nbsp;&nbsp;&nbsp; (After system starts, Plug in instrument)<br>
+ &nbsp;&nbsp;&nbsp; (Plug in instrument)<br>
&nbsp;&nbsp;&nbsp; Desktop -&gt; Settings -&gt; Control Panel -&gt;
Hardware and Sound -&gt; Device Manager -&gt;<br>
&nbsp;&nbsp;&nbsp; Other Devices -&gt; &lt;instrument being
@@ -191,12 +191,7 @@
<br>
<span style="text-decoration: underline;">To install the Argyll
Driver:</span><br>
- Settings -&gt; Power -&gt; <span style="font-weight: bold;">Hold
- Shift Key down and click</span> "Restart" -&gt; Troubleshoot -&gt;
- Advanced Options -&gt; Startup Settings -&gt; Restart -&gt;<br>
- &nbsp;&nbsp;&nbsp; (After Reboot) -&gt; Disable Driver Signature
- Enforcement" (number 7 on the list)<br>
- &nbsp;&nbsp;&nbsp; (After system starts, Plug in instrument)<br>
+ &nbsp;&nbsp;&nbsp; (Plug in instrument)<br>
&nbsp;&nbsp;&nbsp; Desktop -&gt; Settings -&gt; Control Panel -&gt;
Hardware and Sound -&gt; Device Manager<br>
&nbsp;&nbsp;&nbsp; (Locate the instrument in the device list. It may
diff --git a/doc/Installing_OSX.html b/doc/Installing_OSX.html
index d3f9057..8a17291 100644
--- a/doc/Installing_OSX.html
+++ b/doc/Installing_OSX.html
@@ -1,58 +1,59 @@
-<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
+<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
-<head>
- <meta http-equiv="Content-Type"
- content="text/html; charset=ISO-8859-1">
- <meta http-equiv="content-type"
- content="text/html; charset=ISO-8859-1">
- <meta name="GENERATOR"
- content="Mozilla/4.73 [en] (WinNT; I) [Netscape]">
- <title>Argyll Installation on Apple OS X</title>
-</head>
-<body>
-<h1>
-<u>Installing the software on Apple OS X<br>
-</u></h1>
-<br>
-You
-will need to unpack the downloaded file in the location you have chosen
-to hold the executable files. Typically this might be in <span
- style="font-style: italic;">/usr/bin</span>, or perhaps <span
- style="font-style: italic;">$HOME/bin/</span>.<br>
-<br>
-You can unpack it by control-click on the downloaded file
-and &#8220;Open With&#8221; BOMArchiveHelper or Archive Utility. Drag the resulting
-folder to where you want it, e.g. into your home folder (/Users/usrnam
-where usrnam is your username).<br>
-<br>
-Alternatively you can unpack it on the command line using&nbsp; the
-command <span style="font-weight: bold;">tar -zxf</span> <span
- style="font-weight: bold;">archivename.tgz</span>, which will create a
-directory <span style="font-weight: bold;">Argyll_VX.X.X</span>, where
-X.X.X is the version number, and the executables will be in <span
- style="font-weight: bold;">Argyll_VX.X.X/bin</span>. <br>
-<br>
-Open a Terminal shell. This will be in
-Applications-&gt;Utilities-&gt;Terminal (Dragging it to the dock is a
-good idea to make it more accessible).<br>
-<br>
-You will have to
-configure your $PATH environment variable to give access to the
-executables from your command line environment, by editing your <span
- style="font-weight: bold;">.profile</span> file.<br>
-You can do this using a graphical editor, by using the open command:<br>
-<br>
-&nbsp; ~$open .profile<br>
-<br>
-or by using some other editor, such as <span style="font-weight: bold;">vi</span>.<br>
-<br>
-And add the following line to your .path file<br>
-<br>
-&nbsp; PATH=$PATH:$HOME/Argyll_V1.1.1/bin<br>
-<br>
-If you are unfamiliar
-with how to do this, consult an appropriate tutorial, e.g. &lt;<a
- href="http://heather.cs.ucdavis.edu/matloff/public_html/UnixAndC/Unix/ShellIntro.pdf">ShellIntro</a>&gt;.
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;
+ charset=ISO-8859-1">
+ <meta http-equiv="content-type" content="text/html;
+ charset=ISO-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en] (WinNT; I)
+ [Netscape]">
+ <title>Argyll Installation on Apple OS X</title>
+ </head>
+ <body>
+ <h1> <u>Installing the software on Apple OS X<br>
+ </u></h1>
+ <br>
+ You will need to unpack the downloaded file in the location you have
+ chosen to hold the executable files. Typically this might be in <span
+ style="font-style: italic;">/usr/bin</span>, or perhaps <span
+ style="font-style: italic;">$HOME/bin/</span>, or <i>even $HOME.</i><br>
+ <br>
+ You can unpack it by control-click on the downloaded file and &#8220;Open
+ With&#8221; BOMArchiveHelper or Archive Utility. Drag the resulting folder
+ to where you want it, e.g. into your home folder (/Users/usrnam
+ where usrnam is your username).<br>
+ <br>
+ Alternatively you can unpack it on the command line using&nbsp; the
+ command <span style="font-weight: bold;">tar -zxf</span> <span
+ style="font-weight: bold;">archivename.tgz</span>, which will
+ create a directory <span style="font-weight: bold;">Argyll_VX.X.X</span>,
+ where X.X.X is the version number, and the executables will be in <span
+ style="font-weight: bold;">Argyll_VX.X.X/bin</span>. <br>
+ <br>
+ Open a Terminal shell. This will be in
+ Applications-&gt;Utilities-&gt;Terminal (Dragging it to the dock is
+ a good idea to make it more accessible).<br>
+ <br>
+ You will have to configure your $PATH environment variable to give
+ access to the executable from your command line environment, by
+ editing your <span style="font-weight: bold;">.profile</span> file.
+ You can do this using a graphical editor, by using the open command:<br>
+ <br>
+ &nbsp; ~$open .profile<br>
+ <br>
+ or by using some other editor, such as <span style="font-weight:
+ bold;">vi</span>.<br>
+ <br>
+ And add a line similar to the following line to your .path file<br>
+ <br>
+ &nbsp; PATH=$PATH:$HOME/Argyll_VX.X.X/bin<br>
+ <br>
+ where "$HOME/Argyll_VX.X.X/bin" is the path to the executable
+ directory.<br>
+ <br>
+ If you are unfamiliar with how to do this, consult an appropriate
+ tutorial, e.g. &lt;<a
+href="http://heather.cs.ucdavis.edu/matloff/public_html/UnixAndC/Unix/ShellIntro.pdf">ShellIntro</a>&gt;.
The
.tgz
file
@@ -60,224 +61,253 @@ also
contains
several
useful
-reference files (such as
-scanner chart recognition templates, sample illumination spectrum
-etc.) in the ref sub-directory, as well as
-all the current documentation in a doc sub-directory.<br>
-<br>
-For most devices there is nothing special to do. Plug in and go. Some
-devices may not work without some extra help though:<br>
-<h3><a name="ColorMunki"></a><span style="text-decoration: underline;">X-Rite
-ColorMunki</span></h3>
-Some version of X-Rite's ColorMunki drivers released between 2009 and
-2011 install an X-Rite
-daemon that runs as root and grabs the device, preventing any other
-programs (such as Argyll) from opening them. Latter versions seem to be
-more cooperative, and don't suffer from this problem. There are three
-ways of
-working around this problem:<br>
-<br>
-1) Turn off the X-Rite service for the ColorMunki. See &lt;<a
- class="moz-txt-link-freetext"
- href="http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980">http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980</a>&gt;.<br>
-<br>
-2) Run all Argyll programs that need to access the instrument as root.
-For instance:<br>
-<br>
-&nbsp;&nbsp;&nbsp; sudo spotread<br>
-<br>
-and then you will be asked for the root password.<br>
-While these methods will work, they are incovenient. <br>
-<br>
-3) Alter the X-Rite drivers Daeomon so that it runs under your user
-account.<br>
-<br>
-To do this you need to edit the script that controls the X-Rite Daemon.<br>
-<br>
-&nbsp;&nbsp;&nbsp; cd ~<br>
-&nbsp;&nbsp;&nbsp; whoami<br>
-&nbsp;&nbsp;&nbsp; cp
-/Library/LaunchDaemons/com.xrite.device.colormunki.plist temp.plist<br>
-&nbsp;&nbsp;&nbsp; open temp.plist<br>
-<br>
-and add one child below the root:<br>
-<br>
-&nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;">Item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+reference
+
+
+
+ files (such as scanner chart recognition templates, sample
+ illumination spectrum etc.) in the ref sub-directory, as well as all
+ the current documentation in a doc sub-directory.<br>
+ <br>
+ For most devices there is nothing special to do. Plug in and go.
+ Some devices may not work without some extra help though:<br>
+ <h3><a name="ColorMunki"></a><span style="text-decoration:
+ underline;">X-Rite ColorMunki</span></h3>
+ Some version of X-Rite's ColorMunki drivers released between 2009
+ and 2011 install an X-Rite daemon that runs as root and grabs the
+ device, preventing any other programs (such as Argyll) from opening
+ them. Latter versions seem to be more cooperative, and don't suffer
+ from this problem. There are three ways of working around this
+ problem:<br>
+ <br>
+ 1) Turn off the X-Rite service for the ColorMunki. See &lt;<a
+ class="moz-txt-link-freetext"
+href="http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980">http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980</a>&gt;.<br>
+ <br>
+ 2) Run all Argyll programs that need to access the instrument as
+ root. For instance:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; sudo spotread<br>
+ <br>
+ and then you will be asked for the root password.<br>
+ While these methods will work, they are incovenient. <br>
+ <br>
+ 3) Alter the X-Rite drivers Daeomon so that it runs under your user
+ account.<br>
+ <br>
+ To do this you need to edit the script that controls the X-Rite
+ Daemon.<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; cd ~<br>
+ &nbsp;&nbsp;&nbsp; whoami<br>
+ &nbsp;&nbsp;&nbsp; cp
+ /Library/LaunchDaemons/com.xrite.device.colormunki.plist temp.plist<br>
+ &nbsp;&nbsp;&nbsp; open temp.plist<br>
+ <br>
+ and add one child below the root:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;">Item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span><br>
-&nbsp;&nbsp;&nbsp; UserName &nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span><br>
+ &nbsp;&nbsp;&nbsp; UserName &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-myusername<br>
-<br>
-where "myusername" is your username shown by whoami, and save the file.
-You then need
-to copy the modified file back: <br>
-<br>
-&nbsp;&nbsp;&nbsp; sudo cp temp.plist
-/Library/LaunchDaemons/com.xrite.device.colormunki.plist<br>
-<br>
-You will then need to restart the machine for this change to take
-effect, or invoke the following commands:<br>
-<br>
-&nbsp;&nbsp; sudo launchctl unload
-/Library/LaunchDaemons/com.xrite.device.colormunki.plist<br>
-&nbsp;&nbsp; sudo launchctl load
-/Library/LaunchDaemons/com.xrite.device.colormunki.plist<br>
-<br>
-<span style="font-weight: bold;">NOTE</span> that after running Argyll
-tools, you may have to turn the X-Rite service off then on again, or
-disconnect and reconnect the instrument.<br>
-<br>
-<h3><a name="ColorMunki"></a><span style="text-decoration: underline;">X-Rite
-EyeOne
-Pro</span><br>
-</h3>
-Some version of X-Rite's EyeOne Pro drivers drivers released between
-2009 and
-2011 install an X-Rite
-daemon that runs as root and grabs the device, preventing any other
-programs (such as Argyll) from opening them. Latter versions seem to be
-more cooperative, and don't suffer from this problem. There are three
-ways of
-working around this problem:<br>
-<br>
-1) Turn off the X-Rite service for the EyeOne Pro. See &lt;<a
- class="moz-txt-link-freetext"
- href="http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980">http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980</a>&gt;.<br>
-<br>
-2) Run all Argyll programs that need to access the instrument as root.
-For instance:<br>
-<br>
-&nbsp;&nbsp;&nbsp; sudo spotread<br>
-<br>
-and then you will be asked for the root password.<br>
-While these methods will work, they are incovenient. <br>
-<br>
-3) Alter the X-Rite drivers Daeomon so that it runs under your user
-account.<br>
-<br>
-To do this you need to edit the script that controls the X-Rite Daemon.<br>
-<br>
-&nbsp;&nbsp;&nbsp; cd ~<br>
-&nbsp;&nbsp;&nbsp; whoami<br>
-&nbsp;&nbsp;&nbsp; cp
-/Library/LaunchDaemons/com.xrite.device.i1.plist temp.plist<br>
-&nbsp;&nbsp;&nbsp; open temp.plist<br>
-<br>
-and add one child below the root:<br>
-<br>
-&nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;">Item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ myusername<br>
+ <br>
+ where "myusername" is your username shown by whoami, and save the
+ file. You then need to copy the modified file back: <br>
+ <br>
+ &nbsp;&nbsp;&nbsp; sudo cp temp.plist
+ /Library/LaunchDaemons/com.xrite.device.colormunki.plist<br>
+ <br>
+ You will then need to restart the machine for this change to take
+ effect, or invoke the following commands:<br>
+ <br>
+ &nbsp;&nbsp; sudo launchctl unload
+ /Library/LaunchDaemons/com.xrite.device.colormunki.plist<br>
+ &nbsp;&nbsp; sudo launchctl load
+ /Library/LaunchDaemons/com.xrite.device.colormunki.plist<br>
+ <br>
+ <span style="font-weight: bold;">NOTE</span> that after running
+ Argyll tools, you may have to turn the X-Rite service off then on
+ again, or disconnect and reconnect the instrument.<br>
+ <br>
+ <h3><a name="ColorMunki"></a><span style="text-decoration:
+ underline;">X-Rite EyeOne Pro</span><br>
+ </h3>
+ Some version of X-Rite's EyeOne Pro drivers drivers released between
+ 2009 and 2011 install an X-Rite daemon that runs as root and grabs
+ the device, preventing any other programs (such as Argyll) from
+ opening them. Latter versions seem to be more cooperative, and don't
+ suffer from this problem. There are three ways of working around
+ this problem:<br>
+ <br>
+ 1) Turn off the X-Rite service for the EyeOne Pro. See &lt;<a
+ class="moz-txt-link-freetext"
+href="http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980">http://www.xrite.com/product_overview.aspx?ID=1161&amp;Action=support&amp;SupportID=4980</a>&gt;.<br>
+ <br>
+ 2) Run all Argyll programs that need to access the instrument as
+ root. For instance:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; sudo spotread<br>
+ <br>
+ and then you will be asked for the root password.<br>
+ While these methods will work, they are inconvenient. <br>
+ <br>
+ 3) Alter the X-Rite drivers Daemon so that it runs under your user
+ account.<br>
+ <br>
+ To do this you need to edit the script that controls the X-Rite
+ Daemon.<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; cd ~<br>
+ &nbsp;&nbsp;&nbsp; whoami<br>
+ &nbsp;&nbsp;&nbsp; cp
+ /Library/LaunchDaemons/com.xrite.device.i1.plist temp.plist<br>
+ &nbsp;&nbsp;&nbsp; open temp.plist<br>
+ <br>
+ and add one child below the root:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;">Item&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span><br>
-&nbsp;&nbsp;&nbsp; UserName &nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ Value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span><br>
+ &nbsp;&nbsp;&nbsp; UserName &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
string&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-myusername<br>
-<br>
-where "myusername" is your username shown by whoami, and save the file.
-You then need
-to copy the modified file back: <br>
-<br>
-&nbsp;&nbsp;&nbsp; sudo cp temp.plist
-/Library/LaunchDaemons/com.xrite.device.i1.plist<br>
-<br>
-You will then need to restart the machine for this change to take
-effect, or invoke the following commands:<br>
-<br>
-&nbsp;&nbsp; sudo launchctl unload
-/Library/LaunchDaemons/com.xrite.device.i1.plist<br>
-&nbsp;&nbsp; sudo launchctl load
-/Library/LaunchDaemons/com.xrite.device.i1.plist<br>
-<br>
-<span style="font-weight: bold;">NOTE</span> that after running Argyll
-tools, you may have to turn the X-Rite service off then on again, or
-disconnect and reconnect the instrument.<br>
-<br>
-<h3><a name="HCFR"></a>HCFR Colorimeter</h3>
-The default OS X class
-drivers will grab this device, preventing Argyll from accessing it. To
-overcome this, you need to install a codeless kernel extension if you
-wish to use the HCFR colorimeter, that
-prevents this from happening. From the command line you need to create
-a directory called Argyll.kext somewhere convenient, and then place in
-it one file called Info.plist, containing the following:<br>
-<br>
-&nbsp;&nbsp;&nbsp; ----------------- cut here ---------------------<br>
-&nbsp;&nbsp; &lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>
-&nbsp;&nbsp; &lt;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST
-1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;<br>
-&nbsp;&nbsp; &lt;plist version="1.0"&gt;<br>
-&nbsp;&nbsp; &lt;dict&gt;<br>
-&nbsp; &nbsp;&nbsp; &nbsp;
-&lt;key&gt;CFBundleDevelopmentRegion&lt;/key&gt;
-&lt;string&gt;English&lt;/string&gt;<br>
-&nbsp;&nbsp; &nbsp; &nbsp; &lt;key&gt;CFBundleGetInfoString&lt;/key&gt;
-&lt;string&gt;Libusb USB device Shield&lt;/string&gt;<br>
-&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&lt;key&gt;CFBundleIdentifier&lt;/key&gt;
-&lt;string&gt;com.libusb.USB_Shield&lt;/string&gt;<br>
-&nbsp;&nbsp; &nbsp; &nbsp;
-&lt;key&gt;CFBundleInfoDictionaryVersion&lt;/key&gt;
-&lt;string&gt;6.0&lt;/string&gt;<br>
-&nbsp; &nbsp; &nbsp;&nbsp; &lt;key&gt;CFBundleName&lt;/key&gt;
-&lt;string&gt;Libusb USB device Shield&lt;/string&gt;<br>
-&nbsp; &nbsp; &nbsp;&nbsp; &lt;key&gt;CFBundlePackageType&lt;/key&gt;
-&lt;string&gt;KEXT&lt;/string&gt;<br>
-&nbsp;&nbsp; &nbsp; &nbsp; &lt;key&gt;CFBundleSignature&lt;/key&gt;
-&lt;string&gt;????&lt;/string&gt;<br>
-&nbsp; &nbsp; &nbsp;&nbsp; &lt;key&gt;CFBundleVersion&lt;/key&gt;
-&lt;string&gt;6.0&lt;/string&gt;<br>
-&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&lt;key&gt;IOKitPersonalities&lt;/key&gt;<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;dict&gt;<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;
-&lt;key&gt;HCFR&lt;/key&gt;<br>
-&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &lt;dict&gt;<br>
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;
-&lt;key&gt;CFBundleIdentifier&lt;/key&gt;
-&lt;string&gt;com.apple.driver.AppleUSBComposite&lt;/string&gt;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
-&lt;key&gt;IOClass&lt;/key&gt;
-&lt;string&gt;AppleUSBComposite&lt;/string&gt;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp;
-&lt;key&gt;IOProviderClass&lt;/key&gt;
-&lt;string&gt;IOUSBDevice&lt;/string&gt;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp; &lt;key&gt;idVendor&lt;/key&gt;
-&lt;integer&gt;1243&lt;/integer&gt;<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;
-&lt;key&gt;idProduct&lt;/key&gt;
-&lt;integer&gt;91&lt;/integer&gt;<br>
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dict&gt;<br>
-&nbsp;&nbsp; &nbsp; &nbsp; &lt;/dict&gt;<br>
-&nbsp; &nbsp; &nbsp;&nbsp;
-&lt;key&gt;OSBundleCompatibleVersion&lt;/key&gt;
-&lt;string&gt;1.8&lt;/string&gt;<br>
-&nbsp;&nbsp; &nbsp; &nbsp; &lt;key&gt;OSBundleLibraries&lt;/key&gt;<br>
-&nbsp; &nbsp; &nbsp;&nbsp; &lt;dict&gt;<br>
-&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
-&lt;key&gt;com.apple.kernel.iokit&lt;/key&gt;
-&lt;string&gt;6.0&lt;/string&gt;<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/dict&gt;<br>
-&nbsp;&nbsp; &lt;/dict&gt;<br>
-&nbsp;&nbsp; &lt;/plist&gt;<br>
-&nbsp; &nbsp; ----------------- cut here ---------------------<br>
-<br>
-(You can also copy this from the source installation in
-usb/Argyll.kext)<br>
-<br>
-You then need to install it by using:<br>
-<br>
-&nbsp; sudo cp -R Argyll.kext /System/Library/Extensions<br>
-<br>
-supplying the appropriate root password when prompted.<br>
-Reboot the system to activate the extension.<br>
-<br>
-<p><br>
-</p>
-</body>
+
+
+
+ myusername<br>
+ <br>
+ where "myusername" is your username shown by whoami, and save the
+ file. You then need to copy the modified file back: <br>
+ <br>
+ &nbsp;&nbsp;&nbsp; sudo cp temp.plist
+ /Library/LaunchDaemons/com.xrite.device.i1.plist<br>
+ <br>
+ You will then need to restart the machine for this change to take
+ effect, or invoke the following commands:<br>
+ <br>
+ &nbsp;&nbsp; sudo launchctl unload
+ /Library/LaunchDaemons/com.xrite.device.i1.plist<br>
+ &nbsp;&nbsp; sudo launchctl load
+ /Library/LaunchDaemons/com.xrite.device.i1.plist<br>
+ <br>
+ <span style="font-weight: bold;">NOTE</span> that after running
+ Argyll tools, you may have to turn the X-Rite service off then on
+ again, or disconnect and reconnect the instrument.<br>
+ <br>
+ <h3><a name="specbos"></a><span style="text-decoration: underline;">JETI
+specbos
+
+
+
+ 1201 and 1211</span><br>
+ </h3>
+ <br>
+ If you are using the <b>JETI</b> specbos <span style="font-weight:
+ bold;">1211</span><span style="font-weight: bold;"> </span>and <b>1201</b>,
+ then you may need to install the <a
+ href="http://www.ftdichip.com/Drivers/VCP.htm">FTDI Virtual COM
+ Port Drivers</a> (VCP), if they are not already on your system.<br>
+ <br>
+ <h3><a name="HCFR"></a><u>HCFR Colorimeter</u></h3>
+ The default OS X class drivers will grab this device, preventing
+ Argyll from accessing it. To overcome this, you need to install a
+ codeless kernel extension if you wish to use the HCFR colorimeter,
+ that prevents this from happening. From the command line you need to
+ create a directory called Argyll.kext somewhere convenient, and then
+ place in it one file called Info.plist, containing the following:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; ----------------- cut here ---------------------<br>
+ &nbsp;&nbsp; &lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>
+ &nbsp;&nbsp; &lt;!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST
+ 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;<br>
+ &nbsp;&nbsp; &lt;plist version="1.0"&gt;<br>
+ &nbsp;&nbsp; &lt;dict&gt;<br>
+ &nbsp; &nbsp;&nbsp; &nbsp;
+ &lt;key&gt;CFBundleDevelopmentRegion&lt;/key&gt;
+ &lt;string&gt;English&lt;/string&gt;<br>
+ &nbsp;&nbsp; &nbsp; &nbsp;
+ &lt;key&gt;CFBundleGetInfoString&lt;/key&gt; &lt;string&gt;Libusb
+ USB device Shield&lt;/string&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ &lt;key&gt;CFBundleIdentifier&lt;/key&gt;
+ &lt;string&gt;com.libusb.USB_Shield&lt;/string&gt;<br>
+ &nbsp;&nbsp; &nbsp; &nbsp;
+ &lt;key&gt;CFBundleInfoDictionaryVersion&lt;/key&gt;
+ &lt;string&gt;6.0&lt;/string&gt;<br>
+ &nbsp; &nbsp; &nbsp;&nbsp; &lt;key&gt;CFBundleName&lt;/key&gt;
+ &lt;string&gt;Libusb USB device Shield&lt;/string&gt;<br>
+ &nbsp; &nbsp; &nbsp;&nbsp;
+ &lt;key&gt;CFBundlePackageType&lt;/key&gt;
+ &lt;string&gt;KEXT&lt;/string&gt;<br>
+ &nbsp;&nbsp; &nbsp; &nbsp; &lt;key&gt;CFBundleSignature&lt;/key&gt;
+ &lt;string&gt;????&lt;/string&gt;<br>
+ &nbsp; &nbsp; &nbsp;&nbsp; &lt;key&gt;CFBundleVersion&lt;/key&gt;
+ &lt;string&gt;6.0&lt;/string&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ &lt;key&gt;IOKitPersonalities&lt;/key&gt;<br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;dict&gt;<br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;
+ &lt;key&gt;HCFR&lt;/key&gt;<br>
+ &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &lt;dict&gt;<br>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;
+ &lt;key&gt;CFBundleIdentifier&lt;/key&gt;
+ &lt;string&gt;com.apple.driver.AppleUSBComposite&lt;/string&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp; &lt;key&gt;IOClass&lt;/key&gt;
+ &lt;string&gt;AppleUSBComposite&lt;/string&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+ &nbsp; &lt;key&gt;IOProviderClass&lt;/key&gt;
+ &lt;string&gt;IOUSBDevice&lt;/string&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ &nbsp;&nbsp; &lt;key&gt;idVendor&lt;/key&gt;
+ &lt;integer&gt;1243&lt;/integer&gt;<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ &nbsp; &lt;key&gt;idProduct&lt;/key&gt;
+ &lt;integer&gt;91&lt;/integer&gt;<br>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &lt;/dict&gt;<br>
+ &nbsp;&nbsp; &nbsp; &nbsp; &lt;/dict&gt;<br>
+ &nbsp; &nbsp; &nbsp;&nbsp;
+ &lt;key&gt;OSBundleCompatibleVersion&lt;/key&gt;
+ &lt;string&gt;1.8&lt;/string&gt;<br>
+ &nbsp;&nbsp; &nbsp; &nbsp; &lt;key&gt;OSBundleLibraries&lt;/key&gt;<br>
+ &nbsp; &nbsp; &nbsp;&nbsp; &lt;dict&gt;<br>
+ &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &lt;key&gt;com.apple.kernel.iokit&lt;/key&gt;
+ &lt;string&gt;6.0&lt;/string&gt;<br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/dict&gt;<br>
+ &nbsp;&nbsp; &lt;/dict&gt;<br>
+ &nbsp;&nbsp; &lt;/plist&gt;<br>
+ &nbsp; &nbsp; ----------------- cut here ---------------------<br>
+ <br>
+ (You can also copy this from the source installation in
+ usb/Argyll.kext)<br>
+ <br>
+ You then need to install it by using:<br>
+ <br>
+ &nbsp; sudo cp -R Argyll.kext /System/Library/Extensions<br>
+ <br>
+ supplying the appropriate root password when prompted.<br>
+ Reboot the system to activate the extension.<br>
+ <br>
+ <p><br>
+ </p>
+ </body>
</html>
diff --git a/doc/JETI_1211.jpg b/doc/JETI_1211.jpg
new file mode 100644
index 0000000..efbf291
--- /dev/null
+++ b/doc/JETI_1211.jpg
Binary files differ
diff --git a/doc/Performance.html b/doc/Performance.html
index b69f5ae..340cec0 100644
--- a/doc/Performance.html
+++ b/doc/Performance.html
@@ -1,106 +1,142 @@
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
-<head>
- <meta http-equiv="Content-Type"
- content="text/html; charset=iso-8859-1">
- <meta http-equiv="content-type"
- content="text/html; charset=ISO-8859-1">
- <meta name="GENERATOR"
- content="Mozilla/4.73 [en] (WinNT; I) [Netscape]">
- <title>Argyll Performance Tuning</title>
-</head>
-<body>
-<h2>
-<u>Performance Tuning</u></h2>
-<br>
-Some operations in Argyll can be particularly slow, so it is worth
-examining ways of improving performance, or trading memory consumption
-for performance.<br>
-<h3>Creating Device Links and Profiles<br>
-</h3>
-In creating device links or the B2A tables of profiles, the execution
-time is often dominated by the inversion of forward
-color lookup values. An in-memory cache is employed to speed up this
-operation, by keeping computed values in case they can be used more
-than once. The amount of memory used for caching these values is
-pre-set within the inversion code, and by default is set to use half of
-the available RAM on the system, with a minimum of 50 Mbytes.<br>
-<br>
-The reverse cache size can be changed by setting an environment
-variable
-<span style="font-weight: bold;">ARGYLL_REV_CACHE_MULT</span> to a
-number greater or less than than 1.0 This will multiply the size of the
-cache by that number (i.e. 1.5 would increase the cache size by 50%,
-0.5 would halve it).<br>
-<br>
-If you find that <span style="font-weight: bold;">colprof</span>
-or&nbsp; <span style="font-weight: bold;">collink</span>
-are working very slowly, but that your CPU's are nearly idle, then this
-is a sign of disk swapping, and that too much memory is being
-requested.&nbsp; This can be because other applications are also using
-memory, or Argyll's default setting tries to use more memory than is
-actually available. You can try shutting down other applications when
-this happens, or you can <span style="font-weight: bold;">lower</span>
-the amount of memory Argyll uses by setting <span
- style="font-weight: bold;">ARGYLL_REV_CACHE_MULT</span> to a value
-less than 1.0 (ie. try 0.5). <br>
-<br>
-If you have a lot of memory available, you can try increasing the
-cache size to use more of the available RAM (particularly if you get a
-"Warning - Reverse Cell Cache exhausted,
-processing in chunks" message during processing), but if you set it to
-a value too near 2.0 you risk disk swapping, which can slow progress to
-a crawl.<br>
-<br>
-If you have a lot of memory available, then a second adjustment that
-can make a great difference to the time taken
-in creating B2A tables is the resolution of the inverse lookup
-acceleration grid. The finer the grid, the less searching is needed to
-locate the input colorspace values that
-correspond to a target output color value, but the greater the memory
-used in this
-structure, and the greater the setup time needed to initialize the
-acceleration grid. The <span style="font-weight: bold;">ARGYLL_REV_ACC_GRID_RES_MULT</span>
-environment variable can alter the default resolution by a scale
-factor. A value of 0.5 for instance, would halve the resolution
-(typically meaning 1/8 th. the total number of grid entries and
-memory), while a value of 2.0 would double it, typically resulting in 8
-times the memory usage. Increasing the resolution too much will reduce
-the available memory for the reverse cache, and greatly increase setup
-time.<br>
-<br>
-<h3>Setting an environment variable:</h3>
-<br>
-To set an environment variable an MSWindows DOS shell, either use set,
-e.g.;<br>
-<br>
-&nbsp;&nbsp;&nbsp; set ARGYLL_REV_CACHE_MULT=1.5<br>
-<br>
-which will set the value for that session, or set it in<br>
-<br>
-Control Panel-&gt;System-&gt;Advanced-&gt;Environment Variables..<br>
-<br>
-in either user or system variables.<br>
-<br>
-For OS X or Linux, the exact procedure will depend on the shell you are
-running, but<br>
-is usually something like:<br>
-<br>
-&nbsp;&nbsp;&nbsp; export ARGYLL_REV_CACHE_MULT=1.5<br>
-or<br>
-&nbsp;&nbsp;&nbsp; set ARGYLL_REV_CACHE_MULT=1.5<br>
-or<br>
-&nbsp;&nbsp;&nbsp; ARGYLL_REV_CACHE_MULT=1.5<br>
-<br>
-and may need separately exporting, something like:<br>
-<br>
-&nbsp;&nbsp;&nbsp; export ARGYLL_REV_CACHE_MULT<br>
-<br>
-Generally it should be configured in the shell start-up script,&nbsp;
-if you
-want the setting to be used<br>
-for every session.<br>
-<br>
-<br>
-</body>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;
+ charset=ISO-8859-1">
+ <meta http-equiv="content-type" content="text/html;
+ charset=ISO-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en] (WinNT; I)
+ [Netscape]">
+ <title>Argyll Performance Tuning</title>
+ </head>
+ <body>
+ <h2>
+ <u>Performance Tuning</u></h2>
+ <br>
+ Some operations in Argyll can be particularly slow, so it is worth
+ examining ways of improving performance, or trading memory
+ consumption
+ for performance.<br>
+ <h3>Creating Device Links and Profiles<br>
+ </h3>
+ In creating device links or the B2A tables of profiles, the
+ execution
+ time is often dominated by the inversion of forward
+ color lookup values. An in-memory cache is employed to speed up this
+ operation, by keeping computed values in case they can be used more
+ than once. The amount of memory used for caching these values is
+ pre-set within the inversion code, and by default is set to use half
+ of
+ the available RAM on the system, with a minimum of 50 Mbytes.<br>
+ <br>
+ The reverse cache size can be changed by setting an environment
+ variable
+ <span style="font-weight: bold;">ARGYLL_REV_CACHE_MULT</span> to a
+ number greater or less than than 1.0 This will multiply the size of
+ the
+ cache by that number (i.e. 1.5 would increase the cache size by 50%,
+ 0.5 would halve it).<br>
+ <br>
+ If you find that <span style="font-weight: bold;">colprof</span>
+ or&nbsp; <span style="font-weight: bold;">collink</span>
+ are working very slowly, but that your CPU's are nearly idle, then
+ this
+ is a sign of disk swapping, and that too much memory is being
+ requested.&nbsp; This can be because other applications are also
+ using
+ memory, or Argyll's default setting tries to use more memory than is
+ actually available. You can try shutting down other applications
+ when
+ this happens, or you can <span style="font-weight: bold;">lower</span>
+ the amount of memory Argyll uses by setting <span
+ style="font-weight: bold;">ARGYLL_REV_CACHE_MULT</span> to a value
+ less than 1.0 (ie. try 0.5). <br>
+ <br>
+ If you have a lot of memory available, you can try increasing the
+ cache size to use more of the available RAM (particularly if you get
+ a
+ "Warning - Reverse Cell Cache exhausted,
+ processing in chunks" message during processing), but if you set it
+ to
+ a value too near 2.0 you risk disk swapping, which can slow progress
+ to
+ a crawl.<br>
+ <br>
+ If you have a lot of memory available, then a second adjustment that
+ can make a great difference to the time taken
+ in creating B2A tables is the resolution of the inverse lookup
+ acceleration grid. The finer the grid, the less searching is needed
+ to
+ locate the input colorspace values that
+ correspond to a target output color value, but the greater the
+ memory
+ used in this
+ structure, and the greater the setup time needed to initialize the
+ acceleration grid. The <span style="font-weight: bold;">ARGYLL_REV_ACC_GRID_RES_MULT</span>
+ environment variable can alter the default resolution by a scale
+ factor. A value of 0.5 for instance, would halve the resolution
+ (typically meaning 1/8 th. the total number of grid entries and
+ memory), while a value of 2.0 would double it, typically resulting
+ in 8
+ times the memory usage. Increasing the resolution too much will
+ reduce
+ the available memory for the reverse cache, and greatly increase
+ setup
+ time.<br>
+ <br>
+ <h3>Setting an environment variable:</h3>
+ <br>
+ To set an environment variable an MSWindows DOS shell, either use
+ set,
+ e.g.;<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; set ARGYLL_REV_CACHE_MULT=1.5<br>
+ <br>
+ which will set the value for that session, or set it in<br>
+ <br>
+ Control Panel-&gt;System-&gt;Advanced-&gt;Environment Variables..<br>
+ <br>
+ in either user or system variables.<br>
+ <br>
+ You can examine individual variables using<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; echo %VARIABLE_NAME%<br>
+ <br>
+ or see all of them using<br>
+ <br>
+ &nbsp;&nbsp; set<br>
+ <br>
+ <br>
+ For OS X or Linux, the exact procedure will depend on the shell you
+ are
+ running, but<br>
+ is usually something like:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; export ARGYLL_REV_CACHE_MULT=1.5<br>
+ or<br>
+ &nbsp;&nbsp;&nbsp; set ARGYLL_REV_CACHE_MULT=1.5<br>
+ or<br>
+ &nbsp;&nbsp;&nbsp; ARGYLL_REV_CACHE_MULT=1.5<br>
+ <br>
+ and may need separately exporting, something like:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; export ARGYLL_REV_CACHE_MULT<br>
+ <br>
+ Generally it should be configured in the shell start-up
+ script,&nbsp;
+ if you
+ want the setting to be used<br>
+ for every session.<br>
+ <br>
+ You can examine individual variables using<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; echo $VARIABLE_NAME<br>
+ <br>
+ or see all of them using<br>
+ <br>
+ &nbsp;&nbsp; set<br>
+ <br>
+ <br>
+ <br>
+ </body>
</html>
diff --git a/doc/Scenarios.html b/doc/Scenarios.html
index 3995d21..e82a8a4 100644
--- a/doc/Scenarios.html
+++ b/doc/Scenarios.html
@@ -1,152 +1,190 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
- <head>
- <title>Argyll Usage Scenarios</title>
- <meta http-equiv="content-type" content="text/html;
- charset=ISO-8859-1">
- </head>
- <body>
- <h2><u>Typical usage Scenarios and Examples</u></h2>
- Choose a task from the list below. For more details on alternative
- options, follow the links to the individual tools being used.<br>
- <br>
- Note that by default it is assumed that ICC profile have the file
- extension <span style="font-weight: bold;">.icm</span>, but that on
- Apple OS X and Unix/Linux platforms, the <span style="font-weight:
- bold;">.icc</span> extension is expected and should be used.<br>
- <h4><a href="#PM1">Profiling Displays</a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PM1a">Checking you can access your
- display<br>
- </a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PM1b">Adjusting and Calibrating a
- displays</a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PM1c">Adjusting, calibrating and
- profiling in one step<br>
- </a><span style="font-weight: bold;"></span><span
- style="font-weight: bold;"></span><span style="text-decoration:
- underline;"></span></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PM2">Creating display test values</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="#PM3">Taking readings from a
- display</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="#PM4">Creating a display profile</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;"></span><a
- href="#PM5">Installing a display profile</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;"></span><a
- href="#PM6">Expert tips when measuring displays</a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;"></span><a
- href="#PM7">Calibrating and profiling a display that doesn't
- have VideoLUT access.</a></h4>
- <h4><br>
- <a href="#PS1">Profiling Scanners and other input devices such as
- cameras<br>
- </a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PS2">Types of test charts</a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PS3">Taking readings from a
- scanner</a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PS4">Creating a scanner profile</a></h4>
- <h4><br>
- <a href="#PP1">Profiling Printers</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="#PP2">Creating a print profile
- test chart</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PP2b">Printing a
- print profile test chart</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="#PP3">Reading a print test chart
- using an instrument</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="#PP4">Reading a print test chart
- using a scanner</a></h4>
- <h4> </h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PP5">Creating a printer profile<br>
- </a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PP6">Choosing a black generation
- curve</a></h4>
- <br>
- <h4><a href="Scenarios.html#PC1">Calibrating Printers</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC2">Calibrated
- print workflows</a></h4>
- <h4> &nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC3">Creating a
- print calibration test chart</a></h4>
- <h4> </h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC4">Creating a
- printer calibration<br>
- </a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC5">Using a printer
- calibration</a></h4>
- <h4>&nbsp;&nbsp;&nbsp; <a href="#PC6">How profile ink limits are
- handled when calibration is being used<br>
- </a></h4>
- <h4><br>
- <a href="#LP1">Linking Profiles</a></h4>
- <h4><br>
- <a href="#TR1">Transforming colorspaces of raster files</a></h4>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <h3><a name="PM1"></a>Profiling Displays</h3>
- Argyll supports adjusting, calibrating and profiling of displays
- using one of a number of instruments - see <a
- href="instruments.html">instruments</a> for a current list.&nbsp;
- Adjustment and calibration are prior steps to profiling, in which
- the display is adjusted using it's screen controls,&nbsp; and then
- per channel lookup tables are created to make it meet a well behaved
- response of the desired type. The&nbsp; process following that of
- creating a display profile is then similar to that of all other
- output devices :- first a set of device colorspace test values needs
- to be created to exercise the display, then these values need to be
- displayed, while taking measurements of the resulting colors using
- the instrument. Finally, the device value/measured color values need
- to be converted into an ICC profile.<br>
- <br>
- <h3><a name="PM1a"></a>Checking you can access your display<br>
- </h3>
- You might first want to check that you are accessing and can
- calibrate your display. You can do this using the <a
- href="dispwin.html">dispwin</a><span style="font-weight: bold;"></span>
- tool<span style="font-weight: bold;">.</span> If you just run <span
- style="font-weight: bold;">dispwin</span> it will create a test
- window and run through a series of test colors before checking that
- the VideoLUT can be accessed by the display. If you invoke the usage
- for <span style="font-weight: bold;">dispwin</span> (by giving it
- an unrecognized option, e.g. <span style="font-weight: bold;">-?</span>)
- then it will show a list of available displays next to the <span
- style="font-weight: bold;"><span style="font-weight: bold;">-d</span></span>
- flag. Make sure that you are accessing the display you intend to
- calibrate and profile, and that the VideoLUT is effective (the <span
- style="font-weight: bold;">-r</span> flag can be used to just run
- the VideoLUT test). You can also try clearing the VideoLUTs using
- the <span style="font-weight: bold;">-c</span> flag, and loading a
- deliberately strange looking calibration <span style="font-weight:
- bold;">strange.cal</span> that is provided in the Argyll <span
- style="font-weight: bold;">ref</span> directory.<br>
- <br>
- Note that calibrating and/or profiling <span style="font-weight:
- bold;">remote</span> displays is possible using X11 or a web
- browser (see <span style="font-weight: bold;">-d</span> option of
- dispcal and dispread), or by using some external program to send
- test colors to a display (see <span style="font-weight: bold;">-C</span>
- and <span style="font-weight: bold;">-M</span> options of dispcal
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Argyll Usage Scenarios</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=windows-1252">
+ </head>
+ <body>
+ <h2><u>Typical usage Scenarios and Examples</u></h2>
+ Choose a task from the list below. For more details on alternative
+ options, follow the links to the individual tools being used.<br>
+ <br>
+ Note that by default it is assumed that ICC profile have the file
+ extension <span style="font-weight: bold;">.icm</span>, but that on
+ Apple OS X and Unix/Linux platforms, the <span style="font-weight:
+ bold;">.icc</span> extension is expected and should be used.<br>
+ <h4><a href="#PM1">Profiling Displays</a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PM1a">Checking you can access your
+ display<br>
+ </a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PM1b">Adjusting and Calibrating a
+ displays</a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PM1c">Adjusting, calibrating and
+ profiling in one step<br>
+ </a><span style="font-weight: bold;"></span><span
+ style="font-weight: bold;"></span><span style="text-decoration:
+ underline;"></span></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PM2">Creating display test values</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="#PM3">Taking readings from a
+ display</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="#PM4">Creating a display profile</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;"></span><a
+ href="#PM5">Installing a display profile</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;"></span><a
+ href="#PM6">Expert tips when measuring displays</a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <span style="text-decoration: underline;"></span><a
+ href="#PM7">Calibrating and profiling a display that doesn't
+ have VideoLUT access.</a></h4>
+ <h4><br>
+ <a href="#PS1">Profiling Scanners and other input devices such as
+ cameras<br>
+ </a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PS2">Types of test charts</a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PS3">Taking readings from a
+ scanner</a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PS4">Creating a scanner profile</a></h4>
+ <h4><br>
+ <a href="#PP1">Profiling Printers</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="#PP2">Creating a print profile
+ test chart</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PP2b">Printing a
+ print profile test chart</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="#PP3">Reading a print test chart
+ using an instrument</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="#PP4">Reading a print test chart
+ using a scanner</a></h4>
+ <h4> </h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PP5">Creating a printer profile<br>
+ </a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PP6">Choosing a black generation
+ curve</a></h4>
+ <br>
+ <h4><a href="Scenarios.html#PC1">Calibrating Printers</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC2">Calibrated
+ print workflows</a></h4>
+ <h4> &nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC3">Creating a
+ print calibration test chart</a></h4>
+ <h4> </h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC4">Creating a
+ printer calibration<br>
+ </a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="Scenarios.html#PC5">Using a printer
+ calibration</a></h4>
+ <h4>&nbsp;&nbsp;&nbsp; <a href="#PC6">How profile ink limits are
+ handled when calibration is being used<br>
+ </a></h4>
+ <h4> <a href="#LP1">Linking Profiles</a></h4>
+ <h4> <a href="#TR1">Transforming colorspaces of raster files</a></h4>
+ <h4></h4>
+ <h4> <a href="#TV1">Creating Video Calibration 3DLuts</a></h4>
+ <h4><a href="Scenarios.html#TV2">Verifying Video Calibration 3DLuts</a></h4>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <h3><a name="PM1"></a>Profiling Displays</h3>
+ Argyll supports adjusting, calibrating and profiling of displays
+ using one of a number of instruments - see <a
+ href="instruments.html">instruments</a> for a current list.&nbsp;
+ Adjustment and calibration are prior steps to profiling, in which
+ the display is adjusted using it's screen controls,&nbsp; and then
+ per channel lookup tables are created to make it meet a well behaved
+ response of the desired type. The&nbsp; process following that of
+ creating a display profile is then similar to that of all other
+ output devices :- first a set of device colorspace test values needs
+ to be created to exercise the display, then these values need to be
+ displayed, while taking measurements of the resulting colors using
+ the instrument. Finally, the device value/measured color values need
+ to be converted into an ICC profile.<br>
+ <br>
+ <h3><a name="PM1a"></a>Checking you can access your display<br>
+ </h3>
+ You might first want to check that you are accessing and can
+ calibrate your display. You can do this using the <a
+ href="dispwin.html">dispwin</a><span style="font-weight: bold;"></span>
+ tool<span style="font-weight: bold;">.</span> If you just run <span
+ style="font-weight: bold;">dispwin</span> it will create a test
+ window and run through a series of test colors before checking that
+ the VideoLUT can be accessed by the display. If you invoke the usage
+ for <span style="font-weight: bold;">dispwin</span> (by giving it
+ an unrecognized option, e.g. <span style="font-weight: bold;">-?</span>)
+ then it will show a list of available displays next to the <span
+ style="font-weight: bold;"><span style="font-weight: bold;">-d</span></span>
+ flag. Make sure that you are accessing the display you intend to
+ calibrate and profile, and that the VideoLUT is effective (the <span
+ style="font-weight: bold;">-r</span> flag can be used to just run
+ the VideoLUT test). You can also try clearing the VideoLUTs using
+ the <span style="font-weight: bold;">-c</span> flag, and loading a
+ deliberately strange looking calibration <span style="font-weight:
+ bold;">strange.cal</span> that is provided in the Argyll <span
+ style="font-weight: bold;">ref</span> directory.<br>
+ <br>
+ Note that calibrating and/or profiling <span style="font-weight:
+ bold;">remote</span> displays is possible using X11 or a web
+ browser (see <span style="font-weight: bold;">-d</span> option of
+ dispcal and dispread), or by using some external program to send
+ test colors to a display (see <span style="font-weight: bold;">-C</span>
+ and <span style="font-weight: bold;">-M</span> options of dispcal
and dispread), but you may want to refer to <a href="#PM7">Calibrating
- and profiling a display that doesn't have VideoLUT access</a>.<br>
- <br>
- <h3><a name="PM1b"></a>Adjusting and Calibrating Displays</h3>
- Please read <a href="calvschar.html">What's the difference between
- Calibration and Characterization ?</a> if you are unclear as to
- the difference .<br>
- <br>
- The first step is to decide what the target should be for adjustment
- and calibration. This boils down to three things: The desired
- brightness, the desired white point, and the desired response curve.
- The native brightness and white points of a display may be different
- to the desired characteristics for some purposes. For instance, for
- graphic arts use, it might be desirable to run with a warmer white
- point of about 5000 degrees Kelvin, rather than the default display
- white point of 6500 to 9000 Kelvin. Some LCD displays are too bright
- to compare to printed material under available lighting, so it might
- be desirable to reduce the maximum brightness.<br>
- <br>
- You can run <a href="dispcal.html#r">dispcal -r</a> to check on how
- your display is currently set up. (you may have to run this as <span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and profiling a display that doesn't have VideoLUT access</a>.<br>
+ <br>
+ <h3><a name="PM1b"></a>Adjusting and Calibrating Displays</h3>
+ Please read <a href="calvschar.html">What's the difference between
+ Calibration and Characterization ?</a> if you are unclear as to
+ the difference .<br>
+ <br>
+ The first step is to decide what the target should be for adjustment
+ and calibration. This boils down to three things: The desired
+ brightness, the desired white point, and the desired response curve.
+ The native brightness and white points of a display may be different
+ to the desired characteristics for some purposes. For instance, for
+ graphic arts use, it might be desirable to run with a warmer white
+ point of about 5000 degrees Kelvin, rather than the default display
+ white point of 6500 to 9000 Kelvin. Some LCD displays are too bright
+ to compare to printed material under available lighting, so it might
+ be desirable to reduce the maximum brightness.<br>
+ <br>
+ You can run <a href="dispcal.html#r">dispcal -r</a> to check on how
+ your display is currently set up. (you may have to run this as <span
style="text-decoration: underline; color: rgb(204, 51, 204);">dispcal
-yl
@@ -157,330 +195,368 @@
- -r</span> for an LCD display, or <span style="text-decoration:
- underline; color: rgb(204, 51, 204);">dispcal -yc -r</span> for a
- CRT display with most of the colorimeter instruments. If so, this
- will apply to all of the following examples.)<br>
- <br>
- Once this is done, <a href="dispcal.html">dispcal</a> can be run to
- guide you through the display adjustments, and then calibrate it. By
- default, the brightness and white point will be kept the same as the
- devices natural brightness and white point. The default response
- curve is a gamma of 2.4, except for Apple OS X systems prior to 10.6
- where a gamma of 1.8 is the default. 2.4 is close to that of&nbsp;
- many monitors, and close to that of the sRGB colorspace. <br>
- <br>
- A typical calibration that leaves the brightness and white point
- alone, might be:<br>
- <br>
- <a href="dispcal.html">dispcal</a> -v TargetA<br>
- <br>
- which will result in a "TargetA.cal" calibration file, that can then
- be used during the profiling stage.<br>
- <br>
- If the absolutely native response of the display is desired during
- profiling, then calibration should be skipped, and the linear.cal
- file from the "ref" directory used instead as the argument to the -k
- flag of <span style="font-weight: bold;">dispread</span>.<br>
- <br>
- <b>Dispcal</b> will display a test window in the middle of the
- screen, and issue a series of instructions about placing the
- instrument on the display. You may need to make sure that the
- display cursor is not in the test window, and it may also be
- necessary to disable any screensaver and powersavers before starting
- the process, although both <span style="font-weight: bold;">dispcal</span>
- and <span style="font-weight: bold;">dispread</span> will attempt
- to do this for you. It's also highly desirable on CRT's, to clear
- your screen of any white or bright background images or windows
- (running your shell window with white text on a black background
- helps a lot here.), or at least keep any bright areas away from the
- test window, and be careful not to change anything on the display
- while the readings are taken. Lots of bright images or windows can
- affect the ability to measure the black point accurately, and
- changing images on the display can cause inconsistency in the
- readings,&nbsp; and leading to poor results.<span
- style="font-weight: bold;"></span> LCD displays seem to be less
- influenced by what else is on the screen.<br>
- <br>
- If <span style="font-weight: bold;">dispcal</span> is run without
- arguments, it will provide a usage screen. The <span
- style="font-weight: bold;">-c</span> parameter allows selecting a
- communication port for an instrument, or selecting the instrument
- you want to use,&nbsp; and the <a href="dispcal.html#d"><span
- style="font-weight: bold;">-d</span></a> option allows selecting
- a target display on a multi-display system. On some multi-monitor
- systems, it may not be possible to independently calibrate and
- profile each display if they appear as one single screen to the
- operating system, or if it is not possible to set separate video
- lookup tables for each display. You can change the position and size
- of the test window using the <a href="dispcal.html#P"><span
- style="font-weight: bold;">-P</span></a> parameter. You can
- determine how best to arrange the test window, as well as whether
- each display has separate video lookup capability, by experimenting
- with the <a href="dispwin.html">dispwin</a> tool. <br>
- <br>
- For a more detailed discussion on interactively adjusting the
- display controls using <span style="font-weight: bold;">dispcal</span>,
- see <a href="dispcal.html#Adjustment">dispcal-adjustment</a>. Once
- you have adjusted and calibrated your display, you can move on to
- the next step.<br>
- <br>
- When you have calibrated and profiled your display, you can keep it
- calibrated using the <a href="dispcal.html#u">dispcal -u</a>
- option.<br>
- <br>
- <h4><a name="PM1c"></a>Adjusting, calibrating and profiling in one
- step.</h4>
- If a simple matrix/shaper display profile is all that is desired, <span
- style="font-weight: bold;">dispcal</span> can be used to do this,
- permitting display adjustment, calibration and profiling all in one
- operation. This is done by using the <span style="font-weight:
- bold;"><span style="font-weight: bold;">dispcal </span>-o</span>
- flag:<br>
- <br>
- <a href="dispcal.html">dispcal</a> <a href="dispcal.html#v">-v</a>
- <a href="dispcal.html#o">-o</a> <a href="dispcal.html#p1">TargetA</a><br>
- <br>
- This will create both a TargetA.cal file, but also a TargetA.icm
- file. See <a href="dispcal.html#o">-o</a> and <a
- href="dispcal.html#O">-O</a> for other variations.<br>
- <br>
- For more flexibility in creating a display profile, the separate
- steps of creating characterization test values using <span
- style="font-weight: bold;">targen</span>, reading them from the
- display using <span style="font-weight: bold;">dispread</span>, and
- then creating a profile using <span style="font-weight: bold;">colprof</span>
- are used. The following steps illustrate this:<br>
- <h4><a name="PM2"></a>Profiling in several steps: Creating display
- test values</h4>
- If the <span style="font-weight: bold;">dispcal</span> has not been
- used to create a display profile at the same time as adjustment and
- calibration, then it can be used to create a suitable set of
- calibration curves as the first step, or the calibration step can be
- omitted, and the display cansimply be profiled.<br>
- <br>
- The first step in profiling any output device, is to create a set of
- device colorspace test values. The important parameters needed are:
- <br>
- <ul>
- <li>What colorspace does the device use ?</li>
- <li>How many test patches do I want to use ?</li>
- <li>What information do I already have about how the device
- behaves ?</li>
- </ul>
- For a display device, &nbsp;the colorspace will be RGB. The number
- of test patches will depend somewhat on what quality profile you
- want to make, what type of profile you want to make, and how long
- you are prepared to wait when testing the display.<br>
- At a minimum, a few hundred values are needed. A matrix/shaper type
- of profile can get by with fewer test values, while a LUT based
- profile will give better results if more test values are used. A
- typical number might be 200-600 or so values, while 1000-2000 is not
- an unreasonable number for a high quality characterization of a
- display.<br>
- <br>
- To assist the choice of test patch values, it can help to have a
- rough idea of how the device behaves. This could be in the form of
- an ICC profile of a similar device, or a lower quality, or previous
- profile for that particular device. If one were going to make a very
- high quality LUT based profile, then it might be worthwhile to make
- up a smaller, preliminary shaper/matrix profile using a few hundred
- test points, before embarking on testing the device with several
- thousand.<br>
- <br>
- Lets say that we ultimately want to make a profile for the device
- "DisplayA", the simplest approach is to make a set of test values
- that is independent of the characteristics of the particular device:<br>
- <br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d3</a> <a href="targen.html#f">-f500</a>
- <a href="targen.html#p1">DisplayA</a><br>
- <br>
- If there is a preliminary or previous profile called "OldDisplay"
- available, and we want to try creating a "pre-conditioned" set of
- test values that will more efficiently sample the device response,
- then the following would achieve this:<br>
- <u><br>
- </u><a href="targen.html"> targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d3</a> <a href="targen.html#f">-f500</a>
- <a href="targen.html#c">-cOldDisplay.icm</a> <a
- href="targen.html#p1">DisplayA</a><br>
- <br>
- The output of <b>targen</b> will be the file DisplayA.ti1,
- containing the device space test values, as well as expected CIE
- values used for chart recognition purposes.<br>
- <br>
- <h4><a name="PM3"></a>Profiling in several steps: Taking readings
- from a display</h4>
- First it is necessary to connect your measurement instrument to your
- computer, and check which communication port it is connected to. In
- the following example, it is assumed that the instrument is
- connected to the default port 1, which is either the first USB
- instrument found, or serial port found. Invoking dispread so as to
- display the usage information (by using a flag -? or --) will list
- the identified serial and USB ports, and their labels.<br>
- <br>
- <a href="dispread.html">dispread</a> <a href="dispread.html#v">-v</a>
- <a href="dispread.html#p1">DisplayA</a><br>
- <br>
- If we created a calibration for the display using <a
- href="dispcal.html">dispcal</a>, then we will want to use this
- when we take the display readings (e.g. TargetA.cal from the
- calibration example)..<br>
- <br>
- <a href="dispread.html">dispread</a> <a href="dispread.html#v">-v</a>
- <a href="dispread.html#k">-k TargetA.cal</a> <a
- href="dispread.html#p1">DisplayA</a><br>
- <br>
- <b>dispread</b> will display a test window in the middle of the
- screen, and issue a series of instructions about placing the
- instrument on the display. You may need to make sure that the
- display cursor is not in the test window, and it may also be
- necessary to disable any screensaver before starting the process.
- Exactly the same facilities are provided to select alternate
- displays using the <span style="font-weight: bold;">-d</span>
- parameter, and an alternate location and size for the test window
- using the <span style="font-weight: bold;">-P</span> parameter as
- with <span style="font-weight: bold;">dispcal</span>.<br>
- <h4><a name="PM4"></a>Profiling in several steps: Creating a display
- profile</h4>
- There are two basic choices of profile type for a display, a
- shaper/matrix profile, or a LUT based profile. They have different
- tradeoffs. A shaper/matrix profile will work well on a well behaved
- display, that is one that behaves in an additive color manner, will
- give very smooth looking results, and needs fewer test points to
- create. A LUT based profile on the other hand, will model any
- display behaviour more accurately, and can accommodate gamut mapping
- and different intent tables. Often it can show some unevenness and
- contouring in the results though.<br>
- <br>
- To create a matrix/shaper profile, the following suffices:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Display A"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#a">-as</a> <a href="colprof.html#p1">DisplayA</a><br>
- <br>
- For a LUT based profile, where gamut mapping is desired, then a
- source profile will need to be provided to define the source gamut.
- For instance, if the display profile was likely to be linked to a
- CMYK printing source profile, say "swop.icm" or "fogra39l.icm", then
- the following would suffice:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Display A"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#S">-S</a><a href="colprof.html#S">
- fogra39l.icm</a> <a href="colprof.html#c">-cpp</a> <a
- href="colprof.html#d">-dmt</a> <a href="colprof.html#p1">DisplayA</a><br>
- <br>
- Make sure you check the delta E report at the end of the profile
- creation, to see if the profile is behaving reasonably.<br>
- If a calibration file was used with <a href="dispread.html">dispread</a>,
- then it will be converted to a vcgt tag in the profile, so that the
- operating system or other system color tools load the lookup curves
- into the display hardware, when the profile is used.<br>
- <h4><a name="PM5"></a>Installing a display profile</h4>
- <a href="dispwin.html">dispwin</a> provides a convenient way of
- installing a profile as the default system profile for the chosen
- display:<br>
- <br>
- <a href="dispwin.html">dispwin</a> <a href="dispwin.html#I">-I</a>
- <a href="dispwin.html#p1">DisplayA.icm</a><br>
- <br>
- This also sets the display to the calibration contained in the
- profile. If you want to try out a calibration before installing the
- profile, using dispwin without the <span style="font-weight: bold;">-I</span>
- option will load a calibration (ICC profile or .cal file) into the
- current display.<br>
- <br>
- Some systems will automatically set the display to the calibration
- contained in the installed profile (ie. OS X), while on other
- systems (ie. MSWindows and Linux/X11) it is necessary to use some
- tool to do this. On MSWindows XP you could install the
- optional&nbsp; <span style="font-weight: bold;">Microsoft&nbsp;Color&nbsp;Control&nbsp;Panel&nbsp;Applet&nbsp;for&nbsp;Windows&nbsp;XP</span>
- available for download from Microsoft to do this, but&nbsp;<span
- style="font-weight: bold;">NOTE</span> however that it seems to
- have a <span style="font-weight: bold;">bug</span>, in that it
- sometimes associates the profiles with the <span
- style="font-weight: bold;">wrong monitor</span> entry. Other
- display calibration tools will often install a similar tool, so
- beware of there being multiple, competing programs. [ Commonly these
- will be in your Start-&gt;Programs-&gt;Startup folder. ]<br>
- On Microsoft Vista, you need to use dispwin -L or some other tool to
- load the installed profiles calibration at startup.<br>
- <br>
- To use dispwin to load the installed profiles calibration to the
- display, use<br>
- <br>
- <a href="dispwin.html">dispwin</a> <a href="dispwin.html#L">-L</a><br>
- <br>
- As per usual, you can select the appropriate display using the <a
- href="dispwin.html#d">-d</a> flag.<br>
- <br>
- This can be automated on MSWindows and X11/Linux by adding this
- command to an appropriate startup script.<br>
- More system specific details, including how to create such startup
- scripts are <a href="dispprofloc.html">here</a>. <br>
- <br>
- If you are using Microsoft <span style="font-weight: bold;">Vista</span>,
- there is a known <span style="font-weight: bold;">bug</span> in
- Vista that resets the calibration every time a fade-in effect is
- executed, which happens if you lock and unlock the computer, resume
- from sleep or hibernate, or User Access Control is activated. Using
- <a href="dispwin.html">dispwin</a> <a href="dispwin.html#L">-L</a>
- may not restore the calibration, because Vista filters out setting
- (what it thinks) is a calibration that is already loaded. Use <a
- href="dispwin.html">dispwin</a> <a href="dispwin.html#c">-c</a> <a
- href="dispwin.html#L">-L</a><span style="font-family: monospace;"></span>
- as a workaround, as this will first clear the calibration, then
- re-load the current calibration.<br>
- <br>
- On X11/Linux systems, you could try adding <a href="dispwin.html">dispwin</a>
- <a href="dispwin.html#L">-L</a> to your <span style="font-weight:
- bold;">~/.config/autostart</span> file, so that your window
- manager automatically sets calibration when it starts. If you are
- running XRandR 1.2, you might consider running the experimental <a
- href="dispwin.html#D">dispwin -E</a> in the background, as in its
- "daemon" mode it will update the profile and calibration in response
- to any changes in the the connected display.<br>
- <br>
- <h4><a name="PM6"></a>Expert tips when measuring displays:<br>
- </h4>
- Sometimes it can be difficult to get good quality, consistent and
- visually relevant readings from displays, due to various practical
- considerations with regard to instruments and the displays
- themselves. Argyll's tools have some extra options that may assist
- in overcoming these problems.<br>
- <br>
- If you are using an Eye-One Pro or ColorMunki spectrometer, then you
- may wish to use the <a href="dispcal.html#H">high resolution
- spectral mode</a> (<span style="font-weight: bold;">-H</span>).
- This may be better at capturing the often narrow wavelength peaks
- that are typical of display primary colors.<br>
- <br>
- All instruments depend on silicon sensors, and such sensors generate
- a temperature dependant level of noise ("dark noise") that is
- factored out of the measurements by a dark or black instrument
- calibration. The spectrometers in particular need this calibration
- before commencing each set of measurements. Often an instrument will
- warm up as it sits on a display, and this warming up can cause the
- dark noise to increase, leading to inaccuracies in dark patch
- measurements. The longer the measurement takes, the worse this
- problem is likely to be. One way of addressing this is to
- "acclimatise" the instrument before commencing measurements by
- placing it on the screen in a powered up state, and leaving it for
- some time. (Some people leave it for up to an hour to acclimatise.).
- Another approach is to try and <a href="dispcal.html#I">compensate
- for dark calibration changes</a> (<span style="font-weight: bold;">-Ib</span>)
- by doing on the fly calibrations during the measurements, based on
- the assumption that the black level of the display itself won't
- change significantly. <br>
- <br>
- Some displays take a long time to settle down and stabilise. The is
- often the case with LCD (Liquid Crystal) displays that use
- fluorescent back lights, and these sorts of displays can change in
- brightness significantly with changes in temperature. One way of
- addressing this is to make sure that the display is given adequate
- time to warm up before measurements. Another approach is to try and
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -r</span> for an LCD display, or <span style="text-decoration:
+ underline; color: rgb(204, 51, 204);">dispcal -yc -r</span> for a
+ CRT display with most of the colorimeter instruments. If so, this
+ will apply to all of the following examples.)<br>
+ <br>
+ Once this is done, <a href="dispcal.html">dispcal</a> can be run to
+ guide you through the display adjustments, and then calibrate it. By
+ default, the brightness and white point will be kept the same as the
+ devices natural brightness and white point. The default response
+ curve is a gamma of 2.4, except for Apple OS X systems prior to 10.6
+ where a gamma of 1.8 is the default. 2.4 is close to that of&nbsp;
+ many monitors, and close to that of the sRGB colorspace. <br>
+ <br>
+ A typical calibration that leaves the brightness and white point
+ alone, might be:<br>
+ <br>
+ <a href="dispcal.html">dispcal</a> -v TargetA<br>
+ <br>
+ which will result in a "TargetA.cal" calibration file, that can then
+ be used during the profiling stage.<br>
+ <br>
+ If the absolutely native response of the display is desired during
+ profiling, then calibration should be skipped, and the linear.cal
+ file from the "ref" directory used instead as the argument to the -k
+ flag of <span style="font-weight: bold;">dispread</span>.<br>
+ <br>
+ <b>Dispcal</b> will display a test window in the middle of the
+ screen, and issue a series of instructions about placing the
+ instrument on the display. You may need to make sure that the
+ display cursor is not in the test window, and it may also be
+ necessary to disable any screensaver and powersavers before starting
+ the process, although both <span style="font-weight: bold;">dispcal</span>
+ and <span style="font-weight: bold;">dispread</span> will attempt
+ to do this for you. It's also highly desirable on CRT's, to clear
+ your screen of any white or bright background images or windows
+ (running your shell window with white text on a black background
+ helps a lot here.), or at least keep any bright areas away from the
+ test window, and be careful not to change anything on the display
+ while the readings are taken. Lots of bright images or windows can
+ affect the ability to measure the black point accurately, and
+ changing images on the display can cause inconsistency in the
+ readings,&nbsp; and leading to poor results.<span
+ style="font-weight: bold;"></span> LCD displays seem to be less
+ influenced by what else is on the screen.<br>
+ <br>
+ If <span style="font-weight: bold;">dispcal</span> is run without
+ arguments, it will provide a usage screen. The <span
+ style="font-weight: bold;">-c</span> parameter allows selecting a
+ communication port for an instrument, or selecting the instrument
+ you want to use,&nbsp; and the <a href="dispcal.html#d"><span
+ style="font-weight: bold;">-d</span></a> option allows selecting
+ a target display on a multi-display system. On some multi-monitor
+ systems, it may not be possible to independently calibrate and
+ profile each display if they appear as one single screen to the
+ operating system, or if it is not possible to set separate video
+ lookup tables for each display. You can change the position and size
+ of the test window using the <a href="dispcal.html#P"><span
+ style="font-weight: bold;">-P</span></a> parameter. You can
+ determine how best to arrange the test window, as well as whether
+ each display has separate video lookup capability, by experimenting
+ with the <a href="dispwin.html">dispwin</a> tool. <br>
+ <br>
+ For a more detailed discussion on interactively adjusting the
+ display controls using <span style="font-weight: bold;">dispcal</span>,
+ see <a href="dispcal.html#Adjustment">dispcal-adjustment</a>. Once
+ you have adjusted and calibrated your display, you can move on to
+ the next step.<br>
+ <br>
+ When you have calibrated and profiled your display, you can keep it
+ calibrated using the <a href="dispcal.html#u">dispcal -u</a>
+ option.<br>
+ <br>
+ <h4><a name="PM1c"></a>Adjusting, calibrating and profiling in one
+ step.</h4>
+ If a simple matrix/shaper display profile is all that is desired, <span
+ style="font-weight: bold;">dispcal</span> can be used to do this,
+ permitting display adjustment, calibration and profiling all in one
+ operation. This is done by using the <span style="font-weight:
+ bold;"><span style="font-weight: bold;">dispcal </span>-o</span>
+ flag:<br>
+ <br>
+ <a href="dispcal.html">dispcal</a> <a href="dispcal.html#v">-v</a>
+ <a href="dispcal.html#o">-o</a> <a href="dispcal.html#p1">TargetA</a><br>
+ <br>
+ This will create both a TargetA.cal file, but also a TargetA.icm
+ file. See <a href="dispcal.html#o">-o</a> and <a
+ href="dispcal.html#O">-O</a> for other variations.<br>
+ <br>
+ For more flexibility in creating a display profile, the separate
+ steps of creating characterization test values using <span
+ style="font-weight: bold;">targen</span>, reading them from the
+ display using <span style="font-weight: bold;">dispread</span>, and
+ then creating a profile using <span style="font-weight: bold;">colprof</span>
+ are used. The following steps illustrate this:<br>
+ <h4><a name="PM2"></a>Profiling in several steps: Creating display
+ test values</h4>
+ If the <span style="font-weight: bold;">dispcal</span> has not been
+ used to create a display profile at the same time as adjustment and
+ calibration, then it can be used to create a suitable set of
+ calibration curves as the first step, or the calibration step can be
+ omitted, and the display cansimply be profiled.<br>
+ <br>
+ The first step in profiling any output device, is to create a set of
+ device colorspace test values. The important parameters needed are:
+ <br>
+ <ul>
+ <li>What colorspace does the device use ?</li>
+ <li>How many test patches do I want to use ?</li>
+ <li>What information do I already have about how the device
+ behaves ?</li>
+ </ul>
+ For a display device, &nbsp;the colorspace will be RGB. The number
+ of test patches will depend somewhat on what quality profile you
+ want to make, what type of profile you want to make, and how long
+ you are prepared to wait when testing the display.<br>
+ At a minimum, a few hundred values are needed. A matrix/shaper type
+ of profile can get by with fewer test values, while a LUT based
+ profile will give better results if more test values are used. A
+ typical number might be 200-600 or so values, while 1000-2000 is not
+ an unreasonable number for a high quality characterization of a
+ display.<br>
+ <br>
+ To assist the choice of test patch values, it can help to have a
+ rough idea of how the device behaves. This could be in the form of
+ an ICC profile of a similar device, or a lower quality, or previous
+ profile for that particular device. If one were going to make a very
+ high quality LUT based profile, then it might be worthwhile to make
+ up a smaller, preliminary shaper/matrix profile using a few hundred
+ test points, before embarking on testing the device with several
+ thousand.<br>
+ <br>
+ Lets say that we ultimately want to make a profile for the device
+ "DisplayA", the simplest approach is to make a set of test values
+ that is independent of the characteristics of the particular device:<br>
+ <br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d3</a> <a href="targen.html#f">-f500</a>
+ <a href="targen.html#p1">DisplayA</a><br>
+ <br>
+ If there is a preliminary or previous profile called "OldDisplay"
+ available, and we want to try creating a "pre-conditioned" set of
+ test values that will more efficiently sample the device response,
+ then the following would achieve this:<br>
+ <u><br>
+ </u><a href="targen.html"> targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d3</a> <a href="targen.html#f">-f500</a>
+ <a href="targen.html#c">-cOldDisplay.icm</a> <a
+ href="targen.html#p1">DisplayA</a><br>
+ <br>
+ The output of <b>targen</b> will be the file DisplayA.ti1,
+ containing the device space test values, as well as expected CIE
+ values used for chart recognition purposes.<br>
+ <br>
+ <h4><a name="PM3"></a>Profiling in several steps: Taking readings
+ from a display</h4>
+ First it is necessary to connect your measurement instrument to your
+ computer, and check which communication port it is connected to. In
+ the following example, it is assumed that the instrument is
+ connected to the default port 1, which is either the first USB
+ instrument found, or serial port found. Invoking dispread so as to
+ display the usage information (by using a flag -? or --) will list
+ the identified serial and USB ports, and their labels.<br>
+ <br>
+ <a href="dispread.html">dispread</a> <a href="dispread.html#v">-v</a>
+ <a href="dispread.html#p1">DisplayA</a><br>
+ <br>
+ If we created a calibration for the display using <a
+ href="dispcal.html">dispcal</a>, then we will want to use this
+ when we take the display readings (e.g. TargetA.cal from the
+ calibration example)..<br>
+ <br>
+ <a href="dispread.html">dispread</a> <a href="dispread.html#v">-v</a>
+ <a href="dispread.html#k">-k TargetA.cal</a> <a
+ href="dispread.html#p1">DisplayA</a><br>
+ <br>
+ <b>dispread</b> will display a test window in the middle of the
+ screen, and issue a series of instructions about placing the
+ instrument on the display. You may need to make sure that the
+ display cursor is not in the test window, and it may also be
+ necessary to disable any screensaver before starting the process.
+ Exactly the same facilities are provided to select alternate
+ displays using the <span style="font-weight: bold;">-d</span>
+ parameter, and an alternate location and size for the test window
+ using the <span style="font-weight: bold;">-P</span> parameter as
+ with <span style="font-weight: bold;">dispcal</span>.<br>
+ <h4><a name="PM4"></a>Profiling in several steps: Creating a display
+ profile</h4>
+ There are two basic choices of profile type for a display, a
+ shaper/matrix profile, or a LUT based profile. They have different
+ tradeoffs. A shaper/matrix profile will work well on a well behaved
+ display, that is one that behaves in an additive color manner, will
+ give very smooth looking results, and needs fewer test points to
+ create. A LUT based profile on the other hand, will model any
+ display behaviour more accurately, and can accommodate gamut mapping
+ and different intent tables. Often it can show some unevenness and
+ contouring in the results though.<br>
+ <br>
+ To create a matrix/shaper profile, the following suffices:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Display A"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#a">-as</a> <a href="colprof.html#p1">DisplayA</a><br>
+ <br>
+ For a LUT based profile, where gamut mapping is desired, then a
+ source profile will need to be provided to define the source gamut.
+ For instance, if the display profile was likely to be linked to a
+ CMYK printing source profile, say "swop.icm" or "fogra39l.icm", then
+ the following would suffice:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Display A"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#S">-S</a><a href="colprof.html#S">
+ fogra39l.icm</a> <a href="colprof.html#c">-cpp</a> <a
+ href="colprof.html#d">-dmt</a> <a href="colprof.html#p1">DisplayA</a><br>
+ <br>
+ Make sure you check the delta E report at the end of the profile
+ creation, to see if the sample data and profile is behaving
+ reasonably.<br>
+ If a calibration file was used with <a href="dispread.html">dispread</a>,
+ then it will be converted to a vcgt tag in the profile, so that the
+ operating system or other system color tools load the lookup curves
+ into the display hardware, when the profile is used.<br>
+ <h4><a name="PM5"></a>Installing a display profile</h4>
+ <a href="dispwin.html">dispwin</a> provides a convenient way of
+ installing a profile as the default system profile for the chosen
+ display:<br>
+ <br>
+ <a href="dispwin.html">dispwin</a> <a href="dispwin.html#I">-I</a>
+ <a href="dispwin.html#p1">DisplayA.icm</a><br>
+ <br>
+ This also sets the display to the calibration contained in the
+ profile. If you want to try out a calibration before installing the
+ profile, using dispwin without the <span style="font-weight: bold;">-I</span>
+ option will load a calibration (ICC profile or .cal file) into the
+ current display.<br>
+ <br>
+ Some systems will automatically set the display to the calibration
+ contained in the installed profile (ie. OS X), while on other
+ systems (ie. MSWindows and Linux/X11) it is necessary to use some
+ tool to do this. On MSWindows XP you could install the
+ optional&nbsp; <span style="font-weight: bold;">Microsoft&nbsp;Color&nbsp;Control&nbsp;Panel&nbsp;Applet&nbsp;for&nbsp;Windows&nbsp;XP</span>
+ available for download from Microsoft to do this, but&nbsp;<span
+ style="font-weight: bold;">NOTE</span> however that it seems to
+ have a <span style="font-weight: bold;">bug</span>, in that it
+ sometimes associates the profiles with the <span
+ style="font-weight: bold;">wrong monitor</span> entry. Other
+ display calibration tools will often install a similar tool, so
+ beware of there being multiple, competing programs. [ Commonly these
+ will be in your Start-&gt;Programs-&gt;Startup folder. ]<br>
+ On Microsoft Vista, you need to use dispwin -L or some other tool to
+ load the installed profiles calibration at startup.<br>
+ <br>
+ To use dispwin to load the installed profiles calibration to the
+ display, use<br>
+ <br>
+ <a href="dispwin.html">dispwin</a> <a href="dispwin.html#L">-L</a><br>
+ <br>
+ As per usual, you can select the appropriate display using the <a
+ href="dispwin.html#d">-d</a> flag.<br>
+ <br>
+ This can be automated on MSWindows and X11/Linux by adding this
+ command to an appropriate startup script.<br>
+ More system specific details, including how to create such startup
+ scripts are <a href="dispprofloc.html">here</a>. <br>
+ <br>
+ If you are using Microsoft <span style="font-weight: bold;">Vista</span>,
+ there is a known <span style="font-weight: bold;">bug</span> in
+ Vista that resets the calibration every time a fade-in effect is
+ executed, which happens if you lock and unlock the computer, resume
+ from sleep or hibernate, or User Access Control is activated. Using
+ <a href="dispwin.html">dispwin</a> <a href="dispwin.html#L">-L</a>
+ may not restore the calibration, because Vista filters out setting
+ (what it thinks) is a calibration that is already loaded. Use <a
+ href="dispwin.html">dispwin</a> <a href="dispwin.html#c">-c</a> <a
+ href="dispwin.html#L">-L</a><span style="font-family: monospace;"></span>
+ as a workaround, as this will first clear the calibration, then
+ re-load the current calibration.<br>
+ <br>
+ On X11/Linux systems, you could try adding <a href="dispwin.html">dispwin</a>
+ <a href="dispwin.html#L">-L</a> to your <span style="font-weight:
+ bold;">~/.config/autostart</span> file, so that your window
+ manager automatically sets calibration when it starts. If you are
+ running XRandR 1.2, you might consider running the experimental <a
+ href="dispwin.html#D">dispwin -E</a> in the background, as in its
+ "daemon" mode it will update the profile and calibration in response
+ to any changes in the the connected display.<br>
+ <br>
+ <h4><a name="PM6"></a>Expert tips when measuring displays:<br>
+ </h4>
+ Sometimes it can be difficult to get good quality, consistent and
+ visually relevant readings from displays, due to various practical
+ considerations with regard to instruments and the displays
+ themselves. Argyll's tools have some extra options that may assist
+ in overcoming these problems.<br>
+ <br>
+ If you are using an Eye-One Pro or ColorMunki spectrometer, then you
+ may wish to use the <a href="dispcal.html#H">high resolution
+ spectral mode</a> (<span style="font-weight: bold;">-H</span>).
+ This may be better at capturing the often narrow wavelength peaks
+ that are typical of display primary colors.<br>
+ <br>
+ All instruments depend on silicon sensors, and such sensors generate
+ a temperature dependant level of noise ("dark noise") that is
+ factored out of the measurements by a dark or black instrument
+ calibration. The spectrometers in particular need this calibration
+ before commencing each set of measurements. Often an instrument will
+ warm up as it sits on a display, and this warming up can cause the
+ dark noise to increase, leading to inaccuracies in dark patch
+ measurements. The longer the measurement takes, the worse this
+ problem is likely to be. One way of addressing this is to
+ "acclimatise" the instrument before commencing measurements by
+ placing it on the screen in a powered up state, and leaving it for
+ some time. (Some people leave it for up to an hour to acclimatise.).
+ Another approach is to try and <a href="dispcal.html#I">compensate
+ for dark calibration changes</a> (<span style="font-weight: bold;">-Ib</span>)
+ by doing on the fly calibrations during the measurements, based on
+ the assumption that the black level of the display itself won't
+ change significantly. <br>
+ <br>
+ Some displays take a long time to settle down and stabilise. The is
+ often the case with LCD (Liquid Crystal) displays that use
+ fluorescent back lights, and these sorts of displays can change in
+ brightness significantly with changes in temperature. One way of
+ addressing this is to make sure that the display is given adequate
+ time to warm up before measurements. Another approach is to try and
<a href="dispcal.html#I">compensate for display white level</a>&nbsp;
@@ -490,20 +566,57 @@
- (<span style="font-weight: bold;">-Iw</span>) changes by doing on
- the fly calibrations during the measurements. Instrument black level
- drift and display white level drift can be combined (<span
- style="font-weight: bold;">-Ibw</span>).<br>
- <br>
- Colorimeter instruments make use of physical color filters that
- approximate the standard observer spectral sensitivity curves.
- Because these filters are not perfectly accurate, the manufacturer
- calibrates the instrument for typical displays, which is why you
- have to make a selection between CRT (Cathode Ray Tube) and LCD
- (Liquid Crystal Display) modes. If you are measuring a display that
- has primary colorants that differ significantly from those typical
- displays,&nbsp; (ie. you have a Wide Gamut Display), then you may
- get disappointing results with a Colorimeter. One way of addressing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (<span style="font-weight: bold;">-Iw</span>) changes by doing on
+ the fly calibrations during the measurements. Instrument black level
+ drift and display white level drift can be combined (<span
+ style="font-weight: bold;">-Ibw</span>).<br>
+ <br>
+ Colorimeter instruments make use of physical color filters that
+ approximate the standard observer spectral sensitivity curves.
+ Because these filters are not perfectly accurate, the manufacturer
+ calibrates the instrument for typical displays, which is why you
+ have to make a selection between CRT (Cathode Ray Tube) and LCD
+ (Liquid Crystal Display) modes. If you are measuring a display that
+ has primary colorants that differ significantly from those typical
+ displays,&nbsp; (ie. you have a Wide Gamut Display), then you may
+ get disappointing results with a Colorimeter. One way of addressing
this problem is to use a <a href="File_Formats.html#.ccmx">Colorimeter
@@ -512,117 +625,154 @@
- Correction Matrix</a>. These are specific to a particular
- Colorimeter and Display make and model combination, although a
- matrix for a different but similar type of display may give better
- results than none at all. A list of contributed <span
- style="font-weight: bold;">ccmx</span> files is <a
- href="ccmxs.html">here</a>.<br>
- <br>
- <h4><a name="PM7"></a>Calibrating and profiling a display that
- doesn't have VideoLUT access.</h4>
- <p>In some situation there is no access to a displays VideoLUT
- hardware, and this hardware is what is usually used to implement
- display calibration. This could be because the display is being
- accessed via a web server, or because the driver or windowing
- system doesn't support VideoLUT access.<br>
- </p>
- <p>There are two basic options in this situation:<br>
- </p>
- <p>&nbsp; 1) Don't attempt to calibrate, just profile the display.<br>
- &nbsp; 2) Calibrate, but incorporate the calibration in some other
- way in the workflow.<br>
- </p>
- <p>The first case requires nothing special - just skip calibration
- (see the previous section <a href="#PM7">Profiling in several
- steps: Creating display test values</a>).</p>
- <p> In the second case, there are three choices:<br>
- </p>
- <p>&nbsp;2a) Use dispcal to create a calibration and a quick profile
- that incorporates the calibration into the profile.<br>
- &nbsp;2b) Use dispcal to create the calibration, then dispread and
- colprof to create a profile, and then incorporate the calibration
- into the profile using applycal.<br>
- &nbsp;2c) Use dispcal to create the calibration, then dispread and
- colprof to create a profile, and then apply the calibration after
- the profile in a cctiff workflow.<br>
- </p>
- <p>The first case requires nothing special, use dispcal in a normal
- fashioned with the <span style="font-weight: bold;">-o</span>
- option to generate a quick profile.The profile created will <span
- style="text-decoration: underline;">not</span> contain a 'vcgt'
- tag, but instead will have the calibration curves incorporated
- into the profile itself. If calibration parameters are chosen that
- change the displays white point or brightness, then this will
- result in a slightly unusual profile that has a white point that
- does not correspond with device R=G=B=1.0. Some systems may not
- cope properly with this type of profile, and a general shift in
- white point through such a profile can create an odd looking
- display if it is applied to images but not to other elements on
- the display say as GUI decoration elements or other application
- windows.<br>
- </p>
- <p>In the second case, the calibration file created using dispcal
- should be provided to dispread using the <span
- style="font-weight: bold;">-K</span> flag:<br>
- </p>
- <p><a href="dispread.html">dispread</a> <a href="dispread.html#v">-v</a>
- <a href="dispread.html#K">-K TargetA.cal</a> <a
- href="dispread.html#p1">DisplayA</a></p>
- <p><span style="font-weight: bold;"></span>Create the profile as
- usual using colprof. but note that colprof will ignore the
- calibration, and that no 'vcgt' tag will be added to the profile.<br>
- You can then use <a href="applycal.html">applycal </a>to combine
- the calibration into the profile. Note that the resulting profile
- will be slightly unusual, since the profile is not made completely
- consistent with the effects of the calibration, and the device
- R=G=B=1.0 probably not longer corresponds with the PCS white or
- the white point.<br>
- </p>
- In the third case, the same procedure as above is used to create a
- profile, but the calibration is applied in a raster transformation
- workflow explicitly, e.g.:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
- href="cctiff.html#p1">SourceProfile.icm</a> <a
- href="cctiff.html#p1">DisplayA.icm</a> <a href="cctiff.html#p2">DisplayA.cal</a>
- <a href="cctiff.html#p3">infile.tif</a> <a href="cctiff.html#p4">outfile.tif</a><br>
- or<br>
- &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
- href="cctiff.html#p1">SourceProfile.icm</a> <a
- href="cctiff.html#p1">DisplayA.icm</a> <a href="cctiff.html#p2">DisplayA.cal</a>
- <a href="cctiff.html#p3">infile.jpg</a> <a href="cctiff.html#p4">outfile.jpg</a><br>
- <span style="font-weight: bold;"></span><br>
- <hr size="2" width="100%">
- <h3><a name="PS1"></a>Profiling Scanners and other input devices
- such as cameras<br>
- </h3>
- Because a scanner or camera is an input device, it is necessary to
- go about profiling it in quite a different way to an output device.
- To profile it, a test chart is needed to exercise the input device
- response, to which the CIE values for each test patch is known.
- Generally standard reflection or transparency test charts are used
- for this purpose.<br>
- <h4><a name="PS2"></a>Types of test charts</h4>
- The most common and popular test chart for scanner profiling is the
- IT8.7/2 chart. This is a standard format chart generally reproduced
- on photographic film, containing about 264 test patches.<br>
- An accessible and affordable source of such targets is Wolf Faust a
- <a href="http://www.targets.coloraid.de/">www.coloraid.de</a>.<br>
- Another source is LaserSoft <a
- href="http://www.silverfast.com/show/it8/en.html">www.silverfast.com.</a><br>
- The Kodak Q-60 Color Input Target is also a typical example:<br>
- <br>
- <img src="Q60.jpg" alt="Kodak Q60 chart image" height="141"
- width="200"> <br>
- <br>
- A very simple chart that is widely available is the Macbeth
- ColorChecker chart, although it contains only 24 patches and
- therefore is probably not ideal for creating profiles:<br>
- <img alt="ColorChecker 24 patch" src="colorchecker.jpg"
- style="width: 112px; height: 78px;"><br>
- <br>
- Other popular charts are the X-Rite/GretagMacbeth ColorChecker DC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Correction Matrix</a>. These are specific to a particular
+ Colorimeter and Display make and model combination, although a
+ matrix for a different but similar type of display may give better
+ results than none at all. A list of contributed <span
+ style="font-weight: bold;">ccmx</span> files is <a
+ href="ccmxs.html">here</a>.<br>
+ <br>
+ <h4><a name="PM7"></a>Calibrating and profiling a display that
+ doesn't have VideoLUT access.</h4>
+ <p>In some situation there is no access to a displays VideoLUT
+ hardware, and this hardware is what is usually used to implement
+ display calibration. This could be because the display is being
+ accessed via a web server, or because the driver or windowing
+ system doesn't support VideoLUT access.<br>
+ </p>
+ <p>There are two basic options in this situation:<br>
+ </p>
+ <p>&nbsp; 1) Don't attempt to calibrate, just profile the display.<br>
+ &nbsp; 2) Calibrate, but incorporate the calibration in some other
+ way in the workflow.<br>
+ </p>
+ <p>The first case requires nothing special - just skip calibration
+ (see the previous section <a href="#PM7">Profiling in several
+ steps: Creating display test values</a>).</p>
+ <p> In the second case, there are three choices:<br>
+ </p>
+ <p>&nbsp;2a) Use dispcal to create a calibration and a quick profile
+ that incorporates the calibration into the profile.<br>
+ &nbsp;2b) Use dispcal to create the calibration, then dispread and
+ colprof to create a profile, and then incorporate the calibration
+ into the profile using applycal.<br>
+ &nbsp;2c) Use dispcal to create the calibration, then dispread and
+ colprof to create a profile, and then apply the calibration after
+ the profile in a cctiff workflow.<br>
+ </p>
+ <p>The first case requires nothing special, use dispcal in a normal
+ fashioned with the <span style="font-weight: bold;">-o</span>
+ option to generate a quick profile.The profile created will <span
+ style="text-decoration: underline;">not</span> contain a 'vcgt'
+ tag, but instead will have the calibration curves incorporated
+ into the profile itself. If calibration parameters are chosen that
+ change the displays white point or brightness, then this will
+ result in a slightly unusual profile that has a white point that
+ does not correspond with device R=G=B=1.0. Some systems may not
+ cope properly with this type of profile, and a general shift in
+ white point through such a profile can create an odd looking
+ display if it is applied to images but not to other elements on
+ the display say as GUI decoration elements or other application
+ windows.<br>
+ </p>
+ <p>In the second case, the calibration file created using dispcal
+ should be provided to dispread using the <span
+ style="font-weight: bold;">-K</span> flag:<br>
+ </p>
+ <p><a href="dispread.html">dispread</a> <a href="dispread.html#v">-v</a>
+ <a href="dispread.html#K">-K TargetA.cal</a> <a
+ href="dispread.html#p1">DisplayA</a></p>
+ <p><span style="font-weight: bold;"></span>Create the profile as
+ usual using colprof. but note that colprof will ignore the
+ calibration, and that no 'vcgt' tag will be added to the profile.<br>
+ You can then use <a href="applycal.html">applycal </a>to combine
+ the calibration into the profile. Note that the resulting profile
+ will be slightly unusual, since the profile is not made completely
+ consistent with the effects of the calibration, and the device
+ R=G=B=1.0 probably not longer corresponds with the PCS white or
+ the white point.<br>
+ </p>
+ In the third case, the same procedure as above is used to create a
+ profile, but the calibration is applied in a raster transformation
+ workflow explicitly, e.g.:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
+ href="cctiff.html#p1">SourceProfile.icm</a> <a
+ href="cctiff.html#p1">DisplayA.icm</a> <a href="cctiff.html#p2">DisplayA.cal</a>
+ <a href="cctiff.html#p3">infile.tif</a> <a href="cctiff.html#p4">outfile.tif</a><br>
+ or<br>
+ &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
+ href="cctiff.html#p1">SourceProfile.icm</a> <a
+ href="cctiff.html#p1">DisplayA.icm</a> <a href="cctiff.html#p2">DisplayA.cal</a>
+ <a href="cctiff.html#p3">infile.jpg</a> <a href="cctiff.html#p4">outfile.jpg</a><br>
+ <span style="font-weight: bold;"></span><br>
+ <hr size="2" width="100%">
+ <h3><a name="PS1"></a>Profiling Scanners and other input devices
+ such as cameras<br>
+ </h3>
+ Because a scanner or camera is an input device, it is necessary to
+ go about profiling it in quite a different way to an output device.
+ To profile it, a test chart is needed to exercise the input device
+ response, to which the CIE values for each test patch is known.
+ Generally standard reflection or transparency test charts are used
+ for this purpose.<br>
+ <h4><a name="PS2"></a>Types of test charts</h4>
+ The most common and popular test chart for scanner profiling is the
+ IT8.7/2 chart. This is a standard format chart generally reproduced
+ on photographic film, containing about 264 test patches.<br>
+ An accessible and affordable source of such targets is Wolf Faust a
+ <a href="http://www.targets.coloraid.de/">www.coloraid.de</a>.<br>
+ Another source is LaserSoft <a
+ href="http://www.silverfast.com/show/it8/en.html">www.silverfast.com.</a><br>
+ The Kodak Q-60 Color Input Target is also a typical example:<br>
+ <br>
+ <img src="Q60.jpg" alt="Kodak Q60 chart image" height="141"
+ width="200"> <br>
+ <br>
+ A very simple chart that is widely available is the Macbeth
+ ColorChecker chart, although it contains only 24 patches and
+ therefore is probably not ideal for creating profiles:<br>
+ <img alt="ColorChecker 24 patch" src="colorchecker.jpg"
+ style="width: 112px; height: 78px;"><br>
+ <br>
+ Other popular charts are the X-Rite/GretagMacbeth ColorChecker DC
and <a href="http://www.xrite.com/product_overview.aspx?ID=938">ColorChecker
@@ -632,17 +782,54 @@
- SG</a> charts:<br>
- <br>
- <img src="DC.jpg" alt="GretagMacbeth ColorChecker DC chart"
- height="122" width="200"> <img alt="ColorChecker SG" src="SG.jpg"
- style="width: 174px; height: 122px;"><br>
- <br>
- The GretagMacbeth Eye-One Pro Scan Target 1.4 can also be used:<br>
- <br>
- <img alt="Eye-One Scan Target 1.4" src="i1scan14.jpg" style="border:
- 2px solid ; width: 200px; height: 140px;"><br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SG</a> charts:<br>
+ <br>
+ <img src="DC.jpg" alt="GretagMacbeth ColorChecker DC chart"
+ height="122" width="200"> <img alt="ColorChecker SG" src="SG.jpg"
+ style="width: 174px; height: 122px;"><br>
+ <br>
+ The GretagMacbeth Eye-One Pro Scan Target 1.4 can also be used:<br>
+ <br>
+ <img alt="Eye-One Scan Target 1.4" src="i1scan14.jpg" style="border:
+ 2px solid ; width: 200px; height: 140px;"><br>
+ <br>
Also supported is the <a href="http://www.hutchcolor.com/hct.htm">HutchColor
@@ -652,13 +839,50 @@
- HCT</a> :<br>
- <br>
- <img alt="HutchColor HCT" src="HCT.jpg" style="width: 182px; height:
- 140px;"><br>
- <br>
- <br>
- and <a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HCT</a> :<br>
+ <br>
+ <img alt="HutchColor HCT" src="HCT.jpg" style="width: 182px; height:
+ 140px;"><br>
+ <br>
+ <br>
+ and <a
href="http://www.christophe-metairie-photographie.com/eng%20digital%20target.html">Christophe
@@ -668,7 +892,44 @@ href="http://www.christophe-metairie-photographie.com/eng%20digital%20target.htm
- M&eacute;tairie's Digital TargeT 003</a> and <a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Métairie's Digital TargeT 003</a> and <a
href="http://www.christophe-metairie-photographie.com/eng%20digital%20target.html">Christophe
@@ -678,12 +939,49 @@ href="http://www.christophe-metairie-photographie.com/eng%20digital%20target.htm
- M&eacute;tairie's Digital Target - 3</a> :<br>
- <br>
- <img alt="CMP_DT_003" src="CMP_DT_003.jpg" style="width: 186px;
- height: 141px;">&nbsp; <img style="width: 203px; height: 140px;"
- alt="CMP_Digital_Target-3" src="CMP_Digital_Target-3.jpg"><br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Métairie's Digital Target - 3</a> :<br>
+ <br>
+ <img alt="CMP_DT_003" src="CMP_DT_003.jpg" style="width: 186px;
+ height: 141px;">&nbsp; <img style="width: 203px; height: 140px;"
+ alt="CMP_Digital_Target-3" src="CMP_Digital_Target-3.jpg"><br>
+ <br>
and the <a href="http://www.silverfast.com/show/dc-targets/en.html">LaserSoft
@@ -693,106 +991,217 @@ href="http://www.christophe-metairie-photographie.com/eng%20digital%20target.htm
- Imaging DCPro Target</a>:<br>
- <br>
- <img style="width: 153px; height: 122px;" alt="LaserSoft DCPro
- Target" src="LSDC.jpg"><br>
- <br>
- The Datacolor <a
- href="http://spyder.datacolor.com/product-cb-spydercheckr.php">SpyderCheckr</a>:<br>
- <br>
- <img style=" width: 146px; height: 109px;" alt="Datacolor
- SpyderCheckr" src="SpyderChecker.jpg"><br>
- <br>
- One of the QPcard's:<br>
- <a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Imaging DCPro Target</a>:<br>
+ <br>
+ <img style="width: 153px; height: 122px;" alt="LaserSoft DCPro
+ Target" src="LSDC.jpg"><br>
+ <br>
+ The Datacolor <a
+ href="http://spyder.datacolor.com/product-cb-spydercheckr.php">SpyderCheckr</a>:<br>
+ <br>
+ <img style=" width: 146px; height: 109px;" alt="Datacolor
+ SpyderCheckr" src="SpyderChecker.jpg"><br>
+ <br>
+ One of the QPcard's:<br>
+ <a
href="http://www.qpcard.com/en_b2c/color-reference-cards/qpcard201.html">QPcard
- 201</a>:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 201</a>:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <a
href="http://www.qpcard.com/en_b2c/color-reference-cards/instant-camera-raw-profiling-with-qpcard-202.html">QPcard
- 202</a>:<br>
- <br>
- <img style=" width: 41px; height: 141px;" alt="QPCard201"
- src="QPcard201.jpg">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <img
- style=" width: 97px; height: 141px;" alt="QPcard202"
- src="QPcard202.jpg"><br>
- <br>
- <h4><a name="PS3"></a>Taking readings from a scanner or camera<br>
- </h4>
- The test chart you are using needs to be placed on the scanner, and
- the scanner needs to be configured to a suitable state, and restored
- to that same state when used subsequently with the resulting
- profile. For a camera, the chart needs to be lit in a controlled and
- even manner using the light source that will be used for subsequent
- photographs, and should be shot so as to minimise any geometric
- distortion, although the <a href="scanin.html#p">scanin -p</a> flag
- may be used to compensate for some degree of distortion. As with any
- color profiling task, it is important to setup a known and
- repeatable image processing flow, to ensure that the resulting
- profile will be usable.<br>
- <br>
- The chart should be captured and saved to a TIFF format file. I will
- assume the resulting file is called scanner.tif. The raster file
- need only be roughly cropped so as to contain the test chart
- (including the charts edges).<br>
- <br>
- The second step is to extract the RGB values from the scanner.tif
- file, and match then to the reference CIE values. To locate the
- patch values in the scan, the <b>scanin</b> tool needs to be given
- a template <a href="File_Formats.html#.cht">.cht</a> file that
- describes the features of the chart, and how the test patches are
- labeled. Also needed is a file containing the CIE values for each of
- the patches in the chart, which is typically supplied with the
- chart, available from the manufacturers web site, or has been
- measured using a spectrometer.<br>
- <br>
- <div style="margin-left: 40px;">For an IT8.7/2 chart, this is the <span
- style="font-weight: bold;">ref/</span><b>it8.cht</b> file
- supplied with Argyll, and&nbsp; the manufacturer will will supply
- an individual or batch average file along with the chart
- containing this information, or downloadable from their web site.
- For instance, Kodak Q60 target reference files are <a
- href="ftp://ftp.kodak.com/gastds/Q60DATA/">here</a>.<br>
- NOTE that the reference file for the IT8.7/2 chart supplied with <span
- style="font-weight: bold;">Monaco&nbsp;EZcolor</span> can be
- obtained by unzipping the .mrf file. (You may have to make a copy
- of the file with a .zip extension to do this.)<br>
- <br>
- For the ColorChecker 24 patch chart, the <span
- style="font-weight: bold;">ref/ColorChecker.cht</span> file
- should be used, and there is also a <span style="font-weight:
- bold;">ref/ColorChecker.cie</span> file provided that is based
- on the manufacturers reference values for the chart. You can also
- create your own reference file using an instrument and chartread,
- making use of the chart reference file <span style="font-weight:
- bold;">ref/ColorChecker.ti2</span>:<br>
- &nbsp;&nbsp; <a href="chartread.html">chartread</a> -n -a
- ColorChecker.ti2<br>
- Note that due to the small number of patches, a profile created
- from such a chart is not likely to be very detailed.<br>
- <br>
- For the ColorChecker DC chart, the <span style="font-weight:
- bold;">ref/ColorCheckerDC.cht</span> file should be used, and
- there will be a ColorCheckerDC reference file supplied by
- X-Rite/GretagMacbeth with the chart.<br>
- <br>
- The ColorChecker SG is relatively expensive, but is preferred by
- many people because (like the ColorChecker and ColorCheckerDC) its
- colors are composed of multiple different pigments, giving it
- reflective spectra that are more representative of the real world,
- unlike many other charts that are created out of combination of 3
- or 4 colorants.<br>
- A limited CIE reference file is available from X-Rite <a
-href="http://www.xrite.com/documents/apps/public/digital_colorchecker_sg_l_a_b.txt">here</a>,
- but it is not in the usual CGATS format. To convert it to a CIE
- reference file useful for <span style="font-weight: bold;">scanin</span>,
- you will need to edit the X-Rite file using a <span
- style="text-decoration: underline;">plain text</span> editor,
- first deleting everything before the line starting with "A1" and
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 202</a>:<br>
+ <br>
+ <img style=" width: 41px; height: 141px;" alt="QPCard201"
+ src="QPcard201.jpg">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <img
+ style=" width: 97px; height: 141px;" alt="QPcard202"
+ src="QPcard202.jpg"><br>
+ <br>
+ <h4><a name="PS3"></a>Taking readings from a scanner or camera<br>
+ </h4>
+ The test chart you are using needs to be placed on the scanner, and
+ the scanner needs to be configured to a suitable state, and restored
+ to that same state when used subsequently with the resulting
+ profile. For a camera, the chart needs to be lit in a controlled and
+ even manner using the light source that will be used for subsequent
+ photographs, and should be shot so as to minimise any geometric
+ distortion, although the <a href="scanin.html#p">scanin -p</a> flag
+ may be used to compensate for some degree of distortion. As with any
+ color profiling task, it is important to setup a known and
+ repeatable image processing flow, to ensure that the resulting
+ profile will be usable.<br>
+ <br>
+ The chart should be captured and saved to a TIFF format file. I will
+ assume the resulting file is called scanner.tif. The raster file
+ need only be roughly cropped so as to contain the test chart
+ (including the charts edges).<br>
+ <br>
+ The second step is to extract the RGB values from the scanner.tif
+ file, and match then to the reference CIE values. To locate the
+ patch values in the scan, the <b>scanin</b> tool needs to be given
+ a template <a href="File_Formats.html#.cht">.cht</a> file that
+ describes the features of the chart, and how the test patches are
+ labeled. Also needed is a file containing the CIE values for each of
+ the patches in the chart, which is typically supplied with the
+ chart, available from the manufacturers web site, or has been
+ measured using a spectrometer.<br>
+ <br>
+ <div style="margin-left: 40px;">For an IT8.7/2 chart, this is the <span
+ style="font-weight: bold;">ref/</span><b>it8.cht</b> file
+ supplied with Argyll, and&nbsp; the manufacturer will will supply
+ an individual or batch average file along with the chart
+ containing this information, or downloadable from their web site.
+ For instance, Kodak Q60 target reference files are <a
+ href="ftp://ftp.kodak.com/gastds/Q60DATA/">here</a>.<br>
+ NOTE that the reference file for the IT8.7/2 chart supplied with <span
+ style="font-weight: bold;">Monaco&nbsp;EZcolor</span> can be
+ obtained by unzipping the .mrf file. (You may have to make a copy
+ of the file with a .zip extension to do this.)<br>
+ <br>
+ For the ColorChecker 24 patch chart, the <span
+ style="font-weight: bold;">ref/ColorChecker.cht</span> file
+ should be used, and there is also a <span style="font-weight:
+ bold;">ref/ColorChecker.cie</span> file provided that is based
+ on the manufacturers reference values for the chart. You can also
+ create your own reference file using an instrument and chartread,
+ making use of the chart reference file <span style="font-weight:
+ bold;">ref/ColorChecker.ti2</span>:<br>
+ &nbsp;&nbsp; <a href="chartread.html">chartread</a> -n -a
+ ColorChecker.ti2<br>
+ Note that due to the small number of patches, a profile created
+ from such a chart is not likely to be very detailed.<br>
+ <br>
+ For the ColorChecker DC chart, the <span style="font-weight:
+ bold;">ref/ColorCheckerDC.cht</span> file should be used, and
+ there will be a ColorCheckerDC reference file supplied by
+ X-Rite/GretagMacbeth with the chart.<br>
+ <br>
+ The ColorChecker SG is relatively expensive, but is preferred by
+ many people because (like the ColorChecker and ColorCheckerDC) its
+ colors are composed of multiple different pigments, giving it
+ reflective spectra that are more representative of the real world,
+ unlike many other charts that are created out of combination of 3
+ or 4 colorants.<br>
+ A limited CIE reference file is available from X-Rite <a
+href="http://www.xrite.com/documents/apps/public/digital_colorchecker_sg_l_a_b.txt">here</a>,
+ but it is not in the usual CGATS format. To convert it to a CIE
+ reference file useful for <span style="font-weight: bold;">scanin</span>,
+ you will need to edit the X-Rite file using a <span
+ style="text-decoration: underline;">plain text</span> editor,
+ first deleting everything before the line starting with "A1" and
everything after "N10", then prepending <a href="SG_header.txt">this
@@ -801,78 +1210,119 @@ href="http://www.xrite.com/documents/apps/public/digital_colorchecker_sg_l_a_b.t
- header</a>, and appending <a href="SG_footer.txt">this footer</a>,
- making sure there are no blank lines inserted in the process.<br>
- If you do happen to have access to a more comprehensive instrument
- measurement of the ColorChecker SG, or you have measured it
- yourself using a color instrument,<br>
- then you <span style="text-decoration: underline;">may</span>
- need to convert the reference information from spectral <span
- style="font-weight: bold;">ColorCheckerSG.txt</span> file to CIE
- value <span style="font-weight: bold;">ColorCheckerSG.cie</span>
- reference file, follow the following steps:<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="txt2ti3.html">txt2ti3</a>
- ColorCheckerSG.txt ColorCheckerSG<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="spec2cie.html">spec2cie</a>
- ColorCheckerSG.ti3 ColorCheckerSG.cie<br>
- <br>
- For the Eye-One Pro Scan Target 1.4 chart, the <span
- style="font-weight: bold;"><span style="font-weight: bold;">ref/</span>i1_RGB_Scan_1.4.cht</span>
- file should be used, and as there is no reference file
- accompanying this chart, the chart needs to be read with an
- instrument (usually the Eye-One Pro). This can be done using
- chartread,&nbsp; making use of the chart reference file <span
- style="font-weight: bold;">ref/i1_RGB_Scan_1.4.ti2</span>:<br>
- &nbsp;&nbsp;&nbsp; <a href="chartread.html">chartread</a> -n -a
- i1_RGB_Scan_1.4<br>
- and then rename the resulting <span style="font-weight: bold;">i1_RGB_Scan_1.4.ti3</span>
- file to <span style="font-weight: bold;">i1_RGB_Scan_1.4.cie</span><br>
- <span style="font-weight: bold;"></span><br>
- For the HutchColor HCT chart, the <span style="font-weight:
- bold;"><span style="font-weight: bold;">ref/</span>Hutchcolor.cht</span>
- file should be used, and the reference <span style="font-weight:
- bold;">.txt</span> file downloaded from the HutchColor website.<br>
- <br>
- For the Christophe M&eacute;tairie's Digital TargeT 003 chart with
- 285 patches, the <span style="font-weight: bold;"><span
- style="font-weight: bold;">ref/</span>CMP_DT_003.cht</span>
- file should be used, and the cie reference <span
- style="font-weight: bold;"></span>files come with the chart.<br>
- <br>
- For the Christophe M&eacute;tairie's Digital Target-3 chart with
- 570 patches, the <span style="font-weight: bold;">ref/CMP_Digital_Target-3.cht</span>
- file should be used, and the cie reference <span
- style="font-weight: bold;"></span>files come with the chart.<br>
- <br>
- For the LaserSoft DCPro chart, the <span style="font-weight:
- bold;">ref/LaserSoftDCPro.cht</span> file should be used, and
- reference <span style="font-weight: bold;">.txt</span> file
- downloaded from the <a
- href="http://www.silverfast.com/it8calibration/">Silverfast
- website</a>.<br>
- <br>
- For the Datacolor SpyderCheckr, the <span style="font-weight:
- bold;">ref/SpyderChecker.cht</span> file should be used, and a
- reference <span style="font-weight: bold;">ref/SpyderChecker.cie
- </span>file made from measuring a sample chart is also available.
- Alternately you could create your own reference file by
- transcribing the <a
- href="http://spyder.datacolor.com/images/photo_checkr_colordatainfo.jpg">values</a>
- on the Datacolor website. <br>
- <br>
- For the QPCard 201, the <span style="font-weight: bold;">ref/QPcard_201.cht</span>
- file should be used, and a reference <span style="font-weight:
- bold;">ref/QPcard_201.cie</span> file made from measuring a
- sample chart is also available. <br>
- <br>
- For the QPCard 202, the <span style="font-weight: bold;">ref/QPcard_202.cht</span>
- file should be used, and a reference <span style="font-weight:
- bold;">ref/QPcard_202.cie</span> file made from measuring a
- sample chart is also available. <br>
- </div>
- <br>
- For any other type of chart, a chart recognition template file will
- need to be created (this is beyond the scope of the current
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ header</a>, and appending <a href="SG_footer.txt">this footer</a>,
+ making sure there are no blank lines inserted in the process.
+ There are reports that X-Rite have experimented with different ink
+ formulations for certain patches, so the above reference may not
+ be as accurate as desired, and it is preferable to measure your
+ own chart using a spectrometer, if you have the capability.<br>
+ If you do happen to have access to a more comprehensive instrument
+ measurement of the ColorChecker SG, or you have measured it
+ yourself using a color instrument,<br>
+ then you <span style="text-decoration: underline;">may</span>
+ need to convert the reference information from spectral <span
+ style="font-weight: bold;">ColorCheckerSG.txt</span> file to CIE
+ value <span style="font-weight: bold;">ColorCheckerSG.cie</span>
+ reference file, follow the following steps:<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="txt2ti3.html">txt2ti3</a>
+ ColorCheckerSG.txt ColorCheckerSG<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="spec2cie.html">spec2cie</a>
+ ColorCheckerSG.ti3 ColorCheckerSG.cie<br>
+ <br>
+ For the Eye-One Pro Scan Target 1.4 chart, the <span
+ style="font-weight: bold;"><span style="font-weight: bold;">ref/</span>i1_RGB_Scan_1.4.cht</span>
+ file should be used, and as there is no reference file
+ accompanying this chart, the chart needs to be read with an
+ instrument (usually the Eye-One Pro). This can be done using
+ chartread,&nbsp; making use of the chart reference file <span
+ style="font-weight: bold;">ref/i1_RGB_Scan_1.4.ti2</span>:<br>
+ &nbsp;&nbsp;&nbsp; <a href="chartread.html">chartread</a> -n -a
+ i1_RGB_Scan_1.4<br>
+ and then rename the resulting <span style="font-weight: bold;">i1_RGB_Scan_1.4.ti3</span>
+ file to <span style="font-weight: bold;">i1_RGB_Scan_1.4.cie</span><br>
+ <span style="font-weight: bold;"></span><br>
+ For the HutchColor HCT chart, the <span style="font-weight:
+ bold;"><span style="font-weight: bold;">ref/</span>Hutchcolor.cht</span>
+ file should be used, and the reference <span style="font-weight:
+ bold;">.txt</span> file downloaded from the HutchColor website.<br>
+ <br>
+ For the Christophe Métairie's Digital TargeT 003 chart with 285
+ patches, the <span style="font-weight: bold;"><span
+ style="font-weight: bold;">ref/</span>CMP_DT_003.cht</span>
+ file should be used, and the cie reference <span
+ style="font-weight: bold;"></span>files come with the chart.<br>
+ <br>
+ For the Christophe Métairie's Digital Target-3 chart with 570
+ patches, the <span style="font-weight: bold;">ref/CMP_Digital_Target-3.cht</span>
+ file should be used, and the cie reference <span
+ style="font-weight: bold;"></span>files come with the chart.<br>
+ <br>
+ For the LaserSoft DCPro chart, the <span style="font-weight:
+ bold;">ref/LaserSoftDCPro.cht</span> file should be used, and
+ reference <span style="font-weight: bold;">.txt</span> file
+ downloaded from the <a
+ href="http://www.silverfast.com/it8calibration/">Silverfast
+ website</a>.<br>
+ <br>
+ For the Datacolor SpyderCheckr, the <span style="font-weight:
+ bold;">ref/SpyderChecker.cht</span> file should be used, and a
+ reference <span style="font-weight: bold;">ref/SpyderChecker.cie
+ </span>file made from measuring a sample chart is also available.
+ Alternately you could create your own reference file by
+ transcribing the <a
+ href="http://spyder.datacolor.com/images/photo_checkr_colordatainfo.jpg">values</a>
+ on the Datacolor website. <br>
+ <br>
+ For the QPCard 201, the <span style="font-weight: bold;">ref/QPcard_201.cht</span>
+ file should be used, and a reference <span style="font-weight:
+ bold;">ref/QPcard_201.cie</span> file made from measuring a
+ sample chart is also available. <br>
+ <br>
+ For the QPCard 202, the <span style="font-weight: bold;">ref/QPcard_202.cht</span>
+ file should be used, and a reference <span style="font-weight:
+ bold;">ref/QPcard_202.cie</span> file made from measuring a
+ sample chart is also available. <br>
+ </div>
+ <br>
+ For any other type of chart, a chart recognition template file will
+ need to be created (this is beyond the scope of the current
documentation, although see&nbsp; the <a href="cht_format.html">.cht_format
@@ -881,398 +1331,439 @@ href="http://www.xrite.com/documents/apps/public/digital_colorchecker_sg_l_a_b.t
- documentation</a>).<br>
- <br>
- To create the scanner .ti3 file, run the <b>scanin</b> tool as
- follows (assuming an IT8 chart is being used):<br>
- <br>
- <a href="scanin.html"> scanin</a> -v scanner.tif It8.cht It8ref.txt<br>
- <br>
- "It8ref.txt" or "It8ref.cie" is assumed to be the name of the CIE
- reference file supplied by the chart manufacturer. The resulting
- file will be named "<b>scanner.ti3</b>".<br>
- <br>
- <span style="font-weight: bold;">scanin</span> will process 16 bit
- per component .tiff files, which (if the scanner is capable of
- creating such files),&nbsp; may improve the quality of the profile.
- <br>
- <br>
- If you have any doubts about the correctness of the chart
- recognition, or the subsequent profile's delta E report is unusual,
- then use the scanin diagnostic flags <a href="scanin.html#d">-dipn</a>
- and examine the <span style="font-weight: bold;">diag.tif</span>
- diagnostic file, to make sure that the patches are identified and
- aligned correctly. If you have problems getting good automatic
- alignment, then consider doing a manual alignment by locating the
- fiducial marks on your scan, and feeding them into scanin <a
- href="scanin.html#F">-F</a> parameters. The fiducial marks should
- be listed in a clockwise direction starting at the top left.<br>
- <h4><a name="PS4"></a>Creating a scanner or camera input profile</h4>
- Similar to a display profile, an input profile can be either a
- shaper/matrix or LUT based profile. Well behaved input devices will
- probably give the best results with a shaper/matrix profile, and
- this may also be the best choice if your test chart has a small or
- unevenly distributed set of test patchs (ie. the IT8.7.2). If a
- shaper/matrix profile is a poor fit, consider using a LUT type
- profile.<br>
- <br>
- When creating a LUT type profile, there is the choice of XYZ or
- L*a*b* PCS (Device independent, Profile Connection Space). Often for
- input devices, it is better to choose the XYZ PCS, as this may be a
- better fit given that input devices are usually close to being
- linearly additive in behaviour.<br>
- <br>
- If the purpose of the input profile is to use it as a substitute for
- a colorimeter, then the <b>-u</b> flag should be used to avoid
- clipping values above the white point. Unless the shaper/matrix type
- profile is a very good fit, it is probably advisable to use a LUT
- type profile in this situation.<br>
- <br>
- To create a matrix/shaper profile, the following suffices:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Scanner</a> <a href="colprof.html#E">A"</a>
- <a href="colprof.html#q">-qm</a> <a href="colprof.html#a">-as</a> <a
- href="colprof.html#p1">scanner</a><br>
- <br>
- For an XYZ PCS LUT based profile then the following would be used:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Scanner A"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#a">-ax</a> <a href="colprof.html#p1">scanner</a><br>
- <br>
- For the purposes of a poor mans colorimeter, the following would
- generally be used:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Scanner A"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#a">-ax</a> <a href="colprof.html#u">-u</a> <a
- href="colprof.html#p1">scanner</a><br>
- <br>
- Make sure you check the delta E report at the end of the profile
- creation, to see if the profile is behaving reasonably.<br>
- <br>
- <br>
- If profiling a <span style="font-weight: bold;">camera</span> in <span
- style="font-weight: bold;">RAW</span> mode, then there may be some
- advantage in creating a pure matrix only profile, in which it is
- assumed that the camera response is completely linear. This may
- reduce extrapolation artefacts. If setting the white point will be
- done in some application, then it may also be an advantage to use
- the <span style="font-weight: bold;">-u</span> flag and avoid
- setting the white point to that of the profile chart:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Camera"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#a">-am</a> <a href="colprof.html#u">-u</a> <a
- href="colprof.html#p1">scanner</a><br>
- <br>
- <br>
- <hr size="2" width="100%">
- <h3><a name="PP1"></a>Profiling Printers<br>
- </h3>
- The overall process is to create a set of device measurement target
- values, print them out, measure them, and then create an ICC profile
- from the measurements. If the printer is an RGB based printer, then
- the process is only slightly more complicated than profiling a
- display. If the printer is CMYK based, then some additional
- parameters are required to set the total ink limit (TAC) and
- &nbsp;black generation curve.<br>
- <h4><a name="PP2"></a>Creating a print profile test chart</h4>
- The first step in profiling any output device, is to create a set of
- device colorspace test values. The important parameters needed are:<br>
- <ul>
- <li>What colorspace does the device use ?</li>
- <li>How many test patches do I want to use/what paper size do I
- want to use ?</li>
- <li>What instrument am I going to use to read the patches ?<br>
- </li>
- <li>If it is a CMYK device, what is the total ink limit ?<br>
- </li>
- <li>What information do I already have about how the device
- behaves ?</li>
- </ul>
- Most printers running through simple drivers will appear as if they
- are RGB devices. In fact there is no such thing as a real RGB
- printer, since printers use white media and the colorant must
- subtract from the light reflected on it to create color, but the
- printer itself turns the incoming RGB into the native print
- colorspace, so for this reason we will tell targen to use the "Print
- RGB" colorspace, so that it knows that it's really a subtractive
- media. Other drivers will drive a printer more directly, and will
- expect a CMYK profile. [Currently Argyll is not capable of creating
- an ICC profile for devices with more colorants than CMYK. When this
- capability is introduced, it will by creating an additional
- separation profile which then allows the printer to be treated as a
- CMY or CMYK printer.] One way of telling what sort of profile is
- expected for your device is to examine an existing profile for that
- device using <a href="http://www.argyllcms.com/doc/iccdump.html">iccdump</a>.<br>
- <br>
- The number of test patches will depend somewhat on what quality
- profile you want to make, how well behaved the printer is, as well
- as the effort needed to read the number of test values. Generally it
- is convenient to fill a certain paper size with the maximum number
- of test values that will fit.<br>
- <br>
- At a minimum, for an "RGB" device, a few hundred values are needed
- (400-1000). For high quality CMYK profiles, 1000-3000 is not an
- unreasonable number of patches.<br>
- <br>
- To assist the determination of test patch values, it can help to
- have a rough idea of how the device behaves, so that the device test
- point locations can be pre-conditioned. This could be in the form of
- an ICC profile of a similar device, or a lower quality, or previous
- profile for that particular device. If one were going to make a very
- high quality Lut based profile, then it might be worthwhile to make
- up a smaller, preliminary shaper/matrix profile using a few hundred
- test points, before embarking on testing the device with several
- thousand.<br>
- <br>
- The documentation for the <a
- href="http://www.argyllcms.com/doc/targen.html">targen</a> tool
- lists a <a href="http://www.argyllcms.com/doc/targen.html#Table">table</a>
- of paper sizes and number of &nbsp;patches for typical situations.<br>
- <br>
- For a CMYK device, a total ink limit usually needs to be specified.
- Sometimes a device will have a maximum total ink limit set by its
- manufacturer or operator, and some CMYK systems (such as chemical
- proofing systems) don't have any limit. Typical printing devices
- such as Xerographic printers, inkjet printers and printing presses
- will have a limit. The exact procedure for determining an ink limit
- is outside the scope of this document, but one way of going about
- this might be to generate some small (say a few hundred patches)
- with targen &amp; pritntarg with different total ink limits, and
- printing them out, making the ink limit as large as possible without
- striking problems that are caused by too much ink.<br>
- <br>
- Generally one wants to use the maximum possible amount of ink to
- maximize the gamut available on the device. For most CMYK devices,
- an ink limit between 200 and 400 is usual, but and ink limit of 250%
- or over is generally desirable for reasonably dense blacks and dark
- saturated colors. And ink limit of less than 200% will begin to
- compromise the fully saturated gamut, as secondary colors (ie
- combinations of any two primary colorants) will not be able to reach
- full strength.<br>
- <br>
- Once an ink limit is used in printing the characterization test
- chart for a device, it becomes a critical parameter in knowing what
- the characterized gamut of the device is. If after printing the test
- chart, a greater ink limit were to be used, the the software would
- effectively be extrapolating the device behaviour at total ink
- levels beyond that used in the test chart, leading to inaccuracies.<br>
- <br>
- Generally in Argyll, the ink limit is established when creating the
- test chart values, and then carried through the profile making
- process automatically. Once the profile has been made however, the
- ink limit is no longer recorded, and you, the user, will have to
- keep track of it if the ICC profile is used in any program than
- needs to know the usable gamut of the device.<br>
- <br>
- <br>
- Lets consider two devices in our examples, "PrinterA" which is an
- "RGB" device, and "PrinterB" which is CMYK, and has a target ink
- limit of 250%. <br>
- <br>
- The simplest approach is to make a set of test values that is
- independent of the characteristics of the particular device:<br>
- <br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d2</a> <a href="targen.html#f">-f1053</a>
- <a href="targen.html#p1">PrinterA</a><br>
- <br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d4</a> <a href="targen.html#l">-l260</a>
- <a href="targen.html#f">-f1053</a> <a href="targen.html#p1">PrinterB</a><br>
- <br>
- The number of patches chosen here happens to be right for an A4
- paper size being read using a Spectroscan instrument. See the <a
- href="targen.html#Table">table</a> in&nbsp; the <a
- href="targen.html">targen</a> documentation for some other
- suggested numbers.<br>
- <br>
- If there is a preliminary or previous profile called "OldPrinterA"
- available, and we want to try creating a "pre-conditioned" set of
- test values that will more efficiently sample the device response,
- then the following would achieve this:<u><br>
- </u><br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d2</a> <a href="targen.html#f">-f1053</a>
- <a href="targen.html#c">-c OldPrinterA</a>&nbsp;<a
- href="targen.html#p1">PrinterA</a><br>
- <br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d4</a> <a href="targen.html#l">-l260</a>
- <a href="targen.html#f">-f1053</a> <a href="targen.html#c">-c
- OldPrinterB</a> <a href="targen.html#p1">PrinterB</a><br>
- <a href="targen.html#p1"></a><br>
- <br>
- The output of <b>targen</b> will be the file PrinterA.ti1 and
- PrinterB.ti1 respectively, containing the device space test values,
- as well as expected CIE values used for chart recognition purposes.<br>
- <br>
- <h4><a name="PP2b"></a>Printing a print profile test chart<br>
- <br>
- </h4>
- The next step is turn the test values in to a PostScript or TIFF
- raster test file that can printed on the device. The basic
- information that needs to be supplied is the type of instrument that
- will be used to read the patches, as well as the paper size it is to
- be formatted for.<br>
- <br>
- For an X-Rite DTP41, the following would be typical:<br>
- <br>
- <a href="printtarg.html">printtarg</a> <a href="printtarg.html#v">-v</a>
- <a href="printtarg.html#i">-i41</a> <a href="printtarg.html#p">-pA4</a>
- <a href="printtarg.html#p1">PrinterA</a><br>
- &nbsp;<br>
- For a Gretag Eye-One Pro, the following would be typical:<br>
- <br>
- <a href="printtarg.html">printtarg</a> <a href="printtarg.html#v">-v</a>
- <a href="printtarg.html#i">-ii1</a> <a href="printtarg.html#p">-pA4</a>
- <a href="printtarg.html#p1">PrinterA</a><br>
- <br>
- For using with a scanner as a colorimeter, the Gretag Spectroscan
- layout is suitable, but the <a href="printtarg.html#s">-s</a> flag
- should be used so as to generate a layout suitable for scan
- recognition, as well as generating the scan recognition template
- files. (You probably want to use less patches with <span
- style="font-weight: bold;">targen</span>, when using the <span
- style="font-weight: bold;">printtarg -s</span> flag, e.g. 1026
- patches for an A4R page, etc.) The following would be typical:<br>
- <br>
- <a href="printtarg.html">printtarg</a> <a href="printtarg.html#v">-v</a>
- <a href="printtarg.html#s">-s</a> <a href="printtarg.html#i">-iSS</a>
- <a href="printtarg.html#p">-pA4R</a> <a href="printtarg.html#p1">PrinterA</a><br>
- <span style="font-weight: bold;"><br>
- printtarg</span> reads the PrinterA.ti1 file, creates a
- PrinterA.ti2 file containing the layout information as well as the
- device values and expected CIE values, as well as a PrinterA.ps file
- containing the test chart. If the <span style="font-weight: bold;">-s</span>
- flag is used, one or more PrinterA.cht files is created to allow the
- <a href="scanin.html">scanin</a> program to recognize the chart.<br>
- <br>
- To create TIFF raster files rather than PostScript, use the <a
- href="printtarg.html#t"><span style="font-weight: bold;">-t</span></a>
- flag.<br>
- <br>
- <span style="font-weight: bold;">GSview</span> is a good program to
- use to check what the PostScript file will look like, without
- actually printing it out. You could also use <span
- style="font-weight: bold;">Photoshop</span> or <span
- style="font-weight: bold;">ImageMagick</span> for this purpose.<br>
- <br>
- The last step is to print the chart out.<br>
- <br>
- Using a suitable PostScript or raster file printing program,
- downloader, print the chart. If you are not using a TIFF test chart,
- and you do not have a PostScript capable printer, then an
- interpreter like GhostScript or even Photoshop could be used to
- rasterize the file into something that can be printed. Note that it
- is important that the PostScript interpreter or TIFF printing
- application and printer configuration is setup for a device
- profiling run, and that any sort of color conversion of color
- correction be turned off so that the device values in the PostScript
- or TIFF file are sent directly to the device. If the device has a
- calibration system, then it would be usual to have setup and
- calibrated the device before starting the profiling run, and to
- apply calibration to the chart values. If Photoshop was to be used,
- then either the chart needs to be a single page, or separate .eps or
- .tiff files for each page should be used, so that they can be
- converted and printed one at a time (see the <a
- href="printtarg.html#e">-e</a> and <a href="printtarg.html#t">-t</a>
- flags).<br>
- <br>
- <h4><a name="PP3"></a>Reading a print test chart using an instrument</h4>
- Once the test chart has been printed, the color of the patches needs
- to be read using a suitable instrument.<br>
- <br>
- Several different instruments are currently supported, some that
- need to be used patch by patch, some read a strip at a time, and
- some read a sheet at a time. See <a href="instruments.html">instruments</a>
- for a current list.<br>
- <br>
- The instrument needs to be connected to your computer before running
- the <a href="chartread.html">chartread</a> command. Both serial
- port and USB connected Instruments are supported. A serial port to
- USB adapter might have to be used if your computer doesn't have any
- serial ports, and you have a serial interface connected instrument.<br>
- <br>
- If you run <a href="chartread.html">chartread</a> so as to print
- out its usage message (ie. by using a <span style="font-weight:
- bold;">-?</span> or <span style="font-weight: bold;">--</span>
- flags), then it will list any identified serial ports or USB
- connected instruments, and their corresponding number for the <a
- href="chartread.html#c">-c</a> option. By default, <a
- href="chartread.html">chartread</a> will try to connect to the
- first available USB instrument, or an instrument on the first serial
- port.<br>
- <br>
- The only arguments required is to specify the basename of the .ti2
- file. If a non-default serial port is to be used, then the <span
- style="font-weight: bold;">-c</span> option would also be
- specified.<br>
- <br>
- &nbsp;e.g. for a Spectroscan on the second port:<br>
- <br>
- <a href="chartread.html">chartread</a> <a href="chartread.html#c">-c2</a>
- <a href="chartread.html#p1">PrinterA</a><br>
- <br>
- For a DTP41 to the default serial port:<br>
- <br>
- <a href="chartread.html">chartread</a><a href="chartread.html#i"></a>
- <a href="chartread.html#p1">PrinterA</a><br>
- <br>
- <span style="font-weight: bold;">chartread</span> will interactively
- prompt you through the process of reading each sheet or strip. See <a
- href="chartread.html">chartread</a> for more details on the
- responses for each type of instrument. Continue with <a
- href="Scenarios.html#PP5">Creating a printer profile</a>.<br>
- <br>
- <h4><a name="PP4"></a>Reading a print test chart using a scanner or
- camera<br>
- </h4>
- <br>
- Argyll supports using a scanner or even a camera as a substitute for
- a colorimeter. While a scanner or camera is no replacement for a
- color measurement instrument, it may give acceptable results in some
- situations, and may give better results than a generic profile for a
- printing device.<br>
- <br>
- The main limitation of the scanner-as-colorimeter approach are:<br>
- <br>
- * The scanner dynamic range and/or precision may not match the
- printers or what is required for a good profile.<br>
- * The spectral interaction of the scanner test chart and printer
- test chart with the scanner spectral response can cause color
- errors.<br>
- * Spectral differences caused by different black amounts in the
- print test chart can cause color errors. <br>
- * The scanner reference chart gamut may be much smaller than the
- printers gamut, making the scanner profile too inaccurate to be
- useful. <br>
- <br>
- As well as some of the above, a camera may not be suitable if it
- automatically adjusts exposure or white point when taking a picture,
- and this behavior cannot be disabled.<br>
- <br>
- The end result is often a profile that has a noticeable color cast,
- compared to a profile created using a colorimeter or spectrometer.<br>
- <br>
- <br>
- It is assumed that you have created a scanner or camera profile
- following the <a
- href="http://www.argyllcms.com/doc/Scenarios.html#PS1">procedure</a>
- outline above. For best possible results it is advisable to both
- profile the scanner or camera, and use it in scanning the printed
- test chart, in as "raw" mode as possible (i.e. using 16 bits per
- component images, if the scanner or camera is capable of doing so;
- not setting white or black points, using a fixed exposure etc.). It
- is generally advisable to create a LUT type input profile, and use
- the <a href="http://www.argyllcms.com/doc/colprof.html#u">-u</a>
- flag to avoid clipping scanned value whiter than the input
- calibration chart.<br>
- <br>
- Scan or photograph your printer chart (or charts) on the scanner or
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ documentation</a>).<br>
+ <br>
+ To create the scanner .ti3 file, run the <b>scanin</b> tool as
+ follows (assuming an IT8 chart is being used):<br>
+ <br>
+ <a href="scanin.html"> scanin</a> -v scanner.tif It8.cht It8ref.txt<br>
+ <br>
+ "It8ref.txt" or "It8ref.cie" is assumed to be the name of the CIE
+ reference file supplied by the chart manufacturer. The resulting
+ file will be named "<b>scanner.ti3</b>".<br>
+ <br>
+ <span style="font-weight: bold;">scanin</span> will process 16 bit
+ per component .tiff files, which (if the scanner is capable of
+ creating such files),&nbsp; may improve the quality of the profile.
+ <br>
+ <br>
+ If you have any doubts about the correctness of the chart
+ recognition, or the subsequent profile's delta E report is unusual,
+ then use the scanin diagnostic flags <a href="scanin.html#d">-dipn</a>
+ and examine the <span style="font-weight: bold;">diag.tif</span>
+ diagnostic file, to make sure that the patches are identified and
+ aligned correctly. If you have problems getting good automatic
+ alignment, then consider doing a manual alignment by locating the
+ fiducial marks on your scan, and feeding them into scanin <a
+ href="scanin.html#F">-F</a> parameters. The fiducial marks should
+ be listed in a clockwise direction starting at the top left.<br>
+ <h4><a name="PS4"></a>Creating a scanner or camera input profile</h4>
+ Similar to a display profile, an input profile can be either a
+ shaper/matrix or LUT based profile. Well behaved input devices will
+ probably give the best results with a shaper/matrix profile, and
+ this may also be the best choice if your test chart has a small or
+ unevenly distributed set of test patchs (ie. the IT8.7.2). If a
+ shaper/matrix profile is a poor fit, consider using a LUT type
+ profile.<br>
+ <br>
+ When creating a LUT type profile, there is the choice of XYZ or
+ L*a*b* PCS (Device independent, Profile Connection Space). Often for
+ input devices, it is better to choose the XYZ PCS, as this may be a
+ better fit given that input devices are usually close to being
+ linearly additive in behaviour.<br>
+ <br>
+ If the purpose of the input profile is to use it as a substitute for
+ a colorimeter, then the <b>-u</b> flag should be used to avoid
+ clipping values above the white point. Unless the shaper/matrix type
+ profile is a very good fit, it is probably advisable to use a LUT
+ type profile in this situation.<br>
+ <br>
+ To create a matrix/shaper profile, the following suffices:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Scanner</a> <a href="colprof.html#E">A"</a>
+ <a href="colprof.html#q">-qm</a> <a href="colprof.html#a">-as</a> <a
+ href="colprof.html#p1">scanner</a><br>
+ <br>
+ For an XYZ PCS LUT based profile then the following would be used:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Scanner A"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#a">-ax</a> <a href="colprof.html#p1">scanner</a><br>
+ <br>
+ For the purposes of a poor mans colorimeter, the following would
+ generally be used:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Scanner A"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#a">-ax</a> <a href="colprof.html#u">-u</a> <a
+ href="colprof.html#p1">scanner</a><br>
+ <br>
+ Make sure you check the delta E report at the end of the profile
+ creation, to see if the sample data and profile is behaving
+ reasonably. Depending on the type of device, and the consistency of
+ the readings, average errors of 5 or less, and maximum errors of 15
+ or less would normally be expected. If errors are grossly higher
+ than this, then this is an indication that something is seriously
+ wrong with the device measurement, or profile creation.<br>
+ <br>
+ If profiling a <span style="font-weight: bold;">camera</span> in <span
+ style="font-weight: bold;">RAW</span> mode, then there may be some
+ advantage in creating a pure matrix only profile, in which it is
+ assumed that the camera response is completely linear. This may
+ reduce extrapolation artefacts. If setting the white point will be
+ done in some application, then it may also be an advantage to use
+ the <span style="font-weight: bold;">-u</span> flag and avoid
+ setting the white point to that of the profile chart:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Camera"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#a">-am</a> <a href="colprof.html#u">-u</a> <a
+ href="colprof.html#p1">scanner</a><br>
+ <br>
+ <br>
+ <hr size="2" width="100%">
+ <h3><a name="PP1"></a>Profiling Printers<br>
+ </h3>
+ The overall process is to create a set of device measurement target
+ values, print them out, measure them, and then create an ICC profile
+ from the measurements. If the printer is an RGB based printer, then
+ the process is only slightly more complicated than profiling a
+ display. If the printer is CMYK based, then some additional
+ parameters are required to set the total ink limit (TAC) and
+ &nbsp;black generation curve.<br>
+ <h4><a name="PP2"></a>Creating a print profile test chart</h4>
+ The first step in profiling any output device, is to create a set of
+ device colorspace test values. The important parameters needed are:<br>
+ <ul>
+ <li>What colorspace does the device use ?</li>
+ <li>How many test patches do I want to use/what paper size do I
+ want to use ?</li>
+ <li>What instrument am I going to use to read the patches ?<br>
+ </li>
+ <li>If it is a CMYK device, what is the total ink limit ?<br>
+ </li>
+ <li>What information do I already have about how the device
+ behaves ?</li>
+ </ul>
+ Most printers running through simple drivers will appear as if they
+ are RGB devices. In fact there is no such thing as a real RGB
+ printer, since printers use white media and the colorant must
+ subtract from the light reflected on it to create color, but the
+ printer itself turns the incoming RGB into the native print
+ colorspace, so for this reason we will tell targen to use the "Print
+ RGB" colorspace, so that it knows that it's really a subtractive
+ media. Other drivers will drive a printer more directly, and will
+ expect a CMYK profile. [Currently Argyll is not capable of creating
+ an ICC profile for devices with more colorants than CMYK. When this
+ capability is introduced, it will by creating an additional
+ separation profile which then allows the printer to be treated as a
+ CMY or CMYK printer.] One way of telling what sort of profile is
+ expected for your device is to examine an existing profile for that
+ device using <a href="http://www.argyllcms.com/doc/iccdump.html">iccdump</a>.<br>
+ <br>
+ The number of test patches will depend somewhat on what quality
+ profile you want to make, how well behaved the printer is, as well
+ as the effort needed to read the number of test values. Generally it
+ is convenient to fill a certain paper size with the maximum number
+ of test values that will fit.<br>
+ <br>
+ At a minimum, for an "RGB" device, a few hundred values are needed
+ (400-1000). For high quality CMYK profiles, 1000-3000 is not an
+ unreasonable number of patches.<br>
+ <br>
+ To assist the determination of test patch values, it can help to
+ have a rough idea of how the device behaves, so that the device test
+ point locations can be pre-conditioned. This could be in the form of
+ an ICC profile of a similar device, or a lower quality, or previous
+ profile for that particular device. If one were going to make a very
+ high quality Lut based profile, then it might be worthwhile to make
+ up a smaller, preliminary shaper/matrix profile using a few hundred
+ test points, before embarking on testing the device with several
+ thousand.<br>
+ <br>
+ The documentation for the <a
+ href="http://www.argyllcms.com/doc/targen.html">targen</a> tool
+ lists a <a href="http://www.argyllcms.com/doc/targen.html#Table">table</a>
+ of paper sizes and number of &nbsp;patches for typical situations.<br>
+ <br>
+ For a CMYK device, a total ink limit usually needs to be specified.
+ Sometimes a device will have a maximum total ink limit set by its
+ manufacturer or operator, and some CMYK systems (such as chemical
+ proofing systems) don't have any limit. Typical printing devices
+ such as Xerographic printers, inkjet printers and printing presses
+ will have a limit. The exact procedure for determining an ink limit
+ is outside the scope of this document, but one way of going about
+ this might be to generate some small (say a few hundred patches)
+ with targen &amp; pritntarg with different total ink limits, and
+ printing them out, making the ink limit as large as possible without
+ striking problems that are caused by too much ink.<br>
+ <br>
+ Generally one wants to use the maximum possible amount of ink to
+ maximize the gamut available on the device. For most CMYK devices,
+ an ink limit between 200 and 400 is usual, but and ink limit of 250%
+ or over is generally desirable for reasonably dense blacks and dark
+ saturated colors. And ink limit of less than 200% will begin to
+ compromise the fully saturated gamut, as secondary colors (ie
+ combinations of any two primary colorants) will not be able to reach
+ full strength.<br>
+ <br>
+ Once an ink limit is used in printing the characterization test
+ chart for a device, it becomes a critical parameter in knowing what
+ the characterized gamut of the device is. If after printing the test
+ chart, a greater ink limit were to be used, the the software would
+ effectively be extrapolating the device behaviour at total ink
+ levels beyond that used in the test chart, leading to inaccuracies.<br>
+ <br>
+ Generally in Argyll, the ink limit is established when creating the
+ test chart values, and then carried through the profile making
+ process automatically. Once the profile has been made however, the
+ ink limit is no longer recorded, and you, the user, will have to
+ keep track of it if the ICC profile is used in any program than
+ needs to know the usable gamut of the device.<br>
+ <br>
+ <br>
+ Lets consider two devices in our examples, "PrinterA" which is an
+ "RGB" device, and "PrinterB" which is CMYK, and has a target ink
+ limit of 250%. <br>
+ <br>
+ The simplest approach is to make a set of test values that is
+ independent of the characteristics of the particular device:<br>
+ <br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d2</a> <a href="targen.html#f">-f1053</a>
+ <a href="targen.html#p1">PrinterA</a><br>
+ <br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d4</a> <a href="targen.html#l">-l260</a>
+ <a href="targen.html#f">-f1053</a> <a href="targen.html#p1">PrinterB</a><br>
+ <br>
+ The number of patches chosen here happens to be right for an A4
+ paper size being read using a Spectroscan instrument. See the <a
+ href="targen.html#Table">table</a> in&nbsp; the <a
+ href="targen.html">targen</a> documentation for some other
+ suggested numbers.<br>
+ <br>
+ If there is a preliminary or previous profile called "OldPrinterA"
+ available, and we want to try creating a "pre-conditioned" set of
+ test values that will more efficiently sample the device response,
+ then the following would achieve this:<u><br>
+ </u><br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d2</a> <a href="targen.html#f">-f1053</a>
+ <a href="targen.html#c">-c OldPrinterA</a>&nbsp;<a
+ href="targen.html#p1">PrinterA</a><br>
+ <br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d4</a> <a href="targen.html#l">-l260</a>
+ <a href="targen.html#f">-f1053</a> <a href="targen.html#c">-c
+ OldPrinterB</a> <a href="targen.html#p1">PrinterB</a><br>
+ <a href="targen.html#p1"></a><br>
+ <br>
+ The output of <b>targen</b> will be the file PrinterA.ti1 and
+ PrinterB.ti1 respectively, containing the device space test values,
+ as well as expected CIE values used for chart recognition purposes.<br>
+ <br>
+ <h4><a name="PP2b"></a>Printing a print profile test chart<br>
+ <br>
+ </h4>
+ The next step is turn the test values in to a PostScript or TIFF
+ raster test file that can printed on the device. The basic
+ information that needs to be supplied is the type of instrument that
+ will be used to read the patches, as well as the paper size it is to
+ be formatted for.<br>
+ <br>
+ For an X-Rite DTP41, the following would be typical:<br>
+ <br>
+ <a href="printtarg.html">printtarg</a> <a href="printtarg.html#v">-v</a>
+ <a href="printtarg.html#i">-i41</a> <a href="printtarg.html#p">-pA4</a>
+ <a href="printtarg.html#p1">PrinterA</a><br>
+ &nbsp;<br>
+ For a Gretag Eye-One Pro, the following would be typical:<br>
+ <br>
+ <a href="printtarg.html">printtarg</a> <a href="printtarg.html#v">-v</a>
+ <a href="printtarg.html#i">-ii1</a> <a href="printtarg.html#p">-pA4</a>
+ <a href="printtarg.html#p1">PrinterA</a><br>
+ <br>
+ For using with a scanner as a colorimeter, the Gretag Spectroscan
+ layout is suitable, but the <a href="printtarg.html#s">-s</a> flag
+ should be used so as to generate a layout suitable for scan
+ recognition, as well as generating the scan recognition template
+ files. (You probably want to use less patches with <span
+ style="font-weight: bold;">targen</span>, when using the <span
+ style="font-weight: bold;">printtarg -s</span> flag, e.g. 1026
+ patches for an A4R page, etc.) The following would be typical:<br>
+ <br>
+ <a href="printtarg.html">printtarg</a> <a href="printtarg.html#v">-v</a>
+ <a href="printtarg.html#s">-s</a> <a href="printtarg.html#i">-iSS</a>
+ <a href="printtarg.html#p">-pA4R</a> <a href="printtarg.html#p1">PrinterA</a><br>
+ <span style="font-weight: bold;"><br>
+ printtarg</span> reads the PrinterA.ti1 file, creates a
+ PrinterA.ti2 file containing the layout information as well as the
+ device values and expected CIE values, as well as a PrinterA.ps file
+ containing the test chart. If the <span style="font-weight: bold;">-s</span>
+ flag is used, one or more PrinterA.cht files is created to allow the
+ <a href="scanin.html">scanin</a> program to recognize the chart.<br>
+ <br>
+ To create TIFF raster files rather than PostScript, use the <a
+ href="printtarg.html#t"><span style="font-weight: bold;">-t</span></a>
+ flag.<br>
+ <br>
+ <span style="font-weight: bold;">GSview</span> is a good program to
+ use to check what the PostScript file will look like, without
+ actually printing it out. You could also use <span
+ style="font-weight: bold;">Photoshop</span> or <span
+ style="font-weight: bold;">ImageMagick</span> for this purpose.<br>
+ <br>
+ The last step is to print the chart out.<br>
+ <br>
+ Using a suitable PostScript or raster file printing program,
+ downloader, print the chart. If you are not using a TIFF test chart,
+ and you do not have a PostScript capable printer, then an
+ interpreter like GhostScript or even Photoshop could be used to
+ rasterize the file into something that can be printed. Note that it
+ is important that the PostScript interpreter or TIFF printing
+ application and printer configuration is setup for a device
+ profiling run, and that any sort of color conversion of color
+ correction be turned off so that the device values in the PostScript
+ or TIFF file are sent directly to the device. If the device has a
+ calibration system, then it would be usual to have setup and
+ calibrated the device before starting the profiling run, and to
+ apply calibration to the chart values. If Photoshop was to be used,
+ then either the chart needs to be a single page, or separate .eps or
+ .tiff files for each page should be used, so that they can be
+ converted and printed one at a time (see the <a
+ href="printtarg.html#e">-e</a> and <a href="printtarg.html#t">-t</a>
+ flags).<br>
+ <br>
+ <h4><a name="PP3"></a>Reading a print test chart using an instrument</h4>
+ Once the test chart has been printed, the color of the patches needs
+ to be read using a suitable instrument.<br>
+ <br>
+ Several different instruments are currently supported, some that
+ need to be used patch by patch, some read a strip at a time, and
+ some read a sheet at a time. See <a href="instruments.html">instruments</a>
+ for a current list.<br>
+ <br>
+ The instrument needs to be connected to your computer before running
+ the <a href="chartread.html">chartread</a> command. Both serial
+ port and USB connected Instruments are supported. A serial port to
+ USB adapter might have to be used if your computer doesn't have any
+ serial ports, and you have a serial interface connected instrument.<br>
+ <br>
+ If you run <a href="chartread.html">chartread</a> so as to print
+ out its usage message (ie. by using a <span style="font-weight:
+ bold;">-?</span> or <span style="font-weight: bold;">--</span>
+ flags), then it will list any identified serial ports or USB
+ connected instruments, and their corresponding number for the <a
+ href="chartread.html#c">-c</a> option. By default, <a
+ href="chartread.html">chartread</a> will try to connect to the
+ first available USB instrument, or an instrument on the first serial
+ port.<br>
+ <br>
+ The only arguments required is to specify the basename of the .ti2
+ file. If a non-default serial port is to be used, then the <span
+ style="font-weight: bold;">-c</span> option would also be
+ specified.<br>
+ <br>
+ &nbsp;e.g. for a Spectroscan on the second port:<br>
+ <br>
+ <a href="chartread.html">chartread</a> <a href="chartread.html#c">-c2</a>
+ <a href="chartread.html#p1">PrinterA</a><br>
+ <br>
+ For a DTP41 to the default serial port:<br>
+ <br>
+ <a href="chartread.html">chartread</a><a href="chartread.html#i"></a>
+ <a href="chartread.html#p1">PrinterA</a><br>
+ <br>
+ <span style="font-weight: bold;">chartread</span> will interactively
+ prompt you through the process of reading each sheet or strip. See <a
+ href="chartread.html">chartread</a> for more details on the
+ responses for each type of instrument. Continue with <a
+ href="Scenarios.html#PP5">Creating a printer profile</a>.<br>
+ <br>
+ <h4><a name="PP4"></a>Reading a print test chart using a scanner or
+ camera<br>
+ </h4>
+ <br>
+ Argyll supports using a scanner or even a camera as a substitute for
+ a colorimeter. While a scanner or camera is no replacement for a
+ color measurement instrument, it may give acceptable results in some
+ situations, and may give better results than a generic profile for a
+ printing device.<br>
+ <br>
+ The main limitation of the scanner-as-colorimeter approach are:<br>
+ <br>
+ * The scanner dynamic range and/or precision may not match the
+ printers or what is required for a good profile.<br>
+ * The spectral interaction of the scanner test chart and printer
+ test chart with the scanner spectral response can cause color
+ errors.<br>
+ * Spectral differences caused by different black amounts in the
+ print test chart can cause color errors. <br>
+ * The scanner reference chart gamut may be much smaller than the
+ printers gamut, making the scanner profile too inaccurate to be
+ useful. <br>
+ <br>
+ As well as some of the above, a camera may not be suitable if it
+ automatically adjusts exposure or white point when taking a picture,
+ and this behavior cannot be disabled.<br>
+ <br>
+ The end result is often a profile that has a noticeable color cast,
+ compared to a profile created using a colorimeter or spectrometer.<br>
+ <br>
+ <br>
+ It is assumed that you have created a scanner or camera profile
+ following the <a
+ href="http://www.argyllcms.com/doc/Scenarios.html#PS1">procedure</a>
+ outline above. For best possible results it is advisable to both
+ profile the scanner or camera, and use it in scanning the printed
+ test chart, in as "raw" mode as possible (i.e. using 16 bits per
+ component images, if the scanner or camera is capable of doing so;
+ not setting white or black points, using a fixed exposure etc.). It
+ is generally advisable to create a LUT type input profile, and use
+ the <a href="http://www.argyllcms.com/doc/colprof.html#u">-u</a>
+ flag to avoid clipping scanned value whiter than the input
+ calibration chart.<br>
+ <br>
+ Scan or photograph your printer chart (or charts) on the scanner or
camera previously profiled. <big><span style="font-weight: bold;">The
@@ -1282,97 +1773,134 @@ href="http://www.xrite.com/documents/apps/public/digital_colorchecker_sg_l_a_b.t
- scanner or camera must be configured and used exactly the same
- as it was when it was profiled.</span></big><br>
- <br>
- I will assume the resulting scan/photo input file is called <span
- style="font-weight: bold;">PrinterB.tif</span> (or <span
- style="font-weight: bold;">PrinterB1.tif</span>, <span
- style="font-weight: bold;">PrinterB2.tif</span> etc. in the case
- of multiple charts). As with profiling the scanner or camera, the
- raster file need only be roughly cropped so as to contain the test
- chart.<br>
- <br>
- The scanner recognition files created when <span
- style="font-weight: bold;">printtarg</span> was run is assumed to
- be called <span style="font-weight: bold;">PrinterB.cht</span>.
- Using the scanner profile created previously (assumed to be called <span
- style="font-weight: bold;">scanner.icm</span>), the printer test
- chart scan patches are converted to CIE values using the <span
- style="font-weight: bold;">scanin</span> tool:<br>
- <br>
- <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
- href="scanin.html#c">-c</a> <a href="scanin.html#cp1">PrinterB.tif</a>
- <a href="scanin.html#cp2">PrinterB.cht</a> <a
- href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
- <br>
- If there were multiple test chart pages, the results would be
- accumulated page by page using the <a href="scanin.html#ca">-ca</a>
- option, ie., if there were 3 pages:<br>
- <br>
- <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
- href="scanin.html#c">-c</a> <a href="scanin.html#cp1">PrinterB1.tif</a>
- <a href="scanin.html#cp2">PrinterB1.cht</a> <a
- href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
- <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
- href="scanin.html#ca">-ca</a> <a href="scanin.html#cp1">PrinterB2.tif</a>
- <a href="scanin.html#cp2">PrinterB2.cht</a> <a
- href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
- <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
- href="scanin.html#ca">-ca</a> <a href="scanin.html#cp1">PrinterB3.tif</a>
- <a href="scanin.html#cp2">PrinterB3.cht</a> <a
- href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
- <br>
- Now that the <span style="font-weight: bold;">PrinterB.ti3</span>
- data has been obtained, the profile continue in the next section
- with <span style="font-weight: bold;">Creating a printer profile</span>.<br>
- <br>
- If you have any doubts about the correctness of the chart
- recognition, or the subsequent profile's delta E report is unusual,
- then use the scanin diagnostic flags <a href="scanin.html#d">-dipn</a>
- and examine the <span style="font-weight: bold;">diag.tif</span>
- diagnostic file.<br>
- <h4><a name="PP5"></a>Creating a printer profile<br>
- </h4>
- Creating an RGB based printing profile is very similar to creating a
- display device profile. For a CMYK printer, some additional
- information is needed to set the black generation.<br>
- <br>
- Where the resulting profile will be used conventionally (ie. using <a
- href="collink.html">collink</a> <a href="collink.html#s">-s</a>,
- or <a href="cctiff.html">cctiff</a> or most other "dumb" CMMs) it
- is important to specify that gamut mapping should be computed for
- the output (B2A) perceptual and saturation tables. This is done by
- specifying a device profile as the parameter to the <a
- href="colprof.html">colprof</a> <a href="colprof.html#S">-S</a>
- flag. When you intend to create a "general use" profile, it can be a
- good technique to specify the source gamut as the opposite type of
- profile to that being created, i.e. if a printer profile is being
- created, specify a display profile (e.g. sRGB) as the source gamut.
- If a display profile is being created, then specify a printer
- profile as the source (e.g. Figra, SWOP etc.).&nbsp; When linking to
- the profile you have created this way as the output profile, then
- use perceptual intent if the source is the opposite type, and
- relative colorimetric if it is the same type.<br>
- <br>
- "Opposite type of profile" refers to the native gamut of the device,
- and what its fundamental nature is, additive or subtractive. An
- emissive display will have additive primaries (R, G &amp; B), while
- a reflective print, will have subtractive primaries (C, M, Y &amp;
- possibly others), irrespective of what colorspace the printer is
- driven in (a printer might present an RGB interface, but internally
- this will be converted to CMY, and it will have a CMY type of
- gamut).&nbsp; Because of the complimentary nature of additive and
- subtractive device primary colorants, these types of devices have
- the most different gamuts, and hence need the most gamut mapping to
- convert from one colorspace to the other.<br>
- <br>
- If you are creating a profile for a specific purpose, intending to
- link it to a specific input profile, then you will get the best
- results by specifying that source profile as the source gamut.<br>
- <br>
- If a profile is only going to be used as an input profile, or is
- going to be used with a "smart" CMM (e.g. <a href="collink.html">collink</a>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ scanner or camera must be configured and used exactly the same
+ as it was when it was profiled.</span></big><br>
+ <br>
+ I will assume the resulting scan/photo input file is called <span
+ style="font-weight: bold;">PrinterB.tif</span> (or <span
+ style="font-weight: bold;">PrinterB1.tif</span>, <span
+ style="font-weight: bold;">PrinterB2.tif</span> etc. in the case
+ of multiple charts). As with profiling the scanner or camera, the
+ raster file need only be roughly cropped so as to contain the test
+ chart.<br>
+ <br>
+ The scanner recognition files created when <span
+ style="font-weight: bold;">printtarg</span> was run is assumed to
+ be called <span style="font-weight: bold;">PrinterB.cht</span>.
+ Using the scanner profile created previously (assumed to be called <span
+ style="font-weight: bold;">scanner.icm</span>), the printer test
+ chart scan patches are converted to CIE values using the <span
+ style="font-weight: bold;">scanin</span> tool:<br>
+ <br>
+ <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
+ href="scanin.html#c">-c</a> <a href="scanin.html#cp1">PrinterB.tif</a>
+ <a href="scanin.html#cp2">PrinterB.cht</a> <a
+ href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
+ <br>
+ If there were multiple test chart pages, the results would be
+ accumulated page by page using the <a href="scanin.html#ca">-ca</a>
+ option, ie., if there were 3 pages:<br>
+ <br>
+ <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
+ href="scanin.html#c">-c</a> <a href="scanin.html#cp1">PrinterB1.tif</a>
+ <a href="scanin.html#cp2">PrinterB1.cht</a> <a
+ href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
+ <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
+ href="scanin.html#ca">-ca</a> <a href="scanin.html#cp1">PrinterB2.tif</a>
+ <a href="scanin.html#cp2">PrinterB2.cht</a> <a
+ href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
+ <a href="scanin.html">scanin</a> <a href="scanin.html#v">-v</a> <a
+ href="scanin.html#ca">-ca</a> <a href="scanin.html#cp1">PrinterB3.tif</a>
+ <a href="scanin.html#cp2">PrinterB3.cht</a> <a
+ href="scanin.html#cp3">scanner.icm</a> <a href="scanin.html#cp4">PrinterB</a><br>
+ <br>
+ Now that the <span style="font-weight: bold;">PrinterB.ti3</span>
+ data has been obtained, the profile continue in the next section
+ with <span style="font-weight: bold;">Creating a printer profile</span>.<br>
+ <br>
+ If you have any doubts about the correctness of the chart
+ recognition, or the subsequent profile's delta E report is unusual,
+ then use the scanin diagnostic flags <a href="scanin.html#d">-dipn</a>
+ and examine the <span style="font-weight: bold;">diag.tif</span>
+ diagnostic file.<br>
+ <h4><a name="PP5"></a>Creating a printer profile<br>
+ </h4>
+ Creating an RGB based printing profile is very similar to creating a
+ display device profile. For a CMYK printer, some additional
+ information is needed to set the black generation.<br>
+ <br>
+ Where the resulting profile will be used conventionally (ie. using <a
+ href="collink.html">collink</a> <a href="collink.html#s">-s</a>,
+ or <a href="cctiff.html">cctiff</a> or most other "dumb" CMMs) it
+ is important to specify that gamut mapping should be computed for
+ the output (B2A) perceptual and saturation tables. This is done by
+ specifying a device profile as the parameter to the <a
+ href="colprof.html">colprof</a> <a href="colprof.html#S">-S</a>
+ flag. When you intend to create a "general use" profile, it can be a
+ good technique to specify the source gamut as the opposite type of
+ profile to that being created, i.e. if a printer profile is being
+ created, specify a display profile (e.g. sRGB) as the source gamut.
+ If a display profile is being created, then specify a printer
+ profile as the source (e.g. Figra, SWOP etc.).&nbsp; When linking to
+ the profile you have created this way as the output profile, then
+ use perceptual intent if the source is the opposite type, and
+ relative colorimetric if it is the same type.<br>
+ <br>
+ "Opposite type of profile" refers to the native gamut of the device,
+ and what its fundamental nature is, additive or subtractive. An
+ emissive display will have additive primaries (R, G &amp; B), while
+ a reflective print, will have subtractive primaries (C, M, Y &amp;
+ possibly others), irrespective of what colorspace the printer is
+ driven in (a printer might present an RGB interface, but internally
+ this will be converted to CMY, and it will have a CMY type of
+ gamut).&nbsp; Because of the complimentary nature of additive and
+ subtractive device primary colorants, these types of devices have
+ the most different gamuts, and hence need the most gamut mapping to
+ convert from one colorspace to the other.<br>
+ <br>
+ If you are creating a profile for a specific purpose, intending to
+ link it to a specific input profile, then you will get the best
+ results by specifying that source profile as the source gamut.<br>
+ <br>
+ If a profile is only going to be used as an input profile, or is
+ going to be used with a "smart" CMM (e.g. <a href="collink.html">collink</a>
<a href="collink.html#g">-g</a> or <a href="collink.html#G">-G</a>),
then
@@ -1383,69 +1911,113 @@ then
- it can save considerable processing time and space if the -b flag is
- used, and the -S flag not used.<br>
- <br>
- For an RGB printer intended to print RGB originals, the following
- might be a typical profile usage:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Printer A"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#S">-S</a><a href="colprof.html#S"> sRGB.icm</a>
- <a href="colprof.html#c">-cmt</a> <a href="colprof.html#d">-dpp</a>
- <a href="colprof.html#p1">PrinterA</a><br>
- <br>
- or if you intent to print from Fogra, SWOP or other standard CMYK
- style originals:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Printer A"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#S">-S</a><a href="colprof.html#S">
- fogra39l.icm</a> <a href="colprof.html#c">-cmt</a> <a
- href="colprof.html#d">-dpp</a> <a href="colprof.html#p1">PrinterA</a><br>
- <br>
- If you know what colorspace your originals are in, use that as the
- argument to <span style="font-weight: bold;">-S</span>.<br>
- <br>
- <h4><a name="PP6"></a>Choosing a black generation curve (and other
- CMYK printer options)<br>
- </h4>
- For a CMYK printer, it would be normal to specify the type of black
- generation, either as something simple, or as a specific curve. The
- documentation&nbsp; in <a href="colprof.html#k">colprof</a> for the
- details of the options.<span style="font-weight: bold;"><br>
- <br>
- Note</span> that making a good choice of black generation curve
- can affect things such as: how robust neutrals are given printer
- drift or changes in viewing lighting, how visible screening is, and
- how smooth looking the B2A conversion is.<br>
- <br>
- For instance, maximizing the level of K will mean that the neutral
- colors are composed of greater amounts of Black ink, and black ink
- retains its neutral appearance irrespective of printer behavior or
- the spectrum of the illuminant used to view the print. On the other
- hand, output which is dominantly from one of the color channels will
- tend to emphasize the screening pattern and any unevenness (banding
- etc.) of that channel, and the black channel in particular has the
- highest visibility. So in practice, some balance between the levels
- of the four channels is probably best, with more K if the screening
- is fine and a robust neutral balance is important, or less K if the
- screening is more visible and neutral balance is less critical. The
- levels of K at the edges of the gamut of the device will be fixed by
- the nature of the ink combinations that maximize the gamut (ie.
- typically zero ink for light chromatic colors, some combination for
- dark colors, and a high level of black for very dark near neutrals),
- and it is also usually important to set a curve that smoothly
- transitions to the K values at the gamut edges. Dramatic changes in
- K imply equally dramatic changes in CMY, and these abrupt
- transitions will reveal the limited precision and detail that can be
- captured in a lookup table based profile, often resulting in a
- "bumpy" looking output.<br>
- <br>
- If you want to experiment with the various black generation
- parameters, then it might be a good idea to create a preliminary
- profile (using <a href="colprof.html#q">-ql</a> <a
- href="colprof.html#b">-b</a> <a href="colprof.html#ni">-no</a>, <a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ it can save considerable processing time and space if the -b flag is
+ used, and the -S flag not used.<br>
+ <br>
+ For an RGB printer intended to print RGB originals, the following
+ might be a typical profile usage:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Printer A"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#S">-S</a><a href="colprof.html#S"> sRGB.icm</a>
+ <a href="colprof.html#c">-cmt</a> <a href="colprof.html#d">-dpp</a>
+ <a href="colprof.html#p1">PrinterA</a><br>
+ <br>
+ or if you intent to print from Fogra, SWOP or other standard CMYK
+ style originals:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Printer A"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#S">-S</a><a href="colprof.html#S">
+ fogra39l.icm</a> <a href="colprof.html#c">-cmt</a> <a
+ href="colprof.html#d">-dpp</a> <a href="colprof.html#p1">PrinterA</a><br>
+ <br>
+ If you know what colorspace your originals are in, use that as the
+ argument to <span style="font-weight: bold;">-S</span>.<br>
+ <br>
+ Make sure you check the delta E report at the end of the profile
+ creation, to see if the sample data and profile is behaving
+ reasonably. Depending on the type of device, and the consistency of
+ the readings, average errors of 5 or less, and maximum errors of 15
+ or less would normally be expected. If errors are grossly higher
+ than this, then this is an indication that something is seriously
+ wrong with the device measurement, or profile creation.
+ <h4><a name="PP6"></a>Choosing a black generation curve (and other
+ CMYK printer options)<br>
+ </h4>
+ For a CMYK printer, it would be normal to specify the type of black
+ generation, either as something simple, or as a specific curve. The
+ documentation&nbsp; in <a href="colprof.html#k">colprof</a> for the
+ details of the options.<span style="font-weight: bold;"><br>
+ <br>
+ Note</span> that making a good choice of black generation curve
+ can affect things such as: how robust neutrals are given printer
+ drift or changes in viewing lighting, how visible screening is, and
+ how smooth looking the B2A conversion is.<br>
+ <br>
+ For instance, maximizing the level of K will mean that the neutral
+ colors are composed of greater amounts of Black ink, and black ink
+ retains its neutral appearance irrespective of printer behavior or
+ the spectrum of the illuminant used to view the print. On the other
+ hand, output which is dominantly from one of the color channels will
+ tend to emphasize the screening pattern and any unevenness (banding
+ etc.) of that channel, and the black channel in particular has the
+ highest visibility. So in practice, some balance between the levels
+ of the four channels is probably best, with more K if the screening
+ is fine and a robust neutral balance is important, or less K if the
+ screening is more visible and neutral balance is less critical. The
+ levels of K at the edges of the gamut of the device will be fixed by
+ the nature of the ink combinations that maximize the gamut (ie.
+ typically zero ink for light chromatic colors, some combination for
+ dark colors, and a high level of black for very dark near neutrals),
+ and it is also usually important to set a curve that smoothly
+ transitions to the K values at the gamut edges. Dramatic changes in
+ K imply equally dramatic changes in CMY, and these abrupt
+ transitions will reveal the limited precision and detail that can be
+ captured in a lookup table based profile, often resulting in a
+ "bumpy" looking output.<br>
+ <br>
+ If you want to experiment with the various black generation
+ parameters, then it might be a good idea to create a preliminary
+ profile (using <a href="colprof.html#q">-ql</a> <a
+ href="colprof.html#b">-b</a> <a href="colprof.html#ni">-no</a>, <a
href="colprof.html#no">-ni</a> and no <a href="colprof.html#S">-S</a>),
@@ -1454,406 +2026,443 @@ then
- and then used <a href="xicclu.html#g">xicclu</a> to explore the
- effect of the parameters.<br>
- <br>
- For instance, say we have our CMYK .ti3 file <span
- style="font-weight: bold;">PrinterB.ti3</span>. First we make a
- preliminary profile called <span style="font-weight: bold;">PrinterBt</span>:<br>
- <br>
- copy PrinterB.ti3 PrinterBt.ti3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Use
- "cp" on Linux or OSX of course.)<br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#q">-qm</a> <a href="colprof.html#b">-b</a> <a
- href="colprof.html#c">-cmt</a> <a href="colprof.html#d">-dpp</a>
- <a href="colprof.html#p1">PrinterBt</a><br>
- <br>
- Then see what the minimum black level down the neutral axis can be.
- Note that we need to also set any ink limits we've decided on as
- well (coloprof defaulting to 10% less than the value recorded in the
- .ti3 file). In this example the test chart has a 300% total ink
- limit, and we've decided to use 290%:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kz</a> <a href="xicclu.html#l">-l290</a> <a
- href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- Which might be a graph something like this:<br>
- <br>
- <img alt="Graph of CMYK neutral axis with minimum K"
- src="Kgraph1.jpg" style="width: 250px; height: 250px;"><br>
- <br>
- Note&nbsp; how the minimum black is zero up to 93% of the
- white-&gt;black L* curve, and then jumps up to 87%. This is because
- we've reached the total ink limit, and K then has to be substituted
- for CMY, to keep the total under the total ink limit.<br>
- <br>
- Then let's see what the maximum black level down the neutral axis
- can be:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kx</a> <a href="xicclu.html#l">-l290</a> <a
- href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- Which might be a graph something like this:<br>
- <br>
- <img alt="Graph of CMYK neutral axis with maximum K"
- src="Kgraph2.jpg" style="width: 250px; height: 250px;"><br>
- <br>
- Note how the CMY values are fairly low up to 93% of the
- white-&gt;black L* curve (the low levels of CMY are helping set the
- neutral color), and then they jump up. This is because we've reach
- the point where black on it's own, isn't as dark as the color that
- can be achieved using CMY and K. Because the K has a dominant effect
- on the hue of the black, the levels of CMY are often fairly volatile
- in this region.<br>
- <br>
- Any K curve we specify must lie between the black curves of the
- above two graphs.<br>
- <br>
- Let's say we'd like to chose a moderate black curve, one that aims
- for about equal levels of CMY and K. We should also aim for it to be
- fairly smooth, since this will minimize visual artefacts caused by
- the limited fidelity that profile LUT tables are able to represent
- inside the profile.<br>
- <br>
- <img style="width: 340px; height: 258px;" alt="-k parameters"
- src="Kparams.jpg"><br>
- <br>
- <br>
- For minimum discontinuities we should aim for the curve to finish at
- the point it has to reach to satisfy the total ink limit at 87%
- curve and 93% black. For a first try we can simply set a straight
- line to that point: <br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kp 0 0 .93 .87 1.0</a> <a
- href="xicclu.html#l">-l290</a> <a href="xicclu.html#f">-fif</a> <a
- href="xicclu.html#i">-ir</a> <a href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- <img alt="Graph of CMYK neutral axis with kp 0 0 1.0 1.0 1.0 -l290"
- src="Kgraph3.jpg" style="width: 250px; height: 250px;"><br>
- <br>
- The black "curve" hits the 93%/87% mark well, but is a bit too far
- above CMY, so we'll try making the black curve concave:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 0 .93 .87
- 0.65</a> <a href="xicclu.html#l">-l290</a> <a
- href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- <img alt="Graph of CMYK neutral axis with -kp 0 .05 1 .9 1 -l290"
- src="Kgraph4.jpg" style="width: 250px; height: 249px;"><br>
- <br>
- This looks just about perfect, so the the curve parameters can now
- be used to generate our real profile:<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Printer B"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#k">-kp </a><a href="xicclu.html#k">0 0 .93
- .87 0.65</a> <a href="colprof.html#S">-S</a><a
- href="colprof.html#S"> sRGB.icm</a> <a href="colprof.html#c">-cmt</a>
- <a href="colprof.html#d">-dpp</a> <a href="colprof.html#p1">PrinterB</a><br>
- <br>
- and the resulting B2A table black curve can be checked using xicclu:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#f">-fb</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterB.icm</a><br>
- <br>
- <img style="width: 250px; height: 250px;" alt="sadsadas"
- src="Kgraph5.jpg"><br>
- <br>
- <br>
- <hr style="margin-left: 0px; margin-right: auto; width: 20%; height:
- 2px;"><br>
- <span style="font-weight: bold;">Examples of other inkings:<br>
- <br>
- </span>A smoothed zero black inking:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 .7 .93 .87
- 1.0</a> <a href="xicclu.html#l">-l290</a> <a
- href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- <img style="width: 250px; height: 250px;" alt="sadsadas"
- src="Kgraph6.jpg"><br>
- <br>
- A low black inking:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 0 .93 .87
- 0.15</a> <a href="xicclu.html#l">-l290</a> <a
- href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- <img style="width: 250px; height: 250px;" alt="sadsadas"
- src="Kgraph7.jpg"><br>
- <br>
- <br>
- A high black inking:<br>
- <br>
- <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
- href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 0 .93 .87
- 1.2</a> <a href="xicclu.html#l">-l290</a> <a
- href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
- href="xicclu.html#p1">PrinterBt.icm</a><br>
- <br>
- <img style="width: 250px; height: 250px;" alt="sadsadas"
- src="Kgraph8.jpg"><br>
- <br>
- <span style="font-weight: bold;"></span>
- <h4>Overriding the ink limit<br>
- </h4>
- Normally the total ink limit will be read from the <span
- style="font-weight: bold;">PrinterB.ti3</span> file, and will be
- set at a level 10% lower than the number used in creating the test
- chart values using <a href="targen.html#l">targen -l</a>. If you
- want to override this with a lower limit, then use the <a
- href="colprof.html#l">-l flag</a>.<br>
- <br>
- <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
- <a href="colprof.html#E">-D"Printer B"</a> <a href="colprof.html#q">-qm</a>
- <a href="colprof.html#S">-S</a><a href="colprof.html#S"> sRGB.icm</a>
- <a href="colprof.html#c">-cmt</a> <a href="colprof.html#d">-dpp</a>
- <a href="colprof.html#k">-kr</a> <a href="xicclu.html#l">-l290</a>
- <a href="colprof.html#p1">PrinterB</a><br>
- <br>
- Make sure you check the delta E report at the end of the profile
- creation, to see if the profile is behaving reasonably.<br>
- <br>
- One way of checking that your ink limit is not too high, is to use "<span
- style="font-weight: bold;">xicc -fif -ia</span>" to check, by
- setting different ink limits using the <span style="font-weight:
- bold;">-l</span> option, feeding Lab = 0 0 0 into it, and checking
- the resulting&nbsp; black point. Starting with the ink limit used
- with <span style="font-weight: bold;">targen</span> for the test
- chart, reduce it until the black point starts to be affected. If it
- is immediately affected by any reduction in the ink limit, then the
- black point may be improved by increasing the ink limit used to
- generate the test chart and then re-print and re-measuring it,
- assuming other aspects such as wetness, smudging, spreading or
- drying time are not an issue.<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <h3><a name="PC1"></a>Calibrating Printers<br>
- </h3>
- <span style="font-weight: bold;">Profiling</span> creates a
- description of how a device behaves, while <span
- style="font-weight: bold;">calibration</span> on the other hand is
- intended to <span style="text-decoration: underline;">change</span>
- how a device behaves. Argyll has the ability to create per-channel
- device space calibration curves for print devices, that can then be
- used to improve the behavior of of the device, making a subsequent
- profile fit the device more easily and also allow day to day
- correction of device drift without resorting to a full re-profile.<br>
- <br>
- <span style="font-weight: bold;">NOTE:</span> Because calibration
- adds yet another layer to the way color is processed, it is
- recommended that it not be attempted until the normal profiling
- workflow is established, understood and verified.<br>
- <h4><a name="PC2"></a>Calibrated print workflows</h4>
- There are two main workflows that printer calibration curves can be
- applied to:<br>
- <br>
- <span style="text-decoration: underline;">Workflow <span
- style="font-weight: bold;">with</span> native calibration
- capability</span>:<br>
- <br>
- Firstly the printer itself may have the capability of using per
- channel calibration curves. In this situation, the calibration
- process will be largely independent of profiling. Firstly the
- printer is configured to have both its color management and
- calibration disabled (the latter perhaps achieved by loading linear
- calibration curves), and a print calibration test chart that
- consists of per channel color wedges is printed. The calibration
- chart is read and the resulting .ti3 file converted into calibration
- curves by processing it using <span style="font-weight: bold;">printcal</span>.
- The calibration is then installed into the printer. Subsequent
- profiling will be performed on the <span style="text-decoration:
- underline;">calibrated</span> printer (ie. the profile test chart
- will have the calibration curves applied to it by the printer, and
- the resulting ICC profile will represent the behavior of the
- calibrated printer.)<br>
- <br>
- <span style="text-decoration: underline;">Workflow <span
- style="font-weight: bold;">without</span> native calibration
- capability</span>:<br>
- <br>
- The second workflow is one in which the printer has no calibration
- capability itself. In this situation, the calibration process will
- have to be applied using the ICC color management tools, so careful
- coordination with profiling is needed. Firstly the printer is
- configured to have its color management disabled, and a print
- calibration test chart that consists of per channel color wedges is
- printed. The calibration chart is converted into calibration curves
- by reading it and then processing the resultant .ti3 using <span
- style="font-weight: bold;">printcal</span>,. During the subsequent
- <span style="text-decoration: underline;">profiling</span>, the
- calibration curves will need to be applied to the profile test chart
- in the process of using <span style="font-weight: bold;">printtarg</span>.
- Once the the profile has been created, then in subsequent printing
- the calibration curves will need to be applied to an image being
- printed either explicitly when using <span style="font-weight:
- bold;">cctiff</span> to apply color profiles <span
- style="text-decoration: underline;">and</span> calibration, <span
- style="font-weight: bold;">OR</span> by creating a version of the
- profile that has had the calibration curves incorporated into it
- using the <span style="font-weight: bold;">applycal</span> tool.
- The latter is useful when some CMM (color management module) other
- than <span style="font-weight: bold;">cctiff </span>is being used.<br>
- <br>
- Once calibration aim targets for a particular device and mode
- (screening, paper etc.) have been established, then the printer can
- be re-calibrated at any time to bring its per channel behavior back
- into line if it drifts, and the new calibration curves can be
- installed into the printer, or re-incorporated into the profile.
- &nbsp;
- <h4><a name="PC3"></a>Creating a print calibration test chart</h4>
- The first step is to create a print calibration test chart. Since
- calibration only creates per-channel curves, only single channel
- step wedges are required for the chart. The main choice is the
- number of steps in each wedge. For simple fast calibrations perhaps
- as few as 20 steps per channel may be enough, but for a better
- quality of calibration something like 50 or more steps would be a
- better choice.<br>
- <br>
- Let's consider two devices in our examples, "PrinterA" which is an
- "RGB" printer device, and "PrinterB" which is CMYK. In fact there is
- no such thing as a real RGB printer, since printers use white media
- and the colorant must subtract from the light reflected on it to
- create color, but the printer itself turns the incoming RGB into the
- native print colorspace, so for this reason we are careful to tell
- targen to use the "Print RGB" colorspace, so that it knows to create
- step wedges from media white to full colorant values.<br>
- <br>
- For instance, to create a 50 steps per channel calibration test
- chart for our RGB and CMYK devices, the following would be
- sufficient:<br>
- <br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d2</a> <a href="targen.html#s">-s50</a>
- <a href="targen.html#e">-e3</a> <a href="targen.html#f">-f0</a> <a
- href="targen.html#p1">PrinterA_c</a><br>
- <br>
- <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
- &nbsp;<a href="targen.html#d">-d4</a> <a href="targen.html#s">-s50</a>
- <a href="targen.html#e">-e4</a> <a href="targen.html#f">-f0</a> <a
- href="targen.html#p1">PrinterB_c</a><br>
- <a href="targen.html#p1"></a><br>
- For an outline of how to then print and read the resulting test
- chart, see&nbsp; <a href="Scenarios.html#PP2b">Printing a print
- profile test chart</a>, and <a href="Scenarios.html#PP3">Reading
- a print test chart using an instrument</a>. Note that the printer
- must be in an un-profiled and un-calibrated mode when doing this
- print. Having done this, there will be a PrinterA.ti3 or
- PrinterB.ti3 file containing the step wedge calibration chart
- readings.<br>
- <br>
- <span style="font-weight: bold;">NOTE</span> that if you are
- calibrating a raw printer driver, and there is considerable dot
- gain, then you may want to use the <a href="targen.html#p">-p</a>
- parameter to adjust the test chart point distribution to spread them
- more evenly in perceptual space, giving more accurate control over
- the calibration. Typically this will be a value greater than one for
- a device that has dot gain, e.g. values of 1.5, 2.0 or 2.5 might be
- good places to start. You can do a preliminary calibration and use
- the verbose output of printcal to recommend a suitable value for <span
- style="font-weight: bold;">-p</span>.<br>
- <h4><a name="PC4"></a>Creating a printer calibration<br>
- </h4>
- The <a href="printcal.html">printcal</a> tool turns a calibration
- chart <a href="File_Formats.html#.ti3">.ti3</a> file into a <a
- href="File_Formats.html#.cal">.cal</a> file. It has three main
- operating modes:- Initial calibration, Re-Calibration, and
- Verification. (A fourth mode, "Imitation" is very like Initial
- Calibration, but is used for establishing a calibration target that
- a similar printer can attempt to imitate.)<br>
- <br>
- The distinction between Initial Calibration and Re-Calibration is
- that in the initial calibration we establish the "aim points" or
- response we want out of the printer after calibration. There are
- three basic parameters to set this for each channel: Maximum level,
- minimum level, and curve shape.<br>
- <br>
- By default the maximum level will be set using a heuristic which
- attempts to pick the point when there is diminishing returns for
- applying more colorant. This can be overridden using the <span
- style="font-weight: bold;">-x# percent</span> option, where <span
- style="font-weight: bold;">#</span> represents the choice of
- channel this will be applied to. The parameter is the percentage of
- device maximum. <br>
- <br>
- The minimum level defaults to 0, but can be overridden using the <span
- style="font-weight: bold;">-n# deltaE</span> option. A minimum of
- 0 means that zero colorant will correspond to the natural media
- color, but it may be desirable to set a non-pure media color using
- calibration for the purposes of emulating some other media. The
- parameter is in Delta E units.<br>
- <br>
- The curve shape defaults to being perceptually uniform, which means
- that even steps of calibrated device value result in perceptually
- even color steps. In some situations it may be desirable to alter
- this curve (for instance when non color managed output needs to be
- sent to the calibrated printer), and a simple curve shape target can
- be set using the <span style="font-weight: bold;">-t# percent</span>
- parameter. This affects the output value at 50% input value, and
- represents the percentage of perceptual output. By default it is 50%
- perceptual output for 50% device input.<br>
- <br>
- Once a device has been calibrated, it can be re-calibrated to the
- same aim target.<br>
- <br>
- Verification uses a calibration test chart printed through the
- calibration, and compares the achieved response to the aim target.<br>
- <br>
- The simplest possible way of creating the <span style="font-weight:
- bold;">PrinterA.cal</span> file is:<br>
- <br>
- &nbsp; <a href="printcal.html">printcal</a> <a
- href="printcal.html#i">-i</a> <a href="colprof.html#p2">PrinterA_c</a><br>
- <br>
- For more detailed information, you can add the <span
- style="font-weight: bold;">-v</span> and <span
- style="font-weight: bold;">-p</span> flags:<br>
- <br>
- &nbsp; <a href="printcal.html">printcal</a> <a
- href="printcal.html#v">-v</a> <a href="printcal.html#p">-p</a> <a
- href="printcal.html#i">-i</a> <a href="colprof.html#p2">PrinterB_c</a><br>
- <br>
- (You will need to select the plot window and hit a key to advance
- past each plot).<br>
- <br>
- For re-calibration, the name of the previous calibration file will
- need to be supplied, and a new calibration<br>
- file will be created:<br>
- <br>
- &nbsp; <a href="printcal.html">printcal</a> <a
- href="printcal.html#v">-v</a> <a href="printcal.html#p">-p</a> <a
- href="printcal.html#r">-r</a> <a href="colprof.html#p1">PrinterB_c_old</a>
- <a href="colprof.html#p2">PrinterB_c_new</a><br>
- <br>
- Various aim points are normally set automatically by <span
- style="font-weight: bold;">printcal</span>, but these can be
- overridden using the <a href="colprof.html#x">-x</a>, <a
- href="colprof.html#n">-n</a> and <a href="colprof.html#t">-t</a>
- options. e.g. say we wanted to set the maximum ink for Cyan to 80%
- and Black to 95%, we might use:<br>
- <br>
- &nbsp; <a href="printcal.html">printcal</a> <a
- href="printcal.html#v">-v</a> <a href="printcal.html#p">-p</a> <a
- href="printcal.html#i">-i</a> <a href="colprof.html#x">-xc 80</a>
- <a href="colprof.html#x">-xk 95</a> <a href="colprof.html#p2">PrinterB_c</a><br>
- <br>
- <a href="colprof.html#p2"></a>
- <h4><a name="PC5"></a>Using a printer calibration</h4>
- The resulting calibration curves can be used with the following
- other Argyll tools:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and then used <a href="xicclu.html#g">xicclu</a> to explore the
+ effect of the parameters.<br>
+ <br>
+ For instance, say we have our CMYK .ti3 file <span
+ style="font-weight: bold;">PrinterB.ti3</span>. First we make a
+ preliminary profile called <span style="font-weight: bold;">PrinterBt</span>:<br>
+ <br>
+ copy PrinterB.ti3 PrinterBt.ti3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (Use
+ "cp" on Linux or OSX of course.)<br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#q">-qm</a> <a href="colprof.html#b">-b</a> <a
+ href="colprof.html#c">-cmt</a> <a href="colprof.html#d">-dpp</a>
+ <a href="colprof.html#p1">PrinterBt</a><br>
+ <br>
+ Then see what the minimum black level down the neutral axis can be.
+ Note that we need to also set any ink limits we've decided on as
+ well (coloprof defaulting to 10% less than the value recorded in the
+ .ti3 file). In this example the test chart has a 300% total ink
+ limit, and we've decided to use 290%:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kz</a> <a href="xicclu.html#l">-l290</a> <a
+ href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ Which might be a graph something like this:<br>
+ <br>
+ <img alt="Graph of CMYK neutral axis with minimum K"
+ src="Kgraph1.jpg" style="width: 250px; height: 250px;"><br>
+ <br>
+ Note&nbsp; how the minimum black is zero up to 93% of the
+ white-&gt;black L* curve, and then jumps up to 87%. This is because
+ we've reached the total ink limit, and K then has to be substituted
+ for CMY, to keep the total under the total ink limit.<br>
+ <br>
+ Then let's see what the maximum black level down the neutral axis
+ can be:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kx</a> <a href="xicclu.html#l">-l290</a> <a
+ href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ Which might be a graph something like this:<br>
+ <br>
+ <img alt="Graph of CMYK neutral axis with maximum K"
+ src="Kgraph2.jpg" style="width: 250px; height: 250px;"><br>
+ <br>
+ Note how the CMY values are fairly low up to 93% of the
+ white-&gt;black L* curve (the low levels of CMY are helping set the
+ neutral color), and then they jump up. This is because we've reach
+ the point where black on it's own, isn't as dark as the color that
+ can be achieved using CMY and K. Because the K has a dominant effect
+ on the hue of the black, the levels of CMY are often fairly volatile
+ in this region.<br>
+ <br>
+ Any K curve we specify must lie between the black curves of the
+ above two graphs.<br>
+ <br>
+ Let's say we'd like to chose a moderate black curve, one that aims
+ for about equal levels of CMY and K. We should also aim for it to be
+ fairly smooth, since this will minimize visual artefacts caused by
+ the limited fidelity that profile LUT tables are able to represent
+ inside the profile.<br>
+ <br>
+ <img style="width: 340px; height: 258px;" alt="-k parameters"
+ src="Kparams.jpg"><br>
+ <br>
+ <br>
+ For minimum discontinuities we should aim for the curve to finish at
+ the point it has to reach to satisfy the total ink limit at 87%
+ curve and 93% black. For a first try we can simply set a straight
+ line to that point: <br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kp 0 0 .93 .87 1.0</a> <a
+ href="xicclu.html#l">-l290</a> <a href="xicclu.html#f">-fif</a> <a
+ href="xicclu.html#i">-ir</a> <a href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ <img alt="Graph of CMYK neutral axis with kp 0 0 1.0 1.0 1.0 -l290"
+ src="Kgraph3.jpg" style="width: 250px; height: 250px;"><br>
+ <br>
+ The black "curve" hits the 93%/87% mark well, but is a bit too far
+ above CMY, so we'll try making the black curve concave:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 0 .93 .87
+ 0.65</a> <a href="xicclu.html#l">-l290</a> <a
+ href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ <img alt="Graph of CMYK neutral axis with -kp 0 .05 1 .9 1 -l290"
+ src="Kgraph4.jpg" style="width: 250px; height: 249px;"><br>
+ <br>
+ This looks just about perfect, so the the curve parameters can now
+ be used to generate our real profile:<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Printer B"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#k">-kp </a><a href="xicclu.html#k">0 0 .93
+ .87 0.65</a> <a href="colprof.html#S">-S</a><a
+ href="colprof.html#S"> sRGB.icm</a> <a href="colprof.html#c">-cmt</a>
+ <a href="colprof.html#d">-dpp</a> <a href="colprof.html#p1">PrinterB</a><br>
+ <br>
+ and the resulting B2A table black curve can be checked using xicclu:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#f">-fb</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterB.icm</a><br>
+ <br>
+ <img style="width: 250px; height: 250px;" alt="sadsadas"
+ src="Kgraph5.jpg"><br>
+ <br>
+ <br>
+ <hr style="margin-left: 0px; margin-right: auto; width: 20%; height:
+ 2px;"><br>
+ <span style="font-weight: bold;">Examples of other inkings:<br>
+ <br>
+ </span>A smoothed zero black inking:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 .7 .93 .87
+ 1.0</a> <a href="xicclu.html#l">-l290</a> <a
+ href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ <img style="width: 250px; height: 250px;" alt="sadsadas"
+ src="Kgraph6.jpg"><br>
+ <br>
+ A low black inking:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 0 .93 .87
+ 0.15</a> <a href="xicclu.html#l">-l290</a> <a
+ href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ <img style="width: 250px; height: 250px;" alt="sadsadas"
+ src="Kgraph7.jpg"><br>
+ <br>
+ <br>
+ A high black inking:<br>
+ <br>
+ <a href="xicclu.html">xicclu</a> <a href="xicclu.html#g">-g</a> <a
+ href="xicclu.html#k">-kp </a><a href="xicclu.html#k">0 0 .93 .87
+ 1.2</a> <a href="xicclu.html#l">-l290</a> <a
+ href="xicclu.html#f">-fif</a> <a href="xicclu.html#i">-ir</a> <a
+ href="xicclu.html#p1">PrinterBt.icm</a><br>
+ <br>
+ <img style="width: 250px; height: 250px;" alt="sadsadas"
+ src="Kgraph8.jpg"><br>
+ <br>
+ <span style="font-weight: bold;"></span>
+ <h4>Overriding the ink limit<br>
+ </h4>
+ Normally the total ink limit will be read from the <span
+ style="font-weight: bold;">PrinterB.ti3</span> file, and will be
+ set at a level 10% lower than the number used in creating the test
+ chart values using <a href="targen.html#l">targen -l</a>. If you
+ want to override this with a lower limit, then use the <a
+ href="colprof.html#l">-l flag</a>.<br>
+ <br>
+ <a href="colprof.html">colprof</a> <a href="colprof.html#v">-v</a>
+ <a href="colprof.html#E">-D"Printer B"</a> <a href="colprof.html#q">-qm</a>
+ <a href="colprof.html#S">-S</a><a href="colprof.html#S"> sRGB.icm</a>
+ <a href="colprof.html#c">-cmt</a> <a href="colprof.html#d">-dpp</a>
+ <a href="colprof.html#k">-kr</a> <a href="xicclu.html#l">-l290</a>
+ <a href="colprof.html#p1">PrinterB</a><br>
+ <br>
+ Make sure you check the delta E report at the end of the profile
+ creation, to see if the profile is behaving reasonably.<br>
+ <br>
+ One way of checking that your ink limit is not too high, is to use "<span
+ style="font-weight: bold;">xicc -fif -ia</span>" to check, by
+ setting different ink limits using the <span style="font-weight:
+ bold;">-l</span> option, feeding Lab = 0 0 0 into it, and checking
+ the resulting&nbsp; black point. Starting with the ink limit used
+ with <span style="font-weight: bold;">targen</span> for the test
+ chart, reduce it until the black point starts to be affected. If it
+ is immediately affected by any reduction in the ink limit, then the
+ black point may be improved by increasing the ink limit used to
+ generate the test chart and then re-print and re-measuring it,
+ assuming other aspects such as wetness, smudging, spreading or
+ drying time are not an issue.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <h3><a name="PC1"></a>Calibrating Printers<br>
+ </h3>
+ <span style="font-weight: bold;">Profiling</span> creates a
+ description of how a device behaves, while <span
+ style="font-weight: bold;">calibration</span> on the other hand is
+ intended to <span style="text-decoration: underline;">change</span>
+ how a device behaves. Argyll has the ability to create per-channel
+ device space calibration curves for print devices, that can then be
+ used to improve the behavior of of the device, making a subsequent
+ profile fit the device more easily and also allow day to day
+ correction of device drift without resorting to a full re-profile.<br>
+ <br>
+ <span style="font-weight: bold;">NOTE:</span> Because calibration
+ adds yet another layer to the way color is processed, it is
+ recommended that it not be attempted until the normal profiling
+ workflow is established, understood and verified.<br>
+ <h4><a name="PC2"></a>Calibrated print workflows</h4>
+ There are two main workflows that printer calibration curves can be
+ applied to:<br>
+ <br>
+ <span style="text-decoration: underline;">Workflow <span
+ style="font-weight: bold;">with</span> native calibration
+ capability</span>:<br>
+ <br>
+ Firstly the printer itself may have the capability of using per
+ channel calibration curves. In this situation, the calibration
+ process will be largely independent of profiling. Firstly the
+ printer is configured to have both its color management and
+ calibration disabled (the latter perhaps achieved by loading linear
+ calibration curves), and a print calibration test chart that
+ consists of per channel color wedges is printed. The calibration
+ chart is read and the resulting .ti3 file converted into calibration
+ curves by processing it using <span style="font-weight: bold;">printcal</span>.
+ The calibration is then installed into the printer. Subsequent
+ profiling will be performed on the <span style="text-decoration:
+ underline;">calibrated</span> printer (ie. the profile test chart
+ will have the calibration curves applied to it by the printer, and
+ the resulting ICC profile will represent the behavior of the
+ calibrated printer.)<br>
+ <br>
+ <span style="text-decoration: underline;">Workflow <span
+ style="font-weight: bold;">without</span> native calibration
+ capability</span>:<br>
+ <br>
+ The second workflow is one in which the printer has no calibration
+ capability itself. In this situation, the calibration process will
+ have to be applied using the ICC color management tools, so careful
+ coordination with profiling is needed. Firstly the printer is
+ configured to have its color management disabled, and a print
+ calibration test chart that consists of per channel color wedges is
+ printed. The calibration chart is converted into calibration curves
+ by reading it and then processing the resultant .ti3 using <span
+ style="font-weight: bold;">printcal</span>,. During the subsequent
+ <span style="text-decoration: underline;">profiling</span>, the
+ calibration curves will need to be applied to the profile test chart
+ in the process of using <span style="font-weight: bold;">printtarg</span>.
+ Once the the profile has been created, then in subsequent printing
+ the calibration curves will need to be applied to an image being
+ printed either explicitly when using <span style="font-weight:
+ bold;">cctiff</span> to apply color profiles <span
+ style="text-decoration: underline;">and</span> calibration, <span
+ style="font-weight: bold;">OR</span> by creating a version of the
+ profile that has had the calibration curves incorporated into it
+ using the <span style="font-weight: bold;">applycal</span> tool.
+ The latter is useful when some CMM (color management module) other
+ than <span style="font-weight: bold;">cctiff </span>is being used.<br>
+ <br>
+ Once calibration aim targets for a particular device and mode
+ (screening, paper etc.) have been established, then the printer can
+ be re-calibrated at any time to bring its per channel behavior back
+ into line if it drifts, and the new calibration curves can be
+ installed into the printer, or re-incorporated into the profile.
+ &nbsp;
+ <h4><a name="PC3"></a>Creating a print calibration test chart</h4>
+ The first step is to create a print calibration test chart. Since
+ calibration only creates per-channel curves, only single channel
+ step wedges are required for the chart. The main choice is the
+ number of steps in each wedge. For simple fast calibrations perhaps
+ as few as 20 steps per channel may be enough, but for a better
+ quality of calibration something like 50 or more steps would be a
+ better choice.<br>
+ <br>
+ Let's consider two devices in our examples, "PrinterA" which is an
+ "RGB" printer device, and "PrinterB" which is CMYK. In fact there is
+ no such thing as a real RGB printer, since printers use white media
+ and the colorant must subtract from the light reflected on it to
+ create color, but the printer itself turns the incoming RGB into the
+ native print colorspace, so for this reason we are careful to tell
+ targen to use the "Print RGB" colorspace, so that it knows to create
+ step wedges from media white to full colorant values.<br>
+ <br>
+ For instance, to create a 50 steps per channel calibration test
+ chart for our RGB and CMYK devices, the following would be
+ sufficient:<br>
+ <br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d2</a> <a href="targen.html#s">-s50</a>
+ <a href="targen.html#e">-e3</a> <a href="targen.html#f">-f0</a> <a
+ href="targen.html#p1">PrinterA_c</a><br>
+ <br>
+ <a href="targen.html">targen</a> <a href="targen.html#v">-v</a>
+ &nbsp;<a href="targen.html#d">-d4</a> <a href="targen.html#s">-s50</a>
+ <a href="targen.html#e">-e4</a> <a href="targen.html#f">-f0</a> <a
+ href="targen.html#p1">PrinterB_c</a><br>
+ <a href="targen.html#p1"></a><br>
+ For an outline of how to then print and read the resulting test
+ chart, see&nbsp; <a href="Scenarios.html#PP2b">Printing a print
+ profile test chart</a>, and <a href="Scenarios.html#PP3">Reading
+ a print test chart using an instrument</a>. Note that the printer
+ must be in an un-profiled and un-calibrated mode when doing this
+ print. Having done this, there will be a PrinterA.ti3 or
+ PrinterB.ti3 file containing the step wedge calibration chart
+ readings.<br>
+ <br>
+ <span style="font-weight: bold;">NOTE</span> that if you are
+ calibrating a raw printer driver, and there is considerable dot
+ gain, then you may want to use the <a href="targen.html#p">-p</a>
+ parameter to adjust the test chart point distribution to spread them
+ more evenly in perceptual space, giving more accurate control over
+ the calibration. Typically this will be a value greater than one for
+ a device that has dot gain, e.g. values of 1.5, 2.0 or 2.5 might be
+ good places to start. You can do a preliminary calibration and use
+ the verbose output of printcal to recommend a suitable value for <span
+ style="font-weight: bold;">-p</span>.<br>
+ <h4><a name="PC4"></a>Creating a printer calibration<br>
+ </h4>
+ The <a href="printcal.html">printcal</a> tool turns a calibration
+ chart <a href="File_Formats.html#.ti3">.ti3</a> file into a <a
+ href="File_Formats.html#.cal">.cal</a> file. It has three main
+ operating modes:- Initial calibration, Re-Calibration, and
+ Verification. (A fourth mode, "Imitation" is very like Initial
+ Calibration, but is used for establishing a calibration target that
+ a similar printer can attempt to imitate.)<br>
+ <br>
+ The distinction between Initial Calibration and Re-Calibration is
+ that in the initial calibration we establish the "aim points" or
+ response we want out of the printer after calibration. There are
+ three basic parameters to set this for each channel: Maximum level,
+ minimum level, and curve shape.<br>
+ <br>
+ By default the maximum level will be set using a heuristic which
+ attempts to pick the point when there is diminishing returns for
+ applying more colorant. This can be overridden using the <span
+ style="font-weight: bold;">-x# percent</span> option, where <span
+ style="font-weight: bold;">#</span> represents the choice of
+ channel this will be applied to. The parameter is the percentage of
+ device maximum. <br>
+ <br>
+ The minimum level defaults to 0, but can be overridden using the <span
+ style="font-weight: bold;">-n# deltaE</span> option. A minimum of
+ 0 means that zero colorant will correspond to the natural media
+ color, but it may be desirable to set a non-pure media color using
+ calibration for the purposes of emulating some other media. The
+ parameter is in Delta E units.<br>
+ <br>
+ The curve shape defaults to being perceptually uniform, which means
+ that even steps of calibrated device value result in perceptually
+ even color steps. In some situations it may be desirable to alter
+ this curve (for instance when non color managed output needs to be
+ sent to the calibrated printer), and a simple curve shape target can
+ be set using the <span style="font-weight: bold;">-t# percent</span>
+ parameter. This affects the output value at 50% input value, and
+ represents the percentage of perceptual output. By default it is 50%
+ perceptual output for 50% device input.<br>
+ <br>
+ Once a device has been calibrated, it can be re-calibrated to the
+ same aim target.<br>
+ <br>
+ Verification uses a calibration test chart printed through the
+ calibration, and compares the achieved response to the aim target.<br>
+ <br>
+ The simplest possible way of creating the <span style="font-weight:
+ bold;">PrinterA.cal</span> file is:<br>
+ <br>
+ &nbsp; <a href="printcal.html">printcal</a> <a
+ href="printcal.html#i">-i</a> <a href="colprof.html#p2">PrinterA_c</a><br>
+ <br>
+ For more detailed information, you can add the <span
+ style="font-weight: bold;">-v</span> and <span
+ style="font-weight: bold;">-p</span> flags:<br>
+ <br>
+ &nbsp; <a href="printcal.html">printcal</a> <a
+ href="printcal.html#v">-v</a> <a href="printcal.html#p">-p</a> <a
+ href="printcal.html#i">-i</a> <a href="colprof.html#p2">PrinterB_c</a><br>
+ <br>
+ (You will need to select the plot window and hit a key to advance
+ past each plot).<br>
+ <br>
+ For re-calibration, the name of the previous calibration file will
+ need to be supplied, and a new calibration<br>
+ file will be created:<br>
+ <br>
+ &nbsp; <a href="printcal.html">printcal</a> <a
+ href="printcal.html#v">-v</a> <a href="printcal.html#p">-p</a> <a
+ href="printcal.html#r">-r</a> <a href="colprof.html#p1">PrinterB_c_old</a>
+ <a href="colprof.html#p2">PrinterB_c_new</a><br>
+ <br>
+ Various aim points are normally set automatically by <span
+ style="font-weight: bold;">printcal</span>, but these can be
+ overridden using the <a href="colprof.html#x">-x</a>, <a
+ href="colprof.html#n">-n</a> and <a href="colprof.html#t">-t</a>
+ options. e.g. say we wanted to set the maximum ink for Cyan to 80%
+ and Black to 95%, we might use:<br>
+ <br>
+ &nbsp; <a href="printcal.html">printcal</a> <a
+ href="printcal.html#v">-v</a> <a href="printcal.html#p">-p</a> <a
+ href="printcal.html#i">-i</a> <a href="colprof.html#x">-xc 80</a>
+ <a href="colprof.html#x">-xk 95</a> <a href="colprof.html#p2">PrinterB_c</a><br>
+ <br>
+ <a href="colprof.html#p2"></a>
+ <h4><a name="PC5"></a>Using a printer calibration</h4>
+ The resulting calibration curves can be used with the following
+ other Argyll tools:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <a href="printtarg.html#K">printtarg</a>&nbsp;&nbsp;&nbsp;&nbsp;
To
apply
@@ -1871,7 +2480,44 @@ chart,
- and/or to have it included in .ti3 file.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and/or to have it included in .ti3 file.<br>
&nbsp;&nbsp;&nbsp; <a href="cctiff.html#p2">cctiff</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
To
apply
@@ -1889,7 +2535,44 @@ an
- image file.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ image file.<br>
&nbsp;&nbsp;&nbsp; <a href="applycal.html#p1">applycal</a>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1899,7 +2582,44 @@ an
- To incorporate calibration into an ICC profile.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ To incorporate calibration into an ICC profile.<br>
&nbsp;&nbsp;&nbsp; <a href="chartread.html#I">chartread</a>&nbsp;&nbsp;
To
override
@@ -1917,261 +2637,1046 @@ a
- profile chart.<br>
- <br>
- <br>
- In a workflow <span style="font-weight: bold;">with</span> native
- calibration capability, the calibration curves would be used with
- printarg during subsequent <span style="font-weight: bold;">profiling</span>
- so that any ink limit calculations will reflect final device values,
- while not otherwise using the calibration within the ICC workflow:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <a href="printtarg.html">printtarg</a> <a
- href="printtarg.html#v">-v</a> <a href="printtarg.html#i">-ii1</a>
- <a href="printtarg.html#p">-pA4</a> <a href="printtarg.html#I">-I
- PrinterA_c.cal</a> <a href="printtarg.html#p1">PrinterA</a><br>
- <br>
- This will cause the .ti2 and resulting .ti3 and ICC profiles to
- contain the calibration curves, allowing all the tools to be able to
- compute final device value ink limits. The calibration curves must
- also of course be installed into the printer. The means to do this
- is currently outside the scope of Argyll (ie. either the print
- system needs to be able to understand Argyll CAL format files, or
- some tool will be needed to convert Argyll CAL files into the
- printer calibration format).<br>
- <br>
- <br>
- In a workflow <span style="font-weight: bold;">without</span>
- native calibration capability, the calibration curves would be used
- with printarg to <span style="text-decoration: underline;">apply</span>
- the calibration to the test patch samples during subsequent <span
- style="font-weight: bold;">profiling</span>, as well as embedding
- it in the resulting .ti3 to allow all the tools to be able to
- compute final device value ink limits:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <a href="printtarg.html">printtarg</a> <a
- href="printtarg.html#v">-v</a> <a href="printtarg.html#i">-ii1</a>
- <a href="printtarg.html#p">-pA4</a> <a href="printtarg.html#K">-K
- PrinterA_c.cal</a> <a href="printtarg.html#p1">PrinterA</a><br>
- <a href="cctiff.html#p4"></a><br>
- To apply calibration to an ICC profile, so that a calibration
- unaware CMM can be used:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <a href="applycal.html">applycal</a> <a
- href="applycal.html#p1">PrinterA.cal</a> <a
- href="applycal.html#p2">PrinterA.icm</a> <a
- href="applycal.html#p3">PrinterA_cal.icm</a><br>
- <br>
- To apply color management and calibration to a raster image:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
- href="cctiff.html#p1">Source2Destination.icm</a> <a
- href="cctiff.html#p2">PrinterA_c.cal</a> <a href="cctiff.html#p3">infile.tif</a>
- <a href="cctiff.html#p4">outfile.tif</a><br>
- or<br>
- &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
- href="cctiff.html#p1">Source2Destination.icm</a> <a
- href="cctiff.html#p2">PrinterA_c.cal</a> <a href="cctiff.html#p3">infile.jpg</a>
- <a href="cctiff.html#p4">outfile.jpg</a><br>
- <br>
- <br>
- Another useful tool is <a href="synthcal.html">synthcal</a>, that
- allows creating linear or synthetic calibration files for disabling
- calibration or testing.<br>
- Similarly, <a href="fakeread.html">fakeread</a> also supports
- applying calibration curves and embedding them in the resulting .ti3
- file<br>
- <h4><a name="PC6"></a>How profile ink limits are handled when
- calibration is being used.</h4>
- Even though the profiling process is carried out on top of the
- linearized device, and the profiling is generally unaware of the
- underlying non-linearized device values, an exception is made in the
- calculation of ink limits during profiling. This is made possible by
- including the calibration curves in the profile charts .ti2 and
- subsequent .ti3 file and resulting ICC profile <span
- style="font-weight: bold;">'targ'</span> text tag, by way of the <span
- style="font-weight: bold;">printtarg</span> <span
- style="font-weight: bold;">-I</span> or <span style="font-weight:
- bold;">-K</span> options. This is done on the assumption that the
- physical quantity of ink is what's important in setting the ink
- limit, and that the underlying non-linearized device values
- represent such a physical quantity.<br>
- <br>
- <br>
- <hr size="2" width="100%">
- <h3><a name="LP1"></a>Linking Profiles</h3>
- Two device profiles can be linked together to create a device link
- profile, than encapsulates a particular device to device transform.
- Often this step is not necessary, as many systems and tools will
- link two device profiles "on the fly", but creating a device link
- profile gives you the option of using "smart CMM" techniques, such
- as true gamut mapping, improved inverse transform accuracy, tailored
- black generation and ink limiting.<br>
- <br>
- The overall process is to link the input space and output space
- profiles using <a href="collink.html">collink</a>, creating a
- device to device link profile. The device to device link profile can
- then be used by cctiff (or other ICC device profile capable tools),
- to color correct a raster files.<br>
- <br>
- Three examples will be given here, showing the three different modes
- than <span style="font-weight: bold;">collink</span> supports.<br>
- <br>
- In <a href="collink.html#s">simple mode</a>, the two profiles are
- linked together in a similar fashion to other <span
- style="font-weight: bold;">CMMs</span> simply using the forward
- and backwards color transforms defined by the profiles. Any gamut
- mapping is determined by the content of the tables within the two
- profiles, together with the particular intent chosen. Typically the
- same intent will be used for both the source and destination
- profile:<br>
- <br>
- <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
- <a href="collink.html#q">-qm</a> <a href="collink.html#s">-s</a> <a
- href="collink.html#si">-ip</a> <a href="collink.html#so">-op</a>
- <a href="collink.html#p1">SouceProfile.icm</a> <a
- href="collink.html#p2">DestinationProfile.icm</a> <a
- href="collink.html#p3">Source2Destination.icm</a><br>
- <br>
- <br>
- In <a href="collink.html#g">gamut mapping mode</a>, the
- pre-computed intent mappings inside the profiles are not used, but
- instead the gamut mapping between source and destination is tailored
- to the specific gamuts of the two profiles, and the intent parameter
- supplied to <span style="font-weight: bold;">collink</span>.
- Additionally, source and destination viewing conditions should be
- provided, to allow the color appearance space conversion to work as
- intended. The colorimetric B2A table in the destination profile is
- used, and this will determine any black generation and ink limiting:<br>
- <br>
- <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
- <a href="collink.html#q">-qm</a> <a href="collink.html#g">-g</a> <a
- href="collink.html#si">-ip</a> <a href="collink.html#c">-cmt</a>
- <a href="collink.html#d">-dpp</a> <a href="collink.html#p1">MonitorSouceProfile.icm</a>
- <a href="collink.html#p2">DestinationProfile.icm</a> <a
- href="collink.html#p3">Source2Destination.icm</a><br>
- <br>
- <br>
- In <a href="collink.html#G">inverse output table gamut mapping mode</a>,
- the pre-computed intent mappings inside the profiles are not used,
- but instead the gamut mapping between source and destination is
- tailored to the specific gamuts of the two profiles, and the intent
- parameter supplied to <span style="font-weight: bold;">collink</span>.
- In addition, the B2A table is <span style="font-weight: bold;">not</span>
- used in the destination profile, but the A2B table is instead
- inverted, leading to improved transform accuracy, and in CMYK
- devices, allowing the ink limiting and black generation parameters
- to be set:<br>
- <br>
- For a CLUT table based RGB printer destination profile, the
- following would be appropriate:<br>
- <br>
- <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
- <a href="collink.html#q">-qm</a> <a href="collink.html#G">-G</a> <a
- href="collink.html#si">-ip</a> <a href="collink.html#c">-cmt</a>
- <a href="collink.html#d">-dpp</a> <a href="collink.html#p1">MonitorSouceProfile.icm</a>
- <a href="collink.html#p2">RGBDestinationProfile.icm</a> <a
- href="collink.html#p3">Source2Destination.icm</a><br>
- <br>
- For a CMYK profile, the total ink limit needs to be specified (a
- typical value being 10% less than the value used in creating the
- device test chart), and the type of black generation also needs to
- be specified:<br>
- <br>
- <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
- <a href="collink.html#q">-qm</a> <a href="collink.html#G">-G</a> <a
- href="collink.html#si">-ip</a> <a href="collink.html#c">-cmt</a>
- <a href="collink.html#d">-dpp</a> <a href="collink.html#l">-l250</a>
- <a href="collink.html#k">-kr</a> <a href="collink.html#p1">MonitorSouceProfile.icm</a>
- <a href="collink.html#p2">CMYKDestinationProfile.icm</a> <a
- href="collink.html#p3">Source2Destination.icm</a><br>
- <br>
- Note that you should set the source (<a href="collink.html#c">-c</a>)
- and destination (<a href="collink.html#d">-d</a>) viewing conditions
- for the type of device the profile represents, and the conditions
- under which it will be viewed.<br>
- <br>
- <h3><a name="LP2"></a>Soft Proofing Link</h3>
- Often it is desirable to get an idea what a particular devices
- output will look like using a different device. Typically this might
- be trying to evaluate print output using a display. Often it is
- sufficient to use an absolute or relative colorimetric transform
- from the print device space to the display space, but while these
- provide a colorimetric preview of the result, they do not take into
- account the subjective appearance differences due to the different
- device conditions. It can therefore be useful to create a soft proof
- appearance transform using collink:<br>
- <br>
- <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
- <a href="collink.html#q">-qm</a> <a href="collink.html#G">-G</a> <a
- href="collink.html#si">-ila</a> <a href="collink.html#c">-cpp</a>
- <a href="collink.html#d">-dmt</a> <a href="collink.html#l">-t250</a>&nbsp;<a
- href="collink.html#k"></a><a href="collink.html#p1">CMYKDestinationProfile.icm</a>
- <a href="collink.html#p2">MonitorProfile.icm</a> <a
- href="collink.html#p3">SoftProof.icm</a><br>
- <br>
- We use the Luminance matched appearance intent, to preserve the
- subjective apperance of the target device, which takes into account
- the viewing conditions and assumes adaptation to the differences in
- the luminence range, but otherwise not attempting to compress or
- change the gamut.<br>
- &nbsp;
- <hr size="2" width="100%"><br>
- <h3><a name="TR1"></a>Transforming colorspaces of raster files</h3>
- Although a device profile or device link profile may be useful with
- other programs and systems, Argyll provides the tool <a
- href="cctiff.html">cctiff</a> for directly applying a device to
- device transform to a <a href="File_Formats.html#TIFF">TIFF</a> or
- <a href="File_Formats.html#JPEG">JPEG</a> raster file. The cctiff
- tool is capable of linking an arbitrary sequence of device profiles,
- device links, abstract profiles and calibration curves. Each device
- profile can be preceded by the <span style="font-weight: bold;">-i</span>
- option to indicate the intent that should be used. Both 8 and 16 bit
- per component files can be handled, and up to 8 color channels. The
- color transform is optimized to perform the overall transformation
- rapidly.<br>
- <br>
- If a device link is to be used, the following is a typical example:<br>
- <br>
- <a href="cctiff.html">cctiff</a> <a href="cctiff.html#p1">Source2Destination.icm</a>
- <a href="cctiff.html#p3">infile.tif</a> <a href="cctiff.html#p4">outfile.tif</a><br>
- or<br>
- <a href="cctiff.html">cctiff</a> <a href="cctiff.html#p1">Source2Destination.icm</a>
- <a href="cctiff.html#p3">infile.jpg</a> <a href="cctiff.html#p4">outfile.jpg</a><br>
- <br>
- <i><br>
- </i>If a source and destination profile are to be used, the
- following would be a typical example:<br>
- <br>
- <a href="cctiff.html"> cctiff</a>&nbsp; <a href="cctiff.html#i">-ip</a>
- <a href="cctiff.html#p1i">SourceProfile.icm</a> <a
- href="cctiff.html#i">-ip</a> <a href="cctiff.html#p1o">DestinationProfile.icm</a>
- <a href="cctiff.html#p3">infile.tif</a> <a href="cctiff.html#p4">outfile.tif</a><br>
- or<br>
- <a href="cctiff.html"> cctiff</a>&nbsp; <a href="cctiff.html#i">-ip</a>
- <a href="cctiff.html#p1i">SourceProfile.icm</a> <a
- href="cctiff.html#i">-ip</a> <a href="cctiff.html#p1o">DestinationProfile.icm</a>
- <a href="cctiff.html#p3">infile.jpg</a> <a href="cctiff.html#p4">outfile.jpg</a><br>
- <br>
- <br>
- <hr size="2" width="100%"><br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- <br>
- </body>
-</html>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ profile chart.<br>
+ <br>
+ <br>
+ In a workflow <span style="font-weight: bold;">with</span> native
+ calibration capability, the calibration curves would be used with
+ printarg during subsequent <span style="font-weight: bold;">profiling</span>
+ so that any ink limit calculations will reflect final device values,
+ while not otherwise using the calibration within the ICC workflow:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="printtarg.html">printtarg</a> <a
+ href="printtarg.html#v">-v</a> <a href="printtarg.html#i">-ii1</a>
+ <a href="printtarg.html#p">-pA4</a> <a href="printtarg.html#I">-I
+ PrinterA_c.cal</a> <a href="printtarg.html#p1">PrinterA</a><br>
+ <br>
+ This will cause the .ti2 and resulting .ti3 and ICC profiles to
+ contain the calibration curves, allowing all the tools to be able to
+ compute final device value ink limits. The calibration curves must
+ also of course be installed into the printer. The means to do this
+ is currently outside the scope of Argyll (ie. either the print
+ system needs to be able to understand Argyll CAL format files, or
+ some tool will be needed to convert Argyll CAL files into the
+ printer calibration format).<br>
+ <br>
+ <br>
+ In a workflow <span style="font-weight: bold;">without</span>
+ native calibration capability, the calibration curves would be used
+ with printarg to <span style="text-decoration: underline;">apply</span>
+ the calibration to the test patch samples during subsequent <span
+ style="font-weight: bold;">profiling</span>, as well as embedding
+ it in the resulting .ti3 to allow all the tools to be able to
+ compute final device value ink limits:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="printtarg.html">printtarg</a> <a
+ href="printtarg.html#v">-v</a> <a href="printtarg.html#i">-ii1</a>
+ <a href="printtarg.html#p">-pA4</a> <a href="printtarg.html#K">-K
+ PrinterA_c.cal</a> <a href="printtarg.html#p1">PrinterA</a><br>
+ <a href="cctiff.html#p4"></a><br>
+ To apply calibration to an ICC profile, so that a calibration
+ unaware CMM can be used:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="applycal.html">applycal</a> <a
+ href="applycal.html#p1">PrinterA.cal</a> <a
+ href="applycal.html#p2">PrinterA.icm</a> <a
+ href="applycal.html#p3">PrinterA_cal.icm</a><br>
+ <br>
+ To apply color management and calibration to a raster image:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
+ href="cctiff.html#p1">Source2Destination.icm</a> <a
+ href="cctiff.html#p2">PrinterA_c.cal</a> <a href="cctiff.html#p3">infile.tif</a>
+ <a href="cctiff.html#p4">outfile.tif</a><br>
+ or<br>
+ &nbsp;&nbsp;&nbsp; <a href="cctiff.html">cctiff</a> <a
+ href="cctiff.html#p1">Source2Destination.icm</a> <a
+ href="cctiff.html#p2">PrinterA_c.cal</a> <a href="cctiff.html#p3">infile.jpg</a>
+ <a href="cctiff.html#p4">outfile.jpg</a><br>
+ <br>
+ <br>
+ Another useful tool is <a href="synthcal.html">synthcal</a>, that
+ allows creating linear or synthetic calibration files for disabling
+ calibration or testing.<br>
+ Similarly, <a href="fakeread.html">fakeread</a> also supports
+ applying calibration curves and embedding them in the resulting .ti3
+ file<br>
+ <h4><a name="PC6"></a>How profile ink limits are handled when
+ calibration is being used.</h4>
+ Even though the profiling process is carried out on top of the
+ linearized device, and the profiling is generally unaware of the
+ underlying non-linearized device values, an exception is made in the
+ calculation of ink limits during profiling. This is made possible by
+ including the calibration curves in the profile charts .ti2 and
+ subsequent .ti3 file and resulting ICC profile <span
+ style="font-weight: bold;">'targ'</span> text tag, by way of the <span
+ style="font-weight: bold;">printtarg</span> <span
+ style="font-weight: bold;">-I</span> or <span style="font-weight:
+ bold;">-K</span> options. This is done on the assumption that the
+ physical quantity of ink is what's important in setting the ink
+ limit, and that the underlying non-linearized device values
+ represent such a physical quantity.<br>
+ <br>
+ <br>
+ <hr size="2" width="100%">
+ <h3><a name="LP1"></a>Linking Profiles</h3>
+ Two device profiles can be linked together to create a device link
+ profile, than encapsulates a particular device to device transform.
+ Often this step is not necessary, as many systems and tools will
+ link two device profiles "on the fly", but creating a device link
+ profile gives you the option of using "smart CMM" techniques, such
+ as true gamut mapping, improved inverse transform accuracy, tailored
+ black generation and ink limiting.<br>
+ <br>
+ The overall process is to link the input space and output space
+ profiles using <a href="collink.html">collink</a>, creating a
+ device to device link profile. The device to device link profile can
+ then be used by cctiff (or other ICC device profile capable tools),
+ to color correct a raster files.<br>
+ <br>
+ Three examples will be given here, showing the three different modes
+ than <span style="font-weight: bold;">collink</span> supports.<br>
+ <br>
+ In <a href="collink.html#s">simple mode</a>, the two profiles are
+ linked together in a similar fashion to other <span
+ style="font-weight: bold;">CMMs</span> simply using the forward
+ and backwards color transforms defined by the profiles. Any gamut
+ mapping is determined by the content of the tables within the two
+ profiles, together with the particular intent chosen. Typically the
+ same intent will be used for both the source and destination
+ profile:<br>
+ <br>
+ <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
+ <a href="collink.html#q">-qm</a> <a href="collink.html#s">-s</a> <a
+ href="collink.html#si">-ip</a> <a href="collink.html#so">-op</a>
+ <a href="collink.html#p1">SouceProfile.icm</a> <a
+ href="collink.html#p2">DestinationProfile.icm</a> <a
+ href="collink.html#p3">Source2Destination.icm</a><br>
+ <br>
+ <br>
+ In <a href="collink.html#g">gamut mapping mode</a>, the
+ pre-computed intent mappings inside the profiles are not used, but
+ instead the gamut mapping between source and destination is tailored
+ to the specific gamuts of the two profiles, and the intent parameter
+ supplied to <span style="font-weight: bold;">collink</span>.
+ Additionally, source and destination viewing conditions should be
+ provided, to allow the color appearance space conversion to work as
+ intended. The colorimetric B2A table in the destination profile is
+ used, and this will determine any black generation and ink limiting:<br>
+ <br>
+ <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
+ <a href="collink.html#q">-qm</a> <a href="collink.html#g">-g</a> <a
+ href="collink.html#si">-ip</a> <a href="collink.html#c">-cmt</a>
+ <a href="collink.html#d">-dpp</a> <a href="collink.html#p1">MonitorSouceProfile.icm</a>
+ <a href="collink.html#p2">DestinationProfile.icm</a> <a
+ href="collink.html#p3">Source2Destination.icm</a><br>
+ <br>
+ <br>
+ In <a href="collink.html#G">inverse output table gamut mapping mode</a>,
+ the pre-computed intent mappings inside the profiles are not used,
+ but instead the gamut mapping between source and destination is
+ tailored to the specific gamuts of the two profiles, and the intent
+ parameter supplied to <span style="font-weight: bold;">collink</span>.
+ In addition, the B2A table is <span style="font-weight: bold;">not</span>
+ used in the destination profile, but the A2B table is instead
+ inverted, leading to improved transform accuracy, and in CMYK
+ devices, allowing the ink limiting and black generation parameters
+ to be set:<br>
+ <br>
+ For a CLUT table based RGB printer destination profile, the
+ following would be appropriate:<br>
+ <br>
+ <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
+ <a href="collink.html#q">-qm</a> <a href="collink.html#G">-G</a> <a
+ href="collink.html#si">-ip</a> <a href="collink.html#c">-cmt</a>
+ <a href="collink.html#d">-dpp</a> <a href="collink.html#p1">MonitorSouceProfile.icm</a>
+ <a href="collink.html#p2">RGBDestinationProfile.icm</a> <a
+ href="collink.html#p3">Source2Destination.icm</a><br>
+ <br>
+ For a CMYK profile, the total ink limit needs to be specified (a
+ typical value being 10% less than the value used in creating the
+ device test chart), and the type of black generation also needs to
+ be specified:<br>
+ <br>
+ <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
+ <a href="collink.html#q">-qm</a> <a href="collink.html#G">-G</a> <a
+ href="collink.html#si">-ip</a> <a href="collink.html#c">-cmt</a>
+ <a href="collink.html#d">-dpp</a> <a href="collink.html#l">-l250</a>
+ <a href="collink.html#k">-kr</a> <a href="collink.html#p1">MonitorSouceProfile.icm</a>
+ <a href="collink.html#p2">CMYKDestinationProfile.icm</a> <a
+ href="collink.html#p3">Source2Destination.icm</a><br>
+ <br>
+ Note that you should set the source (<a href="collink.html#c">-c</a>)
+ and destination (<a href="collink.html#d">-d</a>) viewing conditions
+ for the type of device the profile represents, and the conditions
+ under which it will be viewed.<br>
+ <br>
+ <h3><a name="LP2"></a>Soft Proofing Link</h3>
+ Often it is desirable to get an idea what a particular devices
+ output will look like using a different device. Typically this might
+ be trying to evaluate print output using a display. Often it is
+ sufficient to use an absolute or relative colorimetric transform
+ from the print device space to the display space, but while these
+ provide a colorimetric preview of the result, they do not take into
+ account the subjective appearance differences due to the different
+ device conditions. It can therefore be useful to create a soft proof
+ appearance transform using collink:<br>
+ <br>
+ <a href="collink.html">collink</a> <a href="collink.html#v">-v</a>
+ <a href="collink.html#q">-qm</a> <a href="collink.html#G">-G</a> <a
+ href="collink.html#si">-ila</a> <a href="collink.html#c">-cpp</a>
+ <a href="collink.html#d">-dmt</a> <a href="collink.html#l">-t250</a>&nbsp;<a
+ href="collink.html#k"></a><a href="collink.html#p1">CMYKDestinationProfile.icm</a>
+ <a href="collink.html#p2">MonitorProfile.icm</a> <a
+ href="collink.html#p3">SoftProof.icm</a><br>
+ <br>
+ We use the Luminance matched appearance intent, to preserve the
+ subjective apperance of the target device, which takes into account
+ the viewing conditions and assumes adaptation to the differences in
+ the luminence range, but otherwise not attempting to compress or
+ change the gamut.<br>
+ &nbsp;
+ <hr size="2" width="100%"><br>
+ <h3><a name="TR1"></a>Transforming colorspaces of raster files</h3>
+ Although a device profile or device link profile may be useful with
+ other programs and systems, Argyll provides the tool <a
+ href="cctiff.html">cctiff</a> for directly applying a device to
+ device transform to a <a href="File_Formats.html#TIFF">TIFF</a> or
+ <a href="File_Formats.html#JPEG">JPEG</a> raster file. The cctiff
+ tool is capable of linking an arbitrary sequence of device profiles,
+ device links, abstract profiles and calibration curves. Each device
+ profile can be preceded by the <span style="font-weight: bold;">-i</span>
+ option to indicate the intent that should be used. Both 8 and 16 bit
+ per component files can be handled, and up to 8 color channels. The
+ color transform is optimized to perform the overall transformation
+ rapidly.<br>
+ <br>
+ If a device link is to be used, the following is a typical example:<br>
+ <br>
+ <a href="cctiff.html">cctiff</a> <a href="cctiff.html#p1">Source2Destination.icm</a>
+ <a href="cctiff.html#p3">infile.tif</a> <a href="cctiff.html#p4">outfile.tif</a><br>
+ or<br>
+ <a href="cctiff.html">cctiff</a> <a href="cctiff.html#p1">Source2Destination.icm</a>
+ <a href="cctiff.html#p3">infile.jpg</a> <a href="cctiff.html#p4">outfile.jpg</a><br>
+ <br>
+ <i><br>
+ </i>If a source and destination profile are to be used, the
+ following would be a typical example:<br>
+ <br>
+ <a href="cctiff.html"> cctiff</a>&nbsp; <a href="cctiff.html#i">-ip</a>
+ <a href="cctiff.html#p1i">SourceProfile.icm</a> <a
+ href="cctiff.html#i">-ip</a> <a href="cctiff.html#p1o">DestinationProfile.icm</a>
+ <a href="cctiff.html#p3">infile.tif</a> <a href="cctiff.html#p4">outfile.tif</a><br>
+ or<br>
+ <a href="cctiff.html"> cctiff</a>&nbsp; <a href="cctiff.html#i">-ip</a>
+ <a href="cctiff.html#p1i">SourceProfile.icm</a> <a
+ href="cctiff.html#i">-ip</a> <a href="cctiff.html#p1o">DestinationProfile.icm</a>
+ <a href="cctiff.html#p3">infile.jpg</a> <a href="cctiff.html#p4">outfile.jpg</a><br>
+ <br>
+ <br>
+ <hr size="2" width="100%"><br>
+ <h3><a name="TV1"></a>Creating Video Calibration 3DLuts</h3>
+ Video calibration typically involves trying to make your actual
+ display device emulate an ideal video display, one which matches
+ what your Video media was intended to be displayed on. An ICC device
+ link embodies the machinery to do exactly this, to take device
+ values in the target source colorspace and transform them into an
+ actual output device colorspace. In the Video and Film industries a
+ very similar, but less sophisticated means of doing this is to use
+ 3DLuts, which come in a multitude of different format. ICC device
+ links have the advantage of being a superset of 3dLuts, encapsulated
+ in a standard file format.<br>
+ <br>
+ To facilitate Video calibration of certain Video systems, ArgyllCMS
+ supports some 3DLut output options as part of <a
+ href="collink.html">collink</a>.<br>
+ <br>
+ What follows here is an outline of how to create Video calibration
+ 3DLuts using ArgyllCMS. First comes a general discussion of various
+ aspects of video device links/3dLuts, and followed with some
+ specific advice regarding the systems that ArgyllCMS supports. Last
+ is some recommended scenarios for verifying the quality of Video
+ calibration achieved.<br>
+ <h5>1) How to display test patches.<br>
+ </h5>
+ Argyll's normal test patch display will be used by default, as long
+ as any video encoding range considerations are dealt with (see
+ Signal encoding below). An alternative when working with MadVR V
+ 0.86.9 or latter, is to use the madTPG to display the patches in
+ which case the MadVR video encoding range setting will operate. This
+ can give some quality benefits due to MadVR's use of dithering. To
+ display patches using MadVR rather than Argyll, start madTPG and
+ then use the option "-d madvr" in dispcal, dispread and dispwin.
+ Leave the MadTPG "VideoLUT" and "3dluts" buttons in their
+ default&nbsp; (enabled) state, as the various tools will
+ automatically take care of disabling the 3dLut and/or calibration
+ curves as needed.<br>
+ <h5>2) White point calibration &amp; neutral axis calibration.</h5>
+ A Device Link is capable of embodying all aspects of the
+ calibration, including correcting the white point and neutral axis
+ behavior of the output device, but making such a Link just from two
+ ICC profile requires the use of Absolute Colorimetric intent during
+ linking, and this reduces flexibility. In addition, a typical ICC
+ device profile may not capture the neutral axis behavior quite as
+ well as an explicit calibration, since it doesn't sample the
+ displays neutral axis behaviour in quite as much detail. It is often
+ desirable therefore, to calibrate the display device so as to have
+ the specific white point desired so that one of the white point
+ relative linking intents can be used, and to improve the displays
+ general neutral axis behavior so that subsequent profiling works to
+ best advantage. In summary, there are basically 4 options in
+ handling white point &amp; neutral axis calibration:<br>
+ <ul>
+ <li>Don't bother correcting the white point. Most displays are
+ close to the typical D65 target, and our eyes adapt to the white
+ automatically unless it is very far from the daylight locus or
+ we have something else to refer to. If this approach is taken,
+ then display profiling and linking can ignore calibration, and
+ one of the non Absolute Colorimetric intents (such as Relative
+ Colorimetric) is chosen during profile linking. It is wise to
+ make sure that the video card VideoLUTs are set to some known
+ state (ie. linear using "dispwin -c" , or set by a an installed
+ ICC display profile) though.<br>
+ </li>
+ <li>Calibrate the white point and linearise the neutral axis using
+ the display controls. Many TV's have internal calibration
+ controls that allow setting the white point, and possibly the
+ neutral axis response. Either a dedicated Video calibration
+ package could be used, or ArgyllCMS <a href="dispcal.html">dispcal</a>'s
+
+
+
+ interactive adjustment mode can be used to set the white point.
+ Note that while adjusting the neutral axis for neutrality may
+ help, the Device Link will override the transfer curve
+ characteristic of the calibrated display, so aiming for a
+ transfer curve approximately the same as the target and
+ reasonably perceptually linear is all that is required. If this
+ approach is taken, then display profiling and linking can ignore
+ calibration, and one of the non Absolute Colorimetric intents is
+ chosen during profile linking. It is wise to make sure that the
+ video card VideoLUTs are set to some known state&nbsp; though.</li>
+ <li>[<b>Recommended</b>] Calibrate the white point and neutral
+ axis using ArgyllCMS <a href="dispcal.html">dispcal</a>. Since
+ the Device Link will override the calibrated transfer curve
+ characteristic of the display, there there may be no point in
+ doing much more than a medium calibration, and choosing a
+ standard that has a straight segment from black, such as L*a*b*,
+ sRGB, Rec709 or SMPTE240 curve. The exact shape of the
+ calibration curve is not critically important, as the profiling
+ and 3dLut will set the final response. If this approach is
+ taken, then the resulting calibration file should be provided to
+ dispread as the <a href="dispcal.html#k">-k parameter</a> or <a
+ href="dispcal.html#K">-K parameter</a>.&nbsp; See also below <b>Choice
+ of where to apply display per channel calibration curves.</b></li>
+ <li>Choose one of the Absolute Colorimetric intents in collink
+ (ie. -i aw). This greatly reduces flexibility, and may not be
+ quite as accurate as an explicit calibration.</li>
+ </ul>
+ If an explicit calibration is used, then it is a good idea to add
+ some test points down the neutral axis when profiling (targen <a
+ href="targen.html#g">-g parameter</a>). <br>
+ <br>
+ <b>3) Choice of where to apply display per channel calibration
+ curves</b><br>
+ <br>
+ If calibration curves are going to be used, then it needs to be
+ decided where they will be applied in the video processing chain.
+ There are two options:<br>
+ <br>
+ <b>a)</b> Install the calibration curves in the playback system. On
+ a PC the display, this can be done by loading the calibration curves
+ into the Video Card temporarily using "dispwin calibration.cal", or
+ installing the ICC profile into the system persistently using
+ something like "<a href="dispwin.html#I">dispwin -I profile.icm</a>",<br>
+ or when using MadVR 0.86.9 or latter by creating a 3dLut with
+ appended calibration curves using <a href="collink#H">-H
+ display.cal</a>.<br>
+ <br>
+ <b>b)</b> The calibration can be incorporated into the Device
+ Link/3dLUT by providing it to collink as the <a
+ href="collink.html#a">-a display.cal</a>. This is the only option
+ if the video display path does not have some separate facility to
+ handle calibration curves. Note that if the playback system has
+ graphic card VideoLUTs then they will have to be set to a defined
+ consistent state such as linear. When using MadVR 0.86.9 or latter
+ this will be done automatically since the -a option will append a
+ linear set of calibration curves to the 3dLut.<br>
+ <br>
+ The choice is dictated by a number of considerations:<br>
+ <ul>
+ <li>Does the video playback path have a facility for installing
+ the calibration curves ? If playing back system is a PC, then
+ typically the Graphics Card supports 1D VideoLUTs, thereby
+ making a) a possible choice.<br>
+ </li>
+ <li>Does the video playback <u>always</u> play back through the
+ Video Card VideoLUTs ? Some systems do not apply VIdeoLUTs to
+ things like overlay plane rendering. If not, then you need to
+ choose b), but also make sure that if it does use the Video Card
+ VideoLUTs in some situations, that they are set to linear (ie.
+ dispcal -c). One way of determining when the VideoLUTs get used
+ or not is to load a distinct calibration such as "strange.cal"
+ provided in the <b>ref</b> folder, and check visually if it is
+ affecting the video or not, ie. "dispcal strange.cal". Note that
+ using MadVR 0.86.9 or latter in combination with a 3dLut with
+ appended calibration curves will apply the calibration even with
+ overlay plane rendering.<br>
+ </li>
+ <li>Do you want/need other applications to share the calibration
+ curves or profile or not ? If you do, then it is desirable to
+ choose a).</li>
+ <li>Quality considerations. VideoLUTs may or may not be of greater
+ depth than the standard 8 bit per color component frame buffer.
+ If they are, and the video path passes that extra depth through
+ to the display, and the display is capable of using that extra
+ depth, then a) may be a desirable choice from a quality point of
+ view. You can get some idea whether this is the case by running
+ "dispcal -R". If the VideoLUT depth is not better than 8 bits,
+ then it may be more desirable to choose b), since renders like
+ MadVR can use dithering to give better than 8 bits precision in
+ the video playback.<br>
+ </li>
+ </ul>
+ <h5>4) Output device calibration and profiling.</h5>
+ Output device profiling should basically follow the guide above in <a
+ href="#PM1b">Adjusting and Calibrating a displays</a> and <a
+ href="#PM1">Profiling Displays</a>. The assumption is that either
+ you are calibrating/profiling your computer display for video, or
+ your TV is connected to the computer you are creating
+ calibrations/profiles on, and that the connection between the PC and
+ TV display is such that full range RGB signals are being used, or
+ that the Video card has automatically or manually been configured to
+ scale full range RGB values to Video levels for the TV. If the
+ latter is not possible, then use the -E options on dispcal and
+ dispread. (See <b>Signal encoding</b> bellow for more details on
+ this). Don't use the -E options on dispcal and dispread if you are
+ using MadVR to display test patches using the "-d madvr" option.<br>
+ <br>
+ Once the profile has been created, it is possible to then use the
+ resulting Device Link/3DLut with signal encoding other than full
+ range or Video level RGB. <br>
+ <h5>5) Target colorspace<br>
+ </h5>
+ In practical terms, there are five common Video and Digital Cinema
+ encoding colorspaces. <br>
+ <br>
+ For Standard Definition:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; EBU 3213 or "PAL 576i" primaries.<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; SMPTE RP 145 or "NTSC 480i" primaries.<br>
+ <br>
+ For High Definition:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Rec 709 primaries.<br>
+ <br>
+ For Ultra High Defintion<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Rec 2020 primaries.<br>
+ <br>
+ For Digital Cinema<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; SMPTE-431-2&nbsp; or "DCI-P3"<br>
+ <br>
+ PAL and NTSC have historically had poorly specified transfer curve
+ encodings, and the Rec 709 HDTV encoding curve is the modern <a
+ href="http://www.poynton.com/notes/DVAI/DVAI_TOC_full.html#23">recommendation</a>,
+ but the overall interpretation of Video sources may in fact be
+ partly determined by the expected standard Video display device
+ characteristics (see <b>Viewing conditions adjustment and gamut
+ mapping</b> below for more details).<br>
+ <br>
+ To enable targeting these colorspaces, ArgyllCMS provides 5 ICC
+ profiles in the ref directory to use as source
+ colorspaces:&nbsp;&nbsp;&nbsp; <br>
+ <br>
+ &nbsp;&nbsp;&nbsp; EBU3213_PAL.icm<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; SMPTE_RP145_NTSC.icm<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Rec709.icm<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Rec2020.icm<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; SMPTE431_P3.icm<br>
+ <h5>6) Signal encoding</h5>
+ Typical PC display output uses full range RGB signals (0 .. 255 in 8
+ bit parlance), while typical Video encoding allows some head &amp;
+ footroom for overshoot and sync of digitized analog signals, and
+ typically uses a 16..235 range in 8 bits. In many cases Video is
+ encoded as luma and color difference signals YCbCr (loosely known as
+ YUV as well), and this also uses a restricted range 16..235 for Y,
+ and 16..240 for Cb and Cr in 8 bit encoding. The extended gamut
+ xvYCC encoding uses 16..235 for Y, and 1..254 for Cb and Cr.<br>
+ <br>
+ The signal encoding comes into play in two situations: 1)
+ Calibrating and profiling the display, and 2) Using the resulting
+ Device Link/3DLut.<br>
+ The encoding may need to be different in these two situations,
+ either because different video source devices are being used for
+ calibration/profiling and for video playback, or because the video
+ playback system uses the Device Link/3DLut at a point in its
+ processing pipeline that requires a specific encoding.<br>
+ <br>
+ For calibration &amp; profiling, the display will be driven by a
+ computer system so that dispcal and dispread can be used. By default
+ these programs expect to output full range RGB signals, and it is
+ assumed that either the display accepts full range signals, or that
+ the graphics card or connection path has been setup to convert the
+ full range values into Video range signals automatically or
+ manually. If this is not the case, then both dispcal and dispread
+ have a -E option that will modify them to output Video range RGB
+ values.<br>
+ <br>
+ If MadVR is the target of the calibration and profiling, then there
+ is an option to use it to display the calibration and profiling test
+ patches (<b>-d madvr</b>). In this case, MadVR should be configured
+ appropriately for full range or Video range encoding, and the -E
+ flag should <u>not</u> be used with dispcal or dispread, since
+ MadVR will be taking care of such conversions.<br>
+ <br>
+ If a calibration file was created using dispcal -E, then using it in
+ dispread will automatically trigger Video level RGB signals during
+ profiling. Any time such a Video level calibration is loaded into
+ the Graphics card VideoLUTs using dispwin, or the calibration curve
+ is converted to a 'vcgt' tag in a profile, the curve will also
+ convert full range RGB to Video range RGB. This should be kept in
+ mind so that if video playback is being performed with the
+ calibration curves installed in the Graphics card VideoLUTs, that
+ full range is converted only once to Video range (ie. In this
+ situation MadVR output should be set to full range if being played
+ back through the calibration curves in hardware, but only if dispcal
+ -E has been used). On the other hand, if the calibration curves are
+ incorporated into the DeviceLink/3dLUT, then the conversion to Video
+ levels has to be done somewhere else in the pipeline, such as using
+ MadVR video level output, or by the graphics card, etc.<br>
+ <br>
+ When creating the Device Link/3dLut, it is often necessary to
+ specify one of the video encodings so that it fits in to the
+ processing pipeline correctly. For instance the eeColor needs to
+ have input and output encoding that suits the HDMI signals passing
+ through it, typically Video Range RGB. MadVR needs Video Level RGB
+ to match the values being passed through the 3dLut at that point.<br>
+ <br>
+ There are several version of YCbCr encoding supported as well, even
+ though neither the eeColor nor the current version of MadVR need or
+ can use them at present.<br>
+ <h5>7) Black point mapping</h5>
+ <p>Video encoding assumes that the black displayed on a device is a
+ perfect black (zero light). No real device has a perfect black,
+ and if a colorimetric intent is used then certain image values
+ near black will get clipped to the display black point, loosing
+ shadow detail. To avoid this, some sort of black point mapping is
+ usually desirable. There are two mechanisms available in collink:
+ a) BT.1886 black point mapping, or b) using one of the smart gamut
+ mapping intents that does black point mapping (e.g. la, p, pa, ms
+ or s).<br>
+ </p>
+ <h5>8) Viewing conditions adjustment and gamut mapping</h5>
+ <p> </p>
+ <p>In historical TV systems, there is a viewing conditions
+ adjustment being made between the bright studio conditions that TV
+ is filmed in, and the typical dim viewing environment that people
+ view it in. This is created by the difference between the encoding
+ response curve gamma of about 2.0, and a typical CRT response
+ curve gamma of 2.4. <br>
+ </p>
+ <p>In theory Rec709 defines the video encoding, but it seems in
+ practice that much video material is adjusted to look as intended
+ when displayed on a reference monitor having a display gamma of
+ somewhere between 2.2 and 2.4, viewed in a dim viewing
+ environment. The modern standard covering the display transfer
+ curve is <a
+ href="http://www.itu.int/rec/R-REC-BT.1886-0-201103-I">BT.1886</a>,
+ which defines a pure power 2.4 curve with a black point offset. So
+ another means of making the viewing adjustment is to apply the
+ BT.1886-like response to Rec709 encoded material. Collink supports
+ this using the <a href="collink.html#I">-I b</a>, and allows some
+ control over the degree of viewing conditions adjustment by
+ overriding the BT.1886 gamma&nbsp; using the <a
+ href="collink.html#Ib">-I b:g.g</a> parameter. This is the <b>recommended</b>
+ approach to start with, since it gives good results with a single
+ parameter.<br>
+ </p>
+ <p> An alternate approach to making this adjustment is to take
+ advantage of the viewing conditions adjustment using the CIECAM02
+ model available in collink. Some control over the degree of
+ viewing conditions adjustment is possible by varying the viewing
+ condition parameters. </p>
+ <p>A third alternative is to combine the two approaches. The source
+ is defined as Rec709 rendered to a model BT.1886 display in dim
+ viewing conditions, and then CIECAM02 is used to adjust for the
+ actual display viewing conditions. Once again, control over the
+ degree of viewing conditions adjustment is possible by varying the
+ viewing condition parameters. </p>
+ <h5>Putting it all together:</h5>
+ In this example we choose to create a display calibration first
+ using dispcal, and create a simple matrix profile as well:<br>
+ <br>
+ &nbsp; <tt>dispcal -v -o -qm -k0 -w 0.3127,0.3290 -gs -o TVmtx.icm
+ TV</tt><br>
+ <br>
+ We are targeting a D65 white point (<tt>-w 0.3127,0.3290)</tt> and
+ an sRGB response curve.<br>
+ <br>
+ If you are using the madTPG you would use:<br>
+ <br>
+ &nbsp; <tt>dispcal -v -d madvr -o -qm -k0 -w 0.3127,0.3290 -gs -o
+ TVmtx.icm TV</tt><br>
+ <br>
+ Then we need to create a display patch test set. We can use the
+ simple matrix to pre-condition the test patches, as this helps
+ distribute them where they will be of most benefit. If have
+ previously profiled your display, you should use that previous
+ profile, or if you decided not to do a dispcal, then the Rec709.icm
+ should be used as a substitute. Some per channel and a moderate
+ number of full spread patches is used here - more will increase
+ profiling accuracy, a smaller number will speed it up. Since the
+ video or film material is typically viewed in a darkened viewing
+ environment, and often uses a range of maximum brightnesses in
+ different scenes, the device behavior in the dark regions of its
+ response are often of great importance, and using the <a
+ href="targen.html#V">targen -V</a> parameter can help improve the
+ accuracy in this region at the expense of slightly lower accuracy in
+ lighter regions.<br>
+ <br>
+ &nbsp; <tt>targen -v -d3 -s30 -g100 -f1000 -cTVmtx.icm -V1.8 TV</tt><br>
+ <br>
+ The display can then be measured:<br>
+ <br>
+ &nbsp; <tt>dispread -v -k TV.cal TV</tt><br>
+ <br>
+ or using madTPG:<br>
+ <br>
+ &nbsp;dispread -v -d madvr -K TV.cal TV<br>
+ <br>
+ and then a cLUT type ICC profile created. Since we will be using
+ collink smart linking, we minimize the B2A table size. We use the
+ default colprof -V parameter carried through from targen:<br>
+ <br>
+ &nbsp; <tt>colprof -v -qh -bl TV</tt><br>
+ <br>
+ Make sure you check the delta E report at the end of the profile
+ creation, to see if the sample data and profile is behaving
+ reasonably. Depending on the type of device, and the consistency of
+ the readings, average errors of 5 or less, and maximum errors of 15
+ or less would normally be expected. If errors are grossly higher
+ than this, then this is an indication that something is seriously
+ wrong with the device measurement, or profile creation.<br>
+ <br>
+ If you would like to use the display ICC profile for general color
+ managed applications, then you would compute a more complete
+ profile:<br>
+ <br>
+ &nbsp; <tt>colprof -v -qh TV</tt><br>
+ <br>
+ The recommended approach then is to create a Device Link that uses a
+ BT.1886 black point and viewing conditions adjustment, say one of
+ the following:<br>
+ <br>
+ <tt>&nbsp; collink -v -Ib:2.4 -G -ir Rec709.icm TV.icm
+ HD.icm&nbsp;&nbsp; # dark conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -Ib&nbsp;&nbsp;&nbsp;&nbsp; -G -ir
+ Rec709.icm TV.icm HD.icm&nbsp;&nbsp; # dim conditions - good
+ default</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -Ib:2.1 -G -ir Rec709.icm TV.icm
+ HD.icm&nbsp;&nbsp; # mid to dim conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -Ib:2.0 -G -ir Rec709.icm TV.icm
+ HD.icm&nbsp;&nbsp; # mid to light conditions</tt><br>
+ <br>
+ or you could do it using pure CIECAM02 adjustment and a black point
+ mapping:<br>
+ <br>
+ <tt>&nbsp; collink -v -ctv -dmd -da:1 -G -ila Rec709.icm TV.icm
+ HD.icm&nbsp; # very dark conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -ctv -dmd -da:3 -G -ila Rec709.icm
+ TV.icm HD.icm&nbsp; # dim conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -ctv -dmd -da:7 -G -ila Rec709.icm
+ TV.icm HD.icm&nbsp; # mid to dim conditions - good default</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -ctv -dmd -da:15 -G -ila Rec709.icm
+ TV.icm HD.icm # mid conditions</tt><br>
+ <br>
+ or using both to model a reference video display system that is
+ adapted to your viewing conditions:<br>
+ <tt><br>
+ </tt><tt> &nbsp; collink -v -Ib -c md -dmd -da:5&nbsp; -G -ila
+ Rec709.icm TV.icm HD.icm # very dark conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -Ib -c md -dmd -da:10 -G -ila Rec709.icm
+ TV.icm HD.icm&nbsp; # dim conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -Ib -c md -dmd -da:18 -G -ila Rec709.icm
+ TV.icm HD.icm&nbsp; # mid to dark conditions</tt><tt><br>
+ </tt><tt> &nbsp; collink -v -Ib -c md -dmd -da:30 -G -ila Rec709.icm
+ TV.icm HD.icm&nbsp;&nbsp; # mid to dark conditions</tt><br>
+ <br>
+ None of the above examples incorporate the calibration curves, so it
+ is assumed that the calibration curves would be installed so that
+ the Video Card applies calibration, ie:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <tt>dispwin TV.cal</tt><br>
+ <br>
+ or the simple matrix profile installed:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <tt>dispwin -I TVmtx.icm</tt><br>
+ <br>
+ or a the more complete display profile could be installed:<br>
+ <br>
+ &nbsp; dispwin -I TV.icm<br>
+ <br>
+ See also <a href="dispprofloc.html">here</a> for information on how
+ to make sure the calibration is loaded on each system start. If not,
+ then you will want to incorporate the calibration in the Device
+ Link/3dlut by using collink "-a TV.cal".<br>
+ <br>
+ If the video path needs Video Level RGB encoding but does not
+ provide a means to do this, then you will want to include the <b>-E</b>
+ flag in the dispcal and dispread command lines above.<br>
+ <br>
+ Below are specific recommendation for the eeColor and MadVR that
+ include the flags to create the .3dlut and encode the input and
+ output values appropriately, but only illustrate using the
+ recommended BT.1886 black point and viewing conditions adjustments,
+ rather than illustrating CIECAM02 etc. use.<br>
+ <br>
+ For faster exploration of different collink option, you could omit
+ the "colprof -bl" option, and use collink "-g" instead of "-G",
+ since this<br>
+ will greatly speed up collink. Once you are happy with the link
+ details, you can then generate a higher quality link/3dLut using
+ "collink -G ..".<br>
+ <br>
+ You can also increase the precision of the device profile by
+ increasing the number of test patches measured (ie. up to a few
+ thousand, depending on how long you are prepared to wait for the
+ measurement to complete, and how stable your display and instrument
+ are).<br>
+ <br>
+ Alternatives to relative colorimetric rendering ("-i r") or
+ luminance matched appearance ("-i la") used in the examples above
+ and below, are, perceptual ("-i p") which will ensure that the
+ source gamut is compressed rather than clipped by the display, or
+ even a saturation rendering ("-i ms"), which will expand the gamut
+ of the source to the full range of the output.<br>
+ <br>
+ <br>
+ <b>eeColor</b><br>
+ <br>
+ For PC use, where the encoding is full range RGB:<br>
+ <br>
+ &nbsp; <tt>collink -v -3e -Ib -G -ir -a TV.cal Rec709.icm TV.icm
+ HD.icm </tt><br>
+ <br>
+ For correct operation both the 3DLut HD.txt and the per channel
+ input curves HD-first1dred.txt, HD-first1dgreen.txt and
+ HD-first1dblue.txt. the latter by copying them over the default
+ input curve files uploaded by the TruVue application.<br>
+ <br>
+ See <a
+ href="http://www.avsforum.com/t/1464890/eecolor-processor-argyllcms">&lt;http://www.avsforum.com/t/1464890/eecolor-processor-argyllcms&gt;</a>
+ for some more details.<br>
+ <br>
+ Where the eeColor is connected from a Video source using HDMI, it
+ will probably be processing TV RGB levels, or YCbCr encoded signals
+ that it converts to/from RGB internally, so<br>
+ <br>
+ &nbsp; <tt>collink -v -3e -et -Et -Ib -G -ir -a TV.cal Rec709.icm
+ TV.icm HD.icm </tt><br>
+ <br>
+ in this case just the HD.txt file needs installing on the eeColor,
+ but make sure that the original linear "first1*.txt files are
+ re-installed, or install the ones generated by collink, which will
+ be linear for -e t mode.<br>
+ <br>
+ <b>MadVR</b><br>
+ <br>
+ MadVR 0.86.9 or latter has a number of features to support accurate
+ profiling and calibration, and is the recommended version to
+ use.&nbsp; It converts from the media colorspace to the 3dLut input
+ space automatically with the type of source being played, but has
+ configuration for to 5 3dLuts, each one optimized for a particular
+ source color space. The advantage of building and installing several
+ 3dLuts is that unnecessary gamut clipping can be avoided.<br>
+ <br>
+ If you are just building one 3dLut then Rec709 source is a good one
+ to pick.<br>
+ <br>
+ If you want to share the VideoLUT calibration curves between your
+ normal desktop and MadVR, then it is recommended that you install
+ the display ICC profile and use the -H option:<br>
+ <br>
+ <tt>&nbsp;&nbsp;&nbsp; collink -v -3m -et -Et -Ib -G -ir -H TV.cal
+ Rec709.icm TV.icm HD.icm</tt><tt><br>
+ </tt><tt> </tt><tt><br>
+ </tt><tt> &nbsp;&nbsp;&nbsp; collink -v -3m -et -Et -Ib -G -ir </tt><tt><tt>-H
+
+
+
+
+
+
+
+
+
+
+
+ TV.cal </tt>EBU3213_PAL.icm TV.icm SD_PAL.icm</tt><tt><br>
+ </tt><tt> </tt><tt><br>
+ </tt><tt> &nbsp;&nbsp;&nbsp; collink -v -3m -et -Et -Ib -G -ir </tt><tt><tt>-H
+
+
+
+
+
+
+
+
+
+
+
+ TV.cal </tt>SMPTE_RP145_NTSC.icm TV.icm SD_NTSC.icm</tt><br>
+ <br>
+ For best quality it is better to let MadVR apply the calibration
+ curves using dithering, and allow it to set the graphics card to
+ linear by using the -a option:<br>
+ <br>
+ <tt>&nbsp;&nbsp;&nbsp; collink -v -3m -et -Et -Ib -G -ir -a TV.cal
+ Rec709.icm TV.icm HD.icm</tt><tt><br>
+ </tt><tt> </tt><tt><br>
+ </tt><tt> &nbsp;&nbsp;&nbsp; collink -v -3m -et -Et -Ib -G -ir </tt><tt><tt>-a
+
+
+
+
+
+
+
+
+
+
+
+ TV.cal </tt>EBU3213_PAL.icm TV.icm SD_PAL.icm</tt><tt><br>
+ </tt><tt> </tt><tt><br>
+ </tt><tt> &nbsp;&nbsp;&nbsp; collink -v -3m -et -Et -Ib -G -ir </tt><tt><tt>-a
+
+
+
+
+
+
+
+
+
+
+
+ TV.cal </tt>SMPTE_RP145_NTSC.icm TV.icm SD_NTSC.icm</tt><br>
+ <br>
+ the consequence though is that the appearance of other application
+ will shift when MadVR is using the 3dLut and loading the calibration
+ curves.<br>
+ <br>
+ The 3dLut can be used by opening the MadVR settings dialog,
+ selecting "calibration" and then selecting "calibrate this display
+ by using an external 3DLUT file", and then using the file dialog to
+ use it.<br>
+ <br>
+ If neither the -a no -H options are used, then no calibration curves
+ will be appended to the 3dLut, and MadVR will not change the
+ VideoLUTs when that 3dLut is in use. It is then up to you to manage
+ the graphics card VideoLUTs in some other fashion.<tt><br>
+ <br>
+ </tt>
+ <hr size="2" width="100%"><br>
+ <h3><a name="TV2"></a>Verifying Video Calibration</h3>
+ <p>Often it is desirable to verify the results of a video
+ calibration and profile, and the following gives an outline of how
+ to use ArgyllCMS tools to do this. It is only possible to expect
+ perfect verification if a colorimetric intent was used during
+ linking - currently it's not possible to exactly verify a
+ perceptual or CIECAM02 viewing condition adjusted link.<br>
+ <br>
+ </p>
+ <p>The first step is to create a set of test points. This is
+ essentially the same as creating a set of test points for the
+ purposes of profiling, although it is best not to create exactly
+ the same set, so as to explore the colorspace at different
+ locatioins. For the purposes here, we'll actually create a regular
+ grid test set, since this makes it easier to visualize the
+ results, although a less regular set would probably be better for
+ numerical evaluation:<br>
+ </p>
+ <p>&nbsp; targen -v -d3 -e1 -m6 -f0 -W verify<br>
+ </p>
+ <p>We make sure there is at least one white patch usin g -e1, a 20%
+ increment grid using -m6, no full spread patches, and create a
+ VRML 3d visualization of the point set using the -W flag. It is
+ good to take a look at the verifyd.wrl file using a VRML viewer.
+ You may want to create several test sets that look at particular
+ aspects, ie. neutral axis response, pure colorant responses, etc.<br>
+ </p>
+ <p>Next we create a reference file by simulating the expected
+ response of the perfect video display system. Assuming the collink
+ options were "-et -Et -Ib -G -ir Rec709.icm TV.icm HD.icm" then we
+ would:<tt><tt><br>
+ </tt></tt></p>
+ <p><tt><tt>&nbsp; copy verify.ti1 ref.ti1<br>
+ &nbsp; fakeread -v -b TV.icm Rec709.icm ref<br>
+ </tt></tt></p>
+ <p>You should adjust the parameters as necessary, so that the
+ reference matches the link options. For instance, if your link
+ options included "-I b:2.15" then the equivalent fakeread option
+ "-b 2.15:TV.icm" should be used, etc.<br>
+ </p>
+ <hr size="2" width="20%">
+ <p>A sanity check we can make at this point is to see what the
+ expected result of the profiling &amp; calibration will be, by
+ simulating the reproduction of this test set:<br>
+ </p>
+ <p><tt>&nbsp; copy verify.ti1 checkA.ti1</tt><tt><br>
+ &nbsp; fakeread -v -et -p HD.icm -Et TV.icm checkA<br>
+ </tt></p>
+ <p>If you used collink -a, then the calibration incorporated in the
+ device link needs to be undone to match what the display profile
+ expects:</p>
+ <p><tt>&nbsp; fakeread -v -et -p HD.icm -Et -K TV.cal TV.icm checkA</tt></p>
+ <p><tt>and then you can verify:<br>
+ </tt></p>
+ <p><tt>&nbsp; colverify -v -n -w -x ref.ti3 checkA.ti3<br>
+ </tt></p>
+ <p>If you have targeted some other white point rather than video D65
+ for the display, then use the -N flag instead of -n to align the
+ white points. [ Note that there can be some small discrepancies in
+ this case in some parts of the color space if a CIECAM02 linking
+ intent was used, due to the slightly different chromatic
+ adaptation algorithm it uses compared to the one used by verify to
+ match the white points.]<tt><br>
+ </tt></p>
+ <p><tt>&nbsp; v</tt><tt>erify -v -N -w -x ref.ti3 checkA.ti3</tt><br>
+ </p>
+ <p>This will give a numerical report of the delta E's, and also
+ generate a VRML plot of the errors in L*a*b* space. The important
+ thing is to take a look at the checkA.wrl file, to see if gamut
+ clipping is occurring - this is the case if the large error
+ vectors are on the sides or top of the gamut. Note that the
+ perfect cube device space values become a rather distorted cube
+ like shape in the perceptual L*a*b* space. If the vectors are
+ small in the bulk of the space, then this indicates that the link
+ is likely to be doing the right thing in making the display
+ emulate the video colorspace with a BT.1886 like black point
+ adjustment. You could also check just the in gamut test points
+ using:<br>
+ </p>
+ <p><tt>&nbsp; v</tt><tt>erify -v -N -w -x -L TV.icm ref.ti3
+ checkA.ti3<br>
+ <br>
+ </tt></p>
+ <hr size="2" width="20%">
+ <p>You can explicitly compare the gamuts of your video space and
+ your display using the gamut tools:<br>
+ </p>
+ <p><tt>&nbsp; iccgamut -ff -ia Rec709</tt><tt><br>
+ </tt><tt> &nbsp; iccgamut -ff -ia TV.icm</tt><tt><br>
+ </tt><tt> &nbsp; viewgam -i Rec709.gam TV.gam gamuts.wrl</tt><br>
+ </p>
+ <p>and look at the gamuts.wrl file, as well as taking notice of % of
+ the video volume that the display intersects. The VRML solid
+ volume will be the video gamut, while the wire frame is the
+ display gamut. If you are not targetting D65 with your display,
+ you should use iccgamut <b>-ir</b> instead of <b>-ia</b>, so as
+ to align the white points.<br>
+ </p>
+ <hr size="2" width="20%">
+ <p>The main check is to actually measure the display response and
+ compare it against the reference. Make sure the display is setup
+ as you would for video playback and then use dispread:<br>
+ </p>
+ <p><tt>&nbsp; copy verify.ti1 checkB.ti1</tt><tt><br>
+ </tt><tt> &nbsp; dispread -v checkB</tt><br>
+ </p>
+ <p>You would add any other options needed (such as <b>-y</b> etc.)
+ to set your instrument up properly. If you are using madTPG, then
+ configure madVR to use the 3dLut you want to measure as the
+ default, and also use the dispread -V flag to make sure that the
+ 3dLut is being used for the measurements: [<b>Note</b> that if the
+ version of MadVR you are using does not have radio buttons in its
+ calibration setup to indicate a default 3dLut, then the 3dLut
+ under test should be the only one set - all others should be
+ blank. ]<br>
+ </p>
+ <p><tt>&nbsp; dispread -v -d madvr -V checkB</tt><br>
+ </p>
+ <p>Verify the same way as above:<br>
+ </p>
+ <p><tt>&nbsp; v</tt><tt>erify -v -n -w -x ref.ti3 checkB.ti3<br>
+ </tt></p>
+ <p>If your display does not cover the full gamut of your video
+ source, the errors are probably dominated by out of gamut colors.
+ You can verify just the in gamut test values by asking verify to
+ skip them, and this will give a better notion of the actual device
+ link and calibration accuracy:<tt><br>
+ </tt></p>
+ <p><tt>&nbsp; v</tt><tt>erify -v -n -w -x -L TV.icm ref.ti3
+ checkB.ti3</tt></p>
+ <p><br>
+ </p>
+ <p>&nbsp;<br>
+ </p>
+ <p><br>
+ <br>
+ </p>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ </body>
+</html>
diff --git a/doc/afiles b/doc/afiles
index b01b147..e58ab5a 100644
--- a/doc/afiles
+++ b/doc/afiles
@@ -45,6 +45,8 @@ i1m.jpg
i1p.jpg
sl.jpg
ss.jpg
+JETI_1211.jpg
+ColorHug.jpg
mox.jpg
moxxr.jpg
Chroma4.jpg
@@ -60,6 +62,9 @@ WideGamutColmters.html
CrushedDisplyBlacks.html
i1proDriver.html
i1proDriver.xls
+i1proHiRes.html
+i1proHiRes.jpg
+i1proHiRes.zip
evalInputTargets.html
YellowGreen.jpg
srgbplot.gif
@@ -118,7 +123,7 @@ timage.html
cube.jpg
surface.jpg
LabSteps.jpg
-verify.html
+colverify.html
viewgam.html
xicclu.html
oeminst.html
diff --git a/doc/cal_format.html b/doc/cal_format.html
index 3e40205..361a329 100644
--- a/doc/cal_format.html
+++ b/doc/cal_format.html
@@ -10,31 +10,24 @@
<h2>Description of the .cal format</h2>
Device calibration information. This is ASCII text, <a
href="File_Formats.html#CGATS">CGATS</a>, Argyll specific format,
- used
- to hold a description of device setup information that brings it to
- a
- desired calibration state. Calibration files are created by <a
- href="synthcal.html">synthcal</a>, <a href="dispcal.html">dispcal</a>
+ used to hold a description of device setup information that brings
+ it to a desired calibration state. Calibration files are created by
+ <a href="synthcal.html">synthcal</a>, <a href="dispcal.html">dispcal</a>
and <a href="printcal.html">printcal</a>.<br>
<br>
While fully compatible with the CGATS.5 Data Exchange Format, the
particular required keywords and fields are unique to Argyll, hence
- an
- Argyll specific file identifier <span style="font-weight: bold;">CAL</span>
+ an Argyll specific file identifier <span style="font-weight: bold;">CAL</span>
is used to avoid confusion with standard ANSI or CGATS files.<br>
<br>
The <span style="font-weight: bold;">.cal</span> format changes
- from
- time to time with new releases, to add new functionality, but
- generally
- retains backwards compatibility. Note that in the description below,
- the word "may" indicates an optional component, while the word
- "shall"
- indicates a necessary component.<br>
+ from time to time with new releases, to add new functionality, but
+ generally retains backwards compatibility. Note that in the
+ description below, the word "may" indicates an optional component,
+ while the word "shall" indicates a necessary component.<br>
<br>
Generally a .cal file contains only one table, the table containing
- the
- setup information. <br>
+ the setup information. <br>
<br>
<br>
The table contains the following:<br>
@@ -50,11 +43,12 @@
style="font-weight: bold;">DESCRIPTOR</span>, <span
style="font-weight: bold;">ORIGINATOR</span>, or <span
style="font-weight: bold;">CREATED</span> keywords and values (as
- per
- CGATS).<br>
+ per CGATS).<br>
<br>
There shall be a <span style="font-weight: bold;">DEVICE_CLASS</span>
keyword that has a value of <span style="font-weight: bold;">"OUTPUT</span>",
+
+
"<span style="font-weight: bold;">DISPLAY</span>" or <span
style="font-weight: bold;">"INPUT"</span>.<br>
This indicates what type of device the calibration information is
@@ -62,65 +56,100 @@
<br>
A <span style="font-weight: bold;">"DISPLAY"</span> type device may
have a <span style="font-weight: bold;">VIDEO_LUT_CALIBRATION_POSSIBLE
- </span>keyword that
- must have a value of "<span style="font-weight: bold;">NO</span>" or
- "<span style="font-weight: bold;">YES</span>", to indicate whether
- the display has the ability to be calibrated by loading VideoLUT
- values.<br>
+
+
+ </span>keyword that must have a value of "<span style="font-weight:
+ bold;">NO</span>" or "<span style="font-weight: bold;">YES</span>",
+
+ to indicate whether the display has the ability to be calibrated by
+ loading VideoLUT values.<br>
+ <br>
+ A <span style="font-weight: bold;">"DISPLAY"</span> type device may
+ have a <span style="font-weight: bold;">TV_OUTPUT_ENCODING </span>keyword
+
+ that must have a value of "<span style="font-weight: bold;">NO</span>"
+ or "<span style="font-weight: bold;">YES</span>", to indicate
+ whether the calibration was created withing the video (16-235)/255
+ compressed range of device value. This is used to signal to a
+ VideoLUT loader whether calibration values should be converted to
+ video encoded range when loaded into hardware. The calibration
+ values stored in the .cal file are never video encoded themselves,
+ i.e. 0.0 is always device minimum, and 1.0 is always device maximum.<br>
<br>
There shall be a keyword <span style="font-weight: bold;">COLOR_REP</span>
that has a value that indicates what colorspaces of the device
- values.
- The colorspaces shall be encoded with one&nbsp; or two letters
- per
- component. The device spaces shall use the
- following letter encoding:<br>
+ values. The colorspaces shall be encoded with one&nbsp; or two
+ letters per component. The device spaces shall use the following
+ letter encoding:<br>
<br>
<span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>&nbsp;&nbsp;&nbsp;
Cyan
+
+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
C<br>
&nbsp;&nbsp;&nbsp; Magenta &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; M<br>
&nbsp;&nbsp;&nbsp; Yellow &nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
Y<br>
&nbsp;&nbsp;&nbsp; Black &nbsp;&nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
K<br>
&nbsp;&nbsp;&nbsp; Orange &nbsp;&nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
O<br>
&nbsp;&nbsp;&nbsp; Red
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
R<br>
&nbsp;&nbsp;&nbsp; Green &nbsp; &nbsp;&nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
G<br>
&nbsp;&nbsp;&nbsp; Blue &nbsp;&nbsp; &nbsp;&nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
B<br>
&nbsp;&nbsp;&nbsp; White &nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; W<br>
&nbsp;&nbsp;&nbsp; Light Cyan
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
c<br>
&nbsp;&nbsp;&nbsp; Light
-Magenta&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Magenta&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
m<br>
&nbsp;&nbsp;&nbsp; Light
-Yellow&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Yellow&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
y<br>
&nbsp;&nbsp;&nbsp; Light
-Black&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Black&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
k<br>
&nbsp;&nbsp;&nbsp; Medium Cyan&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2c<br>
&nbsp;&nbsp;&nbsp; Medium Magenta
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 2m<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2m<br>
&nbsp;&nbsp;&nbsp; Medium Yellow
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2y<br>
&nbsp;&nbsp;&nbsp; Medium Black
@@ -130,53 +159,47 @@ Black&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
There may be an a prefix <span style="font-weight: bold;">i</span>
preceding the device space letter encoding, indicating that although
the space appears to be an additive space, it is in fact a
- subtractive
- device.<br>
+ subtractive device.<br>
<br>
Typical values might be: "<span style="font-weight: bold;">RGB</span><span
style="font-weight: bold;"></span>" for an RGB display, "<span
style="font-weight: bold;">iRGB</span><span style="font-weight:
- bold;"></span>"
- for an RGB printer, "<span style="font-weight: bold;">CMYK</span>"
- for
- a
- printer, "<span style="font-weight: bold;">RGB"</span> for an RGB
- scanner.<br>
+ bold;"></span>" for an RGB printer, "<span style="font-weight:
+ bold;">CMYK</span>" for a printer, "<span style="font-weight:
+ bold;">RGB"</span> for an RGB scanner.<br>
<br>
The <span style="font-weight: bold;">NUMBER_OF_FIELDS</span>
- keyword
- shall have a value that indicates the number of fields in each data
- set, e.g. <span style="font-weight: bold;">4</span> (as per CGATS).<br>
+ keyword shall have a value that indicates the number of fields in
+ each data set, e.g. <span style="font-weight: bold;">4</span> (as
+ per CGATS).<br>
<br>
The start of the declaration of the fields shall be marked by the <span
style="font-weight: bold;">BEGIN_DATA_FORMAT</span> keyword (as
- per
- CGATS).<br>
+ per CGATS).<br>
<br>
The fields shall use the standard CGATS pattern of the full
- colorspace
- identified followed by the individual colorant identifier. There
- shall
- be an initial input index value identified by the letter <span
- style="font-weight: bold;">I</span>.<br>
+ colorspace identified followed by the individual colorant
+ identifier. There shall be an initial input index value identified
+ by the letter <span style="font-weight: bold;">I</span>.<br>
<br>
- For an RGB device, the
- following fields would be used:<br>
+ For an RGB device, the following fields would be used:<br>
<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">RGB_I</span>&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
+
+
The device value input value between 0.0 and 1.0.<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">RGB_R</span>&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
The Red device value input value between 0.0 and 1.0.<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">RGB_G</span>
&nbsp;&nbsp; &nbsp; The Green device value input value between 0.0
- and
- 1.0.<br>
+ and 1.0.<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">RGB_B</span>
&nbsp;&nbsp; &nbsp; The Blue device value input value between 0.0
- and
- 1.0.<br>
+ and 1.0.<br>
<br>
The corresponding field names for a CMYK device would be <span
style="font-weight: bold;">CMYK_I</span>, <span
@@ -198,16 +221,15 @@ Black&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
CGATS).<br>
<br>
Each set of data shall be on one line, and shall be separated by
- white
- space. All values shall be normalized to lie between 0.0 and 1.0.<br>
+ white space. All values shall be normalized to lie between 0.0 and
+ 1.0.<br>
<br>
The end of the values of the data sets shall be marked by the <span
style="font-weight: bold;">END_DATA</span> keyword (as per CGATS).<br>
<br>
There may then be device type specific extra tables that hold target
- or
- device behavior information. These will be specific to the tool that
- creates that particular type of calibration.<br>
+ or device behavior information. These will be specific to the tool
+ that creates that particular type of calibration.<br>
<br>
Generally any other keywords and values will be ignored.<br>
<br>
diff --git a/doc/ccxxmake.html b/doc/ccxxmake.html
index c4d8059..8ef31b7 100644
--- a/doc/ccxxmake.html
+++ b/doc/ccxxmake.html
@@ -42,7 +42,7 @@
using it with the <a href="dispcal.html#X">dispcal</a>, <a
href="dispread.html#X">dispread</a> and <a href="spotread.html#X">spotread</a>
-X option, or it can be <a
- href="file:///D:/src/argyll/doc/oeminst.html">installed</a>, and
+ href="oeminst.html">installed</a>, and
will then appear in the available display type selection (<b>-y</b>
option).<br>
<br>
@@ -69,6 +69,8 @@
+
+
&nbsp; &nbsp; &nbsp; Verbose mode</small><br>
&nbsp; <a href="#S">-S</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Create
@@ -87,6 +89,8 @@ rather
+
+
than CCMX<br>
&nbsp; <a href="#f">-f file1.ti3[,file2.ti3]</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -108,6 +112,8 @@ two
+
+
.ti3 files rather than measure.<br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><font
style="font-family: monospace;" size="-1"><a href="#display">-display
@@ -124,6 +130,8 @@ two
+
+
displayname</a>&nbsp; [X11 only] Choose X11 display name</font><br
style="font-family: monospace;">
<font style="font-family: monospace;" size="-1"></font><font
@@ -153,6 +161,8 @@ m
+
+
for VideoLUT access.</font><br style="font-family: monospace;">
<font style="font-family: monospace;" size="-1">&nbsp;<a href="#d">-d
@@ -168,6 +178,8 @@ m
+
+
n</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Choose
the
@@ -189,6 +201,8 @@ list
+
+
(default 1)</font><br>
<span style="font-family: monospace;">&nbsp;<a href="#dweb">-dweb[:port]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -208,7 +222,21 @@ list
- Display via a web server at port (default 8080)</span><br
+
+
+ Display via a web server at port (default 8080)</span><br>
+ <span style="font-family: monospace;">&nbsp;<a href="#dmadvr">-dmadvr</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ [MSWin] Display via MadVR Video Renderer</span><br
style="font-family: monospace;">
<font style="font-family: monospace;" size="-1">&nbsp;</font><font
style="font-family: monospace;" size="-1"><a href="#p">-p</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -225,6 +253,8 @@ list
+
+
Use telephoto mode (ie. for a projector) (if available)</font><br
style="font-family: monospace;">
&nbsp; <font size="-1"><span style="font-family: monospace;"><a
@@ -244,6 +274,8 @@ list
+
+
Display type - instrument specific list to choose from.</span></font><font
style="font-family: monospace;" size="-1"> (CCMX)</font><br
style="font-family: monospace;">
@@ -261,6 +293,8 @@ list
+
+
ho,vo,ss[,vs]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Position test
window and scale it</font><br style="font-family: monospace;">
<font style="font-family: monospace;" size="-1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -284,6 +318,8 @@ center,
+
+
1.0 = right/bottom etc.</font><br style="font-family: monospace;">
<font style="font-family: monospace;" size="-1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ss:
@@ -306,6 +342,8 @@ normal,
+
+
2.0 = double etc.</font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -315,6 +353,8 @@ normal,
+
+
ss,vs: = optional horizontal, vertical scale.</span></font><br
style="font-family: monospace;">
<font style="font-family: monospace;" size="-1">&nbsp;</font><font
@@ -333,6 +373,8 @@ normal,
+
+
Fill whole screen with black background</font><br
style="font-family: monospace;">
<small style="font-family: monospace;">&nbsp;<span
@@ -358,6 +400,8 @@ on
+
+
test window<br>
</small><font style="font-family: monospace;" size="-1">&nbsp;<a
href="#N">-N</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -374,6 +418,8 @@ on
+
+
Disable initial calibration of instrument</font><small
style="font-family: monospace;"> if possible<br>
</small><span style="font-family: monospace;">&nbsp;</span><font
@@ -392,6 +438,8 @@ on
+
+
Use high resolution spectrum mode (if available)</font><font
style="font-family: monospace;" size="-1"></font><br
style="font-family: monospace;">
@@ -409,6 +457,8 @@ on
+
+
"command"</a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Invoke shell "command" each time a color is set<br>
</font><small style="font-family: monospace;">&nbsp;<a href="#o">-o
@@ -439,6 +489,8 @@ sequence
+
+
combination steps (default 3)</font><br style="font-family:
monospace;">
<font style="font-family: monospace;" size="-1">&nbsp;<a href="#W">-W
@@ -455,6 +507,8 @@ sequence
+
+
n|h|x</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Override
serial
@@ -476,6 +530,8 @@ n
+
+
none, h = HW, x = Xon/Xoff</font><br style="font-family:
monospace;">
<small style="font-family: monospace;">&nbsp;<a href="#D">-D [level]</a>
@@ -500,6 +556,8 @@ overall
+
+
escription</small><br>
<small style="font-family: monospace;">&nbsp;<a href="#I">-I
"displayname"</a> &nbsp;&nbsp;&nbsp;&nbsp; </small><span
@@ -519,11 +577,15 @@ overall
+
+
"displaytech"</a> &nbsp;&nbsp;&nbsp;&nbsp; </small><span
style="font-family: monospace;">Set display technology description</span>
(ie. CRT, LCD etc.)<small style="font-family: monospace;"></small><br>
<tt>&nbsp;<a href="#U">-U c</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
Set UI selection character(s)</tt><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#Yrn">-<font size="-1">Y</font>
@@ -537,8 +599,12 @@ overall
+
+
&nbsp;&nbsp;&nbsp;&nbsp; Override refresh, non-refresh display
mode</span></font><br>
+ <tt>&nbsp;<a href="#YR">-Y R:<i>rate</i></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Override measured refresh rate with rate Hz</tt><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#YA">-<font size="-1">Y</font>A</a><span
style="font-family: monospace;">
@@ -638,6 +704,8 @@ overall
+
+
1,2</span> . Some experimentation may be needed using <a
href="dispwin.html">dispwin</a> on such systems, to discover what
screen has access to the VideoLUT hardware, and which screens the
@@ -660,6 +728,13 @@ overall
style="font-weight: bold;">/sbin/ifconfig</span> (Linux or OS X)
and identify an internet address for your machine that way.<br>
<br>
+ <a name="dmadvr"></a><span style="font-weight: bold;">-dmadvr</span>
+ [MSWin only] causes test patches to be displayed using the MadVR
+ video renderer. Note that you may have to start the video playback
+ software and load a video clip in pause for this to work. MadVR
+ rendering does not need or support VideoLUT access. Test patch
+ colors <u>will</u> be processed by the MadVR 3dLut.<br>
+ <br>
<a name="p"></a>The <span style="font-weight: bold;">-p</span> flag
allows measuring in telephoto mode, using instruments that support
this mode, e.g. the ColorMunki. Telephoto mode is one for taking
@@ -752,6 +827,8 @@ overall
+
+
of particular instruments</a> for more details. This may give
better accuracy for display measurements.<br>
<br>
@@ -860,14 +937,22 @@ overall
+
+
<b>-Y n</b> options overrides the refresh display mode set by the <a
- href="file:///D:/src/argyll/doc/spotread.html#y">-y display type
+ href="spotread.html#y">-y display type
selection</a>, with <b>-Y</b><span style="font-weight: bold;"> r</span>
forcing refresh display mode, and <b>-Y n</b> forcing a non-refresh
display mode. Not all instruments support a display measurement
refresh mode, or the ability to override the mode set by the display
type selection.<br>
<br>
+ <a name="YR"></a> The -<span style="font-weight: bold;">Y R:<i>rate</i></span>
+ options overrides calibration of the instrument refresh rate. This
+ may be useful if the instrument supports this function and the
+ refresh rate cannot be accurately calibrated from the display
+ itself.<br>
+ <br>
<a name="YA"></a> The -<span style="font-weight: bold;">Y A</span>
option uses a non-adaptive integration time emission measurement
mode, if the instrument supports it, such as the Eye-One Pro or
diff --git a/doc/cht_format.html b/doc/cht_format.html
index 1e02db1..80a3e9e 100644
--- a/doc/cht_format.html
+++ b/doc/cht_format.html
@@ -1,576 +1,622 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
-<head>
- <title>Scan Recognition Format File (.cht)</title>
- <meta http-equiv="content-type"
- content="text/html; charset=ISO-8859-1">
- <meta name="author" content="Graeme Gill">
-</head>
-<body>
-<h2>Description of the .cht format</h2>
-[This is a rather inflexible format, that should really be replaced
-with a CGATS style file.]<br>
-<br>
-The <span style="font-weight: bold;">.cht</span> format file is used
-to hold the image recognition information that allows the <a
- href="scanin.html">scanin</a> program to align the input image with
-the specified sample boxes.<br>
-<br>
-A raw <span style="font-weight: bold;">.cht</span> file can be
-produced by running <a href="scanin.html">scanin</a>
-with the <a href="scanin.html#g">-g</a> option, although this will
-then need
-cleaning up manually, using a text editor. The cleanup consists of
-deleting
-any unwanted reference lines from the XLIST and YLISTs, adding the the
-sample
-box references, and possibly adding the expected sample values.<br>
-<br>
-The <span style="font-weight: bold;">.cht</span> image recognition
-file is usually set up to recognized a scanned test chart that includes
-the edges of the chart itself, <span style="font-weight: bold;">not</span>
-a cropped version of the chart that excludes the edges of the chart
-itself. This is to allow <span style="font-weight: bold;">scanin</span>
-to be used with scans that have just be roughly cropped, without
-requiring that a scan be treated in detail with an application such as
-Adobe Photoshop.<br>
-<br>
-The keywords and associated data must be used in the following order: <b>BOXES</b>,
-<b>BOX_SHRINK</b>, <b>REF_ROTATION</b>, <b>XLIST</b>, <b>YLIST</b>
-and <b>EXPECTED</b>.<br>
-<br>
-The physical units used for boxes and edge lists are arbitrary units
-(i.e.
-pixels as generated by scanin -g, but could be mm, inches etc. if
-created
-&nbsp;some other way), the only requirement is that the sample box
-definitions need to agree with the X/YLIST definitions. Typically if a
-scanned chart is used to build the reference, the units will be pixels
-of the scanned chart.<br>
-<br>
-The <b>BOXES</b> keyword introduces the list of diagnostic and sample
-boxes.
-The integer following this keyword must be the total number of
-diagnostic
-and sample boxes, but <span style="font-weight: bold;">not</span>
-including any fiducual marks. The lines following the BOXES keyword must
-then
-contain
-the fiducial mark, diagnostic or sample box definitions. Each box
-definition line
-consists
-of 11 space separated parameters, and can generate a grid of sample or
-diagnostic
-boxes:<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>kl lxs lxe lys lye w h xo yo xi yi</b><br>
-<br>
-with the following usage:<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>kl</b> is a key letter.<br>
-<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">F</span>
-is used to define four fiducial mZarks that may be used for manual
-alignment of an image to the target. The four marks are nominally a
-top left mark, a top right mark, bottom right mark and a bottom left
-mark. The parameters are labeled as follows:<br>
-&nbsp;<b><br>
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </b><b>F _ _ x0 y0 x1 y1 x2 y2
-x3 y3<br>
-<br>
-&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </b>Where the first two
-parameters are not used, and a '_' character should be used as
-a place holder, and the follows the X and Y coordinates for the four
-fiducial marks.<span style="font-weight: bold;"></span><span
- style="font-weight: bold;"></span> Typically fiducial marks are chosen
-to be at the corners of the overall bounding box, or at corner cross
-marks on the chart etc. Fiducial marks may be omitted, but in this case
-manual alignment cannot be used.<br>
-<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<b>D</b> is used for a diagnostic
-box which will show up in the diagnostic raster output, but is not used
-as
-a sample box.&nbsp; The label information can be arbitrary.<br>
-&nbsp;&nbsp; &nbsp;<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<b>X</b> is used for a sequence
-of boxes in which the X label comes first in the concatenated sample
-box label.<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<b>Y</b> is used for a sequence
-of boxes in which the Y label comes first in the concatenated sample
-box label.<br>
-<br>
-&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Boxes are created incrementing in
-the X direction fastest, and the Y direction slowest.<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>lxs</b> is the X axis starting label. This is
-generally a letter or number, and it will be incremented appropriately
-to reach <b>lxe</b><br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>lxe</b> is the X axis ending label. When the X
-label reaches this this value (inclusively), the iteration in the X
-direction will reset.<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>lys</b> is the Y axis starting label. This is
-generally a letter or number, and it will be incremented appropriately
-to reach <b>lye</b><br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>lye</b> is the Y axis ending label. When the Y
-label reaches this this value (inclusively), the iteration through the
-boxes will end.<br>
-<br>
-&nbsp;&nbsp; &nbsp;The X &amp; Y labels will be concatenated to form
-the sample box label.<br>
-<br>
-&nbsp;&nbsp; &nbsp;A sample label that consists of the character '_' is
-treated as a null label (useful for an array that only iterates in one
-direction).<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>w</b>,<b> h</b> are the width and height of each
-box in the array.<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>xo</b>, <b>yo</b> are the origin of the top
-left
-of the array.<br>
-<br>
-&nbsp;&nbsp; &nbsp;<b>xi</b>, <b>yi</b> are the increments between
-each
-box in the array.<br>
-<br>
-A blank line should follow the last box definition line.<br>
-<br>
-The keyword <b>BOX_SHRINK</b> marks the definition of how much each
-sample
-box should be shrunk on each edge before sampling the pixel values.
-This
-allows the sample boxes to be defined at their edges, while allowing a
-safety
-margin for the pixels actually sampled. The units are the same
-arbitrary units
-used for the sample box definitions.<br>
-<br>
-A blank line should follow this keyword.<br>
-<br>
-The optional <b>REF_ROTATION</b> keyword indicates the rotation in
-radians
-clockwise of the reference image when the edge lists were generated.
-This
-amount of rotation is undone to the image before applying the sample
-box
-location information. The rotation is about the origin
-(the
-origin is assumed to be upper left corner). If omitted, the reference
-rotation
-is assumed to be 0.0<br>
-<br>
-A blank line should follow this keyword.<br>
-<br>
-The <b>XLIST</b> is a list of vertical edge reference "ticks", along
-the
-X axis. Ticks are just edge transitions, typically being each edge of
-the sample boxes, but should include edges of any features that have
-significant width and a length that is at least 50% of the available
-space. It is these edge ticks that are used to locate the reference
-cells position within the input raster. The integer after the keyword
-"XLIST" is the number of entries
-in
-the list. The first number in the column is the offset of the tick from
-the
-origin, the second number is used to improve the correlation by
-representing
-the strength of that "tick" relative to the strongest tick which will
-have
-a value 1.0. Strength is measured by the relative length of the edge.<br>
-<br>
-The third number represents the relative number of times this "tick" is
-crossed by lines in the other direction. A line is regarded as crossing
-if part of it is closer to the "tick" line that half the distance to
-the next tick line. The number is normalized so that the largest
-crossing count has a weight of
-1.0. This may be set to 1.0 if it is not known or easily computed.<br>
-<br>
-A blank line should follow the last <b>XLIST</b> edge definition.<br>
-<br>
-The <b>YLIST</b> is same format and details as the <b>XLIST</b>, used
-for
-horizontal edges.<br>
-<br>
-The <b>EXPECTED</b> keyword introduces an optional list of <span
- style="text-decoration: underline;">approximate</span>
-expected
-sample
-box color values, allowing better identification of the possible
-rotation
-of a chart, particularly if it has no asymmetric patch shapes or
-locations
-in the chart. Following the keyword should either be <b>XYZ</b> or <b>LAB</b>,
-depending on the color space used to describe the reference values,
-then
-an integer indicating the number of entries in the list.<br>
-<br>
-Each following expected color entry consists of four values. The first
-is
-the sample box label, which should correspond to one of those defined
-by
-the <b>BOXES</b> entry above. It is an error if no corresponding box
-has
-been defined. The remaining three values are the <span
- style="text-decoration: underline;">approximate</span> XYZ or
-L*a*b*
-color value expected for that sample box. The XYZ values are assumed to
-be
-scaled to a maximum Y value of 100. An expected color value doesn't
-have
-to be provided for every defined sample box, nor is it expected to be
-accurate - it just has to represent the approximate expected color.
-(Actual chart reference values are provided as a separate CGATS file to
-<a href="scanin.html"><span style="font-weight: bold;">scanin</span></a>).<br>
-<br>
-A blank line should follow the last <b>EXPECTED</b> box value.<br>
-<br>
-<br>
-<hr size="2" width="100%"><br>
-The following is an example .cht file, suitable for a typical Q60 IT8
-scan target.<br>
-<tt><br>
-<font size="-1"> BOXES 290<br>
-&nbsp; F _ _ _ _ 1 1&nbsp; 615.5 1.5&nbsp; 615 409<br>
-&nbsp; D ALL ALL _ _ 615 409 1 1 0 0<br>
-&nbsp; D MARK MARK _ _ 14 14 1 1 0 0<br>
-&nbsp; Y 01 22 A L 25.625 25.625 26.625 26.625 25.625 25.625<br>
-&nbsp; X GS00 GS23 _ _ 25.625 51.25 0.0 358.75 25.625 0.0<br>
-<br>
-BOX_SHRINK 3.0<br>
-<br>
-REF_ROTATION -0.002006<br>
-<br>
-XLIST 32<br>
-&nbsp; 1.799625 1.000000 0.312500<br>
-&nbsp; 27.064987 0.874039 0.750000<br>
-&nbsp; 52.592403 0.133439 0.687500<br>
-&nbsp; 78.196610 0.264191 0.687500<br>
-&nbsp; 104.117756 0.165427 0.937500<br>
-&nbsp; 129.377994 0.844432 0.937500<br>
-&nbsp; 155.144274 0.501218 0.875000<br>
-&nbsp; 180.839181 0.491428 0.937500<br>
-&nbsp; 206.359758 0.212384 0.937500<br>
-&nbsp; 232.038808 0.851851 0.937500<br>
-&nbsp; 257.854725 0.162956 0.625000<br>
-&nbsp; 283.552463 0.101243 0.812500<br>
-&nbsp; 300.534000 0.024750 0.812500<br>
-&nbsp; 309.507688 0.093829 1.000000<br>
-&nbsp; 334.711314 0.856821 1.000000<br>
-&nbsp; 360.428194 0.787677 1.000000<br>
-&nbsp; 385.849730 0.748130 0.937500<br>
-&nbsp; 386.650071 0.039487 0.687500<br>
-&nbsp; 394.630372 0.024725 0.687500<br>
-&nbsp; 411.835654 0.802501 0.750000<br>
-&nbsp; 414.017731 0.041974 0.937500<br>
-&nbsp; 437.133504 0.674062 0.937500<br>
-&nbsp; 437.975355 0.103714 1.000000<br>
-&nbsp; 462.938460 0.671643 1.000000<br>
-&nbsp; 463.880560 0.093836 0.937500<br>
-&nbsp; 488.517995 0.679022 1.000000<br>
-&nbsp; 514.338544 0.760511 1.000000<br>
-&nbsp; 540.037492 0.111108 0.625000<br>
-&nbsp; 565.856396 0.133330 0.562500<br>
-&nbsp; 591.114717 0.565475 0.562500<br>
-&nbsp; 603.447516 0.032097 0.312500<br>
-&nbsp; 615.984915 0.829608 0.250000<br>
-<br>
-YLIST 22<br>
-&nbsp; 2.477956 0.993407 0.142857<br>
-&nbsp; 12.988903 0.016393 0.190476<br>
-&nbsp; 14.739109 0.036082 0.190476<br>
-&nbsp; 26.746171 0.911487 0.428571<br>
-&nbsp; 52.537114 0.303282 0.904762<br>
-&nbsp; 78.060317 0.585303 0.857143<br>
-&nbsp; 103.498271 0.606862 0.761905<br>
-&nbsp; 128.994535 0.567266 0.761905<br>
-&nbsp; 154.483041 0.550814 0.714286<br>
-&nbsp; 179.935985 0.623055 0.666667<br>
-&nbsp; 205.552940 0.350826 0.714286<br>
-&nbsp; 212.051372 0.016393 0.714286<br>
-&nbsp; 231.153547 0.824618 0.857143<br>
-&nbsp; 256.697418 0.744268 0.952381<br>
-&nbsp; 282.145841 0.736126 0.904762<br>
-&nbsp; 307.899015 0.536075 0.952381<br>
-&nbsp; 333.262903 0.903282 0.809524<br>
-&nbsp; 340.217754 0.019722 0.190476<br>
-&nbsp; 344.988867 0.019671 0.095238<br>
-&nbsp; 346.988885 0.018032 0.095238<br>
-&nbsp; 358.840278 0.999967 1.000000<br>
-&nbsp; 409.201393 1.000000 0.000000<br>
-<br>
-EXPECTED XYZ 264<br>
-&nbsp; A1&nbsp;&nbsp;&nbsp; 3.85 3.22 1.9<br>
-&nbsp; A2&nbsp;&nbsp;&nbsp; 4.89 3.27 1.6<br>
-&nbsp; A3&nbsp;&nbsp;&nbsp; 5.87 3.31 1.33<br>
-&nbsp; A4&nbsp;&nbsp;&nbsp; 6.3 3.38 1.19<br>
-&nbsp; A5&nbsp;&nbsp;&nbsp; 13.01 11.44 7.64<br>
-&nbsp; A6&nbsp;&nbsp;&nbsp; 16.14 11.99 6.81<br>
-&nbsp; A7&nbsp;&nbsp;&nbsp; 19.35 12.41 6.06<br>
-&nbsp; A8&nbsp;&nbsp;&nbsp; 20.41 11.97 5.3<br>
-&nbsp; A9&nbsp;&nbsp;&nbsp; 43.5 42.81 32.65<br>
-&nbsp; A10&nbsp;&nbsp; 45.58 42.37 30.95<br>
-&nbsp; A11&nbsp;&nbsp; 48.99 43.2 29.9<br>
-&nbsp; A12&nbsp;&nbsp; 50.73 44.02 29.96<br>
-&nbsp; A13&nbsp;&nbsp; 74.46 78.76 66.06<br>
-&nbsp; A14&nbsp;&nbsp; 75.66 76.42 64.08<br>
-&nbsp; A15&nbsp;&nbsp; 78.36 81.34 65.41<br>
-&nbsp; A16&nbsp;&nbsp; 70.52 73.3 59.16<br>
-&nbsp; A17&nbsp;&nbsp; 74.98 75.98 60.69<br>
-&nbsp; A18&nbsp;&nbsp; 72.85 77.3 60.25<br>
-&nbsp; A19&nbsp;&nbsp; 73.09 75.52 64.54<br>
-&nbsp; B1&nbsp;&nbsp;&nbsp; 3.47 3.08 1.41<br>
-&nbsp; B2&nbsp;&nbsp;&nbsp; 4.41 3.25 0.9<br>
-&nbsp; B3&nbsp;&nbsp;&nbsp; 5.04 3.23 0.58<br>
-&nbsp; B4&nbsp;&nbsp;&nbsp; 5.19 3.11 0.47<br>
-&nbsp; B5&nbsp;&nbsp;&nbsp; 13.36 11.59 5.56<br>
-&nbsp; B6&nbsp;&nbsp;&nbsp; 15.97 12.03 3.69<br>
-&nbsp; B7&nbsp;&nbsp;&nbsp; 19.2 12.49 2.2<br>
-&nbsp; B8&nbsp;&nbsp;&nbsp; 19.73 11.52 1.17<br>
-&nbsp; B9&nbsp;&nbsp;&nbsp; 42.19 41.84 29.34<br>
-&nbsp; B10&nbsp;&nbsp; 44.83 42.17 25.93<br>
-&nbsp; B11&nbsp;&nbsp; 48.06 42.9 23.01<br>
-&nbsp; B12&nbsp;&nbsp; 49.63 43.08 21.34<br>
-&nbsp; B13&nbsp;&nbsp; 66.21 72.54 64.61<br>
-&nbsp; B14&nbsp;&nbsp; 70.16 67.1 60.33<br>
-&nbsp; B15&nbsp;&nbsp; 75.46 78.69 51.58<br>
-&nbsp; B16&nbsp;&nbsp; 57.47 59.58 47.66<br>
-&nbsp; B17&nbsp;&nbsp; 68.33 66.45 49.05<br>
-&nbsp; B18&nbsp;&nbsp; 63.89 70.29 51.3<br>
-&nbsp; B19&nbsp;&nbsp; 61.12 62.16 59.79<br>
-&nbsp; C1&nbsp;&nbsp;&nbsp; 4.97 4.75 1.98<br>
-&nbsp; C2&nbsp;&nbsp;&nbsp; 5.18 4.65 1.23<br>
-&nbsp; C3&nbsp;&nbsp;&nbsp; 5.51 4.58 0.71<br>
-&nbsp; C4&nbsp;&nbsp;&nbsp; 5.77 4.61 0.67<br>
-&nbsp; C5&nbsp;&nbsp;&nbsp; 24.57 23.44 10.14<br>
-&nbsp; C6&nbsp;&nbsp;&nbsp; 28.1 24.64 5.22<br>
-&nbsp; C7&nbsp;&nbsp;&nbsp; 31.15 25.28 2.2<br>
-&nbsp; C8&nbsp;&nbsp;&nbsp; 30.85 23.68 1.35<br>
-&nbsp; C9&nbsp;&nbsp;&nbsp; 49.16 49.36 32.37<br>
-&nbsp; C10&nbsp;&nbsp; 51.72 50.72 26.53<br>
-&nbsp; C11&nbsp;&nbsp; 55.24 53.14 21.93<br>
-&nbsp; C12&nbsp;&nbsp; 56.87 53.62 18.46<br>
-&nbsp; C13&nbsp;&nbsp; 57.68 65.65 62.7<br>
-&nbsp; C14&nbsp;&nbsp; 63.46 56.66 55.49<br>
-&nbsp; C15&nbsp;&nbsp; 73 76.11 40.78<br>
-&nbsp; C16&nbsp;&nbsp; 44.73 46.38 36.8<br>
-&nbsp; C17&nbsp;&nbsp; 60.64 55.73 38.1<br>
-&nbsp; C18&nbsp;&nbsp; 52.15 60.27 41.5<br>
-&nbsp; C19&nbsp;&nbsp; 48.13 49.18 54.38<br>
-&nbsp; D1&nbsp;&nbsp;&nbsp; 4.19 4.41 1.93<br>
-&nbsp; D2&nbsp;&nbsp;&nbsp; 4.48 4.72 1.24<br>
-&nbsp; D3&nbsp;&nbsp;&nbsp; 4.55 4.78 0.8<br>
-&nbsp; D4&nbsp;&nbsp;&nbsp; 4.32 4.53 0.78<br>
-&nbsp; D5&nbsp;&nbsp;&nbsp; 27.33 28.55 12.95<br>
-&nbsp; D6&nbsp;&nbsp;&nbsp; 28.68 30.04 7.25<br>
-&nbsp; D7&nbsp;&nbsp;&nbsp; 29.51 31.01 3.41<br>
-&nbsp; D8&nbsp;&nbsp;&nbsp; 27.55 28.44 1.83<br>
-&nbsp; D9&nbsp;&nbsp;&nbsp; 56.06 58.19 38.21<br>
-&nbsp; D10&nbsp;&nbsp; 56.03 58.46 30.02<br>
-&nbsp; D11&nbsp;&nbsp; 56.2 59.33 24.44<br>
-&nbsp; D12&nbsp;&nbsp; 56.19 59.41 19.14<br>
-&nbsp; D13&nbsp;&nbsp; 48.21 57.42 59.53<br>
-&nbsp; D14&nbsp;&nbsp; 58.18 49.14 51.36<br>
-&nbsp; D15&nbsp;&nbsp; 70.98 73.73 33.63<br>
-&nbsp; D16&nbsp;&nbsp; 34.31 35.73 28.22<br>
-&nbsp; D17&nbsp;&nbsp; 54.27 47.53 29.58<br>
-&nbsp; D18&nbsp;&nbsp; 41.67 50.64 32.28<br>
-&nbsp; D19&nbsp;&nbsp; 36.95 37.82 48.09<br>
-&nbsp; E1&nbsp;&nbsp;&nbsp; 4.15 4.75 2.03<br>
-&nbsp; E2&nbsp;&nbsp;&nbsp; 4 4.98 1.37<br>
-&nbsp; E3&nbsp;&nbsp;&nbsp; 3.3 4.49 0.86<br>
-&nbsp; E4&nbsp;&nbsp;&nbsp; 3.11 4.3 0.86<br>
-&nbsp; E5&nbsp;&nbsp;&nbsp; 13.11 14.9 7.06<br>
-&nbsp; E6&nbsp;&nbsp;&nbsp; 12.26 15.23 4.18<br>
-&nbsp; E7&nbsp;&nbsp;&nbsp; 11.53 15.57 2.27<br>
-&nbsp; E8&nbsp;&nbsp;&nbsp; 9.69 13.74 1.51<br>
-&nbsp; E9&nbsp;&nbsp;&nbsp; 39.15 42.08 27.33<br>
-&nbsp; E10&nbsp;&nbsp; 37.43 41.51 22.23<br>
-&nbsp; E11&nbsp;&nbsp; 36.99 42.5 18.85<br>
-&nbsp; E12&nbsp;&nbsp; 36.4 42.58 16.27<br>
-&nbsp; E13&nbsp;&nbsp; 39.97 49.81 56.15<br>
-&nbsp; E14&nbsp;&nbsp; 52.08 41.07 46.36<br>
-&nbsp; E15&nbsp;&nbsp; 68.71 70.76 26.45<br>
-&nbsp; E16&nbsp;&nbsp; 25.7 26.97 21.28<br>
-&nbsp; E17&nbsp;&nbsp; 48.53 40.6 22<br>
-&nbsp; E18&nbsp;&nbsp; 31.62 40.82 23.35<br>
-&nbsp; E19&nbsp;&nbsp; 31.19 31.19 43.4<br>
-&nbsp; F1&nbsp;&nbsp;&nbsp; 1.51 1.91 1.06<br>
-&nbsp; F2&nbsp;&nbsp;&nbsp; 1.29 2.04 0.98<br>
-&nbsp; F3&nbsp;&nbsp;&nbsp; 1.16 2.09 0.82<br>
-&nbsp; F4&nbsp;&nbsp;&nbsp; 1.14 2.04 0.8<br>
-&nbsp; F5&nbsp;&nbsp;&nbsp; 6.53 8.25 5.13<br>
-&nbsp; F6&nbsp;&nbsp;&nbsp; 5.61 8.66 4.38<br>
-&nbsp; F7&nbsp;&nbsp;&nbsp; 4.6 8.77 3.7<br>
-&nbsp; F8&nbsp;&nbsp;&nbsp; 3.45 7.63 2.78<br>
-&nbsp; F9&nbsp;&nbsp;&nbsp; 37.8 41.07 30.91<br>
-&nbsp; F10&nbsp;&nbsp; 35.92 40.76 29.03<br>
-&nbsp; F11&nbsp;&nbsp; 35.42 41.99 29.07<br>
-&nbsp; F12&nbsp;&nbsp; 34 41.8 28<br>
-&nbsp; F13&nbsp;&nbsp; 32.13 42.12 51.99<br>
-&nbsp; F14&nbsp;&nbsp; 45.72 33.34 40.77<br>
-&nbsp; F15&nbsp;&nbsp; 66.26 67.29 19.65<br>
-&nbsp; F16&nbsp;&nbsp; 17.02 18.07 14.4<br>
-&nbsp; F17&nbsp;&nbsp; 41.59 32.53 15.16<br>
-&nbsp; F18&nbsp;&nbsp; 26.26 35.26 18.81<br>
-&nbsp; F19&nbsp;&nbsp; 24.3 23.6 37.48<br>
-&nbsp; G1&nbsp;&nbsp;&nbsp; 2.31 3 2.27<br>
-&nbsp; G2&nbsp;&nbsp;&nbsp; 2 3.21 2.58<br>
-&nbsp; G3&nbsp;&nbsp;&nbsp; 1.66 3.21 2.75<br>
-&nbsp; G4&nbsp;&nbsp;&nbsp; 1.58 3.03 2.6<br>
-&nbsp; G5&nbsp;&nbsp;&nbsp; 8.99 11.08 8.79<br>
-&nbsp; G6&nbsp;&nbsp;&nbsp; 7.68 11.3 9.56<br>
-&nbsp; G7&nbsp;&nbsp;&nbsp; 6.52 11.5 10.2<br>
-&nbsp; G8&nbsp;&nbsp;&nbsp; 5.5 10.85 10.55<br>
-&nbsp; G9&nbsp;&nbsp;&nbsp; 38.29 41.75 33.45<br>
-&nbsp; G10&nbsp;&nbsp; 35.83 41.16 34.11<br>
-&nbsp; G11&nbsp;&nbsp; 34.56 41.83 35.63<br>
-&nbsp; G12&nbsp;&nbsp; 33.69 42.14 36.7<br>
-&nbsp; G13&nbsp;&nbsp; 25.95 35.68 48<br>
-&nbsp; G14&nbsp;&nbsp; 40.6 27.62 36.14<br>
-&nbsp; G15&nbsp;&nbsp; 63.72 63.63 14.35<br>
-&nbsp; G16&nbsp;&nbsp; 10.85 11.82 9.58<br>
-&nbsp; G17&nbsp;&nbsp; 37.23 27.64 11.62<br>
-&nbsp; G18&nbsp;&nbsp; 20.28 28.97 14.15<br>
-&nbsp; G19&nbsp;&nbsp; 17.7 16.74 31.7<br>
-&nbsp; H1&nbsp;&nbsp;&nbsp; 2.56 3.04 2.92<br>
-&nbsp; H2&nbsp;&nbsp;&nbsp; 2.34 3.2 4.12<br>
-&nbsp; H3&nbsp;&nbsp;&nbsp; 2.12 3.28 5.43<br>
-&nbsp; H4&nbsp;&nbsp;&nbsp; 2.06 3.18 5.29<br>
-&nbsp; H5&nbsp;&nbsp;&nbsp; 10.07 11.6 11.24<br>
-&nbsp; H6&nbsp;&nbsp;&nbsp; 9.01 11.68 14.81<br>
-&nbsp; H7&nbsp;&nbsp;&nbsp; 8.22 12 19.42<br>
-&nbsp; H8&nbsp;&nbsp;&nbsp; 7.25 11.55 21.45<br>
-&nbsp; H9&nbsp;&nbsp;&nbsp; 39.25 42.31 36.81<br>
-&nbsp; H10&nbsp;&nbsp; 37.58 41.85 40.37<br>
-&nbsp; H11&nbsp;&nbsp; 37.16 43.07 45.79<br>
-&nbsp; H12&nbsp;&nbsp; 36.27 43.78 49.47<br>
-&nbsp; H13&nbsp;&nbsp; 21.47 30.78 44.22<br>
-&nbsp; H14&nbsp;&nbsp; 36.49 23.35 32.38<br>
-&nbsp; H15&nbsp;&nbsp; 61.58 60.55 10.95<br>
-&nbsp; H16&nbsp;&nbsp; 8.21 8.71 6.91<br>
-&nbsp; H17&nbsp;&nbsp; 33.04 23.26 8.38<br>
-&nbsp; H18&nbsp;&nbsp; 16.22 24.35 10.41<br>
-&nbsp; H19&nbsp;&nbsp; 12.86 11.84 26.82<br>
-&nbsp; I1&nbsp;&nbsp;&nbsp; 4.22 4.44 5.28<br>
-&nbsp; I2&nbsp;&nbsp;&nbsp; 4.35 4.48 8.36<br>
-&nbsp; I3&nbsp;&nbsp;&nbsp; 4.4 4.44 11.94<br>
-&nbsp; I4&nbsp;&nbsp;&nbsp; 4.48 4.58 12.17<br>
-&nbsp; I5&nbsp;&nbsp;&nbsp; 15.15 15.78 15.23<br>
-&nbsp; I6&nbsp;&nbsp;&nbsp; 14.56 15.12 19.52<br>
-&nbsp; I7&nbsp;&nbsp;&nbsp; 14.37 14.81 24.48<br>
-&nbsp; I8&nbsp;&nbsp;&nbsp; 14.11 14.76 30.03<br>
-&nbsp; I9&nbsp;&nbsp;&nbsp; 41.03 42.58 36.94<br>
-&nbsp; I10&nbsp;&nbsp; 40.85 42.23 40.73<br>
-&nbsp; I11&nbsp;&nbsp; 40.86 42.33 45.05<br>
-&nbsp; I12&nbsp;&nbsp; 41.31 42.73 47.77<br>
-&nbsp; I13&nbsp;&nbsp; 17.26 25.93 40.23<br>
-&nbsp; I14&nbsp;&nbsp; 32.66 19.63 28.81<br>
-&nbsp; I15&nbsp;&nbsp; 59.37 57.18 7.79<br>
-&nbsp; I16&nbsp;&nbsp; 4.97 5.32 4.32<br>
-&nbsp; I17&nbsp;&nbsp; 28.62 18.88 5.48<br>
-&nbsp; I18&nbsp;&nbsp; 11.58 18.98 7.25<br>
-&nbsp; I19&nbsp;&nbsp; 9.58 8.34 22.87<br>
-&nbsp; I20&nbsp;&nbsp; 0.45 0.4 0.33<br>
-&nbsp; I21&nbsp;&nbsp; 2.28 1.78 0.98<br>
-&nbsp; I22&nbsp;&nbsp; 2.37 1.95 0.85<br>
-&nbsp; J1&nbsp;&nbsp;&nbsp; 2.15 1.9 2.6<br>
-&nbsp; J2&nbsp;&nbsp;&nbsp; 2.57 2 4.72<br>
-&nbsp; J3&nbsp;&nbsp;&nbsp; 2.93 1.95 8.1<br>
-&nbsp; J4&nbsp;&nbsp;&nbsp; 3.15 1.92 10.76<br>
-&nbsp; J5&nbsp;&nbsp;&nbsp; 11.73 11.6 11.81<br>
-&nbsp; J6&nbsp;&nbsp;&nbsp; 12.98 11.93 16.19<br>
-&nbsp; J7&nbsp;&nbsp;&nbsp; 13.91 12.07 20.95<br>
-&nbsp; J8&nbsp;&nbsp;&nbsp; 14.01 11.59 24.35<br>
-&nbsp; J9&nbsp;&nbsp;&nbsp; 40.75 41.22 36.34<br>
-&nbsp; J10&nbsp;&nbsp; 41.26 41.07 39.74<br>
-&nbsp; J11&nbsp;&nbsp; 42.63 41.68 44.51<br>
-&nbsp; J12&nbsp;&nbsp; 44.02 41.78 49.25<br>
-&nbsp; J13&nbsp;&nbsp; 13.82 21.69 35.98<br>
-&nbsp; J14&nbsp;&nbsp; 28.87 16.33 25.08<br>
-&nbsp; J15&nbsp;&nbsp; 56.04 52.29 4.97<br>
-&nbsp; J16&nbsp;&nbsp; 2.46 2.63 2.29<br>
-&nbsp; J17&nbsp;&nbsp; 24.04 14.75 3.15<br>
-&nbsp; J18&nbsp;&nbsp; 8.12 14.49 4.55<br>
-&nbsp; J19&nbsp;&nbsp; 5.98 4.79 17.76<br>
-&nbsp; J20&nbsp;&nbsp; 8.26 5.37 1.04<br>
-&nbsp; J21&nbsp;&nbsp; 11.52 7.81 1.62<br>
-&nbsp; J22&nbsp;&nbsp; 14.67 10.72 2.6<br>
-&nbsp; K1&nbsp;&nbsp;&nbsp; 5.63 4.7 4.86<br>
-&nbsp; K2&nbsp;&nbsp;&nbsp; 6.74 4.58 7.23<br>
-&nbsp; K3&nbsp;&nbsp;&nbsp; 8.04 4.48 9.73<br>
-&nbsp; K4&nbsp;&nbsp;&nbsp; 9.39 4.76 11.79<br>
-&nbsp; K5&nbsp;&nbsp;&nbsp; 16.66 15.39 14.44<br>
-&nbsp; K6&nbsp;&nbsp;&nbsp; 18.72 15.18 18.23<br>
-&nbsp; K7&nbsp;&nbsp;&nbsp; 21.56 15.5 22.97<br>
-&nbsp; K8&nbsp;&nbsp;&nbsp; 23 15.02 25.37<br>
-&nbsp; K9&nbsp;&nbsp;&nbsp; 42.5 42.02 36.05<br>
-&nbsp; K10&nbsp;&nbsp; 44.55 41.63 39.71<br>
-&nbsp; K11&nbsp;&nbsp; 47.19 41.96 44.03<br>
-&nbsp; K12&nbsp;&nbsp; 49.9 43.14 47.21<br>
-&nbsp; K13&nbsp;&nbsp; 10.61 17.44 31.24<br>
-&nbsp; K14&nbsp;&nbsp; 24.84 13.19 21<br>
-&nbsp; K15&nbsp;&nbsp; 53.12 48.05 3.19<br>
-&nbsp; K16&nbsp;&nbsp; 1.05 1.14 1.13<br>
-&nbsp; K17&nbsp;&nbsp; 19.93 11.34 1.67<br>
-&nbsp; K18&nbsp;&nbsp; 5.3 10.47 2.73<br>
-&nbsp; K19&nbsp;&nbsp; 3.95 2.76 13.94<br>
-&nbsp; K20&nbsp;&nbsp; 30.61 26.43 11.04<br>
-&nbsp; K21&nbsp;&nbsp; 34.91 29.6 11.78<br>
-&nbsp; K22&nbsp;&nbsp; 38.95 34.57 18.4<br>
-&nbsp; L1&nbsp;&nbsp;&nbsp; 3.88 3.12 2.32<br>
-&nbsp; L2&nbsp;&nbsp;&nbsp; 4.93 3.2 2.69<br>
-&nbsp; L3&nbsp;&nbsp;&nbsp; 5.75 3.14 3.02<br>
-&nbsp; L4&nbsp;&nbsp;&nbsp; 7.31 3.79 3.4<br>
-&nbsp; L5&nbsp;&nbsp;&nbsp; 13.29 11.54 9.39<br>
-&nbsp; L6&nbsp;&nbsp;&nbsp; 16.22 11.73 10.32<br>
-&nbsp; L7&nbsp;&nbsp;&nbsp; 19.95 12.08 12.06<br>
-&nbsp; L8&nbsp;&nbsp;&nbsp; 20.79 11.31 12.01<br>
-&nbsp; L9&nbsp;&nbsp;&nbsp; 43.22 42.09 33.78<br>
-&nbsp; L10&nbsp;&nbsp; 45.52 41.88 34.65<br>
-&nbsp; L11&nbsp;&nbsp; 49.04 42.87 35.98<br>
-&nbsp; L12&nbsp;&nbsp; 51.03 43.83 37.78<br>
-&nbsp; L13&nbsp;&nbsp; 7.45 12.77 25.59<br>
-&nbsp; L14&nbsp;&nbsp; 21.26 10.76 17.73<br>
-&nbsp; L15&nbsp;&nbsp; 49.45 43.12 2.14<br>
-&nbsp; L16&nbsp;&nbsp; 0.47 0.49 0.5<br>
-&nbsp; L17&nbsp;&nbsp; 16.04 8.49 0.78<br>
-&nbsp; L18&nbsp;&nbsp; 2.91 6.5 1.39<br>
-&nbsp; L19&nbsp;&nbsp; 2.5 1.45 10.28<br>
-&nbsp; L20&nbsp;&nbsp; 38.7 33.98 20.86<br>
-&nbsp; L21&nbsp;&nbsp; 39.36 35.23 21.23<br>
-&nbsp; L22&nbsp;&nbsp; 41.36 38.77 23.51<br>
-&nbsp; GS0&nbsp;&nbsp;&nbsp; 79.47 82.51 69.04<br>
-&nbsp; GS1&nbsp;&nbsp;&nbsp; 72.62 74.94 59.17<br>
-&nbsp; GS2&nbsp;&nbsp;&nbsp; 63.15 65.11 51.57<br>
-&nbsp; GS3&nbsp;&nbsp;&nbsp; 54.72 56.51 45.03<br>
-&nbsp; GS4&nbsp;&nbsp;&nbsp; 48.1 49.81 39.24<br>
-&nbsp; GS5&nbsp;&nbsp;&nbsp; 42.22 43.64 34.45<br>
-&nbsp; GS6&nbsp;&nbsp;&nbsp; 37.33 38.7 30.5<br>
-&nbsp; GS7&nbsp;&nbsp;&nbsp; 32.38 33.61 26.11<br>
-&nbsp; GS8&nbsp;&nbsp;&nbsp; 27.56 28.7 22.11<br>
-&nbsp; GS9&nbsp;&nbsp;&nbsp; 22.5 23.4 17.99<br>
-&nbsp; GS10&nbsp;&nbsp; 18.77 19.55 14.83<br>
-&nbsp; GS11&nbsp;&nbsp; 15.48 16.08 12.04<br>
-&nbsp; GS12&nbsp;&nbsp; 12.69 13.29 9.98<br>
-&nbsp; GS13&nbsp;&nbsp; 10.35 10.81 7.97<br>
-&nbsp; GS14&nbsp;&nbsp; 8.39 8.77 6.37<br>
-&nbsp; GS15&nbsp;&nbsp; 6.45 6.79 4.97<br>
-&nbsp; GS16&nbsp;&nbsp; 4.95 5.18 3.7<br>
-&nbsp; GS17&nbsp;&nbsp; 3.58 3.82 2.76<br>
-&nbsp; GS18&nbsp;&nbsp; 2.76 2.89 2.06<br>
-&nbsp; GS19&nbsp;&nbsp; 1.97 2.08 1.45<br>
-&nbsp; GS20&nbsp;&nbsp; 1.22 1.31 0.98<br>
-&nbsp; GS21&nbsp;&nbsp; 1 1.05 0.74<br>
-&nbsp; GS22&nbsp;&nbsp; 0.87 0.89 0.65<br>
-&nbsp; GS23&nbsp;&nbsp; 0.34 0.32 0.32<br>
-<br>
-</font> </tt><br>
-<tt> <br>
-</tt><br>
-<br>
-</body>
+ <head>
+ <title>Scan Recognition Format File (.cht)</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=windows-1252">
+ <meta name="author" content="Graeme Gill">
+ </head>
+ <body>
+ <h2>Description of the .cht format</h2>
+ [This is a rather inflexible format, that should really be replaced
+ with a CGATS style file.]<br>
+ <br>
+ The <span style="font-weight: bold;">.cht</span> format file is
+ used
+ to hold the image recognition information that allows the <a
+ href="scanin.html">scanin</a> program to align the input image
+ with
+ the specified sample boxes.<br>
+ <br>
+ A raw <span style="font-weight: bold;">.cht</span> file can be
+ produced by running <a href="scanin.html">scanin</a>
+ with the <a href="scanin.html#g">-g</a> option, although this will
+ then need
+ cleaning up manually, using a text editor. The cleanup consists of
+ deleting
+ any unwanted reference lines from the XLIST and YLISTs, adding the
+ the
+ sample
+ box references, and possibly adding the expected sample values.<br>
+ <br>
+ The <span style="font-weight: bold;">.cht</span> image recognition
+ file is usually set up to recognized a scanned test chart that
+ includes
+ the edges of the chart itself, <span style="font-weight: bold;">not</span>
+ a cropped version of the chart that excludes the edges of the chart
+ itself. This is to allow <span style="font-weight: bold;">scanin</span>
+ to be used with scans that have just be roughly cropped, without
+ requiring that a scan be treated in detail with an application such
+ as
+ Adobe Photoshop.<br>
+ <br>
+ The keywords and associated data must be used in the following
+ order: <b>BOXES</b>,
+ <b>BOX_SHRINK</b>, <b>REF_ROTATION</b>, <b>XLIST</b>, <b>YLIST</b>
+ and <b>EXPECTED</b>.<br>
+ <br>
+ The physical units used for boxes and edge lists are arbitrary units
+ (i.e.
+ pixels as generated by scanin -g, but could be mm, inches etc. if
+ created
+ &nbsp;some other way), the only requirement is that the sample box
+ definitions need to agree with the X/YLIST definitions. Typically if
+ a
+ scanned chart is used to build the reference, the units will be
+ pixels
+ of the scanned chart.<br>
+ <br>
+ The <b>BOXES</b> keyword introduces the list of diagnostic and
+ sample
+ boxes.
+ The integer following this keyword must be the total number of
+ diagnostic
+ and sample boxes, but <span style="font-weight: bold;">not</span>
+ including any fiducual marks. The lines following the BOXES keyword
+ must
+ then
+ contain
+ the fiducial mark, diagnostic or sample box definitions. Each box
+ definition line
+ consists
+ of 11 space separated parameters, and can generate a grid of sample
+ or
+ diagnostic
+ boxes:<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>kl lxs lxe lys lye w h xo yo xi yi</b><br>
+ <br>
+ with the following usage:<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>kl</b> is a key letter.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; <span style="font-weight:
+ bold;">F</span>
+ is used to define four fiducial marks that may be used for manual
+ alignment of an image to the target. The four marks are nominally a
+ top left mark, a top right mark, bottom right mark and a bottom left
+ mark (ie. clockwise order from top left). The parameters are labeled
+ as follows:<br>
+ &nbsp;<b><br>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </b><b>F _ _ x0 y0 x1 y1 x2
+ y2
+ x3 y3<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; </b>Where the first two
+ parameters are not used, and a '_' character should be used as
+ a place holder, and the follows the X and Y coordinates for the four
+ fiducial marks.<span style="font-weight: bold;"></span><span
+ style="font-weight: bold;"></span> Typically fiducial marks are
+ chosen
+ to be at the corners of the overall bounding box, or at corner cross
+ marks on the chart etc. Fiducial marks may be omitted, but in this
+ case
+ manual alignment cannot be used.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<b>D</b> is used for a
+ diagnostic
+ box which will show up in the diagnostic raster output, but is not
+ used
+ as
+ a sample box.&nbsp; The label information can be arbitrary.<br>
+ &nbsp;&nbsp; &nbsp;<br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<b>X</b> is used for a
+ sequence
+ of boxes in which the X label comes first in the concatenated sample
+ box label.<br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<b>Y</b> is used for a
+ sequence
+ of boxes in which the Y label comes first in the concatenated sample
+ box label.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Boxes are created incrementing
+ in
+ the X direction fastest, and the Y direction slowest.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>lxs</b> is the X axis starting label. This is
+ generally a letter or number, and it will be incremented
+ appropriately
+ to reach <b>lxe</b><br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>lxe</b> is the X axis ending label. When the X
+ label reaches this this value (inclusively), the iteration in the X
+ direction will reset.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>lys</b> is the Y axis starting label. This is
+ generally a letter or number, and it will be incremented
+ appropriately
+ to reach <b>lye</b><br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>lye</b> is the Y axis ending label. When the Y
+ label reaches this this value (inclusively), the iteration through
+ the
+ boxes will end.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;The X &amp; Y labels will be concatenated to form
+ the sample box label.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;A sample label that consists of the character '_'
+ is
+ treated as a null label (useful for an array that only iterates in
+ one
+ direction).<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>w</b>,<b> h</b> are the width and height of
+ each
+ box in the array.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>xo</b>, <b>yo</b> are the origin of the top
+ left
+ of the array.<br>
+ <br>
+ &nbsp;&nbsp; &nbsp;<b>xi</b>, <b>yi</b> are the increments between
+ each
+ box in the array.<br>
+ <br>
+ A blank line should follow the last box definition line.<br>
+ <br>
+ The keyword <b>BOX_SHRINK</b> marks the definition of how much each
+ sample
+ box should be shrunk on each edge before sampling the pixel values.
+ This
+ allows the sample boxes to be defined at their edges, while allowing
+ a
+ safety
+ margin for the pixels actually sampled. The units are the same
+ arbitrary units
+ used for the sample box definitions.<br>
+ <br>
+ A blank line should follow this keyword.<br>
+ <br>
+ The optional <b>REF_ROTATION</b> keyword indicates the rotation in
+ radians
+ clockwise of the reference image when the edge lists were generated.
+ This
+ amount of rotation is undone to the image before applying the sample
+ box
+ location information. The rotation is about the origin
+ (the
+ origin is assumed to be upper left corner). If omitted, the
+ reference
+ rotation
+ is assumed to be 0.0<br>
+ <br>
+ A blank line should follow this keyword.<br>
+ <br>
+ The <b>XLIST</b> is a list of vertical edge reference "ticks",
+ along
+ the
+ X axis. Ticks are just edge transitions, typically being each edge
+ of
+ the sample boxes, but should include edges of any features that have
+ significant width and a length that is at least 50% of the available
+ space. It is these edge ticks that are used to locate the reference
+ cells position within the input raster. The integer after the
+ keyword
+ "XLIST" is the number of entries
+ in
+ the list. The first number in the column is the offset of the tick
+ from
+ the
+ origin, the second number is used to improve the correlation by
+ representing
+ the strength of that "tick" relative to the strongest tick which
+ will
+ have
+ a value 1.0. Strength is measured by the relative length of the
+ edge.<br>
+ <br>
+ The third number represents the relative number of times this "tick"
+ is
+ crossed by lines in the other direction. A line is regarded as
+ crossing
+ if part of it is closer to the "tick" line that half the distance to
+ the next tick line. The number is normalized so that the largest
+ crossing count has a weight of
+ 1.0. This may be set to 1.0 if it is not known or easily computed.<br>
+ <br>
+ A blank line should follow the last <b>XLIST</b> edge definition.<br>
+ <br>
+ The <b>YLIST</b> is same format and details as the <b>XLIST</b>,
+ used
+ for
+ horizontal edges.<br>
+ <br>
+ The <b>EXPECTED</b> keyword introduces an optional list of <span
+ style="text-decoration: underline;">approximate</span>
+ expected
+ sample
+ box color values, allowing better identification of the possible
+ rotation
+ of a chart, particularly if it has no asymmetric patch shapes or
+ locations
+ in the chart. Following the keyword should either be <b>XYZ</b> or
+ <b>LAB</b>,
+ depending on the color space used to describe the reference values,
+ then
+ an integer indicating the number of entries in the list.<br>
+ <br>
+ Each following expected color entry consists of four values. The
+ first
+ is
+ the sample box label, which should correspond to one of those
+ defined
+ by
+ the <b>BOXES</b> entry above. It is an error if no corresponding
+ box
+ has
+ been defined. The remaining three values are the <span
+ style="text-decoration: underline;">approximate</span> XYZ or
+ L*a*b*
+ color value expected for that sample box. The XYZ values are assumed
+ to
+ be
+ scaled to a maximum Y value of 100. An expected color value doesn't
+ have
+ to be provided for every defined sample box, nor is it expected to
+ be
+ accurate - it just has to represent the approximate expected color.
+ (Actual chart reference values are provided as a separate CGATS file
+ to
+ <a href="scanin.html"><span style="font-weight: bold;">scanin</span></a>).<br>
+ <br>
+ A blank line should follow the last <b>EXPECTED</b> box value.<br>
+ <br>
+ <br>
+ <hr size="2" width="100%"><br>
+ The following is an example .cht file, suitable for a typical Q60
+ IT8
+ scan target.<br>
+ <tt><br>
+ <font size="-1"> BOXES 290<br>
+ &nbsp; F _ _ _ _ 1 1&nbsp; 615.5 1.5&nbsp; 615 409<br>
+ &nbsp; D ALL ALL _ _ 615 409 1 1 0 0<br>
+ &nbsp; D MARK MARK _ _ 14 14 1 1 0 0<br>
+ &nbsp; Y 01 22 A L 25.625 25.625 26.625 26.625 25.625 25.625<br>
+ &nbsp; X GS00 GS23 _ _ 25.625 51.25 0.0 358.75 25.625 0.0<br>
+ <br>
+ BOX_SHRINK 3.0<br>
+ <br>
+ REF_ROTATION -0.002006<br>
+ <br>
+ XLIST 32<br>
+ &nbsp; 1.799625 1.000000 0.312500<br>
+ &nbsp; 27.064987 0.874039 0.750000<br>
+ &nbsp; 52.592403 0.133439 0.687500<br>
+ &nbsp; 78.196610 0.264191 0.687500<br>
+ &nbsp; 104.117756 0.165427 0.937500<br>
+ &nbsp; 129.377994 0.844432 0.937500<br>
+ &nbsp; 155.144274 0.501218 0.875000<br>
+ &nbsp; 180.839181 0.491428 0.937500<br>
+ &nbsp; 206.359758 0.212384 0.937500<br>
+ &nbsp; 232.038808 0.851851 0.937500<br>
+ &nbsp; 257.854725 0.162956 0.625000<br>
+ &nbsp; 283.552463 0.101243 0.812500<br>
+ &nbsp; 300.534000 0.024750 0.812500<br>
+ &nbsp; 309.507688 0.093829 1.000000<br>
+ &nbsp; 334.711314 0.856821 1.000000<br>
+ &nbsp; 360.428194 0.787677 1.000000<br>
+ &nbsp; 385.849730 0.748130 0.937500<br>
+ &nbsp; 386.650071 0.039487 0.687500<br>
+ &nbsp; 394.630372 0.024725 0.687500<br>
+ &nbsp; 411.835654 0.802501 0.750000<br>
+ &nbsp; 414.017731 0.041974 0.937500<br>
+ &nbsp; 437.133504 0.674062 0.937500<br>
+ &nbsp; 437.975355 0.103714 1.000000<br>
+ &nbsp; 462.938460 0.671643 1.000000<br>
+ &nbsp; 463.880560 0.093836 0.937500<br>
+ &nbsp; 488.517995 0.679022 1.000000<br>
+ &nbsp; 514.338544 0.760511 1.000000<br>
+ &nbsp; 540.037492 0.111108 0.625000<br>
+ &nbsp; 565.856396 0.133330 0.562500<br>
+ &nbsp; 591.114717 0.565475 0.562500<br>
+ &nbsp; 603.447516 0.032097 0.312500<br>
+ &nbsp; 615.984915 0.829608 0.250000<br>
+ <br>
+ YLIST 22<br>
+ &nbsp; 2.477956 0.993407 0.142857<br>
+ &nbsp; 12.988903 0.016393 0.190476<br>
+ &nbsp; 14.739109 0.036082 0.190476<br>
+ &nbsp; 26.746171 0.911487 0.428571<br>
+ &nbsp; 52.537114 0.303282 0.904762<br>
+ &nbsp; 78.060317 0.585303 0.857143<br>
+ &nbsp; 103.498271 0.606862 0.761905<br>
+ &nbsp; 128.994535 0.567266 0.761905<br>
+ &nbsp; 154.483041 0.550814 0.714286<br>
+ &nbsp; 179.935985 0.623055 0.666667<br>
+ &nbsp; 205.552940 0.350826 0.714286<br>
+ &nbsp; 212.051372 0.016393 0.714286<br>
+ &nbsp; 231.153547 0.824618 0.857143<br>
+ &nbsp; 256.697418 0.744268 0.952381<br>
+ &nbsp; 282.145841 0.736126 0.904762<br>
+ &nbsp; 307.899015 0.536075 0.952381<br>
+ &nbsp; 333.262903 0.903282 0.809524<br>
+ &nbsp; 340.217754 0.019722 0.190476<br>
+ &nbsp; 344.988867 0.019671 0.095238<br>
+ &nbsp; 346.988885 0.018032 0.095238<br>
+ &nbsp; 358.840278 0.999967 1.000000<br>
+ &nbsp; 409.201393 1.000000 0.000000<br>
+ <br>
+ EXPECTED XYZ 264<br>
+ &nbsp; A1&nbsp;&nbsp;&nbsp; 3.85 3.22 1.9<br>
+ &nbsp; A2&nbsp;&nbsp;&nbsp; 4.89 3.27 1.6<br>
+ &nbsp; A3&nbsp;&nbsp;&nbsp; 5.87 3.31 1.33<br>
+ &nbsp; A4&nbsp;&nbsp;&nbsp; 6.3 3.38 1.19<br>
+ &nbsp; A5&nbsp;&nbsp;&nbsp; 13.01 11.44 7.64<br>
+ &nbsp; A6&nbsp;&nbsp;&nbsp; 16.14 11.99 6.81<br>
+ &nbsp; A7&nbsp;&nbsp;&nbsp; 19.35 12.41 6.06<br>
+ &nbsp; A8&nbsp;&nbsp;&nbsp; 20.41 11.97 5.3<br>
+ &nbsp; A9&nbsp;&nbsp;&nbsp; 43.5 42.81 32.65<br>
+ &nbsp; A10&nbsp;&nbsp; 45.58 42.37 30.95<br>
+ &nbsp; A11&nbsp;&nbsp; 48.99 43.2 29.9<br>
+ &nbsp; A12&nbsp;&nbsp; 50.73 44.02 29.96<br>
+ &nbsp; A13&nbsp;&nbsp; 74.46 78.76 66.06<br>
+ &nbsp; A14&nbsp;&nbsp; 75.66 76.42 64.08<br>
+ &nbsp; A15&nbsp;&nbsp; 78.36 81.34 65.41<br>
+ &nbsp; A16&nbsp;&nbsp; 70.52 73.3 59.16<br>
+ &nbsp; A17&nbsp;&nbsp; 74.98 75.98 60.69<br>
+ &nbsp; A18&nbsp;&nbsp; 72.85 77.3 60.25<br>
+ &nbsp; A19&nbsp;&nbsp; 73.09 75.52 64.54<br>
+ &nbsp; B1&nbsp;&nbsp;&nbsp; 3.47 3.08 1.41<br>
+ &nbsp; B2&nbsp;&nbsp;&nbsp; 4.41 3.25 0.9<br>
+ &nbsp; B3&nbsp;&nbsp;&nbsp; 5.04 3.23 0.58<br>
+ &nbsp; B4&nbsp;&nbsp;&nbsp; 5.19 3.11 0.47<br>
+ &nbsp; B5&nbsp;&nbsp;&nbsp; 13.36 11.59 5.56<br>
+ &nbsp; B6&nbsp;&nbsp;&nbsp; 15.97 12.03 3.69<br>
+ &nbsp; B7&nbsp;&nbsp;&nbsp; 19.2 12.49 2.2<br>
+ &nbsp; B8&nbsp;&nbsp;&nbsp; 19.73 11.52 1.17<br>
+ &nbsp; B9&nbsp;&nbsp;&nbsp; 42.19 41.84 29.34<br>
+ &nbsp; B10&nbsp;&nbsp; 44.83 42.17 25.93<br>
+ &nbsp; B11&nbsp;&nbsp; 48.06 42.9 23.01<br>
+ &nbsp; B12&nbsp;&nbsp; 49.63 43.08 21.34<br>
+ &nbsp; B13&nbsp;&nbsp; 66.21 72.54 64.61<br>
+ &nbsp; B14&nbsp;&nbsp; 70.16 67.1 60.33<br>
+ &nbsp; B15&nbsp;&nbsp; 75.46 78.69 51.58<br>
+ &nbsp; B16&nbsp;&nbsp; 57.47 59.58 47.66<br>
+ &nbsp; B17&nbsp;&nbsp; 68.33 66.45 49.05<br>
+ &nbsp; B18&nbsp;&nbsp; 63.89 70.29 51.3<br>
+ &nbsp; B19&nbsp;&nbsp; 61.12 62.16 59.79<br>
+ &nbsp; C1&nbsp;&nbsp;&nbsp; 4.97 4.75 1.98<br>
+ &nbsp; C2&nbsp;&nbsp;&nbsp; 5.18 4.65 1.23<br>
+ &nbsp; C3&nbsp;&nbsp;&nbsp; 5.51 4.58 0.71<br>
+ &nbsp; C4&nbsp;&nbsp;&nbsp; 5.77 4.61 0.67<br>
+ &nbsp; C5&nbsp;&nbsp;&nbsp; 24.57 23.44 10.14<br>
+ &nbsp; C6&nbsp;&nbsp;&nbsp; 28.1 24.64 5.22<br>
+ &nbsp; C7&nbsp;&nbsp;&nbsp; 31.15 25.28 2.2<br>
+ &nbsp; C8&nbsp;&nbsp;&nbsp; 30.85 23.68 1.35<br>
+ &nbsp; C9&nbsp;&nbsp;&nbsp; 49.16 49.36 32.37<br>
+ &nbsp; C10&nbsp;&nbsp; 51.72 50.72 26.53<br>
+ &nbsp; C11&nbsp;&nbsp; 55.24 53.14 21.93<br>
+ &nbsp; C12&nbsp;&nbsp; 56.87 53.62 18.46<br>
+ &nbsp; C13&nbsp;&nbsp; 57.68 65.65 62.7<br>
+ &nbsp; C14&nbsp;&nbsp; 63.46 56.66 55.49<br>
+ &nbsp; C15&nbsp;&nbsp; 73 76.11 40.78<br>
+ &nbsp; C16&nbsp;&nbsp; 44.73 46.38 36.8<br>
+ &nbsp; C17&nbsp;&nbsp; 60.64 55.73 38.1<br>
+ &nbsp; C18&nbsp;&nbsp; 52.15 60.27 41.5<br>
+ &nbsp; C19&nbsp;&nbsp; 48.13 49.18 54.38<br>
+ &nbsp; D1&nbsp;&nbsp;&nbsp; 4.19 4.41 1.93<br>
+ &nbsp; D2&nbsp;&nbsp;&nbsp; 4.48 4.72 1.24<br>
+ &nbsp; D3&nbsp;&nbsp;&nbsp; 4.55 4.78 0.8<br>
+ &nbsp; D4&nbsp;&nbsp;&nbsp; 4.32 4.53 0.78<br>
+ &nbsp; D5&nbsp;&nbsp;&nbsp; 27.33 28.55 12.95<br>
+ &nbsp; D6&nbsp;&nbsp;&nbsp; 28.68 30.04 7.25<br>
+ &nbsp; D7&nbsp;&nbsp;&nbsp; 29.51 31.01 3.41<br>
+ &nbsp; D8&nbsp;&nbsp;&nbsp; 27.55 28.44 1.83<br>
+ &nbsp; D9&nbsp;&nbsp;&nbsp; 56.06 58.19 38.21<br>
+ &nbsp; D10&nbsp;&nbsp; 56.03 58.46 30.02<br>
+ &nbsp; D11&nbsp;&nbsp; 56.2 59.33 24.44<br>
+ &nbsp; D12&nbsp;&nbsp; 56.19 59.41 19.14<br>
+ &nbsp; D13&nbsp;&nbsp; 48.21 57.42 59.53<br>
+ &nbsp; D14&nbsp;&nbsp; 58.18 49.14 51.36<br>
+ &nbsp; D15&nbsp;&nbsp; 70.98 73.73 33.63<br>
+ &nbsp; D16&nbsp;&nbsp; 34.31 35.73 28.22<br>
+ &nbsp; D17&nbsp;&nbsp; 54.27 47.53 29.58<br>
+ &nbsp; D18&nbsp;&nbsp; 41.67 50.64 32.28<br>
+ &nbsp; D19&nbsp;&nbsp; 36.95 37.82 48.09<br>
+ &nbsp; E1&nbsp;&nbsp;&nbsp; 4.15 4.75 2.03<br>
+ &nbsp; E2&nbsp;&nbsp;&nbsp; 4 4.98 1.37<br>
+ &nbsp; E3&nbsp;&nbsp;&nbsp; 3.3 4.49 0.86<br>
+ &nbsp; E4&nbsp;&nbsp;&nbsp; 3.11 4.3 0.86<br>
+ &nbsp; E5&nbsp;&nbsp;&nbsp; 13.11 14.9 7.06<br>
+ &nbsp; E6&nbsp;&nbsp;&nbsp; 12.26 15.23 4.18<br>
+ &nbsp; E7&nbsp;&nbsp;&nbsp; 11.53 15.57 2.27<br>
+ &nbsp; E8&nbsp;&nbsp;&nbsp; 9.69 13.74 1.51<br>
+ &nbsp; E9&nbsp;&nbsp;&nbsp; 39.15 42.08 27.33<br>
+ &nbsp; E10&nbsp;&nbsp; 37.43 41.51 22.23<br>
+ &nbsp; E11&nbsp;&nbsp; 36.99 42.5 18.85<br>
+ &nbsp; E12&nbsp;&nbsp; 36.4 42.58 16.27<br>
+ &nbsp; E13&nbsp;&nbsp; 39.97 49.81 56.15<br>
+ &nbsp; E14&nbsp;&nbsp; 52.08 41.07 46.36<br>
+ &nbsp; E15&nbsp;&nbsp; 68.71 70.76 26.45<br>
+ &nbsp; E16&nbsp;&nbsp; 25.7 26.97 21.28<br>
+ &nbsp; E17&nbsp;&nbsp; 48.53 40.6 22<br>
+ &nbsp; E18&nbsp;&nbsp; 31.62 40.82 23.35<br>
+ &nbsp; E19&nbsp;&nbsp; 31.19 31.19 43.4<br>
+ &nbsp; F1&nbsp;&nbsp;&nbsp; 1.51 1.91 1.06<br>
+ &nbsp; F2&nbsp;&nbsp;&nbsp; 1.29 2.04 0.98<br>
+ &nbsp; F3&nbsp;&nbsp;&nbsp; 1.16 2.09 0.82<br>
+ &nbsp; F4&nbsp;&nbsp;&nbsp; 1.14 2.04 0.8<br>
+ &nbsp; F5&nbsp;&nbsp;&nbsp; 6.53 8.25 5.13<br>
+ &nbsp; F6&nbsp;&nbsp;&nbsp; 5.61 8.66 4.38<br>
+ &nbsp; F7&nbsp;&nbsp;&nbsp; 4.6 8.77 3.7<br>
+ &nbsp; F8&nbsp;&nbsp;&nbsp; 3.45 7.63 2.78<br>
+ &nbsp; F9&nbsp;&nbsp;&nbsp; 37.8 41.07 30.91<br>
+ &nbsp; F10&nbsp;&nbsp; 35.92 40.76 29.03<br>
+ &nbsp; F11&nbsp;&nbsp; 35.42 41.99 29.07<br>
+ &nbsp; F12&nbsp;&nbsp; 34 41.8 28<br>
+ &nbsp; F13&nbsp;&nbsp; 32.13 42.12 51.99<br>
+ &nbsp; F14&nbsp;&nbsp; 45.72 33.34 40.77<br>
+ &nbsp; F15&nbsp;&nbsp; 66.26 67.29 19.65<br>
+ &nbsp; F16&nbsp;&nbsp; 17.02 18.07 14.4<br>
+ &nbsp; F17&nbsp;&nbsp; 41.59 32.53 15.16<br>
+ &nbsp; F18&nbsp;&nbsp; 26.26 35.26 18.81<br>
+ &nbsp; F19&nbsp;&nbsp; 24.3 23.6 37.48<br>
+ &nbsp; G1&nbsp;&nbsp;&nbsp; 2.31 3 2.27<br>
+ &nbsp; G2&nbsp;&nbsp;&nbsp; 2 3.21 2.58<br>
+ &nbsp; G3&nbsp;&nbsp;&nbsp; 1.66 3.21 2.75<br>
+ &nbsp; G4&nbsp;&nbsp;&nbsp; 1.58 3.03 2.6<br>
+ &nbsp; G5&nbsp;&nbsp;&nbsp; 8.99 11.08 8.79<br>
+ &nbsp; G6&nbsp;&nbsp;&nbsp; 7.68 11.3 9.56<br>
+ &nbsp; G7&nbsp;&nbsp;&nbsp; 6.52 11.5 10.2<br>
+ &nbsp; G8&nbsp;&nbsp;&nbsp; 5.5 10.85 10.55<br>
+ &nbsp; G9&nbsp;&nbsp;&nbsp; 38.29 41.75 33.45<br>
+ &nbsp; G10&nbsp;&nbsp; 35.83 41.16 34.11<br>
+ &nbsp; G11&nbsp;&nbsp; 34.56 41.83 35.63<br>
+ &nbsp; G12&nbsp;&nbsp; 33.69 42.14 36.7<br>
+ &nbsp; G13&nbsp;&nbsp; 25.95 35.68 48<br>
+ &nbsp; G14&nbsp;&nbsp; 40.6 27.62 36.14<br>
+ &nbsp; G15&nbsp;&nbsp; 63.72 63.63 14.35<br>
+ &nbsp; G16&nbsp;&nbsp; 10.85 11.82 9.58<br>
+ &nbsp; G17&nbsp;&nbsp; 37.23 27.64 11.62<br>
+ &nbsp; G18&nbsp;&nbsp; 20.28 28.97 14.15<br>
+ &nbsp; G19&nbsp;&nbsp; 17.7 16.74 31.7<br>
+ &nbsp; H1&nbsp;&nbsp;&nbsp; 2.56 3.04 2.92<br>
+ &nbsp; H2&nbsp;&nbsp;&nbsp; 2.34 3.2 4.12<br>
+ &nbsp; H3&nbsp;&nbsp;&nbsp; 2.12 3.28 5.43<br>
+ &nbsp; H4&nbsp;&nbsp;&nbsp; 2.06 3.18 5.29<br>
+ &nbsp; H5&nbsp;&nbsp;&nbsp; 10.07 11.6 11.24<br>
+ &nbsp; H6&nbsp;&nbsp;&nbsp; 9.01 11.68 14.81<br>
+ &nbsp; H7&nbsp;&nbsp;&nbsp; 8.22 12 19.42<br>
+ &nbsp; H8&nbsp;&nbsp;&nbsp; 7.25 11.55 21.45<br>
+ &nbsp; H9&nbsp;&nbsp;&nbsp; 39.25 42.31 36.81<br>
+ &nbsp; H10&nbsp;&nbsp; 37.58 41.85 40.37<br>
+ &nbsp; H11&nbsp;&nbsp; 37.16 43.07 45.79<br>
+ &nbsp; H12&nbsp;&nbsp; 36.27 43.78 49.47<br>
+ &nbsp; H13&nbsp;&nbsp; 21.47 30.78 44.22<br>
+ &nbsp; H14&nbsp;&nbsp; 36.49 23.35 32.38<br>
+ &nbsp; H15&nbsp;&nbsp; 61.58 60.55 10.95<br>
+ &nbsp; H16&nbsp;&nbsp; 8.21 8.71 6.91<br>
+ &nbsp; H17&nbsp;&nbsp; 33.04 23.26 8.38<br>
+ &nbsp; H18&nbsp;&nbsp; 16.22 24.35 10.41<br>
+ &nbsp; H19&nbsp;&nbsp; 12.86 11.84 26.82<br>
+ &nbsp; I1&nbsp;&nbsp;&nbsp; 4.22 4.44 5.28<br>
+ &nbsp; I2&nbsp;&nbsp;&nbsp; 4.35 4.48 8.36<br>
+ &nbsp; I3&nbsp;&nbsp;&nbsp; 4.4 4.44 11.94<br>
+ &nbsp; I4&nbsp;&nbsp;&nbsp; 4.48 4.58 12.17<br>
+ &nbsp; I5&nbsp;&nbsp;&nbsp; 15.15 15.78 15.23<br>
+ &nbsp; I6&nbsp;&nbsp;&nbsp; 14.56 15.12 19.52<br>
+ &nbsp; I7&nbsp;&nbsp;&nbsp; 14.37 14.81 24.48<br>
+ &nbsp; I8&nbsp;&nbsp;&nbsp; 14.11 14.76 30.03<br>
+ &nbsp; I9&nbsp;&nbsp;&nbsp; 41.03 42.58 36.94<br>
+ &nbsp; I10&nbsp;&nbsp; 40.85 42.23 40.73<br>
+ &nbsp; I11&nbsp;&nbsp; 40.86 42.33 45.05<br>
+ &nbsp; I12&nbsp;&nbsp; 41.31 42.73 47.77<br>
+ &nbsp; I13&nbsp;&nbsp; 17.26 25.93 40.23<br>
+ &nbsp; I14&nbsp;&nbsp; 32.66 19.63 28.81<br>
+ &nbsp; I15&nbsp;&nbsp; 59.37 57.18 7.79<br>
+ &nbsp; I16&nbsp;&nbsp; 4.97 5.32 4.32<br>
+ &nbsp; I17&nbsp;&nbsp; 28.62 18.88 5.48<br>
+ &nbsp; I18&nbsp;&nbsp; 11.58 18.98 7.25<br>
+ &nbsp; I19&nbsp;&nbsp; 9.58 8.34 22.87<br>
+ &nbsp; I20&nbsp;&nbsp; 0.45 0.4 0.33<br>
+ &nbsp; I21&nbsp;&nbsp; 2.28 1.78 0.98<br>
+ &nbsp; I22&nbsp;&nbsp; 2.37 1.95 0.85<br>
+ &nbsp; J1&nbsp;&nbsp;&nbsp; 2.15 1.9 2.6<br>
+ &nbsp; J2&nbsp;&nbsp;&nbsp; 2.57 2 4.72<br>
+ &nbsp; J3&nbsp;&nbsp;&nbsp; 2.93 1.95 8.1<br>
+ &nbsp; J4&nbsp;&nbsp;&nbsp; 3.15 1.92 10.76<br>
+ &nbsp; J5&nbsp;&nbsp;&nbsp; 11.73 11.6 11.81<br>
+ &nbsp; J6&nbsp;&nbsp;&nbsp; 12.98 11.93 16.19<br>
+ &nbsp; J7&nbsp;&nbsp;&nbsp; 13.91 12.07 20.95<br>
+ &nbsp; J8&nbsp;&nbsp;&nbsp; 14.01 11.59 24.35<br>
+ &nbsp; J9&nbsp;&nbsp;&nbsp; 40.75 41.22 36.34<br>
+ &nbsp; J10&nbsp;&nbsp; 41.26 41.07 39.74<br>
+ &nbsp; J11&nbsp;&nbsp; 42.63 41.68 44.51<br>
+ &nbsp; J12&nbsp;&nbsp; 44.02 41.78 49.25<br>
+ &nbsp; J13&nbsp;&nbsp; 13.82 21.69 35.98<br>
+ &nbsp; J14&nbsp;&nbsp; 28.87 16.33 25.08<br>
+ &nbsp; J15&nbsp;&nbsp; 56.04 52.29 4.97<br>
+ &nbsp; J16&nbsp;&nbsp; 2.46 2.63 2.29<br>
+ &nbsp; J17&nbsp;&nbsp; 24.04 14.75 3.15<br>
+ &nbsp; J18&nbsp;&nbsp; 8.12 14.49 4.55<br>
+ &nbsp; J19&nbsp;&nbsp; 5.98 4.79 17.76<br>
+ &nbsp; J20&nbsp;&nbsp; 8.26 5.37 1.04<br>
+ &nbsp; J21&nbsp;&nbsp; 11.52 7.81 1.62<br>
+ &nbsp; J22&nbsp;&nbsp; 14.67 10.72 2.6<br>
+ &nbsp; K1&nbsp;&nbsp;&nbsp; 5.63 4.7 4.86<br>
+ &nbsp; K2&nbsp;&nbsp;&nbsp; 6.74 4.58 7.23<br>
+ &nbsp; K3&nbsp;&nbsp;&nbsp; 8.04 4.48 9.73<br>
+ &nbsp; K4&nbsp;&nbsp;&nbsp; 9.39 4.76 11.79<br>
+ &nbsp; K5&nbsp;&nbsp;&nbsp; 16.66 15.39 14.44<br>
+ &nbsp; K6&nbsp;&nbsp;&nbsp; 18.72 15.18 18.23<br>
+ &nbsp; K7&nbsp;&nbsp;&nbsp; 21.56 15.5 22.97<br>
+ &nbsp; K8&nbsp;&nbsp;&nbsp; 23 15.02 25.37<br>
+ &nbsp; K9&nbsp;&nbsp;&nbsp; 42.5 42.02 36.05<br>
+ &nbsp; K10&nbsp;&nbsp; 44.55 41.63 39.71<br>
+ &nbsp; K11&nbsp;&nbsp; 47.19 41.96 44.03<br>
+ &nbsp; K12&nbsp;&nbsp; 49.9 43.14 47.21<br>
+ &nbsp; K13&nbsp;&nbsp; 10.61 17.44 31.24<br>
+ &nbsp; K14&nbsp;&nbsp; 24.84 13.19 21<br>
+ &nbsp; K15&nbsp;&nbsp; 53.12 48.05 3.19<br>
+ &nbsp; K16&nbsp;&nbsp; 1.05 1.14 1.13<br>
+ &nbsp; K17&nbsp;&nbsp; 19.93 11.34 1.67<br>
+ &nbsp; K18&nbsp;&nbsp; 5.3 10.47 2.73<br>
+ &nbsp; K19&nbsp;&nbsp; 3.95 2.76 13.94<br>
+ &nbsp; K20&nbsp;&nbsp; 30.61 26.43 11.04<br>
+ &nbsp; K21&nbsp;&nbsp; 34.91 29.6 11.78<br>
+ &nbsp; K22&nbsp;&nbsp; 38.95 34.57 18.4<br>
+ &nbsp; L1&nbsp;&nbsp;&nbsp; 3.88 3.12 2.32<br>
+ &nbsp; L2&nbsp;&nbsp;&nbsp; 4.93 3.2 2.69<br>
+ &nbsp; L3&nbsp;&nbsp;&nbsp; 5.75 3.14 3.02<br>
+ &nbsp; L4&nbsp;&nbsp;&nbsp; 7.31 3.79 3.4<br>
+ &nbsp; L5&nbsp;&nbsp;&nbsp; 13.29 11.54 9.39<br>
+ &nbsp; L6&nbsp;&nbsp;&nbsp; 16.22 11.73 10.32<br>
+ &nbsp; L7&nbsp;&nbsp;&nbsp; 19.95 12.08 12.06<br>
+ &nbsp; L8&nbsp;&nbsp;&nbsp; 20.79 11.31 12.01<br>
+ &nbsp; L9&nbsp;&nbsp;&nbsp; 43.22 42.09 33.78<br>
+ &nbsp; L10&nbsp;&nbsp; 45.52 41.88 34.65<br>
+ &nbsp; L11&nbsp;&nbsp; 49.04 42.87 35.98<br>
+ &nbsp; L12&nbsp;&nbsp; 51.03 43.83 37.78<br>
+ &nbsp; L13&nbsp;&nbsp; 7.45 12.77 25.59<br>
+ &nbsp; L14&nbsp;&nbsp; 21.26 10.76 17.73<br>
+ &nbsp; L15&nbsp;&nbsp; 49.45 43.12 2.14<br>
+ &nbsp; L16&nbsp;&nbsp; 0.47 0.49 0.5<br>
+ &nbsp; L17&nbsp;&nbsp; 16.04 8.49 0.78<br>
+ &nbsp; L18&nbsp;&nbsp; 2.91 6.5 1.39<br>
+ &nbsp; L19&nbsp;&nbsp; 2.5 1.45 10.28<br>
+ &nbsp; L20&nbsp;&nbsp; 38.7 33.98 20.86<br>
+ &nbsp; L21&nbsp;&nbsp; 39.36 35.23 21.23<br>
+ &nbsp; L22&nbsp;&nbsp; 41.36 38.77 23.51<br>
+ &nbsp; GS0&nbsp;&nbsp;&nbsp; 79.47 82.51 69.04<br>
+ &nbsp; GS1&nbsp;&nbsp;&nbsp; 72.62 74.94 59.17<br>
+ &nbsp; GS2&nbsp;&nbsp;&nbsp; 63.15 65.11 51.57<br>
+ &nbsp; GS3&nbsp;&nbsp;&nbsp; 54.72 56.51 45.03<br>
+ &nbsp; GS4&nbsp;&nbsp;&nbsp; 48.1 49.81 39.24<br>
+ &nbsp; GS5&nbsp;&nbsp;&nbsp; 42.22 43.64 34.45<br>
+ &nbsp; GS6&nbsp;&nbsp;&nbsp; 37.33 38.7 30.5<br>
+ &nbsp; GS7&nbsp;&nbsp;&nbsp; 32.38 33.61 26.11<br>
+ &nbsp; GS8&nbsp;&nbsp;&nbsp; 27.56 28.7 22.11<br>
+ &nbsp; GS9&nbsp;&nbsp;&nbsp; 22.5 23.4 17.99<br>
+ &nbsp; GS10&nbsp;&nbsp; 18.77 19.55 14.83<br>
+ &nbsp; GS11&nbsp;&nbsp; 15.48 16.08 12.04<br>
+ &nbsp; GS12&nbsp;&nbsp; 12.69 13.29 9.98<br>
+ &nbsp; GS13&nbsp;&nbsp; 10.35 10.81 7.97<br>
+ &nbsp; GS14&nbsp;&nbsp; 8.39 8.77 6.37<br>
+ &nbsp; GS15&nbsp;&nbsp; 6.45 6.79 4.97<br>
+ &nbsp; GS16&nbsp;&nbsp; 4.95 5.18 3.7<br>
+ &nbsp; GS17&nbsp;&nbsp; 3.58 3.82 2.76<br>
+ &nbsp; GS18&nbsp;&nbsp; 2.76 2.89 2.06<br>
+ &nbsp; GS19&nbsp;&nbsp; 1.97 2.08 1.45<br>
+ &nbsp; GS20&nbsp;&nbsp; 1.22 1.31 0.98<br>
+ &nbsp; GS21&nbsp;&nbsp; 1 1.05 0.74<br>
+ &nbsp; GS22&nbsp;&nbsp; 0.87 0.89 0.65<br>
+ &nbsp; GS23&nbsp;&nbsp; 0.34 0.32 0.32<br>
+ <br>
+ </font> </tt><br>
+ <tt> <br>
+ </tt><br>
+ <br>
+ </body>
</html>
diff --git a/doc/collink.html b/doc/collink.html
index 0b94bc7..778b682 100644
--- a/doc/collink.html
+++ b/doc/collink.html
@@ -27,6 +27,30 @@
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Verbose<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#A">-A "manufacturer"</a><span
@@ -57,6 +81,30 @@ Verify
existing
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
profile, rather than link (Debug option)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -71,6 +119,30 @@ Override
clut
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
res. set by -q</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#n">-n</a><span
@@ -79,6 +151,30 @@ Don't
preserve
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
device curves in result</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -112,15 +208,73 @@ preserve
Include
- abstract profile in link</span><br style="font-family:
- monospace;">
- <span style="font-family: monospace;">&nbsp;</span><a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ abstract profile in link</span></small><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#a">-a file.cal</a><span
+ style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Apply calibration
+ curves</span></small> to link output and append linear<br>
+ &nbsp;<a href="H">-H file.cal</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+ Append calibration curves to 3dlut<br style="font-family:
+ monospace;">
+ </span> <span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#s">-s</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Simple
Mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
(default)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#g">-g [src.gam]</a><span
@@ -133,6 +287,30 @@ Mode
Gamut
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Mapping Mode using inverse outprofile A2B [optional source
gamut]</span><br style="font-family: monospace;">
<br style="font-family: monospace;">
@@ -149,6 +327,30 @@ Gamut
s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= saturation, a = absolute colorimetric</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -162,6 +364,30 @@ s
s
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= saturation, a = absolute colorimetric</span><br
style="font-family: monospace;">
<br style="font-family: monospace;">
@@ -178,12 +404,60 @@ a
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Absolute Colorimetric (in Jab) [ICC Absolute Colorimetric]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
aw
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Absolute Colorimetric (in Jab) with scaling to fit white point<br
style="font-family: monospace;">
</span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -191,12 +465,60 @@ aa
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Absolute Appearance</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
r
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
White Point Matched Appearance [ICC Relative Colorimetric]</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -204,6 +526,30 @@ la
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Luminance matched Appearance</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -211,11 +557,59 @@ p
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Perceptual (Preferred) [ICC Perceptual]<br>
</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
pa
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Perceptual Appearance</span></small><br style="font-family:
monospace;">
<small><span style="font-family: monospace;"></span><span
@@ -224,12 +618,60 @@ ms
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Saturation</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
s
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Enhanced Saturation [ICC Saturation]</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -237,8 +679,56 @@ al
-
- Absolute Colorimetric (Lab)</span><span style="font-family:
- monospace;"></span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Absolute Colorimetric (Lab)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ rl - White Point Matched Colorimetric (Lab)</span><span
+ style="font-family: monospace;"></span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#w">-w [J,a,b]</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; Use forced
@@ -254,6 +744,30 @@ al
either
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
an enumerated choice, or a parameter</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -266,6 +780,30 @@ either
either
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
an enumerated choice, or a parameter:value change<br>
</span></small><small><span style="font-family: monospace;">&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pp - Practical
@@ -276,12 +814,60 @@ either
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; pe - Print evaluation environment (CIE 116-1995)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; pc - Critical print evaluation environment (ISO-3664 P1)</span></small><small><span
style="font-family: monospace;"></span><span style="font-family:
monospace;"></span><span style="font-family: monospace;"></span><span
@@ -296,6 +882,30 @@ either
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
mb - Monitor in bright work environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
@@ -321,6 +931,30 @@ s:surround
n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= auto, a = average, m = dim, d = dark,</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -328,6 +962,30 @@ n
&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
c = transparency (default average)</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -335,6 +993,30 @@ w:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Adapted
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
white point as XYZ (default media white)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -342,12 +1024,60 @@ w:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Adapted
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
white point as x, y</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
a:adaptation&nbsp;
Adaptatation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
luminance in cd.m^2 (default 50.0)</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -356,30 +1086,105 @@ Background
%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
of image luminance (default 20)<br>
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; l:scenewhite&nbsp;
- Scene white in cd.m^2 if surround = auto (default 250)<br
- style="font-family: monospace;">
- </span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; l:imagewhite&nbsp;
+ Image white in cd.m^2 if surround = auto (default 250)</span></small><br
+ style="font-family: monospace;">
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
f:flare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Flare
light
- % of image luminance (default 1)</span><br style="font-family:
- monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ % of image luminance (default 0)<br>
+ </span></small>&nbsp;</span><span style="font-family:
+ monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ g:glare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare light % of
+ ambient (default 1)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-f:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Flare
- color as XYZ (default media white)</span><br style="font-family:
- monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ g:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color as XYZ
+ (default media white)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Flare
+
+
+
+
+
+
+
+
+
+
+
+
+
+ g:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare
color as x, y</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#t">-t <i>tlimit</i></a><span
@@ -388,6 +1193,30 @@ set
source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
total ink limit, 0 - 400% (estimate by default)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -397,6 +1226,30 @@ set
source
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
total ink limit, 0 - 100% (estimate by default)</span><br
style="font-family: monospace;">
<br style="font-family: monospace;">
@@ -413,6 +1266,30 @@ source
t
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= transfer K from source to destination, e = retain K of
destination B2A table</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -420,6 +1297,30 @@ t
z
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= zero K, h = 0.5 K, x = maximum K, r = ramp K (default)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -430,6 +1331,30 @@ z
p
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= black level generation curve parameters</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -441,6 +1366,30 @@ p
q
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= transfer source K to dual curve limits</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -455,6 +1404,30 @@ set
destination
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
total ink limit, 0 - 400% (estimate by default)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -464,16 +1437,349 @@ set
destination
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
total ink limit, 0 - 100% (estimate by default)<br>
- </span></small>&nbsp;&nbsp;<small><span style="font-family:
- monospace;"><a href="#P">-P</a>
+ &nbsp;<a href="#3">-3 flag</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create "3DLut" output file as well as devlink<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ e&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ eeColor .txt file</span></small><br>
+ <tt>&nbsp;&nbsp;&nbsp;&nbsp;
+ m&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+ MadVR .3dlut&nbsp;&nbsp; file</tt><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;<a href="#Ib">-I b</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply BT.1886-like mapping with effective gamma 2.2 to input</span></small><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;<a href="#Ib">-I
+ b:g.g</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply BT.1886-like mapping with effective gamma g.g to
+ input<br>
+ </span></small></span></small>&nbsp;<a href="#IB">-I B</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply BT.1886 mapping with technical gamma 2.4 to input</span></small><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;<a href="#IB">-I B:g.g</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply BT.1886-like mapping with technical gamma g.g to input<br>
+ </span></small>&nbsp;<a href="#e">-e flag</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Video encode input as:<br>
+ &nbsp;<a href="#E">-E flag</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Video encode output as:</span></small><small><span
+ style="font-family: monospace;"><small><span style="font-family:
+ monospace;"><br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ normal RGB 0..1 levels (default)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ RGB (16-235)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec601 YCbCr SD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec709 1125/60Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec709 1250/50Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec2020 YCbCr UHD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 "TV"
+ levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ xvYCC Rec601 YCbCr Rec709 Prims. SD (16-235,240)/255 "TV"
+ levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ xvYCC Rec709 YCbCr Rec709 Prims. HD (16-235,240)/255 "TV"
+ levels<br>
+ </span></small>&nbsp;</span></small>&nbsp; <small><span
+ style="font-family: monospace;"><a href="#P">-P</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Create
gamut
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
gammap_p.wrl and gammap_s.wrl diagostics</span></small><small><br>
- <br>
<span style="font-family: monospace;"></span></small><span
style="font-family: monospace;">&nbsp;<span
style="text-decoration: underline;"><span style="font-style:
@@ -484,9 +1790,57 @@ source
ICC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
profile. A </span><small><span style="font-family: monospace;">TIFF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
or JPEG file with embedded profile may be used here.</span></small><br
style="font-family: monospace;">
&nbsp; <span style="font-family: monospace;"><span
@@ -498,6 +1852,30 @@ destination
ICC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
profile. </span><span style="font-family: monospace;">A </span><small><span
style="font-family: monospace;">TIFF or JPEG file with embedded
profile may be used here.</span></small><br style="font-family:
@@ -570,6 +1948,30 @@ ICC
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp;Override clut res. set by <b>-q</b><br>
<br>
This sets the basic quality of the resulting link, by choosing the
@@ -644,13 +2046,28 @@ ICC
conflict with achieving a smooth mapping, warnings messages will be
emitted.<br>
<br>
- <a name="p"></a> The <b>-p</b> option alows specifying an abstract
- profile be applied between the source and destination profiles. An
- abstract profile is a way of specifying a color adjustment in a
- device independent way. The abstract profile might have been created
- using one of the <span style="font-weight: bold;">tweak</span>
+ <a name="p"></a> The <b>-p</b> parameter allows specifying an
+ abstract profile be applied between the source and destination
+ profiles. An abstract profile is a way of specifying a color
+ adjustment in a device independent way. The abstract profile might
+ have been created using one of the <span style="font-weight: bold;">tweak</span>
tools, such as <a href="refine.html">refine</a>.<br>
<br>
+ <a name="a"></a> The <b>-a</b> parameter causes calibration curves
+ in the supplied file to be applied after the link of the profiles.
+ This is used as an alternative to calibration curves being loaded
+ into the graphics card VideoLut. For MadVR 3dlut output, a linear
+ set of calibration curves will also be appended to the 3dlut,
+ ensuring that the correct VideoLUT curves get loaded at the time the
+ 3dLut is used by MadVR v0.86.9 or latter. By default no calibration
+ curves are appended to a MadVR 3dLut.<br>
+ <br>
+ <a name="H"></a> The <b>-H</b> parameter causes calibration curves
+ in the supplied file to be appended to a MadVR 3dlut output,
+ ensuring that the correct VideoLUT curves get loaded at the time the
+ 3dLut is used by MadVR v0.86.9 or latter. By default no calibration
+ curves are appended to a MadVR 3dLut.<br>
+ <br>
The basic linking style is chosen by using the <b>-s</b> (default),
<b>-g</b> or <b>-G</b> flags. The three behaviors are:<br>
<br>
@@ -698,6 +2115,30 @@ ICC
except the last one (no. <span style="font-weight: bold;">7</span>),
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
the space should be Jab appearance space, with the viewing
conditions generally being those of the source profile viewing
conditions. The source profile will normally be the one used to
@@ -710,6 +2151,30 @@ ICC
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp;<b>p</b> = perceptual, <b>r</b> = relative colorimetric,<br>
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <b>s</b>
@@ -778,10 +2243,10 @@ ICC
<br>
<a name="ila"></a>The <span style="font-weight: bold;">la</span>
intent, Luminance matched appearance, linearly compresses or
- expands the the luminance axis to match the source to the
- destination space, while not otherwise altering the gamut,
- clipping any out of gamut colors to the closest match. This is
- often useful for appearance based soft proofing.<br>
+ expands the the luminance axis from white to black to match the
+ source to the destination space, while not otherwise altering the
+ gamut, clipping any out of gamut colors to the closest match. This
+ is often useful for appearance based soft proofing.<br>
<br>
<a name="ip"></a>The&nbsp; <span style="font-weight: bold;">p</span>
intent, Perceptual, uses "knee" type 3 Dimensional compression to
@@ -816,11 +2281,18 @@ ICC
The white point is mapped precisely from source to destination.<br>
<br>
<a name="ial"></a>The <span style="font-weight: bold;">al</span>
- intent, Absolute Appearance (Lab), is similar to intent <span
- style="font-weight: bold;">a</span>, but L*a*b* colorspace is
- used rather than CIECAM02 Jab appearance space. This often leads
- to poor reproduction of blue and red hues, but can be useful as a
- reference mapping.<br>
+ intent, Absolute Colorimetric (Lab), is similar to intent <span
+ style="font-weight: bold;">a</span>, but <b>L*a*b*</b>
+ colorspace is used rather than CIECAM02 Jab appearance space. This
+ often leads to poor reproduction of blue and red hues, but can be
+ useful as a reference mapping.<br>
+ <br>
+ <a name="iar"></a>The <span style="font-weight: bold;">ar</span>
+ intent, White Point Matched Colorimetric (Lab), is similar to
+ intent <span style="font-weight: bold;">r</span>, but L*a*b*
+ colorspace is used rather than CIECAM02 Jab appearance space. This
+ often leads to poor reproduction of blue and red hues, but can be
+ useful as a reference mapping.<br>
</div>
<br>
<a name="w"></a> The <b>-w</b> flag forces the white points to be
@@ -919,30 +2391,150 @@ ICC
&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp;_______&nbsp; enle<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp;/<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; /<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp;/<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
stle&nbsp; | ------/<br>
@@ -955,6 +2547,30 @@ ICC
White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Black<br>
<br>
</tt>For minimum sensitivity of printed output to the lighting
@@ -1023,6 +2639,243 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
in final calibrated device values if the profile includes
calibration information.<br>
<br>
+ <a name="3"></a>The <b>-3</b> <i>flag</i> triggers creation of a
+ "3dLut" of one of the following formats:<br>
+ &nbsp;&nbsp;&nbsp; <b>e</b>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <a
+ href="http://www.eecolor.com/">eeColor </a>format ".txt" files.
+ This includes 3 input curve files, the cLut file and 3 output curve
+ files.<br>
+ &nbsp;&nbsp;&nbsp; <b>m</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a
+ href="http://forum.doom9.org/showthread.php?t=146228&amp;page=22">MadVR</a>
+ format ".3dlut" file.<br>
+ <br>
+ Some hardware devices and other software make use of cLUT type
+ tables that are analogous to ICC device links, but are typically
+ less sophisticated and flexible. The <b>-3</b> flag allows creation
+ of some of these file formats as well as the normal ICC device link.
+ Choosing one of these formats will typically also configure various
+ other parameters to default values suitable for that format, such as
+ the&nbsp; table resolution (<b>-r</b>), and the use of 1D input and
+ output curves (<b>-n</b>). Other parameters (such as <b>-I</b>, <b>-e</b>
+ and <b>-E</b>) may have to be set to get a table suitable for the
+ particular target and situation.<br>
+ <br>
+ The <b>-3 e</b> eeColor format is basically a 65^3 cLUT, but the
+ hardware is unable to map a 1.0 input value to anything other than
+ 1.0 output. If one of the video input encodings is being used (<b>-e
+ t</b> or <b>-e 7</b> etc.), then this is not an issued, since a
+ 1.0 input is not used for image data. For normal (full) input range
+ (ie. if the eeColor is being used to process the output of a
+ computer Video card, and the video card is not encoding using TV
+ values), then this is a problem, and collink will compensate for
+ this by creating a set of per channel input curve files that can be
+ loaded into the eeColor. The xvYCC encoding (<b>-e x</b> and <b>-e
+ X</b>) uses almost the full range of values for the Cb &amp; Cr
+ values, and also needs per channel input curves to allow a full
+ range of mapping.<br>
+ <br>
+ &nbsp;For this reason collink generates the following 7 files:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; basename-first1dred.txt<br>
+ &nbsp;&nbsp;&nbsp; basename-first1dgreen.txt<br>
+ &nbsp;&nbsp;&nbsp; basename-first1dblue.txt<br>
+ &nbsp;&nbsp;&nbsp; test.txt <br>
+ &nbsp;&nbsp;&nbsp; basename-second1dred.txt<br>
+ &nbsp;&nbsp;&nbsp; basename-second1dgreen.txt<br>
+ &nbsp;&nbsp;&nbsp; basename-second1dblue.txt<br>
+ <br>
+ even though the 1d files will be linear for all cases except the
+ normal and xvYCC input range.<br>
+ <br>
+ The MadVR format is an 8 bit input, 16 bit output cLUT of 100 Mbytes
+ size, and will written to the file <b>basename.3dlut</b>. If the -a
+ or -H options are used, then the MadVR 3dLut will have a set of
+ appropriate per channel calibration curves appended to the 3dLut, to
+ ensure that the hardware is correctly set for it if used with MadVR
+ V0.86.9 or latter. This functionality is analogous to a 'VCGT' tag
+ in a normal ICC display profile.<br>
+ <br>
+ There is more information on the <a href="Scenarios.html">Typical
+ Usage Scenarios</a> page.<br>
+ <b><br>
+ <a name="Ib"></a></b>The <b>-I b</b> flag applies extra input
+ processing, applying <a
+ href="http://www.itu.int/rec/R-REC-BT.1886-0-201103-I">BT.1886</a>-like
+
+
+
+
+
+
+
+
+
+
+
+
+
+ video gamma mapping using an effective gamma of 2.2 by default, and
+ overridable using <b>-I b:g.g</b> where <b>g.g</b> is the gamma.
+ The gamma is an effective gamma, meaning that its effect on 50%
+ input is the same as that of a pure power curve, in spite of any
+ black offset added by BT.1886. This has the benefit of making the
+ overall effect of brightness independent of the black level of the
+ display. Setting an effective gamma other than 2.2 is one way of
+ making the viewing condition adjustment for the different conditions
+ of video encoding and decoding, or for modelling the source
+ colorspace as a rendering on a video display. This would be used as
+ an alternative to using gamut mapping mode and setting explicit
+ input and output viewing conditions, or in combination with
+ appearance adjustments. BT.1886 will only work with matrix type
+ input profiles. The default value of 2.2 is probably suitable for
+ dim viewing conditions, and it may be desirable to override this
+ default if your viewing conditions are darker or lighter. For
+ lighter conditions, try "-I b:2.2". For darker conditions, try "-I
+ b:2.6".<br>
+ <br>
+ <b><a name="IB"></a></b>The <b>-I B</b> flag applies extra input
+ processing, applying <a
+ href="http://www.itu.int/rec/R-REC-BT.1886-0-201103-I">BT.1886</a>
+ video gamma mapping using the BT.1886 gamma of 2.4 by default, and
+ overridable using <b>-I b:g.g</b> where <b>g.g</b> is the gamma.
+ The gamma is the technical gamma, or power applied to the input
+ image, and this means that its effect on 50% input will depend on
+ the black level of the display, making the overall brightness
+ somewhat unpredictable. For a more predictable effect, use <b>-I b</b>.<br>
+ <b><br>
+ <a name="e"></a></b>The <b>-e</b> <i>flag</i> applies a Video
+ encoding to the input. See below<b> and</b> <a href="#E"><b>-E</b></a>
+ for the list of encodings.<br>
+ <br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ xvYCC Rec601 YCbCr Rec709 Prims. SD (16-235,240)/255 "TV"
+ levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ xvYCC Rec709 YCbCr Rec709 Prims. HD (16-235,240)/255 "TV"
+ levels</span></small></span></small><br>
+ <br>
+ When xvYCC is chosen, the encoding is either a Rec601 YCbCr or
+ Rec709 YCbCr with extended range Cb and Cr values, and a hard coded
+ Rec709 source colorspace, corresponding to the xvYCC specifications.
+ The <a href="#p1">source profile</a> provided to collink is used to
+ define the source gamut for gamut mapping, and also the space that
+ any <a href="#Ib">BT.1886</a> processing will be performed in. For
+ instance, if the xvYCC is being used to encode a larger gamut such
+ as UHD Rec2020, or Digital Cinema SMPTE431 P3, then the
+ corresponding ICC profile should be provided as the source profile.<br>
+ <br>
+ <b><a name="E"></a></b>The <b>-E</b> <i>flag</i> applies a Video
+ encoding to the output. The possible encoding are:<br>
+ <br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ normal RGB 0..1 full range levels (default)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ RGB (16-235)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec601 YCbCr SD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec709 1125/60Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec709 1250/50Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec2020 YCbCr UHD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+ Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 "TV"
+ levels<br>
+ </span></small></span></small><br>
+ <br>
<b><a name="P"></a></b>The <b>-P</b> option causes a diagnostic 3D
<a href="File_Formats.html#VRML">VRML</a> plots to be created that
illustrate the gamut mapping generated.<br>
@@ -1044,6 +2897,30 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
For information on typical usage, see the <a href="Scenarios.html">Typical
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Usage Scenarios</a> page.<br>
<br>
<br>
diff --git a/doc/colprof.html b/doc/colprof.html
index de9d5c2..022f984 100644
--- a/doc/colprof.html
+++ b/doc/colprof.html
@@ -3,7 +3,7 @@
<head>
<title>colprof</title>
<meta http-equiv="content-type" content="text/html;
- charset=ISO-8859-1">
+ charset=windows-1252">
<meta name="author" content="Graeme Gill">
</head>
<body>
@@ -26,6 +26,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; Verbose mode<br>
&nbsp;<a href="#A">-A "manufacturer"</a>&nbsp; Set the
manufacturer description string<br>
@@ -42,6 +54,18 @@
Transparency, Matte, Negative, BlackAndWhite<br>
</small></tt><tt><small>&nbsp;<a href="colprof.html#Zi">-Z prsa</a>&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Default
intent: Perceptual, Rel. Colorimetric, Saturation, Abs.
Colorimetric</small></tt><tt><br>
@@ -51,7 +75,8 @@
&nbsp;<a href="#b">-b [lmhun]</a>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp; Low quality B2A table - or specific B2A quality or none
for input device<br>
- &nbsp;<a href="#y">-y</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;<a href="#ni">-ni</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
@@ -63,8 +88,6 @@
- &nbsp; &nbsp; &nbsp; &nbsp; Verify A2B profile<br>
- &nbsp;<a href="#ni">-ni</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -93,6 +116,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; Don't create output (PCS) shaper
curves<br>
</small></tt><tt><small>&nbsp;<a href="#nc">-nc</a>
@@ -123,6 +158,18 @@ x
+
+
+
+
+
+
+
+
+
+
+
+
max K, r = ramp K<br>
&nbsp;<a href="#kp">-k p stle stpo enpo enle shape</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -147,6 +194,18 @@ White
+
+
+
+
+
+
+
+
+
+
+
+
- 1.0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -171,6 +230,18 @@ Wh
+
+
+
+
+
+
+
+
+
+
+
+
0.0 - Bk 1.0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -195,6 +266,18 @@ Wh
+
+
+
+
+
+
+
+
+
+
+
+
0.0 - Bk 1.0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -218,6 +301,18 @@ Black
+
+
+
+
+
+
+
+
+
+
+
+
0.0 - 1.0<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -242,10 +337,34 @@ concave,
+
+
+
+
+
+
+
+
+
+
+
+
1.0-2.0 convex<br>
&nbsp;<a href="#K">-K parameters</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
Same as -k, but target is K locus rather than K value itself<br>
&nbsp;<a href="#l">-l <i>tlimit</i></a>&nbsp;&nbsp; &nbsp;
&nbsp; &nbsp;&nbsp; override CMYK total ink limit, 0 - 400%
@@ -277,6 +396,18 @@ cLUT
+
+
+
+
+
+
+
+
+
+
+
+
x = XYZ cLUT, X = display XYZ cLUT + matrix<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -300,6 +431,18 @@ s
+
+
+
+
+
+
+
+
+
+
+
+
shaper+matrix, m = matrix only,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -324,6 +467,18 @@ S
+
+
+
+
+
+
+
+
+
+
+
+
single shaper+matrix<br>
&nbsp;<a href="#u">-u</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
@@ -333,6 +488,18 @@ S
+
+
+
+
+
+
+
+
+
+
+
+
If input profile, auto scale WP to allow extrapolation</small></tt><tt><br>
</tt><tt> </tt><tt><small><small>&nbsp;<a href="#uc">-uc</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;
@@ -359,17 +526,58 @@ and
+
+
+
+
+
+
+
+
+
+
+
+
primaries to be +ve</tt><tt><br>
- </tt><tt>&nbsp;</tt><tt><small><small><a
- href="file:///D:/src/argyll/doc/colprof.html#f">-f [<i>illum</i>]</a>
+ &nbsp;<a href="#V">-V demphasis</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Degree of dark region cLUT grid emphasis 1.0-3.0 (default 1.00 =
+ none)<br>
+ </tt><tt>&nbsp;</tt><tt><small><small><a href="#f">-f [<i>illum</i>]</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Use Fluorescent
Whitening Agent compensation [opt. simulated inst. illum.:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
M0, M1, M2, </small></small></tt><tt><small><small><small>A,
C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp ]</small></small></small></tt><tt><br>
- </tt><tt><small><small><small><small>&nbsp;<a
- href="file:///D:/src/argyll/doc/colprof.html#i">-i <i>illum</i></a>&nbsp;&nbsp;
+ </tt><tt><small><small><small><small>&nbsp;<a href="#i">-i <i>illum</i></a>&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; Choose illuminant for
computation of CIE XYZ from spectral data &amp; FWA:<br>
@@ -385,6 +593,18 @@ D50
(def.),
D50M2,
+
+
+
+
+
+
+
+
+
+
+
+
D65, F5, F8, F10 or file.sp</small></small></small><br>
&nbsp;<a href="#o">-o <i>observ</i></a>&nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; Choose CIE Observer for spectral data:<br>
@@ -400,6 +620,18 @@ D50M2,
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1931_2 </small></tt><tt><small>(def.)</small></tt><tt><small>,
1964_10, S&amp;B 1955_2, shaw, J&amp;V 1978_2<br>
&nbsp;<a href="#r">-r avgdev</a> &nbsp; &nbsp; &nbsp;
@@ -427,6 +659,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
given source<br>
&nbsp;<a href="#S">-S src.icc</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -440,6 +684,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Apply gamut mapping to output profile perceptual and saturation
B2A table<br>
&nbsp;<a href="#nP">-nP</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -454,6 +710,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Use colormetric source gamut to make output profile perceptual
table<br>
&nbsp;<a href="#nS">-nS</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -468,6 +736,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Use colormetric source gamut to make output profile saturation
table<br>
&nbsp;<a href="#g">-g src.gam</a>
@@ -490,6 +770,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Override gamut mapping intent for output profile saturation
table:<br>
</small></tt><tt><small> &nbsp; &nbsp; &nbsp;
@@ -520,6 +812,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
pa - Perceptual Appearance</small></tt><tt><br>
</tt><tt> </tt><tt><small>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -533,12 +837,37 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ms - Saturation<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s - Enhanced Saturation [ICC
Saturation]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp; &nbsp; al - Absolute Colorimetric (Lab)</small></tt><tt><small><br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+ rl - White Point Matched Colorimetric (Lab)<br>
&nbsp;<a href="#c">-c viewcond</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -551,6 +880,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
set input viewing conditions for output profile CIECAM02 gamut
mapping,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -565,6 +906,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
either an enumerated choice, or a parameter<br>
&nbsp;<a href="#d">-d viewcond</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -578,6 +931,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
set output viewing conditions for output profile CIECAM02, gamut
mapping<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -592,6 +957,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
either an enumerated choice, or a parameter:value change<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -605,6 +982,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Also sets out of gamut clipping CAM space.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -618,6 +1007,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Enumerated Viewing Conditions:<br>
</small></tt><tt><small>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;&nbsp; &nbsp; pp - Practical Reflection Print (ISO-3664
@@ -660,6 +1061,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp; c = transparency (default average)<br>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
@@ -677,20 +1090,41 @@ for
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b:background&nbsp; Background %
of image luminance (default 20)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; l:scenewhite&nbsp;
- Scene white in cd.m^2 if surround = auto (default 250)<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- f:flare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flare light % of
- image luminance (default 1)<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- f:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flare color as XYZ
- (default media white)<br>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flare
- color as x, y<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
+ l:imageewhite&nbsp; Image white in cd.m^2 if surround = auto
+ (default 250)</small></tt><br>
+ <tt><small><small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ f:flare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flare light
+ % of image luminance (default 0)<br>
+ </span></small>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp; </span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+ g:glare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare light % of
+ ambient (default 1)</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ g:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color as
+ XYZ (default media white)</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ g:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare
+ color as x, y</span></small> <br>
&nbsp;<a href="#P">-P</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -704,6 +1138,18 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
Create gamut gammap_p.wrl and gammap_s.wrl diagostics<br>
</small></tt><tt><small>&nbsp;<a href="#O">-O outputfile</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Override
@@ -718,6 +1164,18 @@ Override
+
+
+
+
+
+
+
+
+
+
+
+
the default output filename &amp; extension.</small></tt><tt><br>
</tt><tt> </tt><tt><small>&nbsp;<a href="#p1"><i>inoutfile</i></a>
&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Base name for
@@ -824,13 +1282,6 @@ Override
profiles and matrix profiles will only contain a colorimetric intent
table or matrix.<br>
<br>
- <a name="y"></a> The <b>-y</b> flag does a verification check on
- the AtoB profile. This is done by comparing what CIE colors the
- profile predicts for the test chart test patches, and comparing them
- to the actual values. A summary of the average and maximum Lab delta
- E's will be printed out if this flag is set. If the <b>-v</b> flag
- is also set, then information for each patch will also be printed.<br>
- <br>
<a name="ni"></a><a name="np"></a><a name="no"></a>Normally cLUT
base profiles are generated with three major elements:- per device
channel (shaper) input curves, the multi-dimensional lut table, and
@@ -859,6 +1310,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
device and CIE/spectral sample data and calibration curves used to
create a profile is stored in the <span style="font-weight: bold;">'targ'</span>
text tag in the resulting ICC profile. To suppress this and make the
@@ -873,6 +1336,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
</span>flag. <span style="font-weight: bold;">Note</span> that this
will then preclude final calibrated device value ink limits from
being computed for the resulting profile in subsequent use (ie. <a
@@ -922,6 +1397,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;
&nbsp;_______&nbsp; enle<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -936,6 +1423,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;/<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -949,6 +1448,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
|&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp; /<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -962,6 +1473,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;/<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -975,6 +1498,18 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; /<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
stle&nbsp; | ------/<br>
@@ -996,6 +1531,18 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
+
+
+
+
+
+
+
+
+
+
+
+
Black<br>
</tt> <br>
For minimum sensitivity of printed output to the lighting spectrum,
@@ -1063,8 +1610,8 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
By default (equivalent to <b>-al</b>) profile creates a <span
style="font-weight: bold;">cLUT</span> based table profile with a
PCS (Profile Connection Space) of L*a*b*, which generally gives the
- most accurate results, and allows for the four different rendering
- intents that ICC profiles can support.<br>
+ most robust and accurate results, and allows for the four different
+ rendering intents that ICC profiles can support.<br>
<br>
A cLUT base table profile using a PCS of XYZ can be created if <b>-ax</b>
is used, and this may have the advantage of better accuracy for
@@ -1072,14 +1619,16 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
clipping for displays with a colorant chromaticity that can't be
encoded in L*a*b* PCS space, and may give a more accurate white
point for input devices by avoiding clipping of values above the
- white point that can occur in L*a*b* based cLUT input profiles. By
- default cLUT XYZ PCS Display profiles will also have a set of dummy
- matrix tags included in them, for better compatibility with other
- systems. The dummy matrix deliberately interchanges Red, Green and
- Blue channels, so that it is obvious if the cLUT tables are not
- being used. If it is important for both the cLUT and matrix be
- accurate, use <span style="font-weight: bold;">-aX</span>, which
- will create shaper/matrix tags.<br>
+ white point that can occur in L*a*b* based cLUT input profiles. A <b>disadvantage</b>
+ of this type of profile is that it can be a lot less robust if given
+ a test patch set that is sparse, or too evenly spaced. By default
+ cLUT XYZ PCS Display profiles will also have a set of dummy matrix
+ tags included in them, for better compatibility with other systems.
+ The dummy matrix deliberately interchanges Red, Green and Blue
+ channels, so that it is obvious if the cLUT tables are not being
+ used. If it is important for both the cLUT and matrix be accurate,
+ use <span style="font-weight: bold;">-aX</span>, which will create
+ shaper/matrix tags.<br>
<br>
For RGB input or display profiles, a simpler type of profile using
either a gamma curves or a general shaper curves, combined with a
@@ -1159,6 +1708,25 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
black and primary values, so as to work with these programs, but
this will reduce the accuracy of the profile.<br>
<br>
+ <a name="V"></a>The <b>-V demphasis</b> parameter allows sets the
+ degree to which cLUT grid spacing should emphasize the accuracy of
+ modelling the device response in the dark regions, over that of the
+ lighter regions. By default this value will be a scaled down version
+ of the one set using the <a href="targen.html#V">targen -V</a>
+ parameter, and values in the range <b>1.3 - 1.6</b> are a good
+ place to start. Display devices used for video or film reproduction
+ are typically viewed in dark viewing environments with no strong
+ white reference, and typically employ a range of brightness levels
+ in different scenes. This often means that the devices dark region
+ response is of particular importance, so increasing the density of
+ cLUT grid points in the dark region may improved the balance of
+ accuracy of the resulting profile for video or film reproduction.
+ This is most valuable when used in concert with a set of test points
+ that more densely sample the dark regions, by use of the
+ corresponding targen -V parameter. Emphasizing the dark region
+ characterization will reduce the accuracy of&nbsp; modelling the
+ lighter regions given a certain quality/grid resolution.<br>
+ <br>
<a name="f"></a> The <b>-f</b> flag enables Fluorescent Whitening
Agent (FWA) compensation. This only works if spectral data is
available and, the instrument is not UV filtered.&nbsp; FWA
@@ -1192,6 +1760,18 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
+
+
+
+
+
+
+
+
+
+
+
+
Violet</span> spectral content, otherwise FWA compensation won't
work properly. This means you ideally need to measure your
illuminant spectrum using an instrument that can measure down to
@@ -1500,7 +2080,7 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
profile (.icm extension on the MSWindows platform, .icc on Apple or
Unix platforms). The <span style="font-weight: bold;">-O</span>
parameter will override this default.
- <h3>Discussion</h3>
+ <h3><a name="Di"></a>Discussion</h3>
Note that monochrome profiling isn't currently supported. It may be
supported sometime in the future.<br>
<br>
@@ -1512,7 +2092,7 @@ White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
readings, average errors of 5 or less, and maximum errors of 15 or
less would normally be expected. If errors are grossly higher than
this, then this is an indication that something is seriously wrong
- with the device testing, or profile creation.<br>
+ with the device measurement, or profile creation.<br>
<br>
Given a .ti3 file from a display device that contains calibration
curves (generated by <a href="dispcal.html">dispcal</a>, passed
diff --git a/doc/verify.html b/doc/colverify.html
index bd4a953..3f8bc72 100644
--- a/doc/verify.html
+++ b/doc/colverify.html
@@ -1,13 +1,13 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
- <title>verify</title>
+ <title>colverify</title>
<meta http-equiv="content-type" content="text/html;
charset=ISO-8859-1">
<meta name="author" content="Graeme Gill">
</head>
<body>
- <h2><b>profile/verify</b></h2>
+ <h2><b>profile/colverify</b></h2>
<h3>Summary</h3>
Verify a color transform by comparing CIE measurement values from
two test charts. The charts can be any suitably formatted CGATS or <a
@@ -16,26 +16,29 @@
worst case delta E will be reported, as well as the worst 10% and
best 90% of values.<br>
<h3>Usage Summary</h3>
- <tt><small>verify&nbsp; [-options] target.ti3 measured.ti3<br>
- &nbsp;-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;
-
- &nbsp; Verbose - print each patch value<br>
+ <tt><small>colverify&nbsp; [-options] target.ti3 measured.ti3<br>
+ &nbsp;-v
+ [n]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Verbose mode, n &gt;= 2 print each value<br>
&nbsp;-n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Normalise
+
each files reading to white Y<br>
&nbsp;-N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Normalise
+
each files reading to white XYZ<br>
&nbsp;-D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Use
+
D50 100.0 as L*a*b* white reference<br>
&nbsp;-c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
&nbsp; Show CIE94 delta E values<br>
&nbsp;-k &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp; &nbsp; Show CIEDE2000 delta E values<br>
@@ -44,20 +47,23 @@ Use
&nbsp;-w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
&nbsp; create VRML vector visualisation (measured.wrl)<br>
</small></tt><tt><small>&nbsp;-W
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp; &nbsp; create VRML marker &amp; vector visualisation
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ &nbsp; create VRML marker &amp; vector visualisation
(measured.wrl)</small></tt><tt><br>
</tt><tt> </tt><tt><small>&nbsp;-x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
&nbsp; Use VRML axes<br>
&nbsp;</small></tt><tt><small><small>-f
[illum]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Use Fluorescent
Whitening Agent compensation [opt. simulated inst. illum.:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
M0, M1, M2, A, C, D50 (def.), D50M2, D65, F5, F8, F10 or
file.sp]<br>
&nbsp;-i illum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -65,19 +71,25 @@ Use
data &amp; FWA:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp<br>
&nbsp;-o observ&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Choose
CIE Observer for spectral data:<br>
</small><small>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
1931_2 </small><small>(def.)</small><small>, 1964_10, S&amp;B
- 1955_2, shaw, J&amp;V 1978_2</small><br>
- &nbsp;<i>target.ti3</i>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Target or
- reference patch data file<br>
+ 1955_2, shaw, J&amp;V 1978_2<br>
+ &nbsp;-L profile.icm&nbsp;&nbsp; Skip any first file out of
+ profile gamut patches<br>
+ &nbsp;-X file.ccmx&nbsp;&nbsp;&nbsp;&nbsp; Apply Colorimeter
+ Correction Matrix to second file<br>
+ </small> &nbsp;<i>target.ti3</i>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ Target or reference patch data file<br>
&nbsp;<i>measured.ti3</i> &nbsp; &nbsp; Measured or actual patch
data file</small></tt><br>
<h3>Usage Details and Discussion</h3>
- <b> verify</b> provides a way of verifying how well a color
+ <b> colverify</b> provides a way of verifying how well a color
transformation (such a proofing) performs.<br>
<br>
The <b>-v</b> flag prints out extra information during the
@@ -168,6 +180,17 @@ Use
The same parameter value should be used as was used during the
creation of the profile.<br>
<br>
+ The <b>-L</b><b> profile.icm</b> parameter causes colverify to ignore
+ any patches from the first file that are out of gamut according to
+ the profile. This can be useful in evaluating accuracy without
+ tainting it by impossible to reach colors.<br>
+ <br>
+ The <b>-X</b><b> file.ccmx</b> option applies the given 3x3
+ calibration matrix to the values from the second file before doing
+ any verification. This can be useful in evaluating the effects of a
+ calibration matrix on raw colorimeter values, against reference
+ values measured using a spectrometer.<br>
+ <br>
If both CIE and spectral values are present in the input files, the
CIE values will be used by default. Using the <span
style="font-weight: bold;">-i</span>, <span style="font-weight:
diff --git a/doc/dispcal.html b/doc/dispcal.html
index 7327c8f..e23a8d0 100644
--- a/doc/dispcal.html
+++ b/doc/dispcal.html
@@ -43,6 +43,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Verbose mode<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
@@ -82,6 +96,20 @@ for
+
+
+
+
+
+
+
+
+
+
+
+
+
+
VideoLUT access.</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;<a
href="#d">-d n</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -112,6 +140,20 @@ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1)</span></font><br>
<span style="font-family: monospace;">&nbsp;<a href="#dweb">-dweb[:port]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -132,7 +174,40 @@ list
- Display via a web server at port (default 8080)</span><br
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Display via a web server at port (default 8080)</span><br>
+ <span style="font-family: monospace;">&nbsp;<a href="#dmadvr">-dmadvr</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [MSWin] Display via MadVR Video Renderer</span><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
style="font-family: monospace;"></span><span style="font-family:
@@ -158,6 +233,20 @@ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
listno</a><span style="font-family: monospace;"> &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set communication port from
the following list (default 1)<br>
@@ -208,6 +297,20 @@ list
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Fast ICC Profile Description string (Default "outfile")<br>
&nbsp;<a href="#u">-u</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Update
@@ -237,6 +340,20 @@ ICC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
profile VideoLUTs</span><span style="font-family: monospace;"></span><span
style="font-family: monospace;"></span><br style="font-family:
monospace;">
@@ -262,6 +379,20 @@ ICC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Quality - Low, Medium (def), High<br>
&nbsp;<a href="#p">-p</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -272,6 +403,20 @@ ICC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use telephoto mode (ie. for a projector) (if available)<br>
&nbsp;</span></font><font size="-1"><span style="font-family:
monospace;"><a href="#y">-y X</a>
@@ -295,6 +440,20 @@ ICC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Display type - instrument specific list to choose from.</span></font><font
size="-1"><span style="font-family: monospace;"><br
style="font-family: monospace;">
@@ -328,6 +487,20 @@ in
+
+
+
+
+
+
+
+
+
+
+
+
+
+
deg. K (deflt.)<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
@@ -359,6 +532,20 @@ temperaturee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
in deg. K</span></font><br style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
@@ -383,6 +570,20 @@ temperaturee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set the target white point as chromaticity coordinates</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -407,6 +608,20 @@ temperaturee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set the target white brightness in cd/m^2</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -431,6 +646,20 @@ temperaturee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set the target response curve gamma (Def. 2.4)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -453,6 +682,20 @@ temperaturee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use "-gl" for L*a*b* curve</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -475,6 +718,20 @@ temperaturee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; Use "-gs" for sRGB curve<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Use
@@ -504,6 +761,20 @@ use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-a as well!)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -525,6 +796,20 @@ use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use "-g240" for SMPTE 240M curve </span></font><font size="-1"><span
style="font-family: monospace;">(should use -a as well!)</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -547,6 +832,20 @@ use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use "-G2.4 -f0" for BT.1886</span></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -560,6 +859,20 @@ use
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#G">-G gamma</a><span
@@ -594,6 +907,20 @@ output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
offset (default all output offset)<br>
&nbsp;<a href="#a">-a ambient</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -615,6 +942,20 @@ output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use viewing condition adjustment for ambient in Lux<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#k">-k factor</a>
@@ -647,6 +988,20 @@ output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Set the target black brightness in cd/m^2</span></font><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
@@ -672,10 +1027,25 @@ output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Run n verify passes on final curves<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
- href="#E">-E</a><span style="font-family: monospace;">
+ href="#z">-<font size="-1">z</font></a><span style="font-family:
+ monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -696,6 +1066,20 @@ output
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Run only verify pass on installed calibration curves</span></font><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
@@ -730,6 +1114,20 @@ center,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= right/bottom etc.</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ss:
@@ -759,6 +1157,20 @@ normal,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
= double etc.<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -768,6 +1180,20 @@ normal,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
ss,vs: = optional horizontal, vertical scale.</span></font><br>
<font size="-1"><span style="font-family: monospace;"> &nbsp;<a
href="#F">-F</a>
@@ -791,8 +1217,39 @@ normal,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Fill whole screen with black background</span></font><font
- size="-1"><span style="font-family: monospace;"></span></font><br
+ size="-1"><span style="font-family: monospace;"></span></font><br>
+ <font size="-1"><span style="font-family: monospace;">&nbsp;</span></font><font
+ size="-1"><span style="font-family: monospace;"><a href="#E">-E</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+ </span></font><small><span style="font-family: monospace;">Video
+ encode output as (16-235)/255 "TV" levels</span></small><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
@@ -825,6 +1282,20 @@ on
+
+
+
+
+
+
+
+
+
+
+
+
+
+
test window<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
@@ -852,6 +1323,20 @@ on
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Disable initial calibration of instrument if possible</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#H">-H</a><span
@@ -883,6 +1368,20 @@ on
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Apply Colorimeter Correction Matrix</span></font><br>
<span style="font-family: monospace;">&nbsp;<a href="#X2">-X
file.ccss</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -908,6 +1407,20 @@ Calibration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Spectral Samples for calibration</span><font size="-1"><span
style="font-family: monospace;"><br>
</span></font><small><span style="font-family: monospace;">&nbsp;</span><a
@@ -935,6 +1448,20 @@ Calibration
+
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1931_2 </span></small><small><span
style="font-family: monospace;">(def.)</span></small><small><span
style="font-family: monospace;">, 1964_10, S&amp;B 1955_2, shaw,
@@ -959,14 +1486,42 @@ Calibration
- Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw<br>
- </span></small><font size="-1"><span style="font-family:
- monospace;">&nbsp;</span><a style=" font-family: monospace;"
- href="#YA">-<font size="-1">Y</font> A</a><span
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw</span></small><br>
+ <small><span style="font-family: monospace;"><tt>&nbsp;<a href="#YR">-Y
+
+
+ R:<i>rate</i></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+ Override measured refresh rate with rate Hz<br>
+ </tt>&nbsp;</span></small><font size="-1"><span
+ style="font-family: monospace;"></span><a style=" font-family:
+ monospace;" href="#YA">-<font size="-1">Y</font> A</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; Use non-adaptive integration time mode (if
available).</span></font><br>
+ <font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
+ style=" font-family: monospace;" href="#Yp">-<font size="-1">Y</font>
+ <font size="-1">p</font></a><span style="font-family:
+ monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; Don't wait for the instrument to be placed on
+ the display</span></font><br>
<small><span style="font-family: monospace;"> </span></small><font
size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#C">-C "command"</a><span
@@ -1009,6 +1564,20 @@ none,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
h = HW, x = Xon/Xoff</span></font><font size="-1"><span
style="font-family: monospace;"></span></font><br>
<font size="-1"><span style="font-family: monospace;"> </span></font><font
@@ -1034,6 +1603,20 @@ none,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Print debug diagnostics to stderr</span></font><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
@@ -1059,6 +1642,20 @@ none,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
</span><span style="font-family: monospace;">Base name for created
or updated </span></font><font size="-1"><a style="font-family:
monospace;" href="cal_format.html">.cal</a><span
@@ -1079,7 +1676,9 @@ none,
<br>
<a name="v"></a> The <b>-v</b> flag reports progress information,
as well as other statistics about the progress of calibration. A
- numerical argument greater than 1 gives greater verbosity.<br>
+ numerical argument greater than 1 gives greater verbosity. 2 will
+ give per step adjustment and repeat information, while 3 will give
+ even greater technical detail.<br>
<br>
<a name="display"></a>When running on a UNIX based system that used
the X11 Windowing System, <b>dispcal</b> will by default use the
@@ -1149,6 +1748,20 @@ none,
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1,2</span> . Some experimentation may be needed using <a
href="dispwin.html">dispwin</a> on such systems, to discover what
screen has access to the VideoLUT hardware, and which screens the
@@ -1183,6 +1796,16 @@ none,
See the <a href="#o">-o</a> flag for an explanation of the
implications of having no access to the VideoLUTs.<br>
<br>
+ <a name="dmadvr"></a><span style="font-weight: bold;">-dmadvr</span>
+ [MSWin only] causes test patches to be displayed using the MadVR
+ video renderer. Note that you may have to start the video playback
+ software and load a video clip in pause for this to work. MadVR
+ rendering does not need or support VideoLUT access, but be aware
+ that the state of the Graphics Card VideoLUTs may affect the
+ results, and therefore may have to be set appropriately using
+ dispwin. Test patch colors will <u>not</u> be processed by the
+ MadVR 3dLut by default.<br>
+ <br>
<a name="c"></a> <span style="font-weight: bold;">-c</span> The
instrument is assumed to communicate through a USB or serial
communication port, and the port can be selected with the <b>-c</b>
@@ -1198,9 +1821,11 @@ none,
perform a quick measurement of current display behaviour, reports
and then exits. If the <span style="font-weight: bold;">-r</span>
flag is used the measurement are taken using the currently loaded
- calibration (Video LUT) curves. If <span style="font-weight: bold;">-R</span>
- is use, then the uncalibrated ("raw" or "native") behaviour is
- measured. Reported are: <br>
+ calibration (Video LUT) curves, and in the case of MadVR renderer
+ test patch display the Color Management 3dLut. If <span
+ style="font-weight: bold;">-R</span> is use, then the uncalibrated
+ ("raw" or "native") behaviour is measured (ie. no VideoLut or CM).
+ Reported are: <br>
<br>
&nbsp;&nbsp;&nbsp; Black Brightness in cd/m^2<br>
&nbsp;&nbsp;&nbsp; White Brightness in cd/m^2<br>
@@ -1339,10 +1964,9 @@ none,
and how this works, see <a href="instruments.html">Operation of
particular instruments</a>. <b>3)</b> Any installed CCSS files
(if applicable), or CCMX files. These files are typically created
- using <a href="file:///D:/src/argyll/doc/ccxxmake.html">ccxxmake</a>,
- and installed using <a
- href="file:///D:/src/argyll/doc/oeminst.html">oeminst</a>. The
- default and Base Calibration types will be indicated in the usage.<br>
+ using <a href="ccxxmake.html">ccxxmake</a>, and installed using <a
+ href="oeminst.html">oeminst</a>. The default and Base Calibration
+ types will be indicated in the usage.<br>
<br>
<a name="t"></a><span style="text-decoration: underline;"></span> <span
style="font-weight: bold;">-t</span> Set the target white point
@@ -1410,6 +2034,20 @@ Set
+
+
+
+
+
+
+
+
+
+
+
+
+
+
the target response curve gamma. This is normally an exponential
curve (output = input ^gamma), and defaults to 2.4 on MSWindows and
Macintosh OS X 10.6 or latter and Linux/Unix (which is typical of a
@@ -1438,6 +2076,20 @@ the
+
+
+
+
+
+
+
+
+
+
+
+
+
+
L* curve, which is the response of the CIE L*a*b* perceptual
colorspace (<span style="font-weight: bold;">-gl</span>). the REC
709 video standard response curve (<span style="font-weight: bold;">-g709</span>)
@@ -1517,6 +2169,20 @@ As
+
+
+
+
+
+
+
+
+
+
+
+
+
+
explained above, the gamma value provided to the <span
style="font-weight: bold;">-g</span> option is used to set and
actual response curve that makes an allowance for the non-zero black
@@ -1606,7 +2272,8 @@ As
will then blend over to the native or compromise black point that is
blacker, but not of the right hue. The rate of this blend can be
controlled with the <span style="font-weight: bold;">-A</span>
- parameter (see below).<br>
+ parameter (see below). For applications where maximum contrast ratio
+ is important (such as <b>Video</b>), use <b>-k0</b>. <br>
<br>
<a name="A"></a><span style="font-weight: bold;">-A rate</span>:&nbsp;
If
@@ -1629,6 +2296,20 @@ If
+
+
+
+
+
+
+
+
+
+
+
+
+
+
the black point is not being set completely to the same hue as the
white point (ie. because the <span style="font-weight: bold;">-k</span>
factor is less than 1.0), then the resulting calibration curves will
@@ -1668,7 +2349,7 @@ If
ascertained. The verification uses a fixed number of semi-random
test values to test the calibration.<br>
<br>
- <a name="E"></a><span style="font-weight: bold;">-E</span> Run
+ <a name="z"></a><span style="font-weight: bold;">-z</span> Run
verify pass on the display as it is currently setup (currently
installed LUT curves). This will use the usual input parameters to
establish the expected (target) characteristic. <span
@@ -1677,7 +2358,7 @@ If
display, verify will show the resulting discrepancy. You can use <a
href="dispwin.html">dispwin</a> to load a <span
style="font-weight: bold;">.cal</span> file into the display
- before running dispcal <span style="font-weight: bold;">-E</span>.
+ before running dispcal <span style="font-weight: bold;">-z</span>.
Note that if you set an Ambient light level interactively during the
calibration, you need to enter the same number that was measured and
set using the <span style="font-weight: bold;">-a</span> parameter
@@ -1710,6 +2391,16 @@ If
with black. This can aid black accuracy when measuring CRT displays
or projectors.<br>
<br>
+ <a name="E"></a> The <span style="font-weight: bold;">-E</span>
+ flag causes the display test values to be scaled to the Video RGB
+ encoding range of (16-235)/255. This also modifies the resulting
+ calibration curve behavior downstream of dispcal. If a calibration
+ curve created using -E gets installed or converted to an ICC profile
+ 'vcgt' tag in the process of creating a profile in dispcal or
+ colprof, the incoming full range values will first have the
+ calibration curve applied and then be scaled to the Video encoding
+ range (16-235)/255.<br>
+ <br>
<a name="n"></a><span style="font-weight: bold;">-n</span> When
running on a UNIX based system that used the X11 Windowing System, <b>dispcal</b>
normally selects the override redirect so that the test window will
@@ -1789,6 +2480,20 @@ a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
colorimeters accuracy for a particular type of display.<br>
<br>
<a name="Q"></a> The <b>-Q</b> flag allows specifying a tristimulus
@@ -1832,6 +2537,12 @@ a
style="font-weight: bold;">-Iwb</span>.<span style="font-weight:
bold;"> </span><br>
<br>
+ <a name="YR"></a> The -<span style="font-weight: bold;">Y R:<i>rate</i></span>
+ options overrides calibration of the instrument refresh rate. This
+ may be useful if the instrument supports this function and the
+ refresh rate cannot be accurately calibrated from the display
+ itself.<br>
+ <br>
<a name="YA"></a> The -<span style="font-weight: bold;">Y A</span>
option uses a non-adaptive integration time emission measurement
mode, if the instrument supports it, such as the Eye-One Pro or
@@ -1841,6 +2552,13 @@ a
This may give increased consistency and faster measurement times,
but may also give less accurate low level readings.<br>
<br>
+ <a name="Yp"></a> The -<span style="font-weight: bold;">Y p</span>
+ option skips asking the user to place the instrument on the display.
+ Normally a grey patch is displayed, and then the user is asked to
+ confirm that the instrument is in place, so that readings can
+ commence. This flag disables that check. This may be useful in
+ automating certain operations.<br>
+ <br>
<a name="C"></a> The -<span style="font-weight: bold;">C</span> <span
style="font-weight: bold;">"command" </span>option allows a
method of relaying each test value to some other display than that
diff --git a/doc/dispprofloc.html b/doc/dispprofloc.html
index b583914..668ed16 100644
--- a/doc/dispprofloc.html
+++ b/doc/dispprofloc.html
@@ -11,195 +11,143 @@
</h2>
<br>
Installing a display profile for your monitor is very operating
- system
- dependent, which is why <a href="dispwin.html#I">dispin -I</a> is a
- good way of taking care of all these details. On some systems it is
- not
- the operating system itself that
- supports display profiles, but individual applications, or helper
- programs.<br>
+ system dependent, which is why <a href="dispwin.html#I">dispin -I</a>
+ is a good way of taking care of all these details. On some systems
+ it is not the operating system itself that supports display
+ profiles, but individual applications, or helper programs.<br>
<br>
Please choose from the detailed instructions below that suite your
system:<br>
<br>
- <span style="font-weight: bold;"><a href="#MSW">Microsoft
- Windows</a><br>
+ <span style="font-weight: bold;"><a href="#MSW">Microsoft Windows</a><br>
<a href="#OSX">Apple OS X</a><br>
<a href="#Linux">Linux/UNIX X11</a></span><br>
<br>
<hr style="width: 100%; height: 2px;"><a name="MSW"></a>On <span
style="font-weight: bold;">Microsoft Windows</span>, display
- profiles are typically in one of the
- following directories:<br>
+ profiles are typically in one of the following directories:<br>
<p>&nbsp;&nbsp;&nbsp; MS Windows Me and 98: C:\Windows\System\Color<br>
</p>
<p>&nbsp;&nbsp;&nbsp; MS Windows NT:
- C:\Winnt\system32\spool\drivers\color
- </p>
+ C:\Winnt\system32\spool\drivers\color </p>
<p>&nbsp;&nbsp;&nbsp; MS Window 2000, XP, Vista and 7:
C:\Windows\system32\spool\drivers\color</p>
<p>An alternative to using <span style="font-weight: bold;">dispwin
- -I</span>
- to install your display profiles,
- is to use the Display
- Property dialog, advanced settings, Color management tab, and
- locate
- the profile and install it there. This in
- itself does not cause the profile to be made use of anywhere in
- your
- system.<br>
+ -I</span> to install your display profiles, is to use the
+ Display Property dialog, advanced settings, Color management tab,
+ and locate the profile and install it there. This in itself does
+ not cause the profile to be made use of anywhere in your system.<br>
</p>
<p>If you are using Adobe Photoshop on your system, then you can
- tell
- it to use your monitor profile by editing the appropriate registry
- key,
- typically "My
+ tell it to use your monitor profile by editing the appropriate
+ registry key, typically "My
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Adobe\Color\Monitor\Monitor0",
- to
- contain the name of the display profile, and then restart
- Photoshop
- This is the simplest way of ensuring that the Adobe calibration
- loader
- tool Adobe Gamma loads the video hardware lookup tables from the
- vcgt tag, and
- uses the profile as its display profile.<br>
+ to contain the name of the display profile, and then restart
+ Photoshop This is the simplest way of ensuring that the Adobe
+ calibration loader tool Adobe Gamma loads the video hardware
+ lookup tables from the vcgt tag, and uses the profile as its
+ display profile.<br>
</p>
<p>The adobe gamma tool can be told to use your profile, but the
procedure is slightly tricky: Open adobe gamma from photoshop (in
- the
- Help-&gt;Color Management... menu item), select "Open Adobe
- Gamma", and
- select the "Load.." button. Select your profile and "Open". Select
- "OK"
- in the Adobe Gamma, it will then ask you to save it's modified
- version
- of your profile under a different name. Chose a name for the
- modified
- profile, and save it. Exit from Photoshop. Copy the profile you
- want to
- use, over the modified profile that you saved in Adobe Gamma. (If
- you
- don't do the last step, the profile Photoshop will be using will
- have
- been modified in strange ways from what you intended.)<br>
+ the Help-&gt;Color Management... menu item), select "Open Adobe
+ Gamma", and select the "Load.." button. Select your profile and
+ "Open". Select "OK" in the Adobe Gamma, it will then ask you to
+ save it's modified version of your profile under a different name.
+ Chose a name for the modified profile, and save it. Exit from
+ Photoshop. Copy the profile you want to use, over the modified
+ profile that you saved in Adobe Gamma. (If you don't do the last
+ step, the profile Photoshop will be using will have been modified
+ in strange ways from what you intended.)<br>
</p>
<p>Installing a profile on Microsoft Windows generally doesn't mean
that the profiles calibration will be automatically loaded into a
- display on startup. A separated tool is usually needed to achiev
+ display on startup. A separated tool is usually needed to achieve
this.<br>
</p>
<p>Some Microsoft Windows applications may come with
- "Gamma/VCGT/RAMDAC/Video LUT"
- loader tools, consult their documentation and check your Start
- Menu
- Startup folders. If you don't want to use any of these 3rd party
- tools, you can also use the <a
- href="file:///D:/src/argyll/doc/dispwin.html">dispwin</a>
+ "Gamma/VCGT/RAMDAC/Video LUT" loader tools, so consult their
+ documentation and check your Start Menu Startup folders. If you
+ don't want to use any of these 3rd party tools, you can also use
+ the <a href="dispwin.html">dispwin</a>
tool to do this for you, as it takes either a <a
- href="file:///D:/src/argyll/doc/cal_format.html">.cal</a> or ICC
- file
- as an argument. The <a
- href="http://freshmeat.net/projects/xcalib/">xcalib</a>
- tool could also be used.<br>
+ href="cal_format.html">.cal</a> or ICC
+ file as an argument. The <a
+ href="http://freshmeat.net/projects/xcalib/">xcalib</a> tool
+ could also be used.<br>
</p>
<p>To add a startup item that will load a profiles calibration into
- the
- display using <span style="font-weight: bold;">dispwin</span>,
- use the
- following
- instructions:<br>
+ the display using <span style="font-weight: bold;">dispwin</span>,
+ use the following instructions:<br>
</p>
<p style="margin-left: 40px;">On the task bar, right click and
- select
- "Properties", then select the "Advanced" tab, then click "Add..".
- then
- browse till you locate dispwin.exe. In the box containing the path
- to
- <span style="font-weight: bold;">dispwin.exe</span>, add a space
- then
- the option <span style="font-weight: bold;">-L</span>, eg:<br>
+ select "Properties", then select the "Advanced" tab, then click
+ "Add..". then browse till you locate dispwin.exe. In the box
+ containing the path to <span style="font-weight: bold;">dispwin.exe</span>,
+ add a space then the option <span style="font-weight: bold;">-L</span>,
+ eg:<br>
</p>
<p style="margin-left: 40px;">&nbsp;&nbsp;&nbsp; <span
style="font-weight: bold;">c:\bin\argyll\dispwin -L</span></p>
<p style="margin-left: 40px;">If you don't want to use the default
installed profile, you could explicitly set the calibration file
- to use
- as an argument:</p>
+ to use as an argument:</p>
<p style="margin-left: 40px;">&nbsp;&nbsp;&nbsp; <span
style="font-weight: bold;">c:\bin\argyll\dispwin
c:\myprofiles\mydisplay.icm<br>
</span></p>
<p style="margin-left: 40px;">Click "Next &gt;", select the
- "Startup"
- folder, then name the item (ie.
- "Argyll Calibration Loader"), then press "Finish".<br>
+ "Startup" folder, then name the item (ie. "Argyll Calibration
+ Loader"), then press "Finish".<br>
<br>
You can test it out by simply navigating the "Start" menu to the
"Startup" folder and selecting the item you've just created. If
- you
- want to alter any of the details, navigate to the item again and
- right
- click it, and select "Properties". More than one startup item can
- be
- created to set the calibration for more than one display. You may
- want
- to cut and paste the "Target" line to a normal Command Prompt
- shell to
- check that it works as expected, as it is impossible to catch
- error
- messages in the startup.<br>
+ you want to alter any of the details, navigate to the item again
+ and right click it, and select "Properties". More than one startup
+ item can be created to set the calibration for more than one
+ display. You may want to cut and paste the "Target" line to a
+ normal Command Prompt shell to check that it works as expected, as
+ it is impossible to catch error messages in the startup.<br>
</p>
Microsoft Windows <span style="font-weight: bold;">XP</span> has an
optional <span style="font-weight: bold;">Microsoft&nbsp;Color&nbsp;Control&nbsp;Panel&nbsp;Applet&nbsp;for&nbsp;Windows&nbsp;XP</span>
- available for
- download from
- Microsoft, which handles installation and registering of the a
- display
- profile, and will also automatically set the display calibration on
- system startup. The applet is started from the control panel, and
- first
- you have to "Install..." the profile in the <span
- style="font-weight: bold;">Profiles</span> tab, then associate it
- with
- the display in the <span style="font-weight: bold;">Devices</span>
- tab, but <span style="font-weight: bold;">NOTE</span> that it seems
- to
- have a <span style="font-weight: bold;">bug</span>, in that it
- sometimes associates the profiles with the <span
- style="font-weight: bold;">wrong monitor</span> entry!<br>
- <br>
- On
- Microsoft <span style="font-weight: bold;">Vista</span> you can set
- the display profile in
+ available for download from Microsoft, which handles installation
+ and registering of the a display profile, and will also
+ automatically set the display calibration on system startup. The
+ applet is started from the control panel, and first you have to
+ "Install..." the profile in the <span style="font-weight: bold;">Profiles</span>
+ tab, then associate it with the display in the <span
+ style="font-weight: bold;">Devices</span> tab, but <span
+ style="font-weight: bold;">NOTE</span> that it seems to have a <span
+ style="font-weight: bold;">bug</span>, in that it sometimes
+ associates the profiles with the <span style="font-weight: bold;">wrong
+ monitor</span> entry!<br>
+ <br>
+ On Microsoft <span style="font-weight: bold;">Vista</span> you can
+ set the display profile in
Control&nbsp;Panel&nbsp;-&gt;&nbsp;Hardware&nbsp;and&nbsp;Sound
-&gt;&nbsp;Color&nbsp;Management, as an alternative to <span
style="font-weight: bold;">dispwin -I</span>.&nbsp;In&nbsp;Devices&nbsp;
you&nbsp;select&nbsp;"Use&nbsp;my&nbsp;settings&nbsp;for&nbsp;this
device",&nbsp;and&nbsp;then&nbsp;add&nbsp;the&nbsp;profile&nbsp;you've&nbsp;created.
Unfortunately
- though, it doesn't use the 'vcgt'
- calibration curves on system startup, so a tool such as <span
- style="font-weight: bold;">dispwin</span> will still have to be
- used
- to do this. Note that currently Vista also has a <span
- style="font-weight: bold;">bug</span> that causes the calibration
- curves to be reset whenever the User Account Dialog (and similar) is
- displayed. This problem can only be worked around manually, by
- re-running the startup item whenever this happens. Note that due to
- the
- details of this bug it is necessary to actually reset the
- calibration
- to something else before re-setting it. This can be done quite
- conveniently in dispwin by adding the <span style="font-weight:
- bold;">-c</span>
- flag: e.g.: <span style="font-weight: bold;">c:\bin\argyll\dispwin
- -c
- -L</span><br>
- <br>
- On
- Microsoft <span style="font-weight: bold;">Windows 7</span> you can
- set
- the display profile by opening the <span class="phrase">Color
+
+ though, it doesn't use the 'vcgt' calibration curves on system
+ startup, so a tool such as <span style="font-weight: bold;">dispwin</span>
+ will still have to be used to do this. Note that currently Vista
+ also has a <span style="font-weight: bold;">bug</span> that causes
+ the calibration curves to be reset whenever the User Account Dialog
+ (and similar) is displayed. This problem can only be worked around
+ manually, by re-running the startup item whenever this happens. Note
+ that due to the details of this bug it is necessary to actually
+ reset the calibration to something else before re-setting it. This
+ can be done quite conveniently in dispwin by adding the <span
+ style="font-weight: bold;">-c</span> flag: e.g.: <span
+ style="font-weight: bold;">c:\bin\argyll\dispwin -c -L</span><br>
+ <br>
+ On Microsoft <span style="font-weight: bold;">Windows 7 &amp; 8</span>
+ you can set the display profile by opening the <span class="phrase">Color
+
Management control by clicking the <span class="ui">Start</span>
button and then clicking <span class="ui">Control Panel</span>.
In the search box, type <span class="userInput">color management</span>,
@@ -213,25 +161,25 @@ Unfortunately
profile has been marked "(default)" if you want it to be
automatically used for your display.<br>
<br>
- By default Windows 7 seems to automatically load the default display
- profiles calibration on startup, but needs to be told to do this at
- all other times by changing the system defaults, or if some 3rd
- party tool to load display calibration has been installed. This can
- be done by logging on with a user account that has administrative
- privileges, then opening the <span class="phrase">Color Management
- (see above), and then select the "</span><span class="ui">Advanced</span>"
- tab, and then "<span class="ui">Change system defaults...", then
- select the </span><span class="phrase">"</span><span class="ui">Advanced</span>"
- tab, and select/un-select the "<span class="ui">Use <span
- class="notLocalizable">Windows</span> display calibration</span>"
- check box. (You could use <span style="font-weight: bold;">dispwin
- -I</span> as an alternative to this if you really wanted.)<br>
+ By default Windows 7 &amp; 8 seems to automatically load the default
+ display profiles calibration on startup, but needs to be told to do
+ this at all other times by changing the system defaults, or if some
+ 3rd party tool to load display calibration has been installed. This
+ can be done by logging on with a user account that has
+ administrative privileges, then opening the <span class="phrase">Color
+ Management (see above), and then select the "</span><span
+ class="ui">Advanced</span>" tab, and then "<span class="ui">Change
+ system defaults...", then select the </span><span class="phrase">"</span><span
+ class="ui">Advanced</span>" tab, and select/un-select the "<span
+ class="ui">Use <span class="notLocalizable">Windows</span>
+ display calibration</span>" check box. (You could use <span
+ style="font-weight: bold;">dispwin -I</span> as an alternative to
+ this if you really wanted.)<br>
<br>
&nbsp;<br>
<hr style="width: 100%; height: 2px;"><a name="OSX"></a>On <span
- style="font-weight: bold;">Apple OSX</span>, the display
- profile are in one of the following
- locations:<br>
+ style="font-weight: bold;">Apple OSX</span>, the display profile
+ are in one of the following locations:<br>
<br>
&nbsp;&nbsp;&nbsp; /Network/Library/ColorSync/Profiles<br>
&nbsp;&nbsp;&nbsp; /System/Library/Colorsync/Profiles<br>
@@ -239,25 +187,22 @@ Unfortunately
&nbsp;&nbsp;&nbsp; ~/Library/ColorSync/Profiles<br>
<br>
Note though that&nbsp; /System/Library/Colorsync/Profiles is only
- for
- profiles supplied by Apple. You can use <a href="dispwin.html#S">dispwin
- -S</a>&nbsp; to select the appropriate scope when installing a
- profile
- using <a href="dispwin.html#I">dispwin -I</a>. You can use the
- "System
+ for profiles supplied by Apple. You can use <a
+ href="dispwin.html#S">dispwin -S</a>&nbsp; to select the
+ appropriate scope when installing a profile using <a
+ href="dispwin.html#I">dispwin -I</a>. You can use the "System
Preferences-&gt;Displays-&gt;Color" tool to check that the profile
- has been installed correctly. Note that the contents of
- the description tag (the argument to the <span style="font-weight:
- bold;"><span style="font-weight: bold;">-D</span></span>
- flag used with the <span style="font-weight: bold;">colprof</span>
- tool) will be used to identify the profile.<br>
+ has been installed correctly. Note that the contents of the
+ description tag (the argument to the <span style="font-weight:
+ bold;"><span style="font-weight: bold;">-D</span></span> flag used
+ with the <span style="font-weight: bold;">colprof</span> tool) will
+ be used to identify the profile.<br>
<br>
<hr style="width: 100%; height: 2px;"><a name="Linux"></a>On <span
style="font-weight: bold;">Linux</span> and other <span
style="font-weight: bold;">Unix</span> style systems, there is no
- universally agreed location for ICC profiles yet,
- although the following locations have been suggested at various
- times:<br>
+ universally agreed location for ICC profiles yet, although the
+ following locations have been suggested at various times:<br>
<br>
&nbsp;&nbsp;&nbsp; /usr/share/color/icc<br>
&nbsp;&nbsp;&nbsp; /usr/local/share/color/icc<br>
@@ -270,18 +215,16 @@ Unfortunately
<br>
Argyll <a href="dispwin.html">dispwin</a> follows uses the <a
href="ucmm.html">ucmm</a> scheme for storing user and system
- display
- profiles, and when a display is set to use a profile correctly, it
- will
- follow <a
+ display profiles, and when a display is set to use a profile
+ correctly, it will follow <a
href="http://www.burtonini.com/computing/x-icc-profiles-spec-0.2.html">this
+
convention</a> to make it available to applications.<br>
&nbsp;&nbsp; <br>
If you want the display calibration to be loaded, you should
- consider
- installing a tool to do so at startup, such as <a
- href="file:///D:/src/argyll/doc/dispwin.html">dispwin</a>
- or <a href="http://freshmeat.net/projects/xcalib/">xcalib</a>.<br>
+ consider installing a tool to do so at startup, such as <a
+ href="dispwin.html">dispwin</a> or <a
+ href="http://freshmeat.net/projects/xcalib/">xcalib</a>.<br>
<br>
Using <a href="dispwin.html">dispwin</a> the currently installed
profile for a particular display can be loaded using the <a
@@ -292,21 +235,17 @@ Unfortunately
<br>
</span>which will both upload the installed profile <span
style="font-style: italic;"></span>into the <span
- style="font-weight: bold;"></span>root
- window _ICC_PROFILE property, and also load it into the display
- VideoLUTs. <br>
+ style="font-weight: bold;"></span>root window _ICC_PROFILE
+ property, and also load it into the display VideoLUTs. <br>
<br>
You can use the <span style="font-weight: bold;">dispwin</span> <a
- href="file:///D:/src/argyll/doc/dispwin.html#d">-d</a> parameter
- in
- the usual way to select other
- displays to store or load the calibration using the _ICC_PROFILE
- property.<br>
+ href="dispwin.html#d">-d</a> parameter
+ in the usual way to select other displays to store or load the
+ calibration using the _ICC_PROFILE property.<br>
<br>
To do this when you start your X11 server, you could put the above
command in your <span style="font-weight: bold;">.xinitrc</span>
- file
- in your home directory for each screen.<br>
+ file in your home directory for each screen.<br>
<br>
<br>
</body>
diff --git a/doc/dispread.html b/doc/dispread.html
index e1ce861..071fa7d 100644
--- a/doc/dispread.html
+++ b/doc/dispread.html
@@ -34,6 +34,15 @@
+
+
+
+
+
+
+
+
+
&nbsp;&nbsp;&nbsp;&nbsp; Verbose mode<br>
&nbsp;</small><font size="-1"><a style="font-family: monospace;"
href="#display">-display displayname</a><span
@@ -65,6 +74,15 @@ m
+
+
+
+
+
+
+
+
+
for VideoLUT access.</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;<a
href="#d">-d n</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -88,6 +106,15 @@ list
+
+
+
+
+
+
+
+
+
(default 1)</span></font><small style="font-family: monospace;"><br>
</small><span style="font-family: monospace;">&nbsp;<a href="#dweb">-dweb[:port]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -105,7 +132,30 @@ list
+
+
+
+
+
+
+
+
+
Display via a web server at port (default 8080)</span><br>
+ <span style="font-family: monospace;">&nbsp;<a href="#dmadvr">-dmadvr</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+ [MSWin] Display via MadVR Video Renderer</span><br>
<small style="font-family: monospace;"> <span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
href="#c">-c listno</a><span style="font-family: monospace;">
@@ -126,6 +176,15 @@ list
+
+
+
+
+
+
+
+
+
Use telephoto mode (ie. for a projector) (if available)</span></font><br>
&nbsp; <font size="-1"><span style="font-family: monospace;"><a
href="#y">-y X</a>
@@ -145,6 +204,15 @@ Display
+
+
+
+
+
+
+
+
+
type - instrument specific list to choose from.</span></font><br>
<small style="font-family: monospace;">&nbsp;<span
style="text-decoration: underline;">-</span><a href="#k">k
@@ -162,6 +230,15 @@ Display
+
+
+
+
+
+
+
+
+
Load calibration file into display while reading<br>
</small><small style="font-family: monospace;">&nbsp;<span
style="text-decoration: underline;">-</span><a href="#K">K
@@ -180,7 +257,21 @@ Apply
+
+
+
+
+
+
+
+
+
calibration file to test values while reading</small><br>
+ <tt>&nbsp;<a href="#V">-V</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ [MSWin] Enable MadVR color management (3dLut)</tt><br>
<small style="font-family: monospace;">&nbsp;<a href="#s">-s</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -195,6 +286,15 @@ Apply
+
+
+
+
+
+
+
+
+
&nbsp;&nbsp;&nbsp;&nbsp; Save spectral information (default don't
save)<br>
</small><font style="font-family: monospace;" size="-1">&nbsp;<a
@@ -221,6 +321,15 @@ center,
+
+
+
+
+
+
+
+
+
1.0 = right/bottom etc.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
ss:
@@ -243,6 +352,15 @@ normal,
+
+
+
+
+
+
+
+
+
2.0 = double etc.<br>
</font><font size="-1"><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -251,6 +369,15 @@ normal,
+
+
+
+
+
+
+
+
+
ss,vs: = optional horizontal, vertical scale.</span></font><br>
<font style="font-family: monospace;" size="-1"> &nbsp;</font><font
size="-1"><span style="font-family: monospace;"><a href="#F">-F</a>
@@ -268,7 +395,28 @@ normal,
- Fill whole screen with black background</span></font><br
+
+
+
+
+
+
+
+
+
+ Fill whole screen with black background</span></font><br>
+ <font size="-1"><span style="font-family: monospace;">&nbsp;</span></font><font
+ size="-1"><span style="font-family: monospace;"><a href="#E">-E</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+ </span></font><small><span style="font-family: monospace;">Video
+ encode output as (16-235)/255 "TV" levels</span></small><br
style="font-family: monospace;">
<small style="font-family: monospace;">&nbsp;<span
style="text-decoration: underline;"></span><a href="#n">-n</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -292,6 +440,15 @@ redirect
+
+
+
+
+
+
+
+
+
on test window<br>
</small><small style="font-family: monospace;">&nbsp;<a href="#J">-J</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -308,6 +465,15 @@ redirect
+
+
+
+
+
+
+
+
+
&nbsp;&nbsp;&nbsp;&nbsp; Run calibration first</small><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;<a
href="#N">-N</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -324,6 +490,15 @@ redirect
+
+
+
+
+
+
+
+
+
Disable initial calibration of instrument if possible<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
@@ -355,6 +530,15 @@ Y
+
+
+
+
+
+
+
+
+
100</span></font><small><span style="font-family: monospace;"></span></small><br>
&nbsp; <font size="-1"><span style="font-family: monospace;"><a
href="#X1">-X file.ccmx</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -371,6 +555,15 @@ Y
+
+
+
+
+
+
+
+
+
Apply Colorimeter Correction Matrix</span></font><br>
<span style="font-family: monospace;">&nbsp;<a href="#X2">-X
file.ccss</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -390,6 +583,15 @@ Calibration
+
+
+
+
+
+
+
+
+
Spectral Samples for calibration</span><font size="-1"><span
style="font-family: monospace;"><br>
</span></font><small><span style="font-family: monospace;">&nbsp;</span><a
@@ -411,6 +613,15 @@ Calibration
+
+
+
+
+
+
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1931_2 </span></small><small><span
style="font-family: monospace;">(def.)</span></small><small><span
style="font-family: monospace;">, 1964_10, S&amp;B 1955_2, shaw,
@@ -437,18 +648,46 @@ Both:
- -Ibw<br>
- </span></small><font size="-1"><span style="font-family:
- monospace;">&nbsp;</span><a style=" font-family: monospace;"
- href="#YA">-<font size="-1">Y</font> A</a><span
+
+
+
+
+
+
+
+
+
+ -Ibw</span></small><br>
+ <small><span style="font-family: monospace;"><tt>&nbsp;<a href="#YR">-Y
+ R:<i>rate</i></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Override measured refresh rate with rate Hz<br>
+ </tt>&nbsp;</span></small><font size="-1"><span
+ style="font-family: monospace;"></span><a style=" font-family:
+ monospace;" href="#YA">-<font size="-1">Y</font> A</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
Use non-adaptive integration time mode (if available).</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
+ style=" font-family: monospace;" href="#Yp">-<font size="-1">Y</font>
+ <font size="-1">p</font></a><span style="font-family:
+ monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; Don't wait for the instrument to be placed on
+ the display</span></font><br>
+ <font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#C">-C "command"</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Invoke shell
@@ -480,6 +719,15 @@ n
+
+
+
+
+
+
+
+
+
none, h = HW, x = Xon/Xoff</span></font><br>
<small style="font-family: monospace;">&nbsp;<a href="#D">-D [level]</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Print debug
@@ -498,6 +746,15 @@ n
+
+
+
+
+
+
+
+
+
Base name for input[<a href="File_Formats.html#.ti1">.ti1</a>]/output[<a
href="File_Formats.html#.ti3">.ti3</a>] file.<br>
</small> <br>
@@ -578,6 +835,15 @@ n
+
+
+
+
+
+
+
+
+
1,2</span> . Some experimentation may be needed using <a
href="dispwin.html">dispwin</a> on such systems, to discover what
screen has access to the VideoLUT hardware, and which screens the
@@ -600,9 +866,9 @@ n
URL will be printed once the server is started, or you could run <span
style="font-weight: bold;">ipconfig</span> (MSWin) or <span
style="font-weight: bold;">/sbin/ifconfig</span> (Linux or OS X)
- and identify an internet address for your machine that way.
- <b> JavaScript</b> needs to be enabled in your web browser for this
- to work.<br>
+ and identify an internet address for your machine that way. <b>
+ JavaScript</b> needs to be enabled in your web browser for this to
+ work.<br>
<br>
Note that if you use this method of displaying test patches, that
there is no access to the display VideoLUTs and that the colors will
@@ -613,6 +879,17 @@ n
See the <a href="dispcal.html#o">-o</a> flag for an explanation of
the implications of having no access to the VideoLUTs.<br>
<br>
+ <a name="dmadvr"></a><span style="font-weight: bold;">-dmadvr</span>
+ [MSWin only] causes test patches to be displayed using the MadVR
+ video renderer. Note that you may have to start the video playback
+ software and load a video clip in pause for this to work. MadVR
+ rendering does not need or support VideoLUT access, so the <a
+ href="#K">-K</a> option should be used to read calibrated values.
+ Be aware that the state of the Graphics Card VideoLUTs may affect
+ the results, and therefore may have to be set appropriately using
+ dispwin. By default the test patch colors will <u>not</u> be
+ processed by the MadVR 3dLut (see the -<a href="#V">V</a> flag).<br>
+ <br>
<a name="c"></a> <span style="font-weight: bold;">-c</span>: The
instrument is assumed to communicate through a USB or serial
communication port, and the port can be selected with the <b>-c</b>
@@ -650,9 +927,9 @@ n
and how this works, see <a href="instruments.html">Operation of
particular instruments</a>. <b>3)</b> Any installed CCSS files
(if applicable), or CCMX files. These files are typically created
- using <a href="file:///D:/src/argyll/doc/ccxxmake.html">ccxxmake</a>,
+ using <a href="ccxxmake.html">ccxxmake</a>,
and installed using <a
- href="file:///D:/src/argyll/doc/oeminst.html">oeminst</a>. The
+ href="oeminst.html">oeminst</a>. The
default and Base Calibration types will be indicated in the usage.<br>
<br>
<a name="s"></a><span style="font-weight: bold;">-s</span>: By
@@ -664,7 +941,7 @@ n
<a name="k"></a> <span style="font-weight: bold;">-k: </span>If a
display video lookup table calibration <a
href="File_Formats.html#.cal">.cal</a> file is provided, it will
- be loaded into the display <span style="font-weight: bold;">ViedoLUTs</span>
+ be loaded into the display <span style="font-weight: bold;">VideoLUTs</span>
while the measurements are being taken, thereby being applied to the
measurement values, and the calibration will also included in the
resulting .ti3 data file, so that <a href="colprof.html">colprof</a>
@@ -672,14 +949,20 @@ n
tag in the resulting profile. This is the <span style="font-weight:
bold;">normal</span> way to profile a calibrated display. The
calibration file has usually been created using <a
- href="dispcal.html">dispcal</a>. If a calibration file is not
- created, then the display will be read in whatever calibration state
- it is in. If the calibration file indicates that the displays
- VideoLUTs are not accessible, or if they prove not to be accessible,
- then dispread will switch to <span style="font-weight: bold;">-K</span>
- mode (see below). <span style="font-weight: bold;">NOTE</span> that
- the calibration is loaded into the display hardware just before the
- instrument starts measurement, after the test window first appears.<br>
+ href="dispcal.html">dispcal</a>. If the calibration file indicates
+ that the displays VideoLUTs are not accessible, or if they prove not
+ to be accessible, then dispread will switch to <span
+ style="font-weight: bold;">-K</span> mode (see below). If a
+ calibration file is not supplied using <b>-k</b> or <b>-K</b>,
+ then the display will be measured in whatever calibration state it
+ is in, and no calibration information is saved to the resulting .ti3
+ file.<br>
+ If the calibration file provided created using video range encoding
+ (dispcal -E), then the <b>-E</b> option in dispread will be
+ triggered automatically.<br>
+ <span style="font-weight: bold;">NOTE</span> that the calibration is
+ loaded into the display hardware just before the instrument starts
+ measurement, after the test window first appears.<br>
<br>
<a name="K"></a> <span style="font-weight: bold;">-K: </span>If a
display video lookup table calibration <a
@@ -691,7 +974,18 @@ n
profile. This is <span style="font-weight: bold;">NOT</span>
normally the best way to profile a calibrated display, since the
frame buffer may have lower precision than the VideoLUTs output
- values.<br>
+ values. This is the way calibration should be applied if MadVR is
+ being used to display the test patches. If a calibration file is not
+ supplied using <b>-k</b> or <b>-K</b>, then the display will be
+ measured in whatever calibration state it is in, and no calibration
+ information is saved to the resulting .ti3 file.<br>
+ If the calibration file provided created using video range encoding
+ (dispcal -E), then the <b>-E</b> option in dispread will be
+ triggered automatically.<br>
+ <br>
+ <a name="V"></a><b>-V:</b> [MSWin] If using MadVR to display test
+ patches, then enable Color Managenent (3dLut). This would be used
+ for verification measurement.<br>
<br>
<a name="P"></a> The <span style="font-weight: bold;">-P</span>
parameter allows you to position and size the test patch window. By
@@ -720,6 +1014,12 @@ n
with black. This can aid black accuracy when measuring CRT displays
or projectors.<br>
<br>
+ <a name="E"></a> The <span style="font-weight: bold;">-E</span>
+ flag causes the test values to be scaled to the Video RGB encoding
+ range of 16/255 to 235/255. If the calibration file provided using
+ the <b>-k</b> or <b>-K</b> flag was created using video range
+ encoding, then this option will be triggered automatically.<br>
+ <br>
<a name="n"></a><span style="font-weight: bold;">-n</span>: When
running on a UNIX based system that used the X11 Windowing System, <b>dispread</b>
normally selects the override redirect so that the test window will
@@ -795,6 +1095,15 @@ a
+
+
+
+
+
+
+
+
+
colorimeters accuracy for a particular type of display.<br>
<br>
<a name="Q"></a> The <b>-Q</b> flag allows specifying a tristimulus
@@ -835,9 +1144,14 @@ a
If just display white level compensation is needed, use <span
style="font-weight: bold;">-Iw</span>. If both are needed, use <span
style="font-weight: bold;">-Ibw</span> or <span
- style="font-weight: bold;">-Iwb</span>.<span style="font-weight:
- bold;"> <br>
- <br>
+ style="font-weight: bold;">-Iwb</span>.<br>
+ <br>
+ <a name="YR"></a> The -<span style="font-weight: bold;">Y R:<i>rate</i></span>
+ options overrides calibration of the instrument refresh rate. This
+ may be useful if the instrument supports this function and the
+ refresh rate cannot be accurately calibrated from the display
+ itself.<br>
+ <span style="font-weight: bold;">&nbsp;<br>
</span><a name="YA"></a> The -<span style="font-weight: bold;">Y A</span>
option uses a non-adaptive integration time emission measurement
mode, if the instrument supports it, such as the Eye-One Pro or
@@ -846,7 +1160,14 @@ a
a fixed integration time mode that can be used with display devices.
This may give increased consistency and faster measurement times,
but may also give less accurate low level readings.<br>
- <span style="font-weight: bold;"> <br>
+ <br>
+ <a name="Yp"></a> The -<span style="font-weight: bold;">Y p</span>
+ option skips asking the user to place the instrument on the display.
+ Normally a grey patch is displayed, and then the user is asked to
+ confirm that the instrument is in place, so that readings can
+ commence. This flag disables that check. This may be useful in
+ automating certain operations.<br>
+ <span style="font-weight: bold;"><br>
</span><a name="C"></a> The -<span style="font-weight: bold;">C</span>
<span style="font-weight: bold;">"command" </span>option allows a
method of relaying each test value to some other display than that
diff --git a/doc/dispwin.html b/doc/dispwin.html
index a07d50f..f1d75f5 100644
--- a/doc/dispwin.html
+++ b/doc/dispwin.html
@@ -43,6 +43,10 @@ Verbose
+
+
+
+
mode<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;</span><a style="font-family: monospace;"
@@ -64,6 +68,10 @@ optionally
+
+
+
+
choose a different display m for Video LUT access.<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#d">-d n</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -76,6 +84,10 @@ X11]
+
+
+
+
Choose the display from the following list (default 1)<br>
</span></font><span style="font-family: monospace;">&nbsp;<a
href="#dweb">-dweb[:port]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -84,7 +96,15 @@ X11]
- Display via a web server at port (default 8080)</span><br
+
+
+
+
+ Display via a web server at port (default 8080)</span><br>
+ <span style="font-family: monospace;">&nbsp;<a
+ href="dispwin.html#dmadvr">-dmadvr</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ [MSWin] Display via MadVR Video Renderer</span><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;<a href="#P">-P
@@ -100,6 +120,10 @@ ho,vi:
+
+
+
+
= left/top, 0.5 = center, 1.0 = right/bottom etc.</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -112,11 +136,19 @@ ss:
+
+
+
+
= half, 1.0 = normal, 2.0 = double etc.<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
ss,vs: = optional horizontal, vertical scale.<br>
&nbsp;</span></font><font size="-1"><span style="font-family:
monospace;"><a href="#F">-F</a>
@@ -130,7 +162,18 @@ whole
- screen with black background</span></font><br
+
+
+
+
+ screen with black background</span></font><br>
+ <font size="-1"><span style="font-family: monospace;">&nbsp;</span></font><font
+ size="-1"><span style="font-family: monospace;"><a href="#E">-E</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+ </span></font><small><span style="font-family: monospace;">Video
+ encode output as (16-235)/255 "TV" levels</span></small><br
style="font-family: monospace;">
<font size="-1"><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
@@ -157,6 +200,10 @@ just
+
+
+
+
video LUT loading &amp; Beeps<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#n">-n</a>
@@ -170,7 +217,11 @@ native
- display values (rather than through Video LUT)<br>
+
+
+
+
+ display values (rather than through Video LUT&nbsp; and C.M.)<br>
&nbsp;<a href="#s">-s <span style="font-style: italic;">filename.cal</span></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Save
the
@@ -181,6 +232,10 @@ the
+
+
+
+
currently loaded Video LUT to 'filename'<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#c">-c</a>
@@ -194,6 +249,10 @@ a
+
+
+
+
linear display calibration (clear calibration)</span></font><font
size="-1"><span style="font-family: monospace;"><br>
</span></font><font size="-1"><span style="font-family:
@@ -208,6 +267,10 @@ that
+
+
+
+
calfile/profile cal. is currently loaded in LUT<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#I">-I</a>
@@ -219,6 +282,10 @@ that
+
+
+
+
</span></font><font size="-1"><span style="font-family:
monospace;">Install profile for display and use it's calibration<br>
</span></font><font size="-1"><span style="font-family:
@@ -231,6 +298,10 @@ that
+
+
+
+
</span></font><font size="-1"><span style="font-family:
monospace;">Un-install profile for display<br>
&nbsp;<a href="#S">-S d</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -243,6 +314,10 @@ the
+
+
+
+
install/uninstall scope for OS X [nlu] or Vista [lu]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
d
@@ -254,6 +329,10 @@ is
+
+
+
+
one of: n = network, l = local system, u = user (default)<br>
</span></font><font size="-1"><span style="font-family:
monospace;"></span></font><font size="-1"><span
@@ -266,10 +345,14 @@ is
+
+
+
+
</span></font><font size="-1"><span style="font-family:
monospace;">Load installed profiles cal. into Video LUT<br>
</span></font><font size="-1"><span style="font-family:
- monospace;">&nbsp;<a href="#E">-E</a>
+ monospace;">&nbsp;<a href="#X">-<font size="-1">X</font></a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -278,6 +361,10 @@ is
+
+
+
+
[<span style="font-weight: bold;">X11 only</span>] Run in daemon
loader mode for given X11 server <br>
</span></font><font size="-1"><span style="font-family:
@@ -292,6 +379,10 @@ debug
+
+
+
+
diagnostics to stderr</span></font><font size="-1"><span
style="font-family: monospace;"></span></font><font size="-1"><span
style="font-family: monospace;"></span><span style="font-family:
@@ -309,6 +400,10 @@ display
+
+
+
+
calibration (<a href="cal_format.html">.cal</a> or .icm) into
LUT, and exit.</span><span style="font-family: monospace;"></span><span
style="font-family: monospace;"></span></font><br>
@@ -372,6 +467,10 @@ the
+
+
+
+
difficulty cause by TwinView and MergedFB in X11 based systems, you
can optionally specify a separate display number after the display
that is going to be used to present test patches, for accessing the
@@ -406,6 +505,16 @@ the
operation that depends on accessing the VideoLUTs will either
generate a warning or fail.<br>
<br>
+ <a name="dmadvr"></a><span style="font-weight: bold;">-dmadvr</span>
+ [MSWin only] causes test patches to be displayed using the MadVR
+ video renderer. Note that you may have to start the video playback
+ software and load a video clip in pause for this to work. MadVR
+ rendering does not need or support VideoLUT access, but be aware
+ that the state of the Graphics Card VideoLUTs may affect the results
+ (check this using dispwin). Test patch colors <u>will</u> be
+ processed by the MadVR 3dLut by default (see <a href="#n">-n</a>
+ flag).<br>
+ <br>
<a name="P"></a> The <span style="font-weight: bold;">-P</span>
parameter allows you to position and size the test patch window. By
default it is places in the center of the screen, and sized
@@ -433,6 +542,12 @@ the
with black. This can aid black accuracy when measuring CRT displays
or projectors.<br>
<br>
+ <a name="E"></a> The <span style="font-weight: bold;">-E</span>
+ flag causes the test values to be scaled to the Video RGB encoding
+ range of 16/255 to 235/255. Note that this is not applicable if the
+ MadVR render is being used to display patches, as MadVR should be
+ configured for Video encoding instead.<br>
+ <br>
By default <span style="font-weight: bold;">dispwin</span> will put
a test window on the selected display, and display some test colors,
before darkening&nbsp; then brightening the screen by loading video
@@ -463,7 +578,9 @@ the
If the&nbsp;<a name="n"></a><span style="font-weight: bold;">-n</span>
flag is set, then <span style="font-weight: bold;">dispwin</span>
will display the colors directly on the display, rather than having
- the color values translated through the currently loaded Video LUTs.<br>
+ the color values translated through the currently loaded Video LUTs.
+ In the case of using the MadVR renderer to display the patches, any
+ 3dLut will also be disabled.<br>
<br>
<a name="s"></a> If a <span style="font-weight: bold;">-s <span
style="font-style: italic;">filename.cal</span></span> option is
@@ -507,7 +624,9 @@ the
particular X11 display, and expands it to accomodate XrandR 1.2.
Note that for X11 systems, the properties are not persistent, and
will need to be loaded each time the X11 server is started (see the
- <a href="#L">-L</a> flag).<br>
+ <a href="#L">-L</a> flag). To make sure that the profile calbration
+ 'vcgt' tag gets loaded into the Graphics Card at system start,
+ please read the guide <a href="dispprofloc.html">here</a>.<br>
<br>
<a name="U"></a><span style="font-weight: bold;">-U</span>: The ICC
profile specified as the final argument will be un-installed as the
@@ -539,7 +658,7 @@ the
display on system startup from the installed display profile, if the
system doesn't not do this automatically .<br>
<br>
- <a name="E"></a> <span style="font-weight: bold;">-E</span>: Daemon
+ <a name="X"></a> <span style="font-weight: bold;">-X</span>: Daemon
mode (experimental). When running on a UNIX based system that used
the X11 Windowing System, this option runs dispwin in a "daemon"
mode where it monitors the given X11 server, waiting for any changes
diff --git a/doc/fakeread.html b/doc/fakeread.html
index aa2847c..2a7b5c0 100644
--- a/doc/fakeread.html
+++ b/doc/fakeread.html
@@ -1,248 +1,372 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
-<head>
- <title>fakeread</title>
- <meta http-equiv="content-type"
- content="text/html; charset=ISO-8859-1">
- <meta name="author" content="Graeme Gill">
-</head>
-<body>
-<h2><b>spectro/fakeread</b></h2>
-<h3>Summary</h3>
-Simulate the measurement of a devices response, using an existing
-device profile, or measured test point data set. The device profile can
-be either
-an <a href="File_Formats.html#ICC">ICC</a> or <a
- href="File_Formats.html#MPP">MPP</a> profile, or the data set can be a
-<a href="File_Formats.html#.ti3">.ti3</a> file. A device link
-separation or color space conversion can be applied before the
-print/measure simulation.<br>
-<h3>Usage</h3>
-<small><span style="font-family: monospace;">fakeread [-v] [-s] </span></small><small><span
- style="font-family: monospace;">[<span style="font-style: italic;">separation.ic<span
- style="font-family: monospace;">m</span></span>] </span></small><small><span
- style="font-family: monospace;"></span><i
- style="font-family: monospace;">profile.</i><span
- style="font-family: monospace;">[icm|mpp|ti3] </span><i
- style="font-family: monospace;">inoutfile</i><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <head>
+ <title>fakeread</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=ISO-8859-1">
+ <meta name="author" content="Graeme Gill">
+ </head>
+ <body>
+ <h2><b>spectro/fakeread</b></h2>
+ <h3>Summary</h3>
+ Simulate the measurement of a devices response, using an existing
+ device profile, or measured test point data set. The device profile
+ can be either an <a href="File_Formats.html#ICC">ICC</a> or <a
+ href="File_Formats.html#MPP">MPP</a> profile, or the data set can
+ be a <a href="File_Formats.html#.ti3">.ti3</a> file. A device link
+ separation or color space conversion can be applied before the
+ print/measure simulation, as well as device calibration&nbsp; or
+ inverse calibration curves.<br>
+ <br>
+ <b>fakeread</b> can be useful for creating a data set from an
+ existing profile to re-create a different style of profile (i.e.
+ create a cLUT profile from a matrix profile), for creating synthetic
+ data sets with known amounts of randomness for testing profile
+ creation against a perfectly known ideal, or for creating
+ verification test sets for checking colorimetric colorspace
+ emulation against.<br>
+ <br>
+ The options below are in the order of color processing that fakeread
+ performs.<br>
+ <h3>Usage</h3>
+ <small><span style="font-family: monospace;">fakeread [-options] </span></small><small><span
+ style="font-family: monospace;"></span></small><small><span
+ style="font-family: monospace;"></span><i style="font-family:
+ monospace;">profile.</i><span style="font-family: monospace;">[icm|mpp|ti3]
+
+ </span><i style="font-family: monospace;">inoutfile</i></small><small><span
+ style="font-family: monospace;"><br>
+ &nbsp;-v
+ [n]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Verbose mode [level]<br>
+ &nbsp;-e
+ flag&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Video encode device input to sepration as:<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ normal 0..1 full range RGB levels (default)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ (16-235)/255 "TV" RGB levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec601 YCbCr SD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec709 1125/60Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec709 1250/50Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec2020 YCbCr UHD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 "TV"
+ levels<br>
+ &nbsp;-p <i>separation.icm</i> Use device link separation
+ profile on input<br>
+ &nbsp;-E
+ flag&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Video decode separation device output. See -e above<br>
+ &nbsp;-k <i>file.cal</i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Apply calibration (include in .ti3 output)<br>
+ &nbsp;-i <i>file.cal</i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Include calibration in .ti3 output, but don't apply it<br>
+ &nbsp;-K <i>file.cal</i>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Apply inverse calibration<br>
+ &nbsp;-r
+ level&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Add
+ average random deviation of &lt;level&gt;% to device values
+ (after sep. &amp; cal.)<br>
+ &nbsp;-0
+ pow&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Apply power to device chanel 0-9<br>
+ &nbsp;-b <i>output.icm</i>&nbsp;&nbsp;&nbsp;&nbsp; Apply
+ BT.1886-like mapping with effective gamma 2.2<br>
+ &nbsp;-b g.g:<i>output.icm</i> Apply BT.1886-like mapping with
+ effective gamma g.g<br>
+ &nbsp;-B <i>output.icm</i>&nbsp;&nbsp;&nbsp;&nbsp; Apply
+ BT.1886 mapping with technical gamma 2.4<br>
+ &nbsp;-B g.g:<i>output.icm</i> Apply BT.1886 mapping with
+ technical gamma g.g<br>
+ &nbsp;-I intent&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ r = relative colorimetric, a = absolute (default)<br>
+ &nbsp;-A
+ L,a,b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Scale black point to target Lab value<br>
+ &nbsp;-l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Output Lab rather than XYZ<br>
+ &nbsp;-s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Lookup </span></small><small><span style="font-family:
+ monospace;"><small><a style="font-family: monospace;"
+ href="File_Formats.html#MPP">MPP</a></small>
+ spectral values</span></small><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;-R
+ level&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Add average random deviation of &lt;level&gt;% to output PCS
+ values<br>
+ </span></small>&nbsp;-u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Make random deviations have uniform distributions rather than
+ normal<br>
+ &nbsp;-S
+ seed&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Set random seed<br>
+ </span><span style="font-family: monospace;">&nbsp;</span><i
+ style="font-family: monospace;">profile.</i><span
+ style="font-family: monospace;">[icm|mpp|ti3] &nbsp; &nbsp; </span><a
+ style="font-family: monospace;" href="File_Formats.html#ICC">ICC</a><span
+ style="font-family: monospace;">, </span><a style="font-family:
+ monospace;" href="File_Formats.html#MPP">MPP</a><span
+ style="font-family: monospace;"> or&nbsp;</span><a
+ style="font-family: monospace;" href="File_Formats.html#.ti3">.ti3</a><span
+ style="font-family: monospace;"> profile/file to use</span><br
+ style="font-family: monospace;">
+ &nbsp; <span style="font-family: monospace;"></span><i
+ style="font-family: monospace;">inoutfile</i><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
-&nbsp; &nbsp; &nbsp; Verbose mode</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;-s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
-&nbsp; &nbsp; &nbsp; Lookup </span><a style="font-family: monospace;"
- href="File_Formats.html#MPP">MPP</a><span
- style="font-family: monospace;"> spectral values</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;-p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Use
-separation profile</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;-l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Output
-Lab rather than XYZ<br>
-&nbsp;-k
-file.cal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Apply
-calibration (after sep.) and include in .ti3<br>
-&nbsp;-i
-file.cal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Include
-calibration in .ti3 (but don't apply it)<br>
-</span></small><small><span style="font-family: monospace;">&nbsp;-r
-level&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Add
-average random deviation of &lt;level&gt;% to input device values
-(after sep. &amp; cal.)</span></small><br
- style="font-family: monospace;">
-<small><span style="font-family: monospace;"></span><span
- style="font-family: monospace;">&nbsp;-0
-pow&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Apply
-power to input device chanel 0-9 (after sep. cal. &amp; rand.)</span><br
- style="font-family: monospace;">
-&nbsp;
-<span style="font-family: monospace;">-R
-level&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Add
-average random deviation of &lt;level&gt;% to output PCS values<br>
-</span></small><small><span style="font-family: monospace;">&nbsp;-u
-&nbsp; &nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Make
-random deviations have uniform distributions rather than normal<br>
-&nbsp;-S
-seed&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Set
-random seed<br style="font-family: monospace;">
-</span></small><small><span style="font-family: monospace;"></span><span
- style="font-family: monospace;">&nbsp;-b
-L,a,b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Scale
-black point to target Lab value<br>
-&nbsp;-I
-intent&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-r = relative colorimetric, a = absolute (default)<br
- style="font-family: monospace;">
-</span><span style="font-family: monospace;">&nbsp;[<span
- style="font-style: italic;">separation.ic<span
- style="font-family: monospace;">m</span></span>]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Device
-link separation profile</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><i
- style="font-family: monospace;">profile.</i><span
- style="font-family: monospace;">[icm|mpp|ti3] &nbsp; &nbsp; </span><a
- style="font-family: monospace;" href="File_Formats.html#ICC">ICC</a><span
- style="font-family: monospace;">, </span><a
- style="font-family: monospace;" href="File_Formats.html#MPP">MPP</a><span
- style="font-family: monospace;">
-or&nbsp;</span><a style="font-family: monospace;"
- href="File_Formats.html#.ti3">.ti3</a><span
- style="font-family: monospace;">
-profile/file to use</span><br style="font-family: monospace;">
-&nbsp;
-<span style="font-family: monospace;"></span><i
- style="font-family: monospace;">inoutfile</i><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;
-&nbsp; &nbsp; Base name for
-input[</span><a style="font-family: monospace;"
- href="File_Formats.html#.ti1">.ti1</a><span
- style="font-family: monospace;">]/output[</span><a
- style="font-family: monospace;" href="File_Formats.html#.ti3">.ti3</a><span
- style="font-family: monospace;">] file</span></small><br>
-<b><br>
-Examples</b><br>
-<br>
-fakeread profile.icm testvalues<br>
-fakeread -p separation.icm profile.icm testvalues<br>
-<h3>Comments<br>
-</h3>
-The <span style="font-weight: bold;">-v</span> flag does nothing at
-the moment.<br>
-The <span style="font-weight: bold;">-s</span> flag works only with
-MPP profiles that contain spectral model
-information.<br>
-The <span style="font-weight: bold;">-p</span> flag enables a device
-to device value conversion before
-converting to expected PCS values.<br>
-The <span style="font-weight: bold;">-l</span> flag causes the CIE
-output values to be L*a*b* rather than the
-default XYZ values.<br>
-<br>
-The <b>-k file.cal</b> parameter specifies a printer
-calibration file created by <a href="printcal.html">printcal</a>, and
-the supplied calibration curves will be applied to the chart device
-values after any separation. This allows emulating a system that uses
-per device channel calibration. The calibration curves will also be
-included in
-the resulting .ti3 file, so that they can be passed through to the ICC
-profile allowing accurate computation of ink
-limits.<br>
-<br>
-<a name="i"></a> The <b>-i file.cal</b> parameter specifies a printer
-calibration file created by <a href="printcal.html">printcal</a>,
-and the calibration curves will be
-included in the included in
-the resulting .ti3 file, so that they can be passed through to the ICC
-profile, to allow accurate computation of ink limits.
-The calibration <span style="font-weight: bold;">is not applied</span>
-to tchart values. <span style="font-weight: bold;">Note</span> that if
-the supplied ICC profile contains calibration curves, that these will
-be included in the resulting .ti3 by default.<br>
-<span style="font-weight: bold;"></span><br>
-The <span style="font-weight: bold;">-r</span> parameter is a way of
-simulating instability in the behaviour of
-the simulated
-printing system. The parameter supplied to the flag will be used to
-scale a random offset added to the device values (after any separation
-and calibration is applied). The offset will be a normally distributed
-error with an
-average deviation of level%. A typically value supplied
-might be 1.0 to simulate 1% randomness.<br>
-<br>
-The <span style="font-weight: bold;">-0, -1, -2 .. -9</span>
-parameters are a way of simulating changes in the
-behaviour of the simulated printing system. The parameter supplied to
-the flag will be used to modify the device values (after any
-separation, calibration and device randomness
-is applied) by raising them to the power of the parameter. This applies
-a transfer curve to the simulated device response.<br>
-<br>
-The <span style="font-weight: bold;">-R</span> parameter is a way of
-simulating instability in the behaviour of
-the simulated
-measuring system. The parameter supplied to the flag will be used to
-scale a random offset added to the PCS values. The offset will be a
-normally distributed error with an average deviation of level%. A
-typically value supplied
-might be 1.0 to simulate 1% randomness. <br>
-<br>
-The <span style="font-weight: bold;">-u</span> flag changes the
-distribution of the random offsets applied using the <span
- style="font-weight: bold;">-r</span> or <span
- style="font-weight: bold;">-R</span> flags, from the default standard
-deviation, to a uniform deviation distribution. The level is still
-specified as an average deviation.<br>
-<br>
-The <span style="font-weight: bold;">-S</span> parameter lets a
-particular random seed be used when generating random offsets, so that
-the randomness can be made repeatable. Normally a different seed will
-be used for each run. <br>
-<br>
-The <span style="font-weight: bold;">-b</span> parameter is a way of
-simulating devices that have a different black point to the profile
-used. This only works if an ICC profile is used, and scales the black
-point to the parameter value. This will be done in XYZ space by
-default, and in L*a*b* space if the <span style="font-weight: bold;">-l</span>
-flag is used.<br>
-<br>
-The <span style="font-weight: bold;">-I</span> parameter allows
-changing the intent used in looking up the ICC profile colors to
-relative colorimetric. This would <span
- style="text-decoration: underline;">not</span> be used if you intend
-to make a profile from the resulting .ti3 file, since profiles are
-always made from absolute colorimetric measurement values. Note that
-this flag does nothing if the profile is an MPP or .ti3 file.<br>
-<br>
-Fakeread is useful in creating artificial test value for testing <a
- href="colprof.html">colprof</a>, as well as providing one path for
-turning an MPP profile into an ICC profile. If a <a
- href="File_Formats.html#.ti3">.ti3</a> file is
-specified instead of an <a href="File_Formats.html#ICC">ICC</a> or <a
- href="File_Formats.html#MPP">MPP</a> profile,
-then the closest matching measured points in the .<a
- href="File_Formats.html#.ti3">.ti3</a> are substituted
-for the test values in the <a href="File_Formats.html#.ti1">.ti1</a>
-file on
-output. If the <a href="File_Formats.html#.ti1">.ti1</a>
-file is a monochrome test file with a White device value, then an RGB <a
- href="File_Formats.html#ICC">ICC</a> profile, <a
- href="File_Formats.html#MPP">MPP</a> or <a
- href="File_Formats.html#.ti3">.ti3</a> may be used, and the White
-values will be translated to equal RGB values. If the <a
- href="File_Formats.html#.ti1">.ti1</a>
-file is a monochrome test file with a Black device value, then a CMYK <a
- href="File_Formats.html#ICC">ICC</a> profile, <a
- href="File_Formats.html#MPP">MPP</a> or <a
- href="File_Formats.html#.ti3">.ti3</a> may be used, and the Black
-values will be translated to equal CMY = 0, K = grey values. <span
- style="font-weight: bold;">Note</span> that
-any calibration within a supplied ICC profile is <span
- style="text-decoration: underline;">not</span> applied during the
-conversion, although it will be included in the .ti3 output (see <span
- style="font-weight: bold;">-k</span> and <span
- style="font-weight: bold;">-i</span> flags for how apply calibration
-curves during the conversion and/or include
-a specific calibration curves in the output).<br>
-<br>
-If a separation device profile is provided (e.g. from CMY -&gt; CMYK,
-or perhaps CMYK-&gt;CMYK, to simulate a color correction step before
-"printing"), then this will be applied to the .ti1 device values,
-before converting the the device values into .ti3 PCS values.<br>
-<br>
-<br>
-<br>
-</body>
+
+
+ &nbsp; Base name for input[</span><a style="font-family:
+ monospace;" href="File_Formats.html#.ti1">.ti1</a><span
+ style="font-family: monospace;">]/output[</span><a
+ style="font-family: monospace;" href="File_Formats.html#.ti3">.ti3</a><span
+ style="font-family: monospace;">] file</span></small><br>
+ <b><br>
+ Examples</b><br>
+ <br>
+ fakeread profile.icm testvalues<br>
+ fakeread -p separation.icm profile.icm testvalues<br>
+ <h3>Comments<br>
+ </h3>
+ <a name="v"></a>The <span style="font-weight: bold;">-v</span> flag
+ reports extra information, e.g. on what BT.1886 option is doing. A
+ level &gt; 1 will be more verbose.<br>
+ <br>
+ <a name="e"></a>The <b>-e</b> <i>flag</i> applies a Video encoding
+ to the input of the separation.<small><small><br>
+ <br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ normal 0..1 full range RGB levels (default)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ (16-235)/255 "TV" RGB levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec601 YCbCr SD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec709 1125/60Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec709 1250/50Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec2020 YCbCr UHD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 "TV" lev</small></small><br>
+ <br>
+ <a name="p"></a>The <span style="font-weight: bold;">-p</span> <b><i>separation.icm</i></b>
+ option enables a device to device value conversion before converting
+ to expected PCS values. This might be an ink separation of a video
+ calibration device link. The argument is the name of the ICC device
+ link that defines the separation.<br>
+ <br>
+ <a name="E"></a>The <b>-E</b> <i>flag</i> applies a Video decoding
+ to the output of the separation.<small><small> &nbsp; </small></small>See
+ <a href="#e"><b>-e</b></a> for the list of decodings.<br>
+ <br>
+ <a name="k"></a>The <b>-k file.cal</b> parameter specifies a
+ calibration file created by <a
+ href="printcal.html">printcal</a> or <a
+ href="dispcal.html">dispcal</a>, and the supplied calibration
+ curves will be applied to the chart device values after any
+ separation and before the device profile. This allows emulating a
+ system that uses per device channel calibration. The calibration
+ curves will also be included in the resulting .ti3 file, so that
+ they can be passed through to the ICC profile allowing accurate
+ computation of ink limits.<br>
+ <br>
+ <a name="i"></a> The <b>-i file.cal</b> parameter specifies a
+ printer calibration file created by <a
+ href="printcal.html">printcal</a> or <a
+ href="dispcal.html">dispcal</a>, and the
+ calibration curves will be included in the included in the resulting
+ .ti3 file, so that they can be passed through to the ICC profile, to
+ allow accurate computation of ink limits. The calibration <span
+ style="font-weight: bold;">is not applied</span> to tchart values.
+ <span style="font-weight: bold;">Note</span> that if the supplied
+ ICC profile contains VCGT calibration curves, that these will be
+ included in the resulting .ti3 by default.<br>
+ <br>
+ <a name="K"></a>The <b>-K</b> <b>file.cal</b> parameter specifies
+ a calibration file created by <a
+ href="printcal.html">printcal</a> or <a
+ href="dispcal.html">dispcal</a>, and the
+ inverse of the supplied calibration curves will be applied to the
+ chart device values after any separation and before the device
+ profile. This allows for undoing calibration curves that may be part
+ of a video calibration device link, so that the (calibrated device
+ value) device profile will work as expected.<br>
+ <br>
+ <a name="r"></a>The <span style="font-weight: bold;">-r</span>
+ parameter is a way of simulating instability in the behaviour of the
+ simulated printing system. The parameter supplied to the flag will
+ be used to scale a random offset added to the device values (after
+ any separation and calibration is applied). The offset will be a
+ normally distributed error with an average deviation of level%. A
+ typically value supplied might be 1.0 to simulate 1% randomness.<br>
+ <br>
+ <a name="0"></a>The <span style="font-weight: bold;">-0, -1, -2 ..
+ -9</span> parameters are a way of simulating changes in the
+ behavior of the simulated printing system. The parameter supplied to
+ the flag will be used to modify the device values (after any
+ separation, calibration and device randomness is applied) by raising
+ them to the power of the parameter. This applies a transfer curve to
+ the simulated device response.<br>
+ <br>
+ <a name="b"></a>The <b>-b output.icm</b> flag applies extra input
+ processing, applying <a
+ href="http://www.itu.int/rec/R-REC-BT.1886-0-201103-I">BT.1886</a>-like
+
+
+
+
+
+
+
+
+
+
+
+ video gamma mapping using an effective gamma of 2.2 by default, and
+ overridable using <b>-b g.g:output.icm</b> where <b>g.g</b> is the
+ gamma. <b>output.icm</b> is the display ICC profile that provides
+ the black point that the BT.1886 curves will target. The gamma is an
+ effective gamma, meaning that its effect on 50% input is the same as
+ that of a pure power curve, in spite of any black offset added by
+ BT.1886. This has the benefit of making the overall effect of
+ brightness independent of the black level of the display. Setting an
+ effective gamma other than 2.2 is one way of making the viewing
+ condition adjustment for the different conditions of video encoding
+ and decoding, or for modelling the source colorspace as a rendering
+ on a video display. BT.1886 will only work with matrix type input
+ profiles. Typically this will be used to create a verification test
+ set for checking the operation of a device link or 3dLut created
+ using <a href="collink.html">collink</a>, using the same BT.1886
+ parameters.<br>
+ <br>
+ <b><a name="B"></a></b>The <b>-B output.icm</b> flag applies extra
+ input processing, applying <a
+ href="http://www.itu.int/rec/R-REC-BT.1886-0-201103-I">BT.1886</a>-like
+
+
+
+
+
+
+
+
+
+
+
+ video gamma mapping using a gamma of 2.4 by default, and overridable
+ using <b>-B g.g:output.icm</b> where <b>g.g</b> is the gamma. <b>output.icm</b>
+ is the display ICC profile that provides the black point that the
+ BT.1886 curves will target. The gamma is the technical gamma, or
+ power applied to the input image, and this means that its effect on
+ 50% input will depend on the black level of the display, making the
+ overall brightness somewhat unpredictable. For a more predictable
+ effect, use <b>-b</b>.<br>
+ <br>
+ <a name="I"></a>The <span style="font-weight: bold;">-I</span>
+ parameter allows changing the intent used in looking up the ICC
+ profile colors to relative colorimetric. This would <span
+ style="text-decoration: underline;">not</span> be used if you
+ intend to make a profile from the resulting .ti3 file, since
+ profiles are always made from absolute colorimetric measurement
+ values. Note that this flag does nothing if the profile is an MPP or
+ .ti3 file.<br>
+ <span style="font-weight: bold;"></span><br>
+ <a name="A"></a>The <span style="font-weight: bold;">-A</span>
+ parameter is a way of simulating devices that have a different black
+ point to the profile used. This only works if an ICC profile is
+ used, and scales the black point to the parameter value. This will
+ be done in XYZ space by default, and in L*a*b* space if the <a
+ href="#l"><span style="font-weight: bold;">-l</span></a> flag is
+ used.<br>
+ <br>
+ <a name="l"></a>The <span style="font-weight: bold;">-l</span> flag
+ causes the CIE output values to be L*a*b* rather than the default
+ XYZ values.<br>
+ <br>
+ <a name="s"></a>The <span style="font-weight: bold;">-s</span> flag
+ works if a spectral MPP file is being used as a device profile, and
+ causes the output to include spectral values.<br>
+ <br>
+ <a name="R"></a>The <span style="font-weight: bold;">-R</span>
+ parameter is a way of simulating instability in the behavior of the
+ simulated measuring system. The parameter supplied to the flag will
+ be used to scale a random offset added to the PCS values. The offset
+ will be a normally distributed error with an average deviation of
+ level%. A typically value supplied might be 1.0 to simulate 1%
+ randomness. <br>
+ <br>
+ <a name="u"></a>The <span style="font-weight: bold;">-u</span> flag
+ changes the distribution of the random offsets applied using the <span
+ style="font-weight: bold;">-r</span> or <span style="font-weight:
+ bold;">-R</span> flags, from the default standard deviation, to a
+ uniform deviation distribution. The level is still specified as an
+ average deviation.<br>
+ <br>
+ <a name="S"></a>The <span style="font-weight: bold;">-S</span>
+ parameter lets a particular random seed be used when generating
+ random offsets, so that the randomness can be made repeatable.
+ Normally a different seed will be used for each run. <br>
+ <br>
+ Fakeread is useful in creating artificial test value for testing <a
+ href="colprof.html">colprof</a>, as well as providing one path for
+ turning an MPP profile into an ICC profile. It can also be used to
+ create a reference file for verifying against. If a <a
+ href="File_Formats.html#.ti3">.ti3</a> file is specified instead
+ of an <a href="File_Formats.html#ICC">ICC</a> or <a
+ href="File_Formats.html#MPP">MPP</a> profile, then the closest
+ matching measured points in the .<a href="File_Formats.html#.ti3">.ti3</a>
+ are substituted for the test values in the <a
+ href="File_Formats.html#.ti1">.ti1</a> file on output. If the <a
+ href="File_Formats.html#.ti1">.ti1</a> file is a monochrome test
+ file with a White device value, then an RGB <a
+ href="File_Formats.html#ICC">ICC</a> profile, <a
+ href="File_Formats.html#MPP">MPP</a> or <a
+ href="File_Formats.html#.ti3">.ti3</a> may be used, and the White
+ values will be translated to equal RGB values. If the <a
+ href="File_Formats.html#.ti1">.ti1</a> file is a monochrome test
+ file with a Black device value, then a CMYK <a
+ href="File_Formats.html#ICC">ICC</a> profile, <a
+ href="File_Formats.html#MPP">MPP</a> or <a
+ href="File_Formats.html#.ti3">.ti3</a> may be used, and the Black
+ values will be translated to equal CMY = 0, K = grey values. <span
+ style="font-weight: bold;">Note</span> that any calibration within
+ a supplied ICC profile is <span style="text-decoration: underline;">not</span>
+ applied during the conversion, although it will be included in the
+ .ti3 output (see <span style="font-weight: bold;">-k</span> and <span
+ style="font-weight: bold;">-i</span> flags for how apply
+ calibration curves during the conversion and/or include a specific
+ calibration curves in the output).<br>
+ <br>
+ If a separation device profile is provided (e.g. from CMY -&gt;
+ CMYK, or perhaps CMYK-&gt;CMYK, to simulate a color correction step
+ before "printing", or perhaps a Video RGB-&gt;RGB calibration link)
+ then this will be applied to the .ti1 device values, before
+ converting the the device values into .ti3 PCS values.<br>
+ <br>
+ <br>
+ <br>
+ <br>
+ </body>
</html>
diff --git a/doc/i1proHiRes.html b/doc/i1proHiRes.html
new file mode 100644
index 0000000..d6d8078
--- /dev/null
+++ b/doc/i1proHiRes.html
@@ -0,0 +1,177 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>The i1pro Hi Res. Mode</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=ISO-8859-1">
+ <meta content="Graeme Gill" name="author">
+ </head>
+ <body>
+ <h2 style="text-decoration: underline; font-weight: bold;">Does the
+ i1pro High Resolution mode improve accuracy ?<br>
+ </h2>
+ A question that has been asked is : "<span style="font-weight:
+ bold;">You've extended the Eye-One Pro with a high resolution
+ spectral mode, giving readings at 3.3nm spacing rather than the
+ default 10nm. Does this mode improve accuracy ?</span>"<br>
+ <br>
+ This is a quite reasonable question. The following attempts to
+ answer it.<br>
+ <h4 style="text-decoration: underline;">Why would a higher
+ resolution spectral mode improve accuracy ?<br>
+ </h4>
+ A spectrometer computes CIE tri-stimulus values by measuring
+ spectral values and then weighing those values by the observer
+ curves before summing the weigted values. The accuracy depends on
+ the correct weighting being applied at each wavelength. If the color
+ is composed of very narrow spectra peaks, as is sometimes the case
+ for certain light sources and many display devices, then the exact
+ positioning of one of the peaks on the observer curves may be
+ influencial in the final color value, and too coarse a quanization
+ of the spectral readings may lead to tri-stimulus errors. So in
+ theory increasing the spectral reading resolution to 3.3 nm should
+ lead to improved color accuracy with narrow spectra color sources. <br>
+ <h4 style="text-decoration: underline;">Why may this not work in
+ practice ?</h4>
+ <p>The instrument spectral resolving power is set by a number of
+ factors, and a critical one is the entrance slit width. By
+ measuring a very narrow band source such a as a laser, using the
+ default 10nm resolution indicates a FWHM (<a
+ href="http://en.wikipedia.org/wiki/Full_width_at_half_maximum">Full
+
+
+
+
+ width at half maximum</a>) of about 25nm. Doing a measurement at
+ 3.3nm resolution reveals that the optical limit seems to be about
+ 15nm, so there is some hope of improvement from that perspective.</p>
+ <p>Another factor is that the calibration data for the instrument is
+ only given at 10nm intervals. So to produce calibrated readings at
+ 3.3nm intervals, it is necessary to up-sample the calibration data
+ with sufficient accuracy. If the calibration data is sufficiently
+ smooth (indicating that the underlying device characteristics are
+ also smooth), or any slight inaccuracy will get calibrated out
+ (which is typically the case for reflective measurements) then
+ this may not be a limitation either. In the case of the i1pro2,
+ which seems to have a diffraction grating/light sensor with a less
+ smooth spectral efficiency curve than the Rev A - D models, the
+ task of up-sampling the emissive calibration data with sufficient
+ accuracy is a more difficult.<br>
+ </p>
+ <h4 style="text-decoration: underline;">The verification experiment<br>
+ </h4>
+ To give some indication of whether ArgyllCMS's high resolution
+ spectral mode is capable of improving color measurement accuracy, or
+ at least to indicate that it doesn't noticeably worsen it, the
+ following fairly simple, real world experiment was performed:<br>
+ <br>
+ A measurement target consisting of white + primary + secondary
+ colors (White, Red, Green, Blue, Cyan, Magenta, Yellow) repeated 10
+ times was used. This target was displayed on a conventional LCD
+ screen with a CCFL backlight (MacBook display), and measured using
+ using ArgyllCMS V1.6.0 <a href="dispread.html">dispread</a>:<br>
+ <br>
+ 1) Using a <a
+href="http://www.jeti.com/cms/index.php/instruments-55/radiometer/specbos-1211">JETI
+
+
+
+
+ specbos 1211</a> reference Tele-Spectro-Radiometer.<br>
+ <br>
+ 2) Using an i1pro2 in standard 10nm mode.<br>
+ <br>
+ 3) Using an i1pro2 in ArgyllCMS 3.3nm mode.<br>
+ <br>
+ The resulting readings were then analyzed using <a
+ href="colverify.html">colverify</a>.<br>
+ <br>
+ The results were analyzed two ways, first in absolute value error
+ terms, and secondly in brightness (Y) normalized terms, the latter
+ corresponding to the typical way such readings are used for display
+ calibration and profiling. <br>
+ <br>
+ A second, similar experiment was run on a CRT type display.<br>
+ <h4 style="text-decoration: underline;">Results:</h4>
+ <p><br>
+ LCD display:<br>
+ </p>
+ <p>Absolute errors of i1pro2 10nm mode to specbos 1211:<br>
+ </p>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 3.070420, avg = 2.204137<br>
+ <br>
+ Absolute errors of i1pro2 3.3nm mode to specbos 1211:<br>
+ <br>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 2.108411, avg = 1.568577<br>
+ <br>
+ <br>
+ White Y normalised errors of i1pro2 10nm mode to specbos 1211:<br>
+ <br>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 2.419800, avg = 0.747926<br>
+ <br>
+ White Y normalised errors of i1pro2 3.3nm mode to specbos 1211:<br>
+ <br>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 1.595033, avg = 0.578270<br>
+ <br>
+ <br>
+ So in this particular situation, hi-res mode improves accuracy by
+ somewhere between 0.2 and 0.6 DeltaE 2K.<br>
+ <br>
+ <br>
+ Example of white spectrum for the three measurements (red: 10nm
+ i1pro2, green: 3.3nm i1pro2, black: specbos):<br>
+ <img alt="specbos 1211 (Black), i1pro2 10nm (Red), i1pro2 3.3nm
+ (Green)" src="i1proHiRes.jpg" height="335" width="667"><br>
+ <br>
+ <p><br>
+ CRT display:<br>
+ </p>
+ <p>Absolute errors of i1pro2 10nm mode to specbos 1211:<br>
+ </p>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 1.516886, avg = 0.965740<br>
+ <br>
+ Absolute errors of i1pro2 3.3nm mode to specbos 1211:<br>
+ <br>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 1.751776, avg = 0.887878<br>
+ <br>
+ <br>
+ White Y normalised errors of i1pro2 10nm mode to specbos 1211:<br>
+ <br>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 1.509129, avg = 0.654752<br>
+ <br>
+ White Y normalised errors of i1pro2 3.3nm mode to specbos 1211:<br>
+ <br>
+ &nbsp; Total errors (CIEDE2000):&nbsp;&nbsp;&nbsp;&nbsp; peak =
+ 1.284044, avg = 0.622501<br>
+ <br>
+ <h4 style="text-decoration: underline;">Conclusions:</h4>
+ The results for the conditions of this particular experiment
+ indicate that ArgyllCMS High Resolution mode can very slightly
+ improve colorimetric measurement accuracy of display devices.
+ Accuracy may conceivably be improved a little more than indicated by
+ this experiment for i1pro rev A-D instruments which have a smoother
+ diffraction grating/light sensor characteristic, or it is also
+ conceivable that an unfortunate combination of display spectra and
+ the i1pro2 may result in reduced accuracy. The High Resolution mode
+ is primarily useful for showing more spectral detail, and should
+ probably not be used for colorimetric measurement when the highest
+ possible robustness and reliability is desired. The potential for
+ improved accuracy may be of benefit in other situations though. <br>
+ <h4 style="text-decoration: underline;">Raw Data:</h4>
+ The raw measurement data is available in this <a
+ href="i1proHiRes.zip">.ti3 archive</a>.<br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ </body>
+</html>
diff --git a/doc/i1proHiRes.jpg b/doc/i1proHiRes.jpg
new file mode 100644
index 0000000..c07b37c
--- /dev/null
+++ b/doc/i1proHiRes.jpg
Binary files differ
diff --git a/doc/i1proHiRes.zip b/doc/i1proHiRes.zip
new file mode 100644
index 0000000..49721f9
--- /dev/null
+++ b/doc/i1proHiRes.zip
Binary files differ
diff --git a/doc/iccgamut.html b/doc/iccgamut.html
index 6d2f5ba..fe555cf 100644
--- a/doc/iccgamut.html
+++ b/doc/iccgamut.html
@@ -12,186 +12,226 @@
Create a gamut file or VRML file &nbsp;of the color gamut of an ICC
profile.<br>
<span style="font-weight: bold;"> iccgamut</span> allows creation of
- gamut files from the forward or backwards
- table of an ICC profile, in Lab or CIECAM02 Jab colorspace, and can
- also
- representing the gamut as a VRML file.<br>
+ gamut files from the forward or backwards table of an ICC profile,
+ in Lab or CIECAM02 Jab colorspace, and can also representing the
+ gamut as a VRML file.<br>
<h3>Usage<br>
</h3>
<small><span style="font-family: monospace;">iccgamut [-options] </span><i
style="font-family: monospace;">profile</i><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
Verbose</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-d
- sres&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Surface
- resolution details 1.0 - 50.0</span><br style="font-family:
- monospace;">
+ sres&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Surface resolution
+ details 1.0 - 50.0</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
emit
+
+
+
VRML .wrl file as well as CGATS .gam file</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Don't
+
+
+
add VRML axes or white/black point</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;-k&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Add
+
+
+
VRML markers for prim. &amp; sec. "cusp" points</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-f
- function&nbsp;&nbsp; f =
- forward*, b = backwards</span><br style="font-family:
- monospace;">
- &nbsp;
- <span style="font-family: monospace;"></span></small><small><span
- style="font-family: monospace;">-i
- intent&nbsp;&nbsp;&nbsp;&nbsp; p =
- perceptual, r = relative colorimetric,</span><br
+ function&nbsp;&nbsp; f = forward*, b = backwards</span><br
style="font-family: monospace;">
+ &nbsp; <span style="font-family: monospace;"></span></small><small><span
+ style="font-family: monospace;">-i
+ intent&nbsp;&nbsp;&nbsp;&nbsp; p = perceptual, r = relative
+ colorimetric,</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
s
+
+
+
= saturation, a = absolute (default), d = profile default</span></small><small><span
style="font-family: monospace;"></span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;-o
- order&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = normal
- (priority: lut &gt; matrix &gt; monochrome)</span><br
- style="font-family: monospace;">
+ order&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = normal (priority: lut
+ &gt; matrix &gt; monochrome)</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
r
- = reverse (priority: monochrome &gt;
- matrix &gt; lut)<br>
+
+
+
+ = reverse (priority: monochrome &gt; matrix &gt; lut)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><span
style="font-family: monospace;">-p oride</span><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l
- =
- Lab_PCS (default), j = CIECAM02 Appearance Jab</span></small><small><span
+ = Lab_PCS (default), j = CIECAM02 Appearance Jab</span></small><small><span
style="font-family: monospace;"></span><span style="font-family:
monospace;"></span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-l
- tlimit&nbsp;&nbsp;&nbsp;&nbsp; set total
- ink limit, 0 - 400% (estimate by default)</span><br
- style="font-family: monospace;">
+ tlimit&nbsp;&nbsp;&nbsp;&nbsp; set total ink limit, 0 - 400%
+ (estimate by default)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-L
- klimit&nbsp;&nbsp;&nbsp;&nbsp; set black ink
- limit, 0 - 100% (estimate by default)</span><br
- style="font-family: monospace;">
+ klimit&nbsp;&nbsp;&nbsp;&nbsp; set black ink limit, 0 - 100%
+ (estimate by default)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-c
- viewcond&nbsp;&nbsp; set
- viewing conditions for CIECAM02,</span><br style="font-family:
- monospace;">
+ viewcond&nbsp;&nbsp; set viewing conditions for CIECAM02,</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
either
- an enumerated choice, or a series of
- parameters:value changes</span><br style="font-family:
- monospace;">
+
+
+
+ an enumerated choice, or a series of parameters:value changes</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;"></span></small><small><span
- style="font-family: monospace;">&nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pp - Practical Reflection
- Print
- (ISO-3664 P2)</span><br style="font-family: monospace;">
+ style="font-family: monospace;">&nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; pp - Practical Reflection Print (ISO-3664 P2)</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
&nbsp; pe - Print evaluation environment (CIE 116-1995)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
&nbsp; pc - Critical print evaluation environment (ISO-3664 P1)</span></small><small><span
style="font-family: monospace;"></span><span style="font-family:
monospace;"></span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
&nbsp; &nbsp; mt - Monitor in typical work environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
&nbsp; mb - Monitor in bright work environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; md - Monitor in darkened work
+ &nbsp; &nbsp;&nbsp;&nbsp; md - Monitor in darkened work
environment</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; jm - Projector in dim environment</span><br
+ &nbsp; &nbsp;&nbsp;&nbsp; jm - Projector in dim environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; jd - Projector in dark environment</span><br
+ &nbsp; &nbsp;&nbsp;&nbsp; jd - Projector in dark environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; pcd - Photo CD - original scene
+ &nbsp; &nbsp;&nbsp;&nbsp; pcd - Photo CD - original scene
outdoors</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; ob - Original scene - Bright Outdoors</span><br
+ &nbsp; &nbsp;&nbsp;&nbsp; ob - Original scene - Bright Outdoors</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; cx - Cut Sheet Transparencies on a viewing
- box</span></small><small><span style="font-family: monospace;"></span><span
- style="font-family: monospace;"></span><br style="font-family:
- monospace;">
+ &nbsp; &nbsp;&nbsp;&nbsp; cx - Cut Sheet Transparencies on a
+ viewing box</span></small><small><span style="font-family:
+ monospace;"></span><span style="font-family: monospace;"></span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
s:surround&nbsp;&nbsp;
+
+
+
n = auto, a = average, m = dim, d = dark,</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
+
&nbsp; &nbsp;&nbsp; c = transparency (default average)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
w:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Adapted white point
- as XYZ (default media white)</span><br style="font-family:
- monospace;">
+
+
+
+ Adapted white point as XYZ (default media white)</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
w:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Adapted white point as
- x, y</span><br style="font-family: monospace;">
+
+
+
+ Adapted white point as x, y</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
a:adaptation
+
+
+
Adaptation luminance in cd.m^2 (default 50.0)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
b:background
Background
+
+
+
% of image luminance (default 20)<br>
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; l:scenewhite Scene
- white in
- cd.m^2 if surround = auto (default 250)<br style="font-family:
- monospace;">
- </span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; l:imagewhite Image
+ white in cd.m^2 if surround = auto (default 250)</span></small><br
+ style="font-family: monospace;">
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
f:flare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Flare
- light % of image luminance (default 1)</span><br
- style="font-family: monospace;">
+
+
+
+ Flare light % of image luminance (default 0)<br>
+ </span></small>&nbsp;</span><span style="font-family:
+ monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ g:glare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare light % of ambient
+ (default 1)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-f:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Flare color as
- XYZ (default media white)</span><br style="font-family:
- monospace;">
+
+
+ g:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color as XYZ
+ (default media white)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Flare color as x, y<br>
+
+
+ g:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color as
+ x, y<br>
&nbsp;-s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Create
+
+
+
special cube surface topology plot<br style="font-family:
monospace;">
</span><i style="font-family: monospace;">profile</i><span
style="font-family: monospace;"> &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp; The
- name of the </span><a style="font-family: monospace;"
- href="File_Formats.html#ICC">ICC</a><span style="font-family:
- monospace;">
- profile, as well as the basename of the </span><a
- style="font-family: monospace;" href="File_Formats.html#.gam">gamut</a><span
- style="font-family: monospace;"> [.gam] and/or </span><a
- style="font-family: monospace;" href="File_Formats.html#.wrl">VRML</a><span
- style="font-family: monospace;"> [.wrl] file.</span></small>
- <br>
+ &nbsp;&nbsp; The name of the </span><a style="font-family:
+ monospace;" href="File_Formats.html#ICC">ICC</a><span
+ style="font-family: monospace;"> profile, as well as the
+ basename of the </span><a style="font-family: monospace;"
+ href="File_Formats.html#.gam">gamut</a><span style="font-family:
+ monospace;"> [.gam] and/or </span><a style="font-family:
+ monospace;" href="File_Formats.html#.wrl">VRML</a><span
+ style="font-family: monospace;"> [.wrl] file.</span></small> <br>
<h3>Comments</h3>
The parameters are all those that control which table in the ICC
profile to use, as well as what color space to convert it to. <br>
@@ -201,127 +241,106 @@ Create
cubic L*a*b* units.<br>
<br>
The <b>-d</b> parameter controls the level of detail displayed in
- the
- surface. The parameter roughly corresponds to a deltaE value, so
- smaller
- values give greater detail. The default value is around 10, and is a
- good
- place to start. Small values may take a lot of time to generate, and
- will
- produce big files.<br>
+ the surface. The parameter roughly corresponds to a deltaE value, so
+ smaller values give greater detail. The default value is around 10,
+ and is a good place to start. Small values may take a lot of time to
+ generate, and will produce big files.<br>
<br>
The <b>-w</b> flag causes a VRML file to be produced, as well as a
gamut file.<br>
<br>
- The <b>-n</b> flag suppresses the L*a*b* axes being created in
- the VRML.<br>
+ The <b>-n</b> flag suppresses the L*a*b* axes being created in the
+ VRML.<br>
<br>
The <span style="font-weight: bold;">-k</span> flag adds markers
- for
- each of the primary and secondary "cusp" points (Red, Yellow, Green,
- Cyan, Blue &amp; Magenta). No markers will be displayed if the cusps
- cannot be determined.<br>
+ for each of the primary and secondary "cusp" points (Red, Yellow,
+ Green, Cyan, Blue &amp; Magenta). No markers will be displayed if
+ the cusps cannot be determined.<br>
<br>
The <b>-f </b>parameter allows choosing the ICC table to be used
- in
- plotting the gamut. The backwards tables generally incorporate gamut
- compression, and therefore don't reflect the native capabilities of
- the
- device.<br>
+ in plotting the gamut. The backwards tables generally incorporate
+ gamut compression, and therefore don't reflect the native
+ capabilities of the device.<br>
<br>
The <b>-i</b> flag selects the intent transform used for a lut
- based
- profile. It also selects between relative and absolute colorimetric
- for
- non-lut base profiles. Note that anything other than colorimetric
- may
- not represent the
- native capabilities of the device. The default intent will be
- absolute
- colorimetic for L*a*b* output, and CIECAM02 appearance for Jab
- output.<br>
+ based profile. It also selects between relative and absolute
+ colorimetric for non-lut base profiles. Note that anything other
+ than colorimetric may not represent the native capabilities of the
+ device. The default intent will be absolute colorimetic for L*a*b*
+ output, and CIECAM02 appearance for Jab output.<br>
<br>
An ICC profile is allowed to contain more than the minimum number of
elements or table needed to describe a certain transform, and may
contain redundant descriptions. &nbsp;By default, lut based table
information will be used first if present, followed by matrix/shaper
- information, and only using
- monochrome information if it is all that is present. The <b>-o</b>
- flag,
- reverses this order.&nbsp;&nbsp;&nbsp; <br>
+ information, and only using monochrome information if it is all that
+ is present. The <b>-o</b> flag, reverses this
+ order.&nbsp;&nbsp;&nbsp; <br>
<br>
<span style="font-weight: bold;">-p</span>: By default the gamut
- will
- be created in L*a*b* colorspace. If&nbsp; <span style="font-weight:
- bold;">-pj</span> is selected, then CIECAM02
+ will be created in L*a*b* colorspace. If&nbsp; <span
+ style="font-weight: bold;">-pj</span> is selected, then CIECAM02
appearance space Jab will be used for the output, and the viewing
conditions will be taken into account. Jab space is what is normally
needed to be compatible with the default intents used in <a
href="colprof.html">colprof</a>. <span style="font-weight: bold;"><br>
</span>Note that the CIECAM02 output space selection by default uses
the colorimetric transform of the profile resulting in the
- appearance
- of the native device, but that the perceptual or
+ appearance of the native device, but that the perceptual or
saturation transforms may be used by selecting them using the <span
style="font-weight: bold;">-i</span> parameter, which may give a
different result with some profiles. This may be desirable if an
- image
- is to be transformed through the perceptual or saturation tables of
- a
- profile as part of a link with an Argyll generated output profile,
- since it will then represent the apparent gamut of the image when
- subject to these tables. If the absolute colorimetric intent is
- chosen
- using <span style="font-weight: bold;">-ia</span> in combinations
- with
- <span style="font-weight: bold;">-pj</span>, then&nbsp; Jab with
- a fixed white reference is used, which emulates an absolute CIECAM02
- Jab
- appearance space. <br>
+ image is to be transformed through the perceptual or saturation
+ tables of a profile as part of a link with an Argyll generated
+ output profile, since it will then represent the apparent gamut of
+ the image when subject to these tables. If the absolute colorimetric
+ intent is chosen using <span style="font-weight: bold;">-ia</span>
+ in combinations with <span style="font-weight: bold;">-pj</span>,
+ then&nbsp; Jab with a fixed white reference is used, which emulates
+ an absolute CIECAM02 Jab appearance space. <br>
<br>
The <b>-l</b> parameter allows setting a total ink limit (TAC) for
- printing
- devices. If a device has a total ink limit, and hasn't been
+ printing devices. If a device has a total ink limit, and hasn't been
characterised with device values above this limit, then plotting the
gamut in these areas will almost certainly be misleading. tables. By
- default, a total ink limit will
- be estimated from the profile tables. The ink limit
- will be in final calibrated device values if the profile includes
- calibration information.<br>
+ default, a total ink limit will be estimated from the profile
+ tables. The ink limit will be in final calibrated device values if
+ the profile includes calibration information.<br>
<br>
The <b>-L</b> parameter allows setting a black ink limit for
- printing
- devices. If a device is to be used with a black ink limit, then it
- is
- useful to evaluate
- the gamut with the limit in place. By default, a black ink limit
- will
- be estimated from the profile tables. The ink limit
- will be in final calibrated device values if the profile includes
- calibration information.<br>
+ printing devices. If a device is to be used with a black ink limit,
+ then it is useful to evaluate the gamut with the limit in place. By
+ default, a black ink limit will be estimated from the profile
+ tables. The ink limit will be in final calibrated device values if
+ the profile includes calibration information.<br>
<br>
The <b>-c</b> parameter allows setting the CIECAM02 viewing
- conditions,
- either by choosing a typical viewing environment, or controlling
- particular viewing condition parameters.<br>
+ conditions, either by choosing a typical viewing environment, or
+ controlling particular viewing condition parameters.<br>
<br>
The <span style="font-weight: bold;">-s</span> flag creates a
- special
- hyper-cube surface plot that is artificially colored. This can be
- useful for identifying the topology of the black ink color response.<br>
+ special hyper-cube surface plot that is artificially colored. This
+ can be useful for identifying the topology of the black ink color
+ response.<br>
<h3>Example<br>
</h3>
To create a view in L*a*b* of the absolute gamut of a CMYK file with
- an
- ink limit of 260%, one might use:<br>
+ an ink limit of 260%, one might use:<br>
<br>
&nbsp;&nbsp;&nbsp; <span style="font-style: italic;">iccgamut -w
- -ff
- -ia -l260 profile.icm</span><br>
+ -ff -ia -l260 profile.icm</span><br>
<br>
and the resulting files will be <span style="text-decoration:
underline;">profile.gam</span> and <span style="text-decoration:
underline;">profile.wrl</span>.<br>
+ <br>
+ To create a gamut suitable for CIECAM02&nbsp; gamut mapping space in
+ colprof or collink, something like<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; iccgamut -ir -pj -cmt&nbsp; profile.icm<br>
+ <br>
+ where the viewing conditions "mt" should the same as the source
+ conditions in colprof or collink.<br>
<br style="font-weight: bold;">
<span style="font-weight: bold;"></span><br>
<br>
diff --git a/doc/illumread.html b/doc/illumread.html
index 03b5648..0dcf5bd 100644
--- a/doc/illumread.html
+++ b/doc/illumread.html
@@ -10,15 +10,11 @@
<h2><b>spectro/illumread</b></h2>
<h3>Summary</h3>
Use an instrument or instruments to measure an illuminant spectrum,
- including estimate
- its Ultra Violet content. A combination of direct illumination
- readings
- and readings from a piece of paper having some FWA content are used
- for
- this. (If the UV content is not needed, or a suitable instrument is
- not
- available, then <a href="spotread.html">spotread</a> should be used
- instead.)<br>
+ including estimate its Ultra Violet content. A combination of direct
+ illumination readings and readings from a piece of paper having some
+ FWA content are used for this. (If the UV content is not needed, or
+ a suitable instrument is not available, then <a
+ href="spotread.html">spotread</a> should be used instead.)<br>
<h3>Usage Summary</h3>
<small><span style="font-family: monospace;">illumread [-options]
illuminant.sp</span><br style="font-family: monospace;">
@@ -26,6 +22,7 @@
style="font-family: monospace;" href="#v">-v</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
&nbsp; &nbsp; Verbose mode</span><span style="font-family:
monospace;"></span></small><small><span style="font-family:
monospace;"></span></small><br style="font-family: monospace;">
@@ -34,46 +31,46 @@
style="font-family: monospace;" href="#S">-S</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;
- &nbsp; &nbsp; Plot
- the readings in a graph window.</span><br style="font-family:
- monospace;">
+ &nbsp; &nbsp; &nbsp; Plot the readings in a graph window.</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#c">-c comport</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Set
- COM port, 1..4
- (default 1)</span><span style="font-family: monospace;"></span><span
- style="font-family: monospace;"></span><span style="font-family:
- monospace;"></span></small><small><span style="font-family:
- monospace;"></span></small><font size="-1"><span
+
+ COM port, 1..4 (default 1)</span><span style="font-family:
+ monospace;"></span><span style="font-family: monospace;"></span><span
+ style="font-family: monospace;"></span></small><small><span
+ style="font-family: monospace;"></span></small><font size="-1"><span
style="font-family: monospace;"></span></font><font size="-1"><span
style="font-family: monospace;"><br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#N">-N</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Disable
+
initial calibration of instrument</span></font> if possible<br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#H">-H</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Use high resolution spectrum mode (if
- available)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Use high resolution spectrum mode
+ (if available)<br>
+ <font size="-1">&nbsp;<a href="#Yr">-Y r</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Set refresh measurement mode</font><br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#W">-W n|h|x</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Override
+
serial port flow control: n = none, h = HW, x = Xon/Xoff</span></font><br>
<small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#D">-D [level]</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Print
- debug diagnostics to stderr</span></small><br>
- &nbsp;
- <font size="-1"><span style="font-family: monospace;"><a
+ Print debug diagnostics to stderr</span></small><br>
+ &nbsp; <font size="-1"><span style="font-family: monospace;"><a
href="#file"><span style="font-style: italic;">illuminant.sp</span></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
File
+
to save measurement to<br style="font-family: monospace;">
</span></font><small><span style="font-family: monospace;"></span><span
style="font-family: monospace;"></span></small><br>
@@ -81,40 +78,26 @@ File
<b>illumread</b> uses a suitable instrument to read an illuminant
spectrum, and uses an indirect method to estimate the Ultra Violet
content of the illuminant, so as to provide better accuracy with <a
- href="FWA.html">FWA
- compensation</a>. An instrument or combination of instruments
- capable
- of spectral measurement of both
- emissive measurement and reflective measurement without a U.V.
- filter
- is required for this.<br>
+ href="FWA.html">FWA compensation</a>. An instrument or combination
+ of instruments capable of spectral measurement of both emissive
+ measurement and reflective measurement without a U.V. filter is
+ required for this.<br>
<br>
<a name="v"></a>The <b>-v</b> flag causes extra information to be
- printed out during
- chartread operation.<br>
+ printed out during chartread operation.<br>
<br>
<a name="S"></a>The <b>-S</b> flag enables the plotting of the
- spectral
- reflectance/transmittance values. You must select the plot window
- and
- strike a key
- in it to continue with another measurement.<br>
+ spectral reflectance/transmittance values. You must select the plot
+ window and strike a key in it to continue with another measurement.<br>
<br>
<a name="c"></a> The instrument is assumed to communicate through a
USB or serial communication port, and the initial port can be
- selected
- with the
- <b>-c</b>
- option,
- if the instrument is not connected to the first port. If you invoke
- <span style="font-weight: bold;">illumread</span>
- so as to display the usage
- information (i.e. "illumread -?" or "illumread --"), then the
- discovered
- USB and serial ports will be listed. On
- UNIX/Linux, a list of all possible serial ports are shown, but not
- all
- of them may
+ selected with the <b>-c</b> option, if the instrument is not
+ connected to the first port. If you invoke <span
+ style="font-weight: bold;">illumread</span> so as to display the
+ usage information (i.e. "illumread -?" or "illumread --"), then the
+ discovered USB and serial ports will be listed. On UNIX/Linux, a
+ list of all possible serial ports are shown, but not all of them may
actually be present on your system.<br>
<br>
<a name="N"></a><span style="font-weight: bold;">-N</span> Any
@@ -129,40 +112,39 @@ File
subsequent measurements in a single session.<br>
<br>
<a name="H"></a> The -<span style="font-weight: bold;">H</span>
- option
- turns on high resolution spectral mode, if the instrument supports
- it.
- See <a href="instruments.html">Operation of particular instruments</a>
- for more details.<br>
+ option turns on high resolution spectral mode, if the instrument
+ supports it. See <a href="instruments.html">Operation of particular
+ instruments</a> for more details.<br>
+ <br>
+ <a name="Yr"></a> The -<span style="font-weight: bold;">Y r</span>
+ option turns on refresh mode measurement, if the instrument supports
+ it. This may improve the repeatability of measurements of
+ illuminants that have a repetitive flicker.<br>
<br>
<a name="W"></a>The <b>-W</b> <span style="font-weight: bold;">n|h|x</span>
- parameter overrides the default serial communications
- flow control setting. The value <span style="font-weight: bold;">n</span>
- turns all flow control off, <span style="font-weight: bold;">h</span>
+ parameter overrides the default serial communications flow control
+ setting. The value <span style="font-weight: bold;">n</span> turns
+ all flow control off, <span style="font-weight: bold;">h</span>
sets hardware handshaking, and <span style="font-weight: bold;">x</span>
sets Xon/Xoff handshaking. This commend may be useful in workaround
serial communications issues with some systems and cables. <br>
<br>
- <a name="D"></a>The <b>-D</b> flag causes communications
- and other instrument diagnostics to be printed to stdout. A level
- can
- be set between 1 .. 9, that may give progressively more verbose
+ <a name="D"></a>The <b>-D</b> flag causes communications and other
+ instrument diagnostics to be printed to stdout. A level can be set
+ between 1 .. 9, that may give progressively more verbose
information, depending on the instrument. This can be useful in
- tracking
- down why an instrument can't connect.<br>
+ tracking down why an instrument can't connect.<br>
<br>
<a name="file"></a>The <span style="font-weight: bold; font-style:
- italic;">illuminant.sp</span> is
- the name of the file to save the resulting illuminant spectrum to.
- The
- format used is <a href="File_Formats.html#.sp">.sp</a>.<br>
+ italic;">illuminant.sp</span> is the name of the file to save the
+ resulting illuminant spectrum to. The format used is <a
+ href="File_Formats.html#.sp">.sp</a>.<br>
<br>
<hr style="width: 100%; height: 2px;"><br>
Unlike the other measurement utilities, <span style="font-weight:
- bold;">illumread</span> doesn't connect to the
- instrument until it is about to make a measurement. This allows for
- the
- possibility of using a different instrument for each measurement.<br>
+ bold;">illumread</span> doesn't connect to the instrument until it
+ is about to make a measurement. This allows for the possibility of
+ using a different instrument for each measurement.<br>
<br>
It will display a menu:<br>
<br>
@@ -173,74 +155,55 @@ File
4) Select another instrument, Currently 1 'usb:/bus4/dev2/
(GretagMacbeth i1 Pro)'<br>
5) Compute illuminant spectrum, average result with 0 previous
- readings
- &amp; save it<br>
+ readings &amp; save it<br>
6) Compute illuminant spectrum from this reading &amp; save result<br>
7) Exit<br>
<br>
There are three measurements to be made, after which the illuminant
- can
- be computed and saved. Before each measurement, the instrument may
- need
- calibrating.<br>
+ can be computed and saved. Before each measurement, the instrument
+ may need calibrating.<br>
<br>
The first measurement needs a spectral instrument capable of reading
- in
- an ambient or emissive mode. For instance, a Spectrolino, Eye-One
- Pro
- or ColorMunki would be suitable instruments.<br>
+ in an ambient or emissive mode. For instance, a Spectrolino, Eye-One
+ Pro or ColorMunki would be suitable instruments.<br>
<br>
The second measurement needs a spectral instrument capable of
- reading
- in an projector or emissive mode. For instance, a Spectrolino,
- Eye-One
- Pro or ColorMunki would be suitable instruments.<br>
+ reading in an projector or emissive mode. For instance, a
+ Spectrolino, Eye-One Pro or ColorMunki would be suitable
+ instruments.<br>
<br>
The third measurement needs a spectral instrument capable of reading
- in
- reflective mode with UV included. For instance, a Spectrolino,
- Eye-One
- Pro, DTP20, DTP22 or&nbsp; DTP41 would be suitable instruments, as
- long
- as they are not fitted with UV filters.<br>
+ in reflective mode with UV included. For instance, a Spectrolino,
+ Eye-One Pro, DTP20, DTP22 or&nbsp; DTP41 would be suitable
+ instruments, as long as they are not fitted with UV filters.<br>
<br>
To be able to estimate the level of Ultra Violet (UV) light in the
illuminant, a reasonable sized piece of white paper needs to be
- used.
- The paper should have some noticeable level of FWA (Fluorescent
- Whitener Additive, or Optical Brightening Agents) in it, so that it
- responds to UV light. A piece of cheap copier paper is ideal, since
- cheap paper is typically whitened with large amounts of FWA. If the
- paper is thin (less than 160 gsm) then two or three sheets should be
- used to prevent any background showing through. [If the intention is
- to
- use the illuminant spectrum for proofing to a particular paper, then
- an
- alternative might be to use a piece of the intended paper for this
- purpose. It's unclear which may give a better result.]<br>
+ used. The paper should have some noticeable level of FWA
+ (Fluorescent Whitener Additive, or Optical Brightening Agents) in
+ it, so that it responds to UV light. A piece of cheap copier paper
+ is ideal, since cheap paper is typically whitened with large amounts
+ of FWA. If the paper is thin (less than 160 gsm) then two or three
+ sheets should be used to prevent any background showing through. [If
+ the intention is to use the illuminant spectrum for proofing to a
+ particular paper, then an alternative might be to use a piece of the
+ intended paper for this purpose. It's unclear which may give a
+ better result.]<br>
<br>
The first measurement <span style="font-weight: bold;">1)</span>,
- is
- to use either the ambient or emissive measurement mode to measure
- the
- illumination directly.<br>
+ is to use either the ambient or emissive measurement mode to measure
+ the illumination directly.<br>
<br>
<div style="margin-left: 40px;">If the instrument supports an
- ambient
- measurement capability, then it will be used. If the insrument
- does not
- have an ambient mode, then an emissive measurement mode can be
- used,
- although typically many illuminants are too bright to directly
- point
- the instrument at. A work-around is to reflect the illuminant from
- a
- spectrally flat white surface. A good candidate for this is a
- piece of
- white, fine textured polystyrene foam. [The suitability of a
- reflector
- can be checked using <span style="font-weight: bold;">spotread -S</span>
- to check that the reflection characteristic is close to flat.]<br>
+ ambient measurement capability, then it will be used. If the
+ insrument does not have an ambient mode, then an emissive
+ measurement mode can be used, although typically many illuminants
+ are too bright to directly point the instrument at. A work-around
+ is to reflect the illuminant from a spectrally flat white surface.
+ A good candidate for this is a piece of white, fine textured
+ polystyrene foam. [The suitability of a reflector can be checked
+ using <span style="font-weight: bold;">spotread -S</span> to
+ check that the reflection characteristic is close to flat.]<br>
<br>
<img style="width: 228px; height: 300px;" alt="Measuring Ambient"
src="illumread_1.jpg"><img style="width: 141px; height: 282px;"
@@ -250,22 +213,15 @@ File
</div>
<br>
The second measurement <span style="font-weight: bold;">2)</span>,
- is
- to measure the illuminant after it has reflected from the paper.<br>
+ is to measure the illuminant after it has reflected from the paper.<br>
<br>
<div style="margin-left: 40px;">This is done by placing the paper
- such
- that it is uniformly illuminated with reasonable brightness, and
- then
- placing the instrument so that it receives the reflected light
- from the
- paper. This is typically achieved by placing the instrument close
- to
- the paper at about 45&ordm;, so that it's aperture has a clear
- view of
- the illuminated paper, but avoiding shadowing the region that is
- in
- view. <br>
+ such that it is uniformly illuminated with reasonable brightness,
+ and then placing the instrument so that it receives the reflected
+ light from the paper. This is typically achieved by placing the
+ instrument close to the paper at about 45&ordm;, so that it's
+ aperture has a clear view of the illuminated paper, but avoiding
+ shadowing the region that is in view. <br>
<br>
<img style="width: 219px; height: 261px;" alt="Measuring via
Paper" src="illumread_5.jpg"><img style="width: 252px; height:
@@ -273,33 +229,29 @@ File
</div>
<br>
The third measurement <span style="font-weight: bold;">3)</span>,
- is
- to measure the paper directly using the instrument reflective mode
- measurement.<br>
+ is to measure the paper directly using the instrument reflective
+ mode measurement.<br>
<div style="margin-left: 40px;"><img style="width: 186px; height:
162px;" alt="Measuring Paper" src="illumread_6.jpg"><br>
</div>
If a different instrument is needed, use <span style="font-weight:
- bold;">4)</span> to select from the available
- instruments attached to your computer.<br>
+ bold;">4)</span> to select from the available instruments attached
+ to your computer.<br>
<br>
Once these three measurements have been made, then the illuminant
- readings spectrum
- can be computed and save using <span style="font-weight: bold;">6)</span>,
- or a series of readings can be made with each reading being averages
- with the previous readings before saving it by using <span
- style="font-weight: bold;">5)</span>. Note that the averaged
- readings
- will be weighted by their absolute intensities, and that while the
- direct and indirect illumination needs measuring for each reading,
- the
- same paper measurement can be used each time.<br>
- <br>
- If plotting is enabled, a plot of the
- measured (black) and with estimated UV (red) is plotted. This is
- followed by a plot showing measured paper reflectance (black) and
- the
- FWA calculated paper reflectance (red).<br>
+ readings spectrum can be computed and save using <span
+ style="font-weight: bold;">6)</span>, or a series of readings can
+ be made with each reading being averages with the previous readings
+ before saving it by using <span style="font-weight: bold;">5)</span>.
+ Note that the averaged readings will be weighted by their absolute
+ intensities, and that while the direct and indirect illumination
+ needs measuring for each reading, the same paper measurement can be
+ used each time.<br>
+ <br>
+ If plotting is enabled, a plot of the measured (black) and with
+ estimated UV (red) is plotted. This is followed by a plot showing
+ measured paper reflectance (black) and the FWA calculated paper
+ reflectance (red).<br>
<br>
<br>
Illumread can then be terminated using <span style="font-weight:
diff --git a/doc/instruments.html b/doc/instruments.html
index 896c0e5..0bcc62d 100644
--- a/doc/instruments.html
+++ b/doc/instruments.html
@@ -1,28 +1,44 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
- <head>
- <title>Operation of particular instruments</title>
- <meta http-equiv="content-type" content="text/html;
- charset=ISO-8859-1">
- </head>
- <body>
- <h2><u>Operation of particular instruments</u></h2>
- <span style="font-weight: bold;">Please note that instruments are
- being driven by ArgyllCMS drivers, and that any problems or
- queries regarding instrument<br>
- operation </span><span style="font-weight: bold;">should be
- directed to the Argyll's author(s) or the Argyll mailing list, and
- not to any</span> <span style="font-weight: bold;">other party.</span><span
- style="font-weight: bold;"></span><br>
- <br>
- The following instruments are directly supported:<br>
- (Please <span style="font-weight: bold;">note</span> the <a
- href="Installing.html">installation instructions</a> for each
- platform - they contain important information for getting your
- instruments working.)<br>
- <br>
- X-Rite:<br>
- &nbsp;&nbsp;&nbsp; <a href="#DTP20">DTP20 "Pulse"</a>&nbsp;
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Operation of particular instruments</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=windows-1252">
+ </head>
+ <body>
+ <h2><u>Operation of particular instruments</u></h2>
+ <span style="font-weight: bold;">Please note that instruments are
+ being driven by ArgyllCMS drivers, and that any problems or
+ queries regarding instrument<br>
+ operation </span><span style="font-weight: bold;">should be
+ directed to the Argyll's author(s) or the Argyll mailing list, and
+ not to any</span> <span style="font-weight: bold;">other party.</span><span
+ style="font-weight: bold;"></span><br>
+ <br>
+ The following instruments are directly supported:<br>
+ (Please <span style="font-weight: bold;">note</span> the <a
+ href="Installing.html">installation instructions</a> for each
+ platform - they contain important information for getting your
+ instruments working.)<br>
+ <br>
+ JETI:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="#specbos">specbos 1211 &amp; 1201</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+ - Tele-Spectro-Radiometer<br>
+ <br>
+ X-Rite:<br>
+ &nbsp;&nbsp;&nbsp; <a href="#DTP20">DTP20 "Pulse"</a>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -45,7 +61,19 @@
- - "swipe" type reflective spectrometer, that can be used untethered.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - "swipe" type reflective spectrometer, that can be used untethered.<br>
&nbsp;&nbsp;&nbsp; <a href="#DTP22">DTP22 Digital Swatchbook</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -68,7 +96,19 @@
- - spot type reflective spectrometer.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - spot type reflective spectrometer.<br>
&nbsp;&nbsp;&nbsp; <a href="#DTP41">DTP41</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -91,9 +131,21 @@
- - spot and strip reading reflective spectrometer.<br>
- &nbsp;&nbsp;&nbsp; <a href="#DTP41">DTP41T</a> &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+ - spot and strip reading reflective spectrometer.<br>
+ &nbsp;&nbsp;&nbsp; <a href="#DTP41">DTP41T</a> &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -116,7 +168,19 @@
- - spot and strip reading reflective/transmissive spectrometer.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - spot and strip reading reflective/transmissive spectrometer.<br>
&nbsp;&nbsp;&nbsp; <a href="#dtp51">DTP51</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -139,7 +203,19 @@
- - strip reading reflective colorimeter.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - strip reading reflective colorimeter.<br>
&nbsp;&nbsp;&nbsp; <a href="#DTP92">DTP92</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -162,7 +238,19 @@
- - CRT display colorimeter.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - CRT display colorimeter.<br>
&nbsp;&nbsp;&nbsp; <a href="#DTP94">DTP94</a> <font size="-1">"Optix
@@ -185,7 +273,19 @@
- XR"</font> or "Optix XR2" or "Optix Pro"- display colorimeter.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ XR"</font> or "Optix XR2" or "Optix Pro"- display colorimeter.<br>
<a href="#ColorMunki"><span style="text-decoration: underline;"></span></a>&nbsp;&nbsp;&nbsp;
@@ -208,62 +308,73 @@
- <a href="#ColorMunki"><span style="text-decoration: underline;">ColorMunki</span></a>
- Design or Photo&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - spot and "swipe"
- reflective/emissive spectrometer (UV cut only).<br>
- &nbsp;&nbsp;&nbsp; <a href="#i1d"><span style="text-decoration:
- underline;">ColorMunki</span></a> Create or Smile&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
- colorimeter. (Similar to an Eye-One Display 2)<br>
- &nbsp;&nbsp;&nbsp; <a href="#Huey">Lenovo W</a> &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - built in laptop
- Huey display colorimeter.<br>
- &nbsp;&nbsp;&nbsp; <a href="#i1d3">Eye-One Display 3</a> &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; - i1 DisplayPro and ColorMunki Display<br>
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [ The OEM
- i1Display Pro and<br>
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- NEC SpectraSensor Pro are also reported to work.]<br>
- &nbsp; &nbsp; <a href="instruments.html#i1p2">Eye-One Pro2</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; - spot and
- "swipe" reflective/emissive spectrometer.<br>
- <br>
- Gretag-Macbeth (now X-Rite):<br>
- &nbsp; &nbsp; <a href="#sl">Spectrolino</a> &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot reflective/emissive
- spectrometer<br>
- &nbsp; &nbsp; <a href="#ss">SpectroScan</a> &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; - spot reflective/emissive, XY table
- reflective spectrometer&nbsp; <br>
- &nbsp; &nbsp; <a href="#ss">SpectroScanT</a> &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; - spot reflective/emissive/transmissive, XY
- table reflective spectrometer<br>
- &nbsp; &nbsp; <a href="#i1p">Eye-One Pro</a> "EFI ES-1000" &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe" reflective/emissive
- spectrometer<br>
- &nbsp; &nbsp; <a href="instruments.html#i1m">Eye-One Monitor</a>
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe" emissive spectrometer<br>
- &nbsp;&nbsp;&nbsp; <a href="#i1d">Eye-One Display 1 or 2&nbsp; or
- LT</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
- colorimeter<br>
- &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">HP DreamColor or
- APS</a>&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+ <a href="#ColorMunki"><span style="text-decoration: underline;">ColorMunki</span></a>
+ Design or Photo&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - spot and "swipe"
+ reflective/emissive spectrometer (UV cut only).<br>
+ &nbsp;&nbsp;&nbsp; <a href="#i1d"><span style="text-decoration:
+ underline;">ColorMunki</span></a> Create or Smile&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
+ colorimeter. (Similar to an Eye-One Display 2)<br>
+ &nbsp;&nbsp;&nbsp; <a href="#Huey">Lenovo W</a> &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - built in laptop
+ Huey display colorimeter.<br>
+ &nbsp;&nbsp;&nbsp; <a href="#i1d3">Eye-One Display 3</a> &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; - i1 DisplayPro and ColorMunki Display<br>
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [ The OEM
+ i1Display Pro, NEC SpectraSensor Pro,<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;&nbsp; Quato Silver Haze 3 OEM and HP
+ DreamColor&nbsp; i1d3 are also reported to work.]<br>
+ &nbsp; &nbsp; <a href="instruments.html#i1p2">Eye-One Pro2</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; - spot and
+ "swipe" reflective/emissive spectrometer.<br>
+ <br>
+ Gretag-Macbeth (now X-Rite):<br>
+ &nbsp; &nbsp; <a href="#sl">Spectrolino</a> &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - spot reflective/emissive
+ spectrometer<br>
+ &nbsp; &nbsp; <a href="#ss">SpectroScan</a> &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; - spot reflective/emissive, XY table
+ reflective spectrometer&nbsp; <br>
+ &nbsp; &nbsp; <a href="#ss">SpectroScanT</a> &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; - spot reflective/emissive/transmissive, XY
+ table reflective spectrometer<br>
+ &nbsp; &nbsp; <a href="#i1p">Eye-One Pro</a> "EFI ES-1000" &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe" reflective/emissive
+ spectrometer<br>
+ &nbsp; &nbsp; <a href="instruments.html#i1m">Eye-One Monitor</a>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; - spot and "swipe" emissive spectrometer<br>
+ &nbsp;&nbsp;&nbsp; <a href="#i1d">Eye-One Display 1 or 2&nbsp; or
+ LT</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display
+ colorimeter<br>
+ &nbsp;&nbsp;&nbsp; <a href="instruments.html#i1d">HP DreamColor or
+ APS</a>&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -286,8 +397,20 @@
- - display colorimeter. (Treated as a Eye-One Display 2)<br>
- &nbsp;&nbsp;&nbsp; <a href="#i1d">CalMAN X2</a>
+
+
+
+
+
+
+
+
+
+
+
+
+ - display colorimeter. (Treated as a Eye-One Display 2)<br>
+ &nbsp;&nbsp;&nbsp; <a href="#i1d">CalMAN X2</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -310,17 +433,29 @@
- - display colorimeter. (Treated as a Eye-One Display 2)<br>
- &nbsp;&nbsp;&nbsp; <a href="#Huey">Huey</a> &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter<br>
- <br>
- Sequel imaging (Now X-Rite):<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="#mox">MonacoOPTIX</a> &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Treated
- as an Eye-One Display 1)<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - display colorimeter. (Treated as a Eye-One Display 2)<br>
+ &nbsp;&nbsp;&nbsp; <a href="#Huey">Huey</a> &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter<br>
+ <br>
+ Sequel imaging (Now X-Rite):<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="#mox">MonacoOPTIX</a> &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Treated
+ as an Eye-One Display 1)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -343,9 +478,21 @@
- [The Sequel Chroma 4 may also work.]<br>
- <br>
- Lacie Blue
+
+
+
+
+
+
+
+
+
+
+
+
+ [The Sequel Chroma 4 may also work.]<br>
+ <br>
+ Lacie Blue
Eye:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -368,15 +515,6 @@
- - see <a href="#i1d">Eye-One Display</a><br>
- <br>
- DataColor ColorVision:<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="#spyd2">Spyder 2</a> &nbsp;
- &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
- that the user must <a href="oeminst.html">supply</a> firmware)<br>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -388,6 +526,17 @@
+
+ - see <a href="#i1d">Eye-One Display</a><br>
+ <br>
+ DataColor ColorVision:<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="#spyd2">Spyder 2</a> &nbsp;
+ &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
+ that the user must <a href="oeminst.html">supply</a> firmware)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
@@ -398,20 +547,6 @@
- [The Spyder 1 also seems to work.]<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="#spyd3">Spyder 3</a> &nbsp;
- &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter.<br>
- &nbsp;&nbsp;&nbsp;&nbsp; <a href="#spyd4">Spyder 4</a> &nbsp;
- &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
- that the user must <a href="oeminst.html">supply</a> calibration
- data)<br>
- <br>
- Other:<br>
- &nbsp;&nbsp;&nbsp; <span class="titre"><a href="#HCFR">Colorim&egrave;tre
@@ -433,6 +568,21 @@
+
+ [The Spyder 1 also seems to work.]<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="#spyd3">Spyder 3</a> &nbsp;
+ &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter.<br>
+ &nbsp;&nbsp;&nbsp;&nbsp; <a href="#spyd4">Spyder 4</a> &nbsp;
+ &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - display colorimeter (Note
+ that the user must <a href="oeminst.html">supply</a> calibration
+ data)<br>
+ <br>
+ Other:<br>
+ &nbsp;&nbsp;&nbsp; <span class="titre"><a href="#HCFR">Colorimètre
HCFR</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -455,9 +605,6 @@
- - display colorimeter<br>
- </span>&nbsp;&nbsp;&nbsp;
- ColorHug&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -469,10 +616,15 @@
+
+ - display colorimeter<br>
+ </span>&nbsp;&nbsp;&nbsp; <a href="#ColorHug">ColorHug</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
- - display colorimeter. Experimental only, does not work on all
- platforms.<br>
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -485,284 +637,289 @@
- Set environmental variable ENABLE_COLORHUG=true to test it.<span
- class="titre"><br>
- </span><br>
- Other instruments can be supported indirectly, since patch result
- files created by other packages can be imported into Argyll.<br>
- <span class="titre"><br>
- General information about:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <a href="#strip">Strip reading instruments</a><br>
- </span>&nbsp;&nbsp;&nbsp; <a href="#xy">X-Y Table instruments</a><br>
- &nbsp;&nbsp;&nbsp; <a href="#spot">Spot reading instruments</a><br>
- <span style="font-weight: bold;"></span><br>
- <br>
- There is a <a href="ccmxs.html">list of contributed</a> <span
- style="font-weight: bold;">ccmx</span> (Colorimeter Correction
- Matrix) files.<br>
- <br>
- <hr style="width: 100%; height: 2px;">
- <h3><a name="strip"></a>Strip reading instruments</h3>
- When used with a <span style="font-weight: bold;">DT20</span>, <span
- style="font-weight: bold;">DTP41</span>, <span
- style="font-weight: bold;">DTP51</span>, <span
- style="font-weight: bold;">Eye-One Pro<span style="font-weight:
- bold;"> </span></span>or <span style="font-weight: bold;">ColorMunki</span>
- strip reading instrument, chartread will first establish
- communications with the instrument, and then set it up ready to read
- the strips. The strips are labeled A to ZZ, and for each strip it
- will prompt:<br>
- <br>
- &nbsp;&nbsp;&nbsp; About to read strip XX&nbsp; :<br>
- <br>
- where XX is the strip label, and this is followed by the available
- options to navigate, read the strip, or finish. Note that the normal
- (forward) direction of strip reading is one that starts at the strip
- label.<br>
- <br>
- For the <span style="font-weight: bold;">DTP51</span> you should
- feed the strip into the instrument, and the microswitch will trigger
- the read.<br>
- <br>
- For the <span style="font-weight: bold;">DTP41</span> you should
- line the appropriate strip up in the machine, and press its button.<br>
- <br>
- For the <span style="font-weight: bold;">Eye-One Pro</span> you
- should set the guide to the appropriate strip, place the instrument
- <span style="text-decoration: underline;">ahead</span> of the first
- patch on blank paper, and then press and hold the instruments
- button. When you hear a beep from the computer, you can then move
- the instrument steadily over the patches, releasing the button after
- the instrument is past the last patch. Moving the instrument too
- fast or changing speeds may cause a mis-read, or a scan with few
- samples read per patch.<br>
- <br>
- For the <span style="font-weight: bold;">ColorMunki</span> with the
- default chart, the patches are the same width as the silver portion
- of body (white version), or the textured portion of the body (black
- version). Place aperture of the the instrument (located at its
- center) in the white space ahead of the first patch, and then press
- and hold the instruments button. When you hear a beep from the
- computer, you can then move the instrument steadily over the
- patches, releasing the button after the instrument is past the last
- patch. Moving the instrument too fast or changing speeds may cause a
- mis-read, or a scan with few samples read per patch. For the <span
- style="font-weight: bold;">high density</span> ColorMunki chart (<a
- href="printtarg.html#h">printtarg -h</a>), the patches are
- arranged so that three rows are exactly the width of the&nbsp; body
- of the instrument. If you are careful you can use this to guide the
- center of the instrument over each row, or you may prefer to use
- something like a plastic ruler to help guide the instrument.<br>
- <br>
- Using the <span style="font-weight: bold;">DTP20</span> or the <span
- style="font-weight: bold;">Eye-One Pro</span> or <span
- style="font-weight: bold;">ColorMunki</span> with a randomized
- chart layout, the strip may be scanned from either direction. If a
- randomized chart layout has not been used for the <span
- style="font-weight: bold;">Eye-One Pro</span> or <span
- style="font-weight: bold;">ColorMunki</span>, then the chart
- should only be read in the one direction (use <a
- href="chartread.html#B">chartread -B</a>).<br>
- <br>
- Note that you may have to check that system alert sounds are enabled
- and at a suitable volume to in order to hear the beep prompt. For
- the Eye-One Pro and ColorMunki, a second beep will sound after a
- successfully read strip, or a double beep will sound,&nbsp;
- indicating a failure or warning that needs attention. See also the
- note on Linux in <a href="Installing_Linux.html">installation</a>.<br>
- <br>
- If the strip is read successfully there will be a single "success"
- beep, and the line will be followed with:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read strip&nbsp; XX&nbsp; : <br>
- &nbsp;&nbsp;&nbsp; Strip read OK<br>
- <br>
- If there is an error of some sort there will be a double "fail"
- beep, and a message will be issued, and you will be asked whether to
- abort the chart reading, or retry the<br>
- failed strip:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read strip XX&nbsp; : <br>
- &nbsp;&nbsp;&nbsp; Strip read failed due to misread (Not enough
- patches)<br>
- <br>
- &nbsp;&nbsp;&nbsp; Hit Esc to give up, any other key to retry:<br>
- <br>
- If you are unable to successfully read a strip after several
- retries, you can skip that strip using the <span
- style="font-weight: bold;">'n'</span> key, and save<br>
- the chart readings without that strip.<br>
- <br>
- If the strip is read successfully, but the patches values don't seem
- to be what is expected, you will get a double "fail" beep&nbsp; and
- the following type of warning:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read strip&nbsp; XX&nbsp; :<br>
- &nbsp;&nbsp;&nbsp; (Warning) Seem to have read strip&nbsp; YY&nbsp;
- rather than&nbsp; XX !<br>
- &nbsp;&nbsp;&nbsp; Hit Return to use it anyway, any other key to
- retry, Esc, ^C or Q to give up:<br>
- <br>
- This could be because you have accidentally read the wrong strip (a
- common mistake), or it could be that the device response is so
- different from what is expected that warning is erroneous, or you
- may get a lot of these sorts of warnings if you are accidentally
- reading the wrong chart. You may also get this sort of warning if
- you are not using bi-direction reading (chartread -B), and read the
- strip from the wrong end.<br>
- If you are absolutely sure you lined up the correct strip, then hit
- return, otherwise line the appropriate strip up again, and hit some
- other key (ie. space).<br>
- Erroneous warnings are less likely if a previous profile for a
- device was given to <span style="font-weight: bold;">targen</span>
- to set more accurate expectations.<br>
- <br>
- You may also see the following type of warning:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read strip&nbsp; XX&nbsp; :<br>
- &nbsp;&nbsp;&nbsp; (Warning) Patch error YY.YYY (&gt;35 not good,
- &gt;95 bad)<br>
- &nbsp;&nbsp; There is at least one patch with an very unexpected
- response!<br>
- &nbsp;&nbsp;&nbsp; Hit Return to use it anyway, any other key to
- retry, Esc, ^C or Q to give up:<br>
- <br>
- Similar to the previous warning, this indicates that while the right
- strip appears to have been read, one of the patch readings is quite
- different to what is expected. This may indicate an error of some
- sort (ie. damaged test chart, or bad instrument positioning), or may
- be erroneous if the actual device response is quite different to the
- expectation. Erroneous warnings are less likely if a previous
- profile for a device was given to <span style="font-weight: bold;">targen</span>
- to set more accurate expectations.<br>
- <br>
- You can also navigate the next strip to be read using the <span
- style="font-weight: bold;">'f'</span> key to move forward and the
- <span style="font-weight: bold;">'b'</span> keys<span
- style="font-weight: bold;"></span><span style="font-weight: bold;"></span>
- to move backwards. The prompt will indicate whether this strip has
- already been read or not, or whether all strips have been read. You
- can also use <span style="font-weight: bold;">'n'</span> to move
- forward to the next unread strip. After each successful reading it
- will move forward to the next unread strip. When you are finished,
- use the <span style="font-weight: bold;">'d'</span> to indicate
- that you are done. You can choose to finish before all the strips
- are read, and the patches that have been read will be saved to the
- .ti3 file. This is useful if you are unable to read a particular
- strip successfully, or if you are unable to finish the chart in one
- session, and you can later <span style="text-decoration:
- underline;">resume</span> reading the chart by using the <span
- style="font-weight: bold;">chartread -r</span> flag. [You could
- resume reading the chart patch by patch using the <span
- style="font-weight: bold;">chartread -r -p</span> if you are
- unable to read a strip successfully.]<br>
- <br>
- When reading in patch by patch mode, there are a few additional
- navigation options, such as <span style="font-weight: bold;"><span
- style="font-weight: bold;">F</span></span> to move forward 10
- patches, <span style="font-weight: bold;">B</span> to move
- backwards 10 patches, and <span style="font-weight: bold;">g</span>
- to go to a specific patch.<br>
- <br>
- You can abort the whole process at any time by hitting Escape, and
- the readings will not be saved.<br>
- <br>
- <hr style="width: 100%; height: 2px;">
- <h3><a name="xy"></a>X-Y Table instruments</h3>
- When you are using an XY table type instrument, such as a Gretag <span
- style="font-weight: bold;">SpectroScan</span>, &nbsp;chartread
- will first establish communications with the instrument, and then
- set it up ready to read the chart. You will be prompted for each
- sheet with a message such as:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Please make sure that the white reference is in
- slot 1, then<br>
- &nbsp;&nbsp;&nbsp; place sheet 1 of 4 on table, then<br>
- &nbsp;&nbsp;&nbsp; hit return to continue, Esc to give up<br>
- <br>
- After hitting return you will be prompted to line up three squares
- on the sheet, one at a time:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Using the XY table controls, locate patch A1 with
- the sight,<br>
- &nbsp;&nbsp;&nbsp; then hit return to continue, Esc to give up<br>
- <br>
- On completing this, the instrument will commence reading each sheet.<br>
- <br>
- <hr style="width: 100%; height: 2px;">
- <h3><a name="spot"></a>Spot reading instruments</h3>
- When used with a <span style="font-weight: bold;">DT22</span> or <span
- style="font-weight: bold;">SpectroLino</span> or use the patch by
- patch reading mode (<span style="font-weight: bold;">chartread -p</span>)
- with the <span style="font-weight: bold;"></span> <span
- style="font-weight: bold;">Eye-One Pro<span style="font-weight:
- bold;"> </span></span>or <span style="font-weight: bold;">ColorMunki</span>
- instrument, or use the external values mode (<span
- style="font-weight: bold;">chartread -x</span>), chartread will
- first establish communications with the instrument, and then set it
- up ready to read the patches. The patches are typically labeled by
- column A to ZZ, and row 1-999. Each patch will prompt:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read patch 'XX'&nbsp; :<br>
- <br>
- where XX is the patch label, and this is followed by the available
- options to navigate, read the strip, or finish.<br>
- <br>
- Place the instrument on the indicated patch, and trigger a reading
- using one of the available methods (typically using the instrument
- switch of pressing a key).<br>
- <br>
- There should be an audible prompt on a successful or failed reading.
- <br>
- <br>
- Note that you may have to check that system alert sounds are enabled
- and at a suitable volume to in order to hear the beep prompt. For
- the Eye-One Pro and ColorMunki, a second beep will sound after a
- successfully read strip, or a double beep will sound,&nbsp;
- indicating a failure or warning that needs attention. See also the
- note on Linux in <a href="Installing_Linux.html">installation</a>.<br>
- <br>
- If the patch is read successfully, the line will be completed with:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read patch&nbsp; XX&nbsp; :<br>
- &nbsp;&nbsp;&nbsp; Patch read OK<br>
- <br>
- If there is an error of some sort, a message will be issued, and you
- will be asked whether to abort the chart reading, or retry the<br>
- failed patch:<br>
- <br>
- &nbsp;&nbsp;&nbsp; Ready to read patch XX&nbsp; : read_strip
- returned 'Strip misread' (Bad reading)<br>
- <br>
- &nbsp;&nbsp;&nbsp; Strip read failed due to misread<br>
- &nbsp;&nbsp;&nbsp; Hit Esc to give up, any other key to retry:<br>
- <br>
- You can navigate the next patch to be read using the <span
- style="font-weight: bold;">'f'</span> key to move forward and the
- <span style="font-weight: bold;">'b'</span> keys<span
- style="font-weight: bold;"></span><span style="font-weight: bold;"></span>
- to move backwards, while <span style="font-weight: bold;">'F'</span>
- and <span style="font-weight: bold;">'B'</span> will move forward
- and backwards by 10 patches. The prompt will indicate whether this
- patch has already been read or not, or whether all patches have been
- read. You can also use <span style="font-weight: bold;">'n'</span>
- to move forward to the next unread patch. When you are finished, use
- the <span style="font-weight: bold;">'d'</span> to indicate that
- you are done. You can choose to finish before all the patches are
- read, and they will be saved to the .ti3 file. This is useful if you
- are unable to finish the chart in one session, and you can later <span
- style="text-decoration: underline;">resume</span> reading the
- chart by using the <span style="font-weight: bold;">chartread -r</span>
- flag.<br>
- <br>
- You can abort the whole process at any time by hitting Escape, and
- the readings will not be saved.<br>
- <br>
- <span style="font-weight: bold;"></span>
- <hr style="width: 100%; height: 2px;">
- <h3><a name="displaytype"></a>Display Type<br>
- </h3>
+
+
+
+
+
+
+ - display colorimeter<span class="titre"><br>
+ </span><br>
+ Other instruments can be supported indirectly, since patch result
+ files created by other packages can be imported into Argyll.<br>
+ <span class="titre"><br>
+ General information about:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <a href="#strip">Strip reading instruments</a><br>
+ </span>&nbsp;&nbsp;&nbsp; <a href="#xy">X-Y Table instruments</a><br>
+ &nbsp;&nbsp;&nbsp; <a href="#spot">Spot reading instruments</a><br>
+ <span style="font-weight: bold;"></span><br>
+ <br>
+ There is a <a href="ccmxs.html">list of contributed</a> <span
+ style="font-weight: bold;">ccmx</span> (Colorimeter Correction
+ Matrix) files.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;">
+ <h3><a name="strip"></a>Strip reading instruments</h3>
+ When used with a <span style="font-weight: bold;">DT20</span>, <span
+ style="font-weight: bold;">DTP41</span>, <span
+ style="font-weight: bold;">DTP51</span>, <span
+ style="font-weight: bold;">Eye-One Pro<span style="font-weight:
+ bold;"> </span></span>or <span style="font-weight: bold;">ColorMunki</span>
+ strip reading instrument, chartread will first establish
+ communications with the instrument, and then set it up ready to read
+ the strips. The strips are labeled A to ZZ, and for each strip it
+ will prompt:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; About to read strip XX&nbsp; :<br>
+ <br>
+ where XX is the strip label, and this is followed by the available
+ options to navigate, read the strip, or finish. Note that the normal
+ (forward) direction of strip reading is one that starts at the strip
+ label.<br>
+ <br>
+ For the <span style="font-weight: bold;">DTP51</span> you should
+ feed the strip into the instrument, and the microswitch will trigger
+ the read.<br>
+ <br>
+ For the <span style="font-weight: bold;">DTP41</span> you should
+ line the appropriate strip up in the machine, and press its button.<br>
+ <br>
+ For the <span style="font-weight: bold;">Eye-One Pro</span> you
+ should set the guide to the appropriate strip, place the instrument
+ <span style="text-decoration: underline;">ahead</span> of the first
+ patch on blank paper, and then press and hold the instruments
+ button. When you hear a beep from the computer, you can then move
+ the instrument steadily over the patches, releasing the button after
+ the instrument is past the last patch. Moving the instrument too
+ fast or changing speeds may cause a mis-read, or a scan with few
+ samples read per patch.<br>
+ <br>
+ For the <span style="font-weight: bold;">ColorMunki</span> with the
+ default chart, the patches are the same width as the silver portion
+ of body (white version), or the textured portion of the body (black
+ version). Place aperture of the the instrument (located at its
+ center) in the white space ahead of the first patch, and then press
+ and hold the instruments button. When you hear a beep from the
+ computer, you can then move the instrument steadily over the
+ patches, releasing the button after the instrument is past the last
+ patch. Moving the instrument too fast or changing speeds may cause a
+ mis-read, or a scan with few samples read per patch. For the <span
+ style="font-weight: bold;">high density</span> ColorMunki chart (<a
+ href="printtarg.html#h">printtarg -h</a>), the patches are
+ arranged so that three rows are exactly the width of the&nbsp; body
+ of the instrument. If you are careful you can use this to guide the
+ center of the instrument over each row, or you may prefer to use
+ something like a plastic ruler to help guide the instrument.<br>
+ <br>
+ Using the <span style="font-weight: bold;">DTP20</span> or the <span
+ style="font-weight: bold;">Eye-One Pro</span> or <span
+ style="font-weight: bold;">ColorMunki</span> with a randomized
+ chart layout, the strip may be scanned from either direction. If a
+ randomized chart layout has not been used for the <span
+ style="font-weight: bold;">Eye-One Pro</span> or <span
+ style="font-weight: bold;">ColorMunki</span>, then the chart
+ should only be read in the one direction (use <a
+ href="chartread.html#B">chartread -B</a>).<br>
+ <br>
+ Note that you may have to check that system alert sounds are enabled
+ and at a suitable volume to in order to hear the beep prompt. For
+ the Eye-One Pro and ColorMunki, a second beep will sound after a
+ successfully read strip, or a double beep will sound,&nbsp;
+ indicating a failure or warning that needs attention. See also the
+ note on Linux in <a href="Installing_Linux.html">installation</a>.<br>
+ <br>
+ If the strip is read successfully there will be a single "success"
+ beep, and the line will be followed with:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read strip&nbsp; XX&nbsp; : <br>
+ &nbsp;&nbsp;&nbsp; Strip read OK<br>
+ <br>
+ If there is an error of some sort there will be a double "fail"
+ beep, and a message will be issued, and you will be asked whether to
+ abort the chart reading, or retry the<br>
+ failed strip:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read strip XX&nbsp; : <br>
+ &nbsp;&nbsp;&nbsp; Strip read failed due to misread (Not enough
+ patches)<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Hit Esc to give up, any other key to retry:<br>
+ <br>
+ If you are unable to successfully read a strip after several
+ retries, you can skip that strip using the <span
+ style="font-weight: bold;">'n'</span> key, and save<br>
+ the chart readings without that strip.<br>
+ <br>
+ If the strip is read successfully, but the patches values don't seem
+ to be what is expected, you will get a double "fail" beep&nbsp; and
+ the following type of warning:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read strip&nbsp; XX&nbsp; :<br>
+ &nbsp;&nbsp;&nbsp; (Warning) Seem to have read strip&nbsp; YY&nbsp;
+ rather than&nbsp; XX !<br>
+ &nbsp;&nbsp;&nbsp; Hit Return to use it anyway, any other key to
+ retry, Esc, ^C or Q to give up:<br>
+ <br>
+ This could be because you have accidentally read the wrong strip (a
+ common mistake), or it could be that the device response is so
+ different from what is expected that warning is erroneous, or you
+ may get a lot of these sorts of warnings if you are accidentally
+ reading the wrong chart. You may also get this sort of warning if
+ you are not using bi-direction reading (chartread -B), and read the
+ strip from the wrong end.<br>
+ If you are absolutely sure you lined up the correct strip, then hit
+ return, otherwise line the appropriate strip up again, and hit some
+ other key (ie. space).<br>
+ Erroneous warnings are less likely if a previous profile for a
+ device was given to <span style="font-weight: bold;">targen</span>
+ to set more accurate expectations.<br>
+ <br>
+ You may also see the following type of warning:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read strip&nbsp; XX&nbsp; :<br>
+ &nbsp;&nbsp;&nbsp; (Warning) Patch error YY.YYY (&gt;35 not good,
+ &gt;95 bad)<br>
+ &nbsp;&nbsp; There is at least one patch with an very unexpected
+ response!<br>
+ &nbsp;&nbsp;&nbsp; Hit Return to use it anyway, any other key to
+ retry, Esc, ^C or Q to give up:<br>
+ <br>
+ Similar to the previous warning, this indicates that while the right
+ strip appears to have been read, one of the patch readings is quite
+ different to what is expected. This may indicate an error of some
+ sort (ie. damaged test chart, or bad instrument positioning), or may
+ be erroneous if the actual device response is quite different to the
+ expectation. Erroneous warnings are less likely if a previous
+ profile for a device was given to <span style="font-weight: bold;">targen</span>
+ to set more accurate expectations.<br>
+ <br>
+ You can also navigate the next strip to be read using the <span
+ style="font-weight: bold;">'f'</span> key to move forward and the
+ <span style="font-weight: bold;">'b'</span> keys<span
+ style="font-weight: bold;"></span><span style="font-weight: bold;"></span>
+ to move backwards. The prompt will indicate whether this strip has
+ already been read or not, or whether all strips have been read. You
+ can also use <span style="font-weight: bold;">'n'</span> to move
+ forward to the next unread strip. After each successful reading it
+ will move forward to the next unread strip. When you are finished,
+ use the <span style="font-weight: bold;">'d'</span> to indicate
+ that you are done. You can choose to finish before all the strips
+ are read, and the patches that have been read will be saved to the
+ .ti3 file. This is useful if you are unable to read a particular
+ strip successfully, or if you are unable to finish the chart in one
+ session, and you can later <span style="text-decoration:
+ underline;">resume</span> reading the chart by using the <span
+ style="font-weight: bold;">chartread -r</span> flag. [You could
+ resume reading the chart patch by patch using the <span
+ style="font-weight: bold;">chartread -r -p</span> if you are
+ unable to read a strip successfully.]<br>
+ <br>
+ When reading in patch by patch mode, there are a few additional
+ navigation options, such as <span style="font-weight: bold;"><span
+ style="font-weight: bold;">F</span></span> to move forward 10
+ patches, <span style="font-weight: bold;">B</span> to move
+ backwards 10 patches, and <span style="font-weight: bold;">g</span>
+ to go to a specific patch.<br>
+ <br>
+ You can abort the whole process at any time by hitting Escape, and
+ the readings will not be saved.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;">
+ <h3><a name="xy"></a>X-Y Table instruments</h3>
+ When you are using an XY table type instrument, such as a Gretag <span
+ style="font-weight: bold;">SpectroScan</span>, &nbsp;chartread
+ will first establish communications with the instrument, and then
+ set it up ready to read the chart. You will be prompted for each
+ sheet with a message such as:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Please make sure that the white reference is in
+ slot 1, then<br>
+ &nbsp;&nbsp;&nbsp; place sheet 1 of 4 on table, then<br>
+ &nbsp;&nbsp;&nbsp; hit return to continue, Esc to give up<br>
+ <br>
+ After hitting return you will be prompted to line up three squares
+ on the sheet, one at a time:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Using the XY table controls, locate patch A1 with
+ the sight,<br>
+ &nbsp;&nbsp;&nbsp; then hit return to continue, Esc to give up<br>
+ <br>
+ On completing this, the instrument will commence reading each sheet.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;">
+ <h3><a name="spot"></a>Spot reading instruments</h3>
+ When used with a <span style="font-weight: bold;">DT22</span> or <span
+ style="font-weight: bold;">SpectroLino</span> or use the patch by
+ patch reading mode (<span style="font-weight: bold;">chartread -p</span>)
+ with the <span style="font-weight: bold;"></span> <span
+ style="font-weight: bold;">Eye-One Pro<span style="font-weight:
+ bold;"> </span></span>or <span style="font-weight: bold;">ColorMunki</span>
+ instrument, or use the external values mode (<span
+ style="font-weight: bold;">chartread -x</span>), chartread will
+ first establish communications with the instrument, and then set it
+ up ready to read the patches. The patches are typically labeled by
+ column A to ZZ, and row 1-999. Each patch will prompt:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read patch 'XX'&nbsp; :<br>
+ <br>
+ where XX is the patch label, and this is followed by the available
+ options to navigate, read the strip, or finish.<br>
+ <br>
+ Place the instrument on the indicated patch, and trigger a reading
+ using one of the available methods (typically using the instrument
+ switch of pressing a key).<br>
+ <br>
+ There should be an audible prompt on a successful or failed reading.
+ <br>
+ <br>
+ Note that you may have to check that system alert sounds are enabled
+ and at a suitable volume to in order to hear the beep prompt. For
+ the Eye-One Pro and ColorMunki, a second beep will sound after a
+ successfully read strip, or a double beep will sound,&nbsp;
+ indicating a failure or warning that needs attention. See also the
+ note on Linux in <a href="Installing_Linux.html">installation</a>.<br>
+ <br>
+ If the patch is read successfully, the line will be completed with:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read patch&nbsp; XX&nbsp; :<br>
+ &nbsp;&nbsp;&nbsp; Patch read OK<br>
+ <br>
+ If there is an error of some sort, a message will be issued, and you
+ will be asked whether to abort the chart reading, or retry the<br>
+ failed patch:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Ready to read patch XX&nbsp; : read_strip
+ returned 'Strip misread' (Bad reading)<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; Strip read failed due to misread<br>
+ &nbsp;&nbsp;&nbsp; Hit Esc to give up, any other key to retry:<br>
+ <br>
+ You can navigate the next patch to be read using the <span
+ style="font-weight: bold;">'f'</span> key to move forward and the
+ <span style="font-weight: bold;">'b'</span> keys<span
+ style="font-weight: bold;"></span><span style="font-weight: bold;"></span>
+ to move backwards, while <span style="font-weight: bold;">'F'</span>
+ and <span style="font-weight: bold;">'B'</span> will move forward
+ and backwards by 10 patches. The prompt will indicate whether this
+ patch has already been read or not, or whether all patches have been
+ read. You can also use <span style="font-weight: bold;">'n'</span>
+ to move forward to the next unread patch. When you are finished, use
+ the <span style="font-weight: bold;">'d'</span> to indicate that
+ you are done. You can choose to finish before all the patches are
+ read, and they will be saved to the .ti3 file. This is useful if you
+ are unable to finish the chart in one session, and you can later <span
+ style="text-decoration: underline;">resume</span> reading the
+ chart by using the <span style="font-weight: bold;">chartread -r</span>
+ flag.<br>
+ <br>
+ You can abort the whole process at any time by hitting Escape, and
+ the readings will not be saved.<br>
+ <br>
+ <span style="font-weight: bold;"></span>
+ <hr style="width: 100%; height: 2px;">
+ <h3><a name="displaytype"></a>Display Type<br>
+ </h3>
Many of the colorimeters have a <span style="font-weight: bold;">display
@@ -780,360 +937,398 @@
- type</span> selection parameter. Depending on the instrument, this
- may combine two related functions: 1) Changing the measurement mode
- to suite either refresh-type, or non-refresh displays, and 2)
- Changing the calibration to suite a particular displays spectral
- characteristics.<br>
- <br>
- A refresh type display uses a technology that presents different
- portions of the image at different times, doing so at a high enough
- rate that this is normally imperceptible. This time varying
- characteristic can interfere with measuring a display color unless
- the instrument makes allowances for it, typically by making its
- measurement period a multiple of the display refresh period. Display
- types that <span style="font-weight: bold;">refresh</span> are CRT
- (Cathode Ray Tube), Single chip DLP (Digital Light Processing) and
- Plasma displays. An example of a <span style="font-weight: bold;">non-refresh</span>
- display technology is LCD (Liquid Crystal Display), although is a
- few cases the back-light illumination may have a low enough
- frequency flicker to benefit from the refresh mode.<br>
- <br>
- Instruments in which the display type selection only changes the
- measurement mode (i.e. i1d3), will typically have some other
- independent option to set the calibration type. Simpler instruments
- combine the measurement mode with a calibration selections,
- typically refresh+CRT and non-refresh+LCD. Some instruments are a
- hybrid of both (Spyder4), where the display type can select between
- generic refresh/non-refresh that can then use a .CCSS to set the
- calibration type, or a combined selection of non-refresh and a
- particular display type.<br>
- <br>
- See <a
- href="http://en.wikipedia.org/wiki/Comparison_of_display_technology">Comparison_of_display_technology</a>
- for some background on different display technologies.<br>
- <br>
- <hr size="2" width="100%"><br>
- <h3><a name="refreshmeasurement"></a>Refresh Rate Measurement</h3>
- <p>Most of the colorimeters that have a refresh display type
- selection, also have an ability to measure the refresh rate of a
- display. Some of the spectrometers also have a display refresh
- rate measurement capability when in an emissive measurement mode,
- even though they don't use this to support a refresh display mode.
- You can do a display refresh rate measurement in <a
- href="spotread.html">spotread</a> using the <b>'F' </b>key.
- The particular instruments have a range of accuracy when making
- this measurement. A rough guide is as follows:<br>
- <br>
- </p>
- <table border="1" cellpadding="2" cellspacing="2" height="230"
- width="372">
- <tbody>
- <tr>
- <td valign="top"><b>Instrument</b></td>
- <td valign="top"><b>Typical error in Hz.</b></td>
- </tr>
- <tr>
- <td valign="top">DTP92<br>
- </td>
- <td valign="top">0.1<br>
- </td>
- </tr>
- <tr>
- <td valign="top">i1 Display 2<br>
- </td>
- <td valign="top">0.5<br>
- </td>
- </tr>
- <tr>
- <td valign="top">Spyder 2<br>
- </td>
- <td valign="top">0.7<br>
- </td>
- </tr>
- <tr>
- <td valign="top">Spyder 3<br>
- </td>
- <td valign="top">3<br>
- </td>
- </tr>
- <tr>
- <td valign="top">Spyder 4<br>
- </td>
- <td valign="top">3<br>
- </td>
- </tr>
- <tr>
- <td valign="top">i1 Display Pro<br>
- </td>
- <td valign="top">0.05<br>
- </td>
- </tr>
- <tr>
- <td valign="top">i1 Pro Spectro.<br>
- </td>
- <td valign="top">0.05<br>
- </td>
- </tr>
- <tr>
- <td valign="top">ColorMunki Spectro.<br>
- </td>
- <td valign="top">0.05<br>
- </td>
- </tr>
- </tbody>
- </table>
- <p><br>
- </p>
- <hr style="width: 100%; height: 8px;"><br>
- <span style="font-weight: bold;"></span><br>
- <span style="font-weight: bold;"><a name="ColorMunki"></a><span
- style="font-weight: bold;">ColorMunki </span>Design or Photo <span
- style="font-weight: bold;">reflective/emissive spectrometer</span><br>
- <br>
- <img style="width: 272px; height: 243px;" alt="" title="ColorMunki
- (White)" src="ColorMunki.jpg">&nbsp;&nbsp; <br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">ColorMunki</span> <span
- style="font-weight: bold;">Design or Photo </span>from <a
- href="http://www.xrite.com/">X-Rite</a>&nbsp; is currently
- available in two different packages from the manufacturer. These
- packages differ in what features the manufacturers software
- provides, as well as cosmetic differences between the instrument
- (white and black). This comparison <a
- href="http://www.colormunki.com/product/show?page=2">chart</a>
- illustrates the differences. Used with Argyll, there are no
- differences in operation of a ColorMunki instrument, irrespective of
- which package it came with. The ColorMunki Design has the lowest
- RRP, but the Photo package may be cheaper with discounting .<br>
- <br>
- <span style="font-weight: bold;">Limitations &amp; Features:</span><br>
- <br>
- Unlike the Eye-One Pro, the ColorMunki is only available in a U.V.
- Cut (ie. "Ultra Violet filtered") model. This means that it is not
- suitable for use with the&nbsp; Fluorescent Whitener Additive
- Compensation option in Argyll (see <a href="FWA.html">here</a> for
- a discussion about what FWA compensation is).<br>
- <br>
- Like the Eye-One Pro, this instrument does support the <a
- href="spotread.html#H">high resolution</a> spectral mode.<br>
- <br>
- <span style="font-weight: bold;">OS X and X-Rite drivers</span><br>
- <br>
- Please note the installation <a
- href="Installing_OSX.html#ColorMunki">instructions</a>.<br>
- <br>
- <span style="font-weight: bold;">Tips &amp; Tricks:<br>
- <br>
- </span>In handling the instrument when about to make a reading, be
- very careful not to accidentally press the switch - it is large and
- easily pressed by accident. A guide of some sort (ie. a plastic
- ruler) can help a lot in&nbsp; keeping the instrument over a line
- of&nbsp; patches. <br>
- <br>
- <span style="font-weight: bold;">Patch recognition:</span><br>
- <br>
- For the best chances of good patch recognition, the instrument
- should be drawn smoothly and not too rapidly over the strip. (This
- can be a little tricky due to the two small rubber feet on the
- bottom of the device that aid its spot reading guide.) If there is a
- misread, try slowing down slightly. Generally a higher quality set
- of readings will result if slower scans are used, since there will
- then be more samples averaged for each patch. <br>
- <br>
- In <a href="chartread.html">chartread</a>, the -<span
- style="font-weight: bold;">T ratio</span> argument modifies the
- patch consistency tolerance threshold for the ColorMunki. In
- recognizing patches in a strip, the instrument takes multiple
- readings as the strip is read, and then divide the readings up into
- each patch. It then check the consistency of the multiple readings
- corresponding to each patch, and reject the measurement if they are
- too inconsistent. For some media (ie. a coarser screens, fabric
- etc.) the default tolerance may be unreasonably tight, so the <span
- style="font-weight: bold;">-T ratio</span> argument can be used to
- modify this criteria. To loosen the tolerance, use a number greater
- than 1.0 (ie. 1.5, 2.0). <br>
- <br>
- Note that <a href="printtarg.html">printtarg</a> provides the <a
- href="printtarg.html#h">-h</a> option that allows the choice of
- two different patch row widths with ColorMunki test charts. [Some
- people have successfully used the i1Pro patch layout with the
- ColorMunki, by making a guide to keep it over the much narrower
- patchs.]<br>
- <br>
- <span style="font-weight: bold;"></span><br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><span
- style="font-weight: bold;"></span><br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
- <hr style="width: 100%; height: 2px;"><span style="font-weight:
- bold;"><br>
- <a name="DTP20"></a></span><span style="font-weight: bold;">DTP20
- "Pulse" reflective spectrometer<br>
- <br>
- </span><span style="font-weight: bold;"><img title="DTP20" alt=""
- src="DTP20.jpg" style="width: 304px; height: 210px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">DTP20</span> from <a
- href="http://www.xrite.com/">X-Rite</a> was discontinued during
- 2007, but may still be available from old stock or second hand. <br>
- <br>
- <span style="font-weight: bold;">Special features:</span><br>
- <br>
- The <span style="font-weight: bold;">DTP20</span> has a couple of
- unique features that Argyll can take advantage of. One is that it
- can operate un-tethered (off line). A whole chart can be read
- un-tethered by first clearing any previous readings in the
- instrument, then reading the chart TID strip, before reading all the
- other strips. The instrument can then be connected up to <span
- style="font-weight: bold;">chartread</span>, which will recognize
- the chart, and download all the measurements.<br>
- If there is no chart in the instrument when chartread connects to
- it, then it will use the strip by strip tethered mode, just like the
- other strip instruments. If the right number of spot readings are
- present in the instrument, these will be used by <span
- style="font-weight: bold;">chartread</span> too.<br>
- <br>
- Un-tethered spot measurements can also be read in using&nbsp; <span
- style="font-weight: bold;">spotread</span>, which will notice the
- stored readings, and offer to print them out, or they can be
- ignored, and tethered readings taken. This will clear any saved spot
- readings.<br>
- <br>
- <span style="font-weight: bold;">Note</span> that tethered (on-line)
- strip reading will only work if the firmware in the device is
- version 1.03 or greater. You can check the firmware version by
- running with the verbose option: <span style="font-weight: bold;">-v<br>
- <br>
- Chart printing:<br>
- <span style="font-weight: bold;"><br>
- </span></span>Because the DTP20 measures exact distances using the
- markings on its ruler, it's critical that the chart be printed out
- exactly the right size. If the chart gets re-sized at all in the
- process of printing it, the DTP20 is likely to fail in reading it.
- If you have a problem with this, you might want to increase the page
- margins using the <span style="font-weight: bold;">printtarg -m</span>
- parameter, or find a printing path that preserves the test chart
- size correctly.<br>
- <br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><span
- style="font-weight: bold;">Operation:<br>
- <br>
- </span>When reading in tethered (on-line) mode, that the instrument
- takes <span style="font-weight: bold;">several seconds</span> to
- download the measurements after each strip, and that the indicator
- will be in "rainbow" mode while this occurs. <span
- style="text-decoration: underline;">Wait</span> until the
- indicator turns solid green again before starting to measure the
- next strip.<br>
- <br>
- To <span style="font-weight: bold;">reset</span> the instrument and
- clear any stored readings: press the button three times in quick
- succession. The indicator will turn solid blue. Then hold the button
- down until the instrument beeps and the indicator goes out. Release
- the button and the indicator should flash then return to solid green
- (ready).<br>
- <br>
- To <span style="font-weight: bold;">calibrate</span> the
- instrument, place it on its calibration tile, then press the button
- three times in quick succession.The indicator will turn solid blue.
- Click the button another three times in quick succession, and the
- indicator should turn yellow. Then hold the button down until the
- instrument beeps and the indicator goes out. Release the button and
- the instrument should flash and then turn solid green.<br>
- <br>
- If the chart is particularly <span style="font-weight: bold;">small</span>,
- the patches may end up printed very close to the edge of the chart,
- and therefore it may be difficult to confine your scan to the chart,
- and passing<br>
- the instrument over the edge of the chart may prevent it reading
- successfully. One way of working around this is to place the chart
- on a larger piece of paper of the same type.<br>
- <br>
- The <span style="font-weight: bold;">speed</span> of scan can be
- quite critical with this instrument. In particular, it doesn't work
- very well if the scan is too <span style="font-weight: bold;">slow</span>.
- You don't want to go too fast either, as this reduces the number of
- samples per patch.<br>
- <br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><span
- style="font-weight: bold;"></span><br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
- <hr style="width: 100%; height: 2px;"><span style="font-weight:
- bold;"><br>
- <a name="DTP22"></a></span><span style="font-weight: bold;">DTP22
- Digital Swatchbook reflective spectrometer</span><br>
- <span style="font-weight: bold;"><br>
- <img alt="" src="DTP22.jpg" style="width: 222px; height: 193px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">DTP22</span> from <a
- href="http://www.xrite.com/">X-Rite</a> is a discontinued
- instrument.&nbsp; It may still be available second hand. It is
- capable of reading colored patches one at a time.<br>
- <br>
- <br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
- <hr style="width: 100%; height: 2px;"><span style="font-weight:
- bold;"><br>
- <a name="DTP41"></a>DTP41 reflective, DTP41T
- reflective/transmissive spectrometers<br>
- <br>
- <img alt="" src="DTP41.jpg" style="width: 263px; height: 298px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">DTP41</span> and <span
- style="font-weight: bold;">DTP41T</span> from <a
- href="http://www.xrite.com/">X-Rite</a> is a discontinued
- instrument.&nbsp; It may still be available second hand. <br>
- <br>
- The series II instruments (<span style="font-weight: bold;">DTP41B</span>
- and <span style="font-weight: bold;">DTP41TB</span>) offer both
- serial and USB connection. Note that currently only serial operation
- using Argyll is possible with these instruments.<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <a name="dtp51"></a><span style="font-weight: bold;">DTP51
- reflective colorimeter<br>
- <br>
- <img alt="" src="DTP51.jpg" style="width: 263px; height: 223px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">DTP51</span> from <a
- href="http://www.xrite.com/">X-Rite</a> is a discontinued
- instrument.&nbsp; It may still be available second hand. <br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"><br>
- </span></span>The DTP51's switch is triggered by inserting a strip
- into the slot.<br>
- <br>
- <br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
- <hr style="width: 100%; height: 2px;"><span style="font-weight:
- bold;"><br>
- <a name="DTP92"></a>DTP92 CRT display colorimeter<br>
- <br>
- <img alt="" src="DTP92.jpg" style="width: 223px; height: 180px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">DTP92</span><span
- style="font-weight: bold;"></span> from <a
- href="http://www.xrite.com/">X-Rite</a> is a discontinued
- instrument.&nbsp; It may still be available second hand. It will
- only read CRT technology displays.<br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ type</span> selection parameter. Depending on the instrument, this
+ may combine two related functions: 1) Changing the measurement mode
+ to suite either refresh-type, or non-refresh displays, and 2)
+ Changing the calibration to suite a particular displays spectral
+ characteristics.<br>
+ <br>
+ A refresh type display uses a technology that presents different
+ portions of the image at different times, doing so at a high enough
+ rate that this is normally imperceptible. This time varying
+ characteristic can interfere with measuring a display color unless
+ the instrument makes allowances for it, typically by making its
+ measurement period a multiple of the display refresh period. Display
+ types that <span style="font-weight: bold;">refresh</span> are CRT
+ (Cathode Ray Tube), Single chip DLP (Digital Light Processing) and
+ Plasma displays. An example of a <span style="font-weight: bold;">non-refresh</span>
+ display technology is LCD (Liquid Crystal Display), although is a
+ few cases the back-light illumination may have a low enough
+ frequency flicker to benefit from the refresh mode.<br>
+ <br>
+ Instruments in which the display type selection only changes the
+ measurement mode (i.e. i1d3), will typically have some other
+ independent option to set the calibration type. Simpler instruments
+ combine the measurement mode with a calibration selections,
+ typically refresh+CRT and non-refresh+LCD. Some instruments are a
+ hybrid of both (Spyder4), where the display type can select between
+ generic refresh/non-refresh that can then use a .CCSS to set the
+ calibration type, or a combined selection of non-refresh and a
+ particular display type.<br>
+ <br>
+ See <a
+ href="http://en.wikipedia.org/wiki/Comparison_of_display_technology">Comparison_of_display_technology</a>
+ for some background on different display technologies.<br>
+ <br>
+ <hr size="2" width="100%"><br>
+ <h3><a name="refreshmeasurement"></a>Refresh Rate Measurement</h3>
+ <p>Most of the colorimeters that have a refresh display type
+ selection, also have an ability to measure the refresh rate of a
+ display. Some of the spectrometers also have a display refresh
+ rate measurement capability when in an emissive measurement mode,
+ even though they don't use this to support a refresh display mode.
+ You can do a display refresh rate measurement in <a
+ href="spotread.html">spotread</a> using the <b>'F' </b>key.
+ The particular instruments have a range of accuracy when making
+ this measurement. A rough guide is as follows:<br>
+ <br>
+ </p>
+ <table border="1" height="230" width="372" cellpadding="2"
+ cellspacing="2">
+ <tbody>
+ <tr>
+ <td valign="top"><b>Instrument</b></td>
+ <td valign="top"><b>Typical error in Hz.</b></td>
+ </tr>
+ <tr>
+ <td valign="top">spectrobos 1211/1201<br>
+ </td>
+ <td valign="top">0.05<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">DTP92<br>
+ </td>
+ <td valign="top">0.1<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">i1 Display 2<br>
+ </td>
+ <td valign="top">0.5<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">Spyder 2<br>
+ </td>
+ <td valign="top">0.7<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">Spyder 3<br>
+ </td>
+ <td valign="top">3<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">Spyder 4<br>
+ </td>
+ <td valign="top">3<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">i1 Display Pro<br>
+ </td>
+ <td valign="top">0.05<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">i1 Pro Spectro.<br>
+ </td>
+ <td valign="top">0.05<br>
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">ColorMunki Spectro.<br>
+ </td>
+ <td valign="top">0.05<br>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <p><br>
+ </p>
+ <hr size="2" width="100%">
+ <p><span style="font-weight: bold;"><a name="specbos"></a><span
+ style="font-weight: bold;">specbos 1211 and 1201
+ Tele-Spectro-Radiometer<br>
+ </span></span></p>
+ <img alt="JETI specbos 1211" src="JETI_1211.jpg" height="210"
+ width="211">
+ <p><span style="font-weight: bold;"><br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">specbos 1211</span><span
+ style="font-weight: bold;"> </span>and <b>1201</b>from <a
+ href="http://www.jeti.com/">JETI</a>&nbsp; are currently
+ available instruments. These are reference grade instruments
+ capable of emissive and ambient measurements, and are often used
+ for monitor, projector and cinema calibration and
+ characterization, amongst many other uses.<br>
+ </p>
+ <hr size="2" width="100%">
+ <p><br>
+ </p>
+ <span style="font-weight: bold;"></span><br>
+ <span style="font-weight: bold;"><a name="ColorMunki"></a><span
+ style="font-weight: bold;">ColorMunki </span>Design or Photo <span
+ style="font-weight: bold;">reflective/emissive spectrometer</span><br>
+ <br>
+ <img style="width: 272px; height: 243px;" alt="" title="ColorMunki
+ (White)" src="ColorMunki.jpg">&nbsp;&nbsp; <br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">ColorMunki</span> <span
+ style="font-weight: bold;">Design or Photo </span>from <a
+ href="http://www.xrite.com/">X-Rite</a>&nbsp; is currently
+ available in two different packages from the manufacturer. These
+ packages differ in what features the manufacturers software
+ provides, as well as cosmetic differences between the instrument
+ (white and black). This comparison <a
+ href="http://www.colormunki.com/product/show?page=2">chart</a>
+ illustrates the differences. Used with Argyll, there are no
+ differences in operation of a ColorMunki instrument, irrespective of
+ which package it came with. The ColorMunki Design has the lowest
+ RRP, but the Photo package may be cheaper with discounting .<br>
+ <br>
+ <span style="font-weight: bold;">Limitations &amp; Features:</span><br>
+ <br>
+ Unlike the Eye-One Pro, the ColorMunki is only available in a U.V.
+ Cut (ie. "Ultra Violet filtered") model. This means that it is not
+ suitable for use with the&nbsp; Fluorescent Whitener Additive
+ Compensation option in Argyll (see <a href="FWA.html">here</a> for
+ a discussion about what FWA compensation is).<br>
+ <br>
+ Like the Eye-One Pro, this instrument does support the <a
+ href="spotread.html#H">high resolution</a> spectral mode.<br>
+ <br>
+ <span style="font-weight: bold;">OS X and X-Rite drivers</span><br>
+ <br>
+ Please note the installation <a
+ href="Installing_OSX.html#ColorMunki">instructions</a>.<br>
+ <br>
+ <span style="font-weight: bold;">Tips &amp; Tricks:<br>
+ <br>
+ </span>In handling the instrument when about to make a reading, be
+ very careful not to accidentally press the switch - it is large and
+ easily pressed by accident. A guide of some sort (ie. a plastic
+ ruler) can help a lot in&nbsp; keeping the instrument over a line
+ of&nbsp; patches. <br>
+ <br>
+ <span style="font-weight: bold;">Patch recognition:</span><br>
+ <br>
+ For the best chances of good patch recognition, the instrument
+ should be drawn smoothly and not too rapidly over the strip. (This
+ can be a little tricky due to the two small rubber feet on the
+ bottom of the device that aid its spot reading guide.) If there is a
+ misread, try slowing down slightly. Generally a higher quality set
+ of readings will result if slower scans are used, since there will
+ then be more samples averaged for each patch. <br>
+ <br>
+ In <a href="chartread.html">chartread</a>, the -<span
+ style="font-weight: bold;">T ratio</span> argument modifies the
+ patch consistency tolerance threshold for the ColorMunki. In
+ recognizing patches in a strip, the instrument takes multiple
+ readings as the strip is read, and then divide the readings up into
+ each patch. It then check the consistency of the multiple readings
+ corresponding to each patch, and reject the measurement if they are
+ too inconsistent. For some media (ie. a coarser screens, fabric
+ etc.) the default tolerance may be unreasonably tight, so the <span
+ style="font-weight: bold;">-T ratio</span> argument can be used to
+ modify this criteria. To loosen the tolerance, use a number greater
+ than 1.0 (ie. 1.5, 2.0). <br>
+ <br>
+ Note that <a href="printtarg.html">printtarg</a> provides the <a
+ href="printtarg.html#h">-h</a> option that allows the choice of
+ two different patch row widths with ColorMunki test charts. [Some
+ people have successfully used the i1Pro patch layout with the
+ ColorMunki, by making a guide to keep it over the much narrower
+ patchs.]<br>
+ <br>
+ <span style="font-weight: bold;"></span><br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><span
+ style="font-weight: bold;"></span><br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
+ <hr style="width: 100%; height: 2px;"><span style="font-weight:
+ bold;"><br>
+ <a name="DTP20"></a></span><span style="font-weight: bold;">DTP20
+ "Pulse" reflective spectrometer<br>
+ <br>
+ </span><span style="font-weight: bold;"><img title="DTP20" alt=""
+ src="DTP20.jpg" style="width: 304px; height: 210px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">DTP20</span> from <a
+ href="http://www.xrite.com/">X-Rite</a> was discontinued during
+ 2007, but may still be available from old stock or second hand. <br>
+ <br>
+ <span style="font-weight: bold;">Special features:</span><br>
+ <br>
+ The <span style="font-weight: bold;">DTP20</span> has a couple of
+ unique features that Argyll can take advantage of. One is that it
+ can operate un-tethered (off line). A whole chart can be read
+ un-tethered by first clearing any previous readings in the
+ instrument, then reading the chart TID strip, before reading all the
+ other strips. The instrument can then be connected up to <span
+ style="font-weight: bold;">chartread</span>, which will recognize
+ the chart, and download all the measurements.<br>
+ If there is no chart in the instrument when chartread connects to
+ it, then it will use the strip by strip tethered mode, just like the
+ other strip instruments. If the right number of spot readings are
+ present in the instrument, these will be used by <span
+ style="font-weight: bold;">chartread</span> too.<br>
+ <br>
+ Un-tethered spot measurements can also be read in using&nbsp; <span
+ style="font-weight: bold;">spotread</span>, which will notice the
+ stored readings, and offer to print them out, or they can be
+ ignored, and tethered readings taken. This will clear any saved spot
+ readings.<br>
+ <br>
+ <span style="font-weight: bold;">Note</span> that tethered (on-line)
+ strip reading will only work if the firmware in the device is
+ version 1.03 or greater. You can check the firmware version by
+ running with the verbose option: <span style="font-weight: bold;">-v<br>
+ <br>
+ Chart printing:<br>
+ <span style="font-weight: bold;"><br>
+ </span></span>Because the DTP20 measures exact distances using the
+ markings on its ruler, it's critical that the chart be printed out
+ exactly the right size. If the chart gets re-sized at all in the
+ process of printing it, the DTP20 is likely to fail in reading it.
+ If you have a problem with this, you might want to increase the page
+ margins using the <span style="font-weight: bold;">printtarg -m</span>
+ parameter, or find a printing path that preserves the test chart
+ size correctly.<br>
+ <br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><span
+ style="font-weight: bold;">Operation:<br>
+ <br>
+ </span>When reading in tethered (on-line) mode, that the instrument
+ takes <span style="font-weight: bold;">several seconds</span> to
+ download the measurements after each strip, and that the indicator
+ will be in "rainbow" mode while this occurs. <span
+ style="text-decoration: underline;">Wait</span> until the
+ indicator turns solid green again before starting to measure the
+ next strip.<br>
+ <br>
+ To <span style="font-weight: bold;">reset</span> the instrument and
+ clear any stored readings: press the button three times in quick
+ succession. The indicator will turn solid blue. Then hold the button
+ down until the instrument beeps and the indicator goes out. Release
+ the button and the indicator should flash then return to solid green
+ (ready).<br>
+ <br>
+ To <span style="font-weight: bold;">calibrate</span> the
+ instrument, place it on its calibration tile, then press the button
+ three times in quick succession.The indicator will turn solid blue.
+ Click the button another three times in quick succession, and the
+ indicator should turn yellow. Then hold the button down until the
+ instrument beeps and the indicator goes out. Release the button and
+ the instrument should flash and then turn solid green.<br>
+ <br>
+ If the chart is particularly <span style="font-weight: bold;">small</span>,
+ the patches may end up printed very close to the edge of the chart,
+ and therefore it may be difficult to confine your scan to the chart,
+ and passing<br>
+ the instrument over the edge of the chart may prevent it reading
+ successfully. One way of working around this is to place the chart
+ on a larger piece of paper of the same type.<br>
+ <br>
+ The <span style="font-weight: bold;">speed</span> of scan can be
+ quite critical with this instrument. In particular, it doesn't work
+ very well if the scan is too <span style="font-weight: bold;">slow</span>.
+ You don't want to go too fast either, as this reduces the number of
+ samples per patch.<br>
+ <br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><span
+ style="font-weight: bold;"></span><br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
+ <hr style="width: 100%; height: 2px;"><span style="font-weight:
+ bold;"><br>
+ <a name="DTP22"></a></span><span style="font-weight: bold;">DTP22
+ Digital Swatchbook reflective spectrometer</span><br>
+ <span style="font-weight: bold;"><br>
+ <img alt="" src="DTP22.jpg" style="width: 222px; height: 193px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">DTP22</span> from <a
+ href="http://www.xrite.com/">X-Rite</a> is a discontinued
+ instrument.&nbsp; It may still be available second hand. It is
+ capable of reading colored patches one at a time.<br>
+ <br>
+ <br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
+ <hr style="width: 100%; height: 2px;"><span style="font-weight:
+ bold;"><br>
+ <a name="DTP41"></a>DTP41 reflective, DTP41T
+ reflective/transmissive spectrometers<br>
+ <br>
+ <img alt="" src="DTP41.jpg" style="width: 263px; height: 298px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">DTP41</span> and <span
+ style="font-weight: bold;">DTP41T</span> from <a
+ href="http://www.xrite.com/">X-Rite</a> is a discontinued
+ instrument.&nbsp; It may still be available second hand. <br>
+ <br>
+ The series II instruments (<span style="font-weight: bold;">DTP41B</span>
+ and <span style="font-weight: bold;">DTP41TB</span>) offer both
+ serial and USB connection. Note that currently only serial operation
+ using Argyll is possible with these instruments.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <a name="dtp51"></a><span style="font-weight: bold;">DTP51
+ reflective colorimeter<br>
+ <br>
+ <img alt="" src="DTP51.jpg" style="width: 263px; height: 223px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">DTP51</span> from <a
+ href="http://www.xrite.com/">X-Rite</a> is a discontinued
+ instrument.&nbsp; It may still be available second hand. <br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"><br>
+ </span></span>The DTP51's switch is triggered by inserting a strip
+ into the slot.<br>
+ <br>
+ <br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span>
+ <hr style="width: 100%; height: 2px;"><span style="font-weight:
+ bold;"><br>
+ <a name="DTP92"></a>DTP92 CRT display colorimeter<br>
+ <br>
+ <img alt="" src="DTP92.jpg" style="width: 223px; height: 180px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">DTP92</span><span
+ style="font-weight: bold;"></span> from <a
+ href="http://www.xrite.com/">X-Rite</a> is a discontinued
+ instrument.&nbsp; It may still be available second hand. It will
+ only read CRT technology displays.<br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -1156,32 +1351,44 @@
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
- Tube display, that is of the Refresh type [Default, CB2].<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="DTP94"></a>DTP94, </span><font
- size="-1">"Optix XR"</font> or "Optix XR2" or "Optix Pro" <span
- style="font-weight: bold;">display colorimetrers</span><br>
- <span style="font-weight: bold;"><br>
- <img title="DTP94" alt="" src="DTP94.jpg" style="width: 138px;
- height: 171px;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp; <img alt="" title="Optix XR/Pro" src="moxxr.jpg"
- style="width: 155px; height: 190px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">DTP94 </span>from <a
- href="http://www.xrite.com/">X-Rite</a> is a discontinued
- instrument, although it is still being supplied to OEMs.&nbsp; It
- may still be available as old stock, or second hand. It was sold as
- an instrument without software as the DTP94, and packaged with
- software from the manufacturer as the "Optix XR" range.<br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
+ Tube display, that is of the Refresh type [Default, CB2].<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="DTP94"></a>DTP94, </span><font
+ size="-1">"Optix XR"</font> or "Optix XR2" or "Optix Pro" <span
+ style="font-weight: bold;">display colorimetrers</span><br>
+ <span style="font-weight: bold;"><br>
+ <img title="DTP94" alt="" src="DTP94.jpg" style="width: 138px;
+ height: 171px;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; <img alt="" title="Optix XR/Pro" src="moxxr.jpg"
+ style="width: 155px; height: 190px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">DTP94 </span>from <a
+ href="http://www.xrite.com/">X-Rite</a> is a discontinued
+ instrument, although it is still being supplied to OEMs.&nbsp; It
+ may still be available as old stock, or second hand. It was sold as
+ an instrument without software as the DTP94, and packaged with
+ software from the manufacturer as the "Optix XR" range.<br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1199,8 +1406,20 @@
- LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
- Crystal Display, that is of the Non-Refresh type [default, CB1].<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
+ Crystal Display, that is of the Non-Refresh type [default, CB1].<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -1223,23 +1442,35 @@
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
- Tube display, that is of the Refresh type [CB2].<br>
- &nbsp;&nbsp;&nbsp; <b>g</b>&nbsp;&nbsp;&nbsp;
- Generic&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Generic
- display [CB3]<br>
- &nbsp;&nbsp; <br>
- <br>
- <span style="font-weight: bold;"></span>
- <hr style="width: 100%; height: 2px;"><span style="font-weight:
- bold;"><br>
- <a name="sl"></a>Spectrolino reflective/emissive spectrometer<br>
- <br>
- <img alt="" src="sl.jpg" style="width: 239px; height: 200px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
+ Tube display, that is of the Refresh type [CB2].<br>
+ &nbsp;&nbsp;&nbsp; <b>g</b>&nbsp;&nbsp;&nbsp;
+ Generic&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Generic
+ display [CB3]<br>
+ &nbsp;&nbsp; <br>
+ <br>
+ <span style="font-weight: bold;"></span>
+ <hr style="width: 100%; height: 2px;"><span style="font-weight:
+ bold;"><br>
+ <a name="sl"></a>Spectrolino reflective/emissive spectrometer<br>
+ <br>
+ <img alt="" src="sl.jpg" style="width: 239px; height: 200px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
</span>The <span style="font-weight: bold;">Spectrolino </span>from
Gretag
@@ -1263,220 +1494,237 @@ Gretag
- MacBeth (Now X-Rite) is a discontinued instrument. It is often
- available second hand. If buying it second hand, make sure it comes
- with all it's accessories, including white reference, spot reading
- adapter, display reading adapters, filters (UV, polarizing, D65),
- serial cable adapter and power supply.<br>
- <span style="font-weight: bold;"><br>
- </span>
- <hr style="width: 100%; height: 2px;"><span style="font-weight:
- bold;"><br>
- <a name="ss"></a>SpectroScan reflective/emissive and SpectroScanT
- reflective/emissive/transmissive spectrometers<br>
- <br>
- <img style="width: 336px; height: 294px;" alt="" src="ss.jpg"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">SpectroScan</span> and
- <span style="font-weight: bold;">SpectroScanT</span> from Gretag
- MacBeth (Now X-Rite) is a discontinued instrument. It is the
- combination of an X-Y table and the <span style="font-weight:
- bold;">Spectrolino</span> instrument. The <span
- style="font-weight: bold;">SpectroScanT</span> is capable of
- measuring transparency. It is often available second hand. If buying
- it second hand, make sure it comes with all it's accessories,
- including white reference, spot reading adapter, display reading
- adapters, filters (UV, polarizing, D65) and power supply.<br>
- <br>
- If measuring transparencies using a SpectroScanT, the <b>Enter</b>
- key on the instrument may be used to trigger each reading. It will
- be recognized after each previous reading has been completed.<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <br>
- <span style="font-weight: bold;"><a name="i1p2"></a>Eye-One Pro2:</span><br>
- <img style=" width: 357px; height: 234px;" alt="Eye-One Pro 2"
- src="i1pro2.jpg"><br>
- <br>
- There is support for some of the new features of the Eye-One Pro2
- (also known as the Eye-One Pro Rev E), in particular the&nbsp; Rev E
- measurement mode, spectrometer stray light reduction, wavelength
- calibration, and improved black level tracking. This new support can
- be disabled and an Eye-One Pro2 operated in legacy mode by setting
- the environment variable ARGYLL_DISABLE_I1PRO2_DRIVER. See <a
- href="file:///D:/src/argyll/doc/instruments.html#i1p">Eye-One Pro
- reflective/emissive spectrometer</a><span style="font-weight:
- bold;"> </span>below for details on the operation of this type of
- instrument.<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="i1p"></a>Eye-One Pro and
- Eye-One Pro2 reflective/emissive spectrometer<br>
- <br>
- <img alt="" src="i1p.jpg" style="width: 347px; height: 234px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">Eye-One Pro</span> from
- <a href="http://www.xrite.com/">X-Rite</a> (was Gretag MacBeth) is
- available in two packages from the manufacturer. These packages
- differ partly in what accessories come with the instrument, but
- primarily in what features the manufacturers software provides. This
- comparison <a
- href="http://www.xrite.com/product_overview.aspx?ID=812">chart</a>
- illustrates the differences. Used with Argyll, there are no
- differences in operation of an Eye-One Pro instrument, irrespective
- of which package it came with. The lowest cost package is the <a
- href="http://www.xrite.com/product_overview.aspx?ID=1461">i1 Basic
- Pro</a>.<br>
- <br>
- The EFI ES-1000 (which is a re-badged Eye-One Pro) is also reported
- to work with Argyll.<br>
- <br>
- Unless you know what you're doing, and have a very specific reason
- to buy an instrument fitted with a UV (Ultra Violet) filter, make
- sure that you buy an instrument without the filter. A UV filtered
- instrument can't deal intelligently with FWA (Fluorescent Whitener
- Additive) effects in paper. (Look <a href="FWA.html">here</a> for
- more information about FWA compensation.) Using FWA compensation you
- can make measurements using ISO 13655:2009 M0, M1 and M2 conditions.
- The M2 condition emulates a UV cut instrument.<br>
- <br>
- There have been four revisions of the Eye-One Pro, Rev. A, B, D and
- E (AKA Eye-One Pro2). The rev B, D and E are capable of sampling
- twice as fast as the Rev. A version of the instrument, and are also
- available with an ambient light reading capability.<br>
- <br>
- <span style="font-weight: bold;">NOTE</span> for those running on
- older versions of Linux with a Rev. D, there was a problem with the
- Linux USB stack that causes the instrument to stop working once it
- has been used. The only workaround is to unplug and replug the
- instrument in again, whereupon it can be used one time again. A fix
- for this problem was in the&nbsp; Linux 2.6.26 kernel release.<br>
- <br>
- See also <a href="i1proDriver.html">How can I have confidence in
- the i1pro Driver ?</a><br>
- <br>
- <span style="font-weight: bold;">Patch recognition:</span><br>
- <br>
- For the best chances of good patch recognition, the instrument
- should be drawn smoothly and not too rapidly over the strip. If
- there is a misread, try slowing down slightly. The Rev A and B.
- instruments have a slower sampling rate than the latter revision
- instruments, and hence must be used a bit more slowly. Generally a
- higher quality set of readings will result if slower scans are used,
- since there will then be more samples averaged for each patch.<br>
- <br>
- In <a href="chartread.html">chartread</a>, the -<span
- style="font-weight: bold;">T ratio</span> argument modifies the
- patch consistency tolerance threshold for the Eye-One Pro. In
- recognizing patches in a strip, the instrument takes multiple
- readings as the strip is read, and then divide the readings up into
- each patch. It then check the consistency of the multiple readings
- corresponding to each patch, and reject the measurement if they are
- too inconsistent. For some media (ie. a coarser screens, fabric
- etc.) the default tolerance may be unreasonably tight, so the <span
- style="font-weight: bold;">-T ratio</span> argument can be used to
- modify this criteria. To loosen the tolerance, use a number greater
- than 1.0 (ie. 1.5, 2.0). <span style="font-weight: bold;"></span><br>
- <br>
- <span style="font-weight: bold;">Special features:</span><br>
- <br>
- A feature unique to Argyll when used with the Eye-One Pro, is the
- high resolution spectral mode. This returns spectral measurements at
- 3.333 nm spacing, rather than the default 10nm spacing, and also
- extends the range of wavelengths very slightly. This high resolution
- may assist in giving better accuracy for "peaky" emissive sources
- such as illuminants and displays. The high resolution mode is
- selected by using the <span style="font-weight: bold;">-H</span>
- flag on the command line to <span style="font-weight: bold;">dispcal</span>,
- <span style="font-weight: bold;">dispread</span>, <span
- style="font-weight: bold;">chartread</span>, and <span
- style="font-weight: bold;">spotread</span>. It can also be toggled
- on and off within <span style="font-weight: bold;">spotread</span>
- using the <span style="font-weight: bold;">h</span> key. The
- extended range down to 350nm may give some information about an
- illuminants ultra violet content, although the accuracy of the
- readings between 350-380, and 730-740nm should not be relied upon.<br>
- <br>
- <img alt="High res. and standard res. spectrum."
- src="Fluorescent.jpg" style="width: 750px; height: 375px;"><br>
- <br>
- <img alt="C.R.T high res. and standard res. spectrum."
- src="CRTspectrum.jpg" style="width: 750px; height: 375px;"><br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="i1m"></a>Eye-One Monitor
- emissive spectrometer<br>
- <br>
- <img alt="" src="i1m.jpg" style="width: 347px; height: 234px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">Eye-One Monitor</span>
- from <a href="http://www.xrite.com/">X-Rite</a> (was Gretag
- MacBeth) is a discontinued instrument. It was a lower cost version
- of the <span style="font-weight: bold;">Eye-One Pro</span> without
- reflective measurement capability. See <a href="#i1p">Eye-One Pro
- reflective/emissive spectrometer</a><span style="font-weight:
- bold;"> </span>for details on the operation of this instrument.<br>
- <br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="i1d"></a>Eye-One Display
- 1, Eye-One Display 2, Eye-One Display LT, ColorMunki Create,
- ColorMunki Smile colorimeters,<br>
- <br>
- <img style=" width: 124px; height: 168px;" alt="ColorMunki Smile"
- src="Smile.jpg"><img alt="Eye-One Display 2" src="i1d.jpg"
- style="width: 145px; height: 168px;"> <img style="width: 133px;
- height: 168px;" alt="ColorMunki Create"
- src="ColorMunkiCreate.jpg"><br>
- <br>
- Instrument Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">ColorMunki Smile</span>
- colorimeter is a currently available instrument.<br>
- The <span style="font-weight: bold;">Eye-One Display LT</span> and
- <span style="font-weight: bold;">Eye-One Display 2</span> are
- discontinued products, although they may still be available from
- some retailers, second hand, and may still be shipped with some
- displays as part of their calibration capability.<br>
- The <span style="font-weight: bold;">ColorMunki Create</span>
- colorimeter is a discontinued product, although they may still be
- available from some retailers or second hand,can also be used. They
- will appear as an i1Display2 colorimeter.<br>
- The <span style="font-weight: bold;">HP DreamColor</span>
- colorimeter can also be used, and will appear as an i1Display2
- colorimeter [note that it is calibrated for the DreamColor display].<br>
- The <span style="font-weight: bold;">HP APS</span> (Advanced
- Profiling Solution) colorimeter is also reported to work, and will
- appear as an i1Display2.<br>
- The <span style="font-weight: bold;">CalMAN X2</span> colorimeter
- is also reported to work, and will appear as an i1Display2
- colorimeter.<br>
- The&nbsp; <span style="font-weight: bold;">Lacie Blue Eye</span> <span
- style="font-weight: bold;"></span> colorimeter is also reported to
- work, and will appear as an i1Display2 colorimeter.<br>
- <br>
- <span style="font-weight: bold;"></span>The <span
- style="font-weight: bold;">Eye-One Display 1</span> is a
- discontinued instrument. <br>
- <br>
- The Eye-One Display LT came with a less expensive<span
- style="text-decoration: underline;"></span> package with more
- limited software from the manufacture.<br>
- The Eye-One Display 2 package came with more software
- features,&nbsp; but the instruments are virtually identical, and
- will operate identically using Argyll.<br>
- The ColorMunki Create<span style="text-decoration: underline;"></span>
- package is another alternative, and will operate identically using
- Argyll.<br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ MacBeth (Now X-Rite) is a discontinued instrument. It is often
+ available second hand. If buying it second hand, make sure it comes
+ with all it's accessories, including white reference, spot reading
+ adapter, display reading adapters, filters (UV, polarizing, D65),
+ serial cable adapter and power supply.<br>
+ <span style="font-weight: bold;"><br>
+ </span>
+ <hr style="width: 100%; height: 2px;"><span style="font-weight:
+ bold;"><br>
+ <a name="ss"></a>SpectroScan reflective/emissive and SpectroScanT
+ reflective/emissive/transmissive spectrometers<br>
+ <br>
+ <img style="width: 336px; height: 294px;" alt="" src="ss.jpg"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">SpectroScan</span> and
+ <span style="font-weight: bold;">SpectroScanT</span> from Gretag
+ MacBeth (Now X-Rite) is a discontinued instrument. It is the
+ combination of an X-Y table and the <span style="font-weight:
+ bold;">Spectrolino</span> instrument. The <span
+ style="font-weight: bold;">SpectroScanT</span> is capable of
+ measuring transparency. It is often available second hand. If buying
+ it second hand, make sure it comes with all it's accessories,
+ including white reference, spot reading adapter, display reading
+ adapters, filters (UV, polarizing, D65) and power supply.<br>
+ <br>
+ If measuring transparencies using a SpectroScanT, the <b>Enter</b>
+ key on the instrument may be used to trigger each reading. It will
+ be recognized after each previous reading has been completed.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <br>
+ <span style="font-weight: bold;"><a name="i1p2"></a>Eye-One Pro2:</span><br>
+ <img style=" width: 357px; height: 234px;" alt="Eye-One Pro 2"
+ src="i1pro2.jpg"><br>
+ <br>
+ There is support for some of the new features of the Eye-One Pro2
+ (also known as the Eye-One Pro Rev E), in particular the&nbsp; Rev E
+ measurement mode, spectrometer stray light reduction, wavelength
+ calibration, and improved black level tracking. This new support can
+ be disabled and an Eye-One Pro2 operated in legacy mode by setting
+ the environment variable ARGYLL_DISABLE_I1PRO2_DRIVER. See <a
+ href="instruments.html#i1p">Eye-One Pro reflective/emissive
+ spectrometer</a><span style="font-weight: bold;"> </span>below
+ for details on the operation of this type of instrument.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="i1p"></a>Eye-One Pro and
+ Eye-One Pro2 reflective/emissive spectrometer<br>
+ <br>
+ <img alt="" src="i1p.jpg" style="width: 347px; height: 234px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">Eye-One Pro</span> from
+ <a href="http://www.xrite.com/">X-Rite</a> (was Gretag MacBeth) is
+ available in two packages from the manufacturer. These packages
+ differ partly in what accessories come with the instrument, but
+ primarily in what features the manufacturers software provides. This
+ comparison <a
+ href="http://www.xrite.com/product_overview.aspx?ID=812">chart</a>
+ illustrates the differences. Used with Argyll, there are no
+ differences in operation of an Eye-One Pro instrument, irrespective
+ of which package it came with. The lowest cost package is the <a
+ href="http://www.xrite.com/product_overview.aspx?ID=1461">i1 Basic
+ Pro</a>.<br>
+ <br>
+ The EFI ES-1000 (which is a re-badged Eye-One Pro) is also reported
+ to work with Argyll.<br>
+ <br>
+ Unless you know what you're doing, and have a very specific reason
+ to buy an instrument fitted with a UV (Ultra Violet) filter, make
+ sure that you buy an instrument without the filter. A UV filtered
+ instrument can't deal intelligently with FWA (Fluorescent Whitener
+ Additive) effects in paper. (Look <a href="FWA.html">here</a> for
+ more information about FWA compensation.) Using FWA compensation you
+ can make measurements using ISO 13655:2009 M0, M1 and M2 conditions.
+ The M2 condition emulates a UV cut instrument.<br>
+ <br>
+ There have been four revisions of the Eye-One Pro, Rev. A, B, D and
+ E (AKA Eye-One Pro2). The rev B, D and E are capable of sampling
+ twice as fast as the Rev. A version of the instrument, and are also
+ available with an ambient light reading capability.<br>
+ <br>
+ <span style="font-weight: bold;">NOTE</span> for those running on
+ older versions of Linux with a Rev. D, there was a problem with the
+ Linux USB stack that causes the instrument to stop working once it
+ has been used. The only workaround is to unplug and replug the
+ instrument in again, whereupon it can be used one time again. A fix
+ for this problem was in the&nbsp; Linux 2.6.26 kernel release.<br>
+ <br>
+ See also <a href="i1proDriver.html">How can I have confidence in
+ the i1pro Driver ?</a><br>
+ <br>
+ <span style="font-weight: bold;">Patch recognition:</span><br>
+ <br>
+ For the best chances of good patch recognition, the instrument
+ should be drawn smoothly and not too rapidly over the strip. If
+ there is a misread, try slowing down slightly. The Rev A and B.
+ instruments have a slower sampling rate than the latter revision
+ instruments, and hence must be used a bit more slowly. Generally a
+ higher quality set of readings will result if slower scans are used,
+ since there will then be more samples averaged for each patch.<br>
+ <br>
+ In <a href="chartread.html">chartread</a>, the -<span
+ style="font-weight: bold;">T ratio</span> argument modifies the
+ patch consistency tolerance threshold for the Eye-One Pro. In
+ recognizing patches in a strip, the instrument takes multiple
+ readings as the strip is read, and then divide the readings up into
+ each patch. It then check the consistency of the multiple readings
+ corresponding to each patch, and reject the measurement if they are
+ too inconsistent. For some media (ie. a coarser screens, fabric
+ etc.) the default tolerance may be unreasonably tight, so the <span
+ style="font-weight: bold;">-T ratio</span> argument can be used to
+ modify this criteria. To loosen the tolerance, use a number greater
+ than 1.0 (ie. 1.5, 2.0). <span style="font-weight: bold;"></span><br>
+ <br>
+ <span style="font-weight: bold;">Special features:</span><br>
+ <br>
+ A feature unique to Argyll when used with the Eye-One Pro, is the
+ high resolution spectral mode. This returns spectral measurements at
+ 3.333 nm spacing, rather than the default 10nm spacing, and also
+ extends the range of wavelengths very slightly. This high resolution
+ may assist in giving better accuracy for "peaky" emissive sources
+ such as illuminants and displays. The high resolution mode is
+ selected by using the <span style="font-weight: bold;">-H</span>
+ flag on the command line to <span style="font-weight: bold;">dispcal</span>,
+ <span style="font-weight: bold;">dispread</span>, <span
+ style="font-weight: bold;">chartread</span>, and <span
+ style="font-weight: bold;">spotread</span>. It can also be toggled
+ on and off within <span style="font-weight: bold;">spotread</span>
+ using the <span style="font-weight: bold;">h</span> key.<br>
+ <br>
+ Note that while finer spectral resolution will worsen the signal to
+ noise ratio of the individual spectral values, the signal to noise
+ ratio of the resulting tri-stimulus color values will be identical
+ to normal resolution mode, since the same overall integration is
+ performed. <br>
+ <br>
+ See <a href="i1proHiRes.html">Does the i1pro High Resolution mode
+ improve accuracy ?</a><br>
+ <br>
+ <img alt="High res. and standard res. spectrum."
+ src="Fluorescent.jpg" style="width: 750px; height: 375px;"><br>
+ <br>
+ <img alt="C.R.T high res. and standard res. spectrum."
+ src="CRTspectrum.jpg" style="width: 750px; height: 375px;"><br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="i1m"></a>Eye-One Monitor
+ emissive spectrometer<br>
+ <br>
+ <img alt="" src="i1m.jpg" style="width: 347px; height: 234px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">Eye-One Monitor</span>
+ from <a href="http://www.xrite.com/">X-Rite</a> (was Gretag
+ MacBeth) is a discontinued instrument. It was a lower cost version
+ of the <span style="font-weight: bold;">Eye-One Pro</span> without
+ reflective measurement capability. See <a href="#i1p">Eye-One Pro
+ reflective/emissive spectrometer</a><span style="font-weight:
+ bold;"> </span>for details on the operation of this instrument.<br>
+ <br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="i1d"></a>Eye-One Display
+ 1, Eye-One Display 2, Eye-One Display LT, ColorMunki Create,
+ ColorMunki Smile colorimeters,<br>
+ <br>
+ <img style=" width: 124px; height: 168px;" alt="ColorMunki Smile"
+ src="Smile.jpg"><img alt="Eye-One Display 2" src="i1d.jpg"
+ style="width: 145px; height: 168px;"> <img style="width: 133px;
+ height: 168px;" alt="ColorMunki Create"
+ src="ColorMunkiCreate.jpg"><br>
+ <br>
+ Instrument Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">ColorMunki Smile</span>
+ colorimeter is a currently available instrument.<br>
+ The <span style="font-weight: bold;">Eye-One Display LT</span> and
+ <span style="font-weight: bold;">Eye-One Display 2</span> are
+ discontinued products, although they may still be available from
+ some retailers, second hand, and may still be shipped with some
+ displays as part of their calibration capability.<br>
+ The <span style="font-weight: bold;">ColorMunki Create</span>
+ colorimeter is a discontinued product, although they may still be
+ available from some retailers or second hand,can also be used. They
+ will appear as an i1Display2 colorimeter.<br>
+ The <span style="font-weight: bold;">HP DreamColor</span>
+ colorimeter can also be used, and will appear as an i1Display2
+ colorimeter [note that it is calibrated for the DreamColor display].<br>
+ The <span style="font-weight: bold;">HP APS</span> (Advanced
+ Profiling Solution) colorimeter is also reported to work, and will
+ appear as an i1Display2.<br>
+ The <span style="font-weight: bold;">CalMAN X2</span> colorimeter
+ is also reported to work, and will appear as an i1Display2
+ colorimeter.<br>
+ The&nbsp; <span style="font-weight: bold;">Lacie Blue Eye</span> <span
+ style="font-weight: bold;"></span> colorimeter is also reported to
+ work, and will appear as an i1Display2 colorimeter.<br>
+ <br>
+ <span style="font-weight: bold;"></span>The <span
+ style="font-weight: bold;">Eye-One Display 1</span> is a
+ discontinued instrument. <br>
+ <br>
+ The Eye-One Display LT came with a less expensive<span
+ style="text-decoration: underline;"></span> package with more
+ limited software from the manufacture.<br>
+ The Eye-One Display 2 package came with more software
+ features,&nbsp; but the instruments are virtually identical, and
+ will operate identically using Argyll.<br>
+ The ColorMunki Create<span style="text-decoration: underline;"></span>
+ package is another alternative, and will operate identically using
+ Argyll.<br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <br>
The Display Selections for the <span style="font-weight: bold;">ColorMunki
@@ -1484,23 +1732,47 @@ Gretag
- Smile</span> are:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">f</span>
- &nbsp;&nbsp; LCD with CCFL back-light&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp; A Liquid Crystal display that uses a Cold
- Cathode Fluorescent back lighting. [Default, CB1]<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ Smile</span> are:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">f</span>
+ &nbsp;&nbsp; LCD with CCFL back-light&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp; A Liquid Crystal display that uses a Cold
+ Cathode Fluorescent back lighting. [Default, CB1]<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">e</span>&nbsp;&nbsp;&nbsp;
- LCD with LED back-light&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A Liquid Crystal display that uses
- Light Emitting Diode back lighting.<br>
- <br>
- other instruments will offer:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD with LED back-light&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A Liquid Crystal display that uses
+ Light Emitting Diode back lighting.<br>
+ <br>
+ other instruments will offer:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1523,8 +1795,20 @@ Gretag
- LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
- Crystal Display, that is of the Non-Refresh type. [Default, CB1]<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
+ Crystal Display, that is of the Non-Refresh type. [Default, CB1]<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -1547,121 +1831,141 @@ Gretag
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A
- Cathode Ray Tube display, that is of the Refresh type. [CB2]<br>
- <br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="i1d3"></a></span>&nbsp; <span
- style="font-weight: bold;">i1 DisplayPro and ColorMunki Display<span
- style="font-weight: bold;"> colorimeters (i1 Display 3)</span><br>
- <br>
- <img alt="i1 Display Pro" src="i1d3_1.jpg" style="width: 194px;
- height: 223px;"> <img style="width: 176px; height: 222px;"
- alt="ColorMunki Display" src="i1d3_2.jpg"><br>
- <br>
- Instrument Availability:<br>
- <br>
- </span>Both instruments are currently available..<br>
- <br>
- The ColorMunki Display is a less expensive <a
-href="http://xritephoto.com/ph_product_overview.aspx?id=1513&amp;catid=149">package</a>
- with more limited software from the manufacture, and takes a
- noticeably longer time to make most measurements (a minimum of 1
- second), but both instruments will take longer for very dark
- samples, and under these conditions the speed difference is less
- significant.<br>
- <br>
- The i1Display Pro <a
-href="http://xritephoto.com/ph_product_overview.aspx?id=1454&amp;catid=109">package</a>
- comes with i1Profiler, and the instrument is generally faster than
- the ColorMunki Display, but other than this and the software
- package, the instruments appear to be virtually identical. (Note
- though that the ColorMunki Display is <u>unable</u> to measure the
- refresh period, so is less repeatable in this mode than the
- i1Display Pro).<br>
- <br>
- Both instruments are capable of using CCSS (<a
- href="File_Formats.html#ccss">Colorimeter Calibration Spectral
- Sample</a>) files, and this also gives the instrument the
- capability of using a non-default standard observer. CCSS files can
- be created using the <a href="ccxxmake.html">ccxxmake</a> tool, and
- installed or translated from the .EDR files that are provided with
- the instrument CD using the <a href="oeminst.html">oeminst</a>
- utility using a spectrometer as a reference.<br>
- <br>
- There are some OEM versions of this instrument around too, and the <a
- href="http://www.spectracal.com/">SpectraCal OEM i1Display</a>, <a
- href="http://www.chromapure.com/">ChromaPure</a> and <a
- href="http://www.necdisplay.com/p/sensors/mdsvsensor3">NEC
- SpectraSensor Pro</a> instruments are also reported to work. They
- will appear as a be a the same as the i1Display Pro.<br>
- <span style="font-weight: bold;">[Note</span> that if you have an
- OEM version of this instrument, it's worth checking if they come
- with any extra .edr files, that can then be translated for use with
- ArgyllCMS using <a href="oeminst.html">oeminst</a>.]<br>
- <br>
- On MSWindows, if you have installed the Manufacturers applications,
- you may have to shut the i1Profiler tray application down before
- Argyll can open the instrument.<br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span><span
- style="font-weight: bold;"></span>&nbsp;&nbsp;&nbsp;&nbsp; A
- non-refresh type display [Default, CB1].<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r</span>
- &nbsp;&nbsp;&nbsp; A refresh type display&nbsp; - The refresh period
- is measured, and the integration time adjusted appropriately. [CB2]<br>
- <br>
- With the manufacturers .edr files &amp; reference Argyll .ccss files
- installed, the following selections are:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span><span
- style="font-weight: bold;"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A
- non-refresh type display [Default, CB1].<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r</span>
- &nbsp;&nbsp;&nbsp;&nbsp; A refresh type display&nbsp; - The refresh
- period is measured, and the integration time adjusted appropriately.
- [CB2]<br>
- &nbsp;&nbsp;&nbsp; <b>c</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CRT
- (Hitachi CM2112MET, Diamond View 1772ie)<br>
- &nbsp;&nbsp;&nbsp; <b>l</b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LCD CCFL
- IPS (CCFL AC EIZO HP with CORRECTION)<br>
- &nbsp;&nbsp;&nbsp; <b>L</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LCD CCFL
- Wide Gamut IPS (WG CCFL NEC241 271)<br>
- &nbsp;&nbsp;&nbsp; <b>b&nbsp;</b>&nbsp;&nbsp;&nbsp;&nbsp; LCD RGB
- LED IPS (RGBLED HP SOYO)<br>
- &nbsp;&nbsp;&nbsp; <b>e</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LCD White
- LED IPS (WLED AC LG Samsung)<br>
- &nbsp;&nbsp;&nbsp; <b>p</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Projector
- (Marantz HP Panasonic Projectors Hybrid EDR)<br>
- <br>
- <b>Note when measuring CRT displays:<br>
- </b><br>
- The small magnet in the ambient light cover used to signal what
- position it is in, can interfere in the operation of the CRT
- display, particularly if the ambient cover is in it's natural
- position at 180 degrees away from the measuring lens. One way of
- minimizing this is to swing the cover down so that it touches the
- display adjacent to the lens, thereby moving the magnet away from
- the display surface. A more thorough but inconvenient way of
- avoiding this problem is to unclip the ambient light cover and slide
- it down the cable.<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="Huey"></a>Huey colorimeter<br>
- <br>
- <img alt="" src="Huey.jpg" style="width: 128px; height: 202px;"><br>
- <br>
- Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">Huey </span>is widely
- available under the <a href="http://www.pantone.com/">Pantone</a>
- name as well as the manufacturer, <a href="http://www.xrite.com/">X-Rite</a>.
- There lower cost Huey is now discontinued, while the <a
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A
+ Cathode Ray Tube display, that is of the Refresh type. [CB2]<br>
+ <br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="i1d3"></a></span>&nbsp; <span
+ style="font-weight: bold;">i1 DisplayPro and ColorMunki Display<span
+ style="font-weight: bold;"> colorimeters (i1 Display 3)</span><br>
+ <br>
+ <img alt="i1 Display Pro" src="i1d3_1.jpg" style="width: 194px;
+ height: 223px;"> <img style="width: 176px; height: 222px;"
+ alt="ColorMunki Display" src="i1d3_2.jpg"><br>
+ <br>
+ Instrument Availability:<br>
+ <br>
+ </span>Both instruments are currently available..<br>
+ <br>
+ The ColorMunki Display is a less expensive <a
+href="http://xritephoto.com/ph_product_overview.aspx?id=1513&amp;catid=149">package</a>
+ with more limited software from the manufacture, and takes a
+ noticeably longer time to make most measurements (a minimum of 1
+ second), but both instruments will take longer for very dark
+ samples, and under these conditions the speed difference is less
+ significant.<br>
+ <br>
+ The i1Display Pro <a
+href="http://xritephoto.com/ph_product_overview.aspx?id=1454&amp;catid=109">package</a>
+ comes with i1Profiler, and the instrument is generally faster than
+ the ColorMunki Display, but other than this and the software
+ package, the instruments appear to be virtually identical. (Note
+ though that the ColorMunki Display is <u>unable</u> to measure the
+ refresh period, so is less repeatable in this mode than the
+ i1Display Pro).<br>
+ <br>
+ Both instruments are capable of using CCSS (<a
+ href="File_Formats.html#ccss">Colorimeter Calibration Spectral
+ Sample</a>) files, and this also gives the instrument the
+ capability of using a non-default standard observer. CCSS files can
+ be created using the <a href="ccxxmake.html">ccxxmake</a> tool, and
+ installed or translated from the .EDR files that are provided with
+ the instrument CD using the <a href="oeminst.html">oeminst</a>
+ utility using a spectrometer as a reference.<br>
+ <br>
+ There are some OEM versions of this instrument around too, and the <a
+ href="http://www.spectracal.com/">SpectraCal OEM i1Display</a>, <a
+ href="http://www.chromapure.com/">ChromaPure</a>, <a
+ href="http://www.necdisplay.com/p/sensors/mdsvsensor3">NEC
+ SpectraSensor Pro</a> and <a
+href="http://www8.hp.com/us/en/products/oas/product-detail.html?oid=5225568">HP
+
+
+
+
+
+
+ DreamColor</a> instruments are also reported to work. They will
+ appear as a be a the same as the i1Display Pro.<br>
+ <span style="font-weight: bold;">[Note</span> that if you have an
+ OEM version of this instrument, it's worth checking if they come
+ with any extra .edr files, that can then be translated for use with
+ ArgyllCMS using <a href="oeminst.html">oeminst</a>.]<br>
+ <br>
+ On MSWindows, if you have installed the Manufacturers applications,
+ you may have to shut the i1Profiler tray application down before
+ Argyll can open the instrument.<br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span><span
+ style="font-weight: bold;"></span>&nbsp;&nbsp;&nbsp;&nbsp; A
+ non-refresh type display [Default, CB1].<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r</span>
+ &nbsp;&nbsp;&nbsp; A refresh type display&nbsp; - The refresh period
+ is measured, and the integration time adjusted appropriately. [CB2]<br>
+ <br>
+ With the manufacturers .edr files &amp; reference Argyll .ccss files
+ installed, the following selections are:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span><span
+ style="font-weight: bold;"></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A
+ non-refresh type display [Default, CB1].<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r</span>
+ &nbsp;&nbsp;&nbsp;&nbsp; A refresh type display&nbsp; - The refresh
+ period is measured, and the integration time adjusted appropriately.
+ [CB2]<br>
+ &nbsp;&nbsp;&nbsp; <b>c</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CRT
+ (Hitachi CM2112MET, Diamond View 1772ie)<br>
+ &nbsp;&nbsp;&nbsp; <b>l</b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LCD CCFL
+ IPS (CCFL AC EIZO HP with CORRECTION)<br>
+ &nbsp;&nbsp;&nbsp; <b>L</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LCD CCFL
+ Wide Gamut IPS (WG CCFL NEC241 271)<br>
+ &nbsp;&nbsp;&nbsp; <b>b&nbsp;</b>&nbsp;&nbsp;&nbsp;&nbsp; LCD RGB
+ LED IPS (RGBLED HP SOYO)<br>
+ &nbsp;&nbsp;&nbsp; <b>e</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LCD White
+ LED IPS (WLED AC LG Samsung)<br>
+ &nbsp;&nbsp;&nbsp; <b>p</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Projector
+ (Marantz HP Panasonic Projectors Hybrid EDR)<br>
+ <br>
+ <b>Note when measuring CRT displays:<br>
+ </b><br>
+ The small magnet in the ambient light cover used to signal what
+ position it is in, can interfere in the operation of the CRT
+ display, particularly if the ambient cover is in it's natural
+ position at 180 degrees away from the measuring lens. One way of
+ minimizing this is to swing the cover down so that it touches the
+ display adjacent to the lens, thereby moving the magnet away from
+ the display surface. A more thorough but inconvenient way of
+ avoiding this problem is to unclip the ambient light cover and slide
+ it down the cable.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="Huey"></a>Huey colorimeter<br>
+ <br>
+ <img alt="" src="Huey.jpg" style="width: 128px; height: 202px;"><br>
+ <br>
+ Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">Huey </span>is widely
+ available under the <a href="http://www.pantone.com/">Pantone</a>
+ name as well as the manufacturer, <a href="http://www.xrite.com/">X-Rite</a>.
+ There lower cost Huey is now discontinued, while the <a
href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
@@ -1684,12 +1988,24 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- Pro</a> is still available.<br>
- <span style="font-weight: bold;"></span><br>
- <span style="font-weight: bold;">Operation:</span><br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ Pro</a> is still available.<br>
+ <span style="font-weight: bold;"></span><br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1712,8 +2028,20 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
- Crystal Display, that is of the Non-Refresh type. [Default, CB1]<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
+ Crystal Display, that is of the Non-Refresh type. [Default, CB1]<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -1736,33 +2064,45 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
- Tube display, that is of the Refresh type. [CB2]<br>
- <br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="mox"></a>MonacoOPTIX
- colorimeters<br>
- <br>
- <img alt="" src="mox.jpg" style="width: 115px; height: 147px;">
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <img alt="" src="Chroma4.jpg"
- style="width: 135px; height: 146px;"><br>
- <br>
- Instrument Availability:<br>
- </span><br>
- <span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">MonacoOPTIX</span> from
- Monaco Soft is a discontinued instrument.&nbsp; It may still be
- available as old stock, or second hand. It was sold packaged with
- software from the manufacturer. The Sequel Chroma 4 appears to be a
- similar instrument, and both seem to operate as if they were an
- Eye-One Display 1 using Argyll.<br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
+ Tube display, that is of the Refresh type. [CB2]<br>
+ <br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="mox"></a>MonacoOPTIX
+ colorimeters<br>
+ <br>
+ <img alt="" src="mox.jpg" style="width: 115px; height: 147px;">
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <img alt="" src="Chroma4.jpg"
+ style="width: 135px; height: 146px;"><br>
+ <br>
+ Instrument Availability:<br>
+ </span><br>
+ <span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">MonacoOPTIX</span> from
+ Monaco Soft is a discontinued instrument.&nbsp; It may still be
+ available as old stock, or second hand. It was sold packaged with
+ software from the manufacturer. The Sequel Chroma 4 appears to be a
+ similar instrument, and both seem to operate as if they were an
+ Eye-One Display 1 using Argyll.<br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -1785,8 +2125,20 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
- Tube display, that is of the Refresh type.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
+ Tube display, that is of the Refresh type.<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1809,41 +2161,53 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
- Crystal Display, that is of the Non-Refresh type.<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="spyd2"></a>Spyder 2
- colorimeter<br>
- <br>
- <img alt="" src="Spyd2.jpg" style="width: 218px; height: 232px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">Spyder 2 </span><span
- style="font-weight: bold;"></span>has been superseded by the
- Spyder 3 &amp; 4, but may be available second hand.<br>
- [The Spyder 1 has also been reported as working, but this has not
- been confirmed.]<br>
- <span style="font-weight: bold;"><br>
- </span><span style="font-weight: bold;">Operation:<br>
- </span><br>
- <span style="font-weight: bold;">Important Note </span>about the
- ColorVision Spyder 2 instrument support:<br>
- <br>
- This instrument cannot function without the driver software having
- access to the vendor supplied PLD firmware pattern for it.<br>
- This firmware is not provided with Argyll, since it is not available
- under a compatible license.<br>
- <br>
- The purchaser of a Spyder 2 instrument should have received a copy
- of this firmware along with their instrument, and should therefore
- be able to enable the Argyll driver for this instrument by using the
- <a href="oeminst.html">oeminst</a> tool.<span style="font-weight:
- bold;"></span><br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
+ Crystal Display, that is of the Non-Refresh type.<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="spyd2"></a>Spyder 2
+ colorimeter<br>
+ <br>
+ <img alt="" src="Spyd2.jpg" style="width: 218px; height: 232px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">Spyder 2 </span><span
+ style="font-weight: bold;"></span>has been superseded by the
+ Spyder 3 &amp; 4, but may be available second hand.<br>
+ [The Spyder 1 has also been reported as working, but this has not
+ been confirmed.]<br>
+ <span style="font-weight: bold;"><br>
+ </span><span style="font-weight: bold;">Operation:<br>
+ </span><br>
+ <span style="font-weight: bold;">Important Note </span>about the
+ ColorVision Spyder 2 instrument support:<br>
+ <br>
+ This instrument cannot function without the driver software having
+ access to the vendor supplied PLD firmware pattern for it.<br>
+ This firmware is not provided with Argyll, since it is not available
+ under a compatible license.<br>
+ <br>
+ The purchaser of a Spyder 2 instrument should have received a copy
+ of this firmware along with their instrument, and should therefore
+ be able to enable the Argyll driver for this instrument by using the
+ <a href="oeminst.html">oeminst</a> tool.<span style="font-weight:
+ bold;"></span><br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -1866,8 +2230,20 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; A Liquid Crystal
- Display, that is of the Non-Refresh type. [Default, CB1]<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; A Liquid Crystal
+ Display, that is of the Non-Refresh type. [Default, CB1]<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -1890,131 +2266,143 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
- Tube display, that is of the Refresh type. [CB2]<br>
- <br>
- <br>
- <span style="font-weight: bold;">Linux USB hub problems:<br>
- <br>
- </span>Note that the Spyder doesn't appear to operate at all well on
- Linux if attached to a secondary USB hub. You may have such a
- secondary hub built into your motherboard. If Argyll has difficulty
- in reliably talking to the Spyder, try connecting it directly to the
- computer rather than via a usb hub, or try using a USB port on your
- computer that connects directly to a root hub. This is probably due
- to a bug in the Linux EHCI driver, and a fix is due to appear in the
- Linux kernel sometime after July 2011. The name of the fix is "EHCI:
- fix direction handling for interrupt data toggles".<br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="spyd3"></a>Spyder 3
- colorimeter<br>
- <br>
- <img style="width: 262px; height: 220px;" alt="Spyder3"
- src="Spyd3.jpg"> <img style="width: 193px; height: 220px;"
- alt="Spyder3Express" src="Spyd3x.jpg"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">Spyder3Elite</span>, <span
- style="font-weight: bold;">Spyder3Pro</span> and <span
- style="font-weight: bold;">Spyder3Express</span> are being
- superseded by the Spyder4, but may still stocked by some dealers,
- and may be available second hand. The <span style="font-weight:
- bold;">Spyder3Elite</span> and <span style="font-weight: bold;">Spyder3Pro</span>
- appear to be identical hardware with different software from the
- manufacturer. The <span style="font-weight: bold;">Spyder3Express</span>
- lacks the ambient sensor.<br>
- <br>
- [Note that this instrument doesn't seem particularly suited to
- measuring CRT displays, since it no longer seems to synchronise its
- readings to a CRT refresh, and you can no longer remove the LCD
- filter, reducing its sensitivity compared to the Spyder 2 in CRT
- mode. The Spyder 2 or one of the other instruments may be a better
- choice if you particularly need to measure CRTs or Refresh
- displays.]<br>
- <span style="font-weight: bold;"><br>
- </span><span style="font-weight: bold;">Operation:<br>
- </span><br>
- The ambient light sensor can be used with the <span
- style="font-weight: bold;">Spyder3Elite</span> and <span
- style="font-weight: bold;">Spyder3Pro</span> instruments, but is
- only capable of monochrome readings.<span style="font-weight: bold;"><br>
- </span><br>
- The Display Selections for this instrument are:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span> | <span
- style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp; A
- non-refresh type display [Default, CB1]<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r | c</span>
- &nbsp;&nbsp;&nbsp; A refresh type display. [CB2]<br>
- <br>
- <br>
- <hr style="width: 100%; height: 2px;"><br>
- <span style="font-weight: bold;"><a name="spyd4"></a>Spyder 4
- colorimeter<br>
- <br>
- <img style=" width: 262px; height: 220px;" alt="Spyder4"
- src="Spyd4.jpg"> <br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;">Spyder4Elite</span>, <span
- style="font-weight: bold;">Spyder4Pro</span> and <span
- style="font-weight: bold;">Spyder4Express</span> are a currently
- available instruments. The <span style="font-weight: bold;">Spyder4Elite</span>
- and <span style="font-weight: bold;">Spyder4Pro</span> appear to be
- identical hardware with different software from the manufacturer.
- The <span style="font-weight: bold;">Spyder4Express</span> lacks
- the ambient sensor.<br>
- <span style="font-weight: bold;"><br>
- </span><span style="font-weight: bold;">Operation:<br>
- </span><br>
- These instruments are capable of using using CCSS (<a
- href="File_Formats.html#ccss">Colorimeter Calibration Spectral
- Sample</a>) files, and this also gives the instrument the
- capability of using a non-default standard observer. CCSS files can
- be created using the <a href="ccxxmake.html">ccxxmake</a> tool
- using a spectrometer as a reference.<br>
- <br>
- <span style="font-weight: bold;">Important Note </span>about the
- DataColor Spyder 4 vendor display type/calibration support:<br>
- <br>
- This instrument does not have a full range of display type
- calibration selections available without the vendor supplied
- calibration data for it.<br>
- This calibration data is not provided with Argyll, since it is not
- available under a compatible license.<br>
- You can use CCSS files as an alternative (see above), or as the
- purchaser of a Spyder 4 instrument you should have received a copy
- of the calibration data along with their instrument, and should
- therefore be able to enable the full range of display type
- selections in Argyll by using the <a href="oeminst.html">oeminst</a>
- tool.<br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span> | <span
- style="font-weight: bold;">l</span>&nbsp;&nbsp; &nbsp;
- &nbsp;&nbsp; A non-refresh type display with a generic calibration
- [Default, CB1].<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r | c</span> <span
- style="font-weight: bold;"></span> &nbsp; &nbsp; &nbsp;&nbsp; A
- refresh type display with a generic calibration.[CB2]<br>
- <br>
- The Display Selections for this instrument when the manufacturers
- calibration information has been installed is:<br>
- <br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n&nbsp;&nbsp; </span><span
- style="font-weight: bold;"></span>&nbsp;&nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp; A non-refresh type display with a generic
- calibration [Default, CB1].<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r</span> <span
- style="font-weight: bold;"></span> &nbsp; &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp; A refresh type display with a generic
- calibration.[CB2]<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">f &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp;&nbsp; LCD, CCFL
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
+ Tube display, that is of the Refresh type. [CB2]<br>
+ <br>
+ <br>
+ <span style="font-weight: bold;">Linux USB hub problems:<br>
+ <br>
+ </span>Note that the Spyder doesn't appear to operate at all well on
+ Linux if attached to a secondary USB hub. You may have such a
+ secondary hub built into your motherboard. If Argyll has difficulty
+ in reliably talking to the Spyder, try connecting it directly to the
+ computer rather than via a usb hub, or try using a USB port on your
+ computer that connects directly to a root hub. This is probably due
+ to a bug in the Linux EHCI driver, and a fix is due to appear in the
+ Linux kernel sometime after July 2011. The name of the fix is "EHCI:
+ fix direction handling for interrupt data toggles".<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="spyd3"></a>Spyder 3
+ colorimeter<br>
+ <br>
+ <img style="width: 262px; height: 220px;" alt="Spyder3"
+ src="Spyd3.jpg"> <img style="width: 193px; height: 220px;"
+ alt="Spyder3Express" src="Spyd3x.jpg"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">Spyder3Elite</span>, <span
+ style="font-weight: bold;">Spyder3Pro</span> and <span
+ style="font-weight: bold;">Spyder3Express</span> are being
+ superseded by the Spyder4, but may still stocked by some dealers,
+ and may be available second hand. The <span style="font-weight:
+ bold;">Spyder3Elite</span> and <span style="font-weight: bold;">Spyder3Pro</span>
+ appear to be identical hardware with different software from the
+ manufacturer. The <span style="font-weight: bold;">Spyder3Express</span>
+ lacks the ambient sensor.<br>
+ <br>
+ [Note that this instrument doesn't seem particularly suited to
+ measuring CRT displays, since it no longer seems to synchronise its
+ readings to a CRT refresh, and you can no longer remove the LCD
+ filter, reducing its sensitivity compared to the Spyder 2 in CRT
+ mode. The Spyder 2 or one of the other instruments may be a better
+ choice if you particularly need to measure CRTs or Refresh
+ displays.]<br>
+ <span style="font-weight: bold;"><br>
+ </span><span style="font-weight: bold;">Operation:<br>
+ </span><br>
+ The ambient light sensor can be used with the <span
+ style="font-weight: bold;">Spyder3Elite</span> and <span
+ style="font-weight: bold;">Spyder3Pro</span> instruments, but is
+ only capable of monochrome readings.<span style="font-weight: bold;"><br>
+ </span><br>
+ The Display Selections for this instrument are:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span> | <span
+ style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp; A
+ non-refresh type display [Default, CB1]<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r | c</span>
+ &nbsp;&nbsp;&nbsp; A refresh type display. [CB2]<br>
+ <br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><br>
+ <span style="font-weight: bold;"><a name="spyd4"></a>Spyder 4
+ colorimeter<br>
+ <br>
+ <img style=" width: 262px; height: 220px;" alt="Spyder4"
+ src="Spyd4.jpg"> <br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;">Spyder4Elite</span>, <span
+ style="font-weight: bold;">Spyder4Pro</span> and <span
+ style="font-weight: bold;">Spyder4Express</span> are a currently
+ available instruments. The <span style="font-weight: bold;">Spyder4Elite</span>
+ and <span style="font-weight: bold;">Spyder4Pro</span> appear to be
+ identical hardware with different software from the manufacturer.
+ The <span style="font-weight: bold;">Spyder4Express</span> lacks
+ the ambient sensor.<br>
+ <span style="font-weight: bold;"><br>
+ </span><span style="font-weight: bold;">Operation:<br>
+ </span><br>
+ These instruments are capable of using using CCSS (<a
+ href="File_Formats.html#ccss">Colorimeter Calibration Spectral
+ Sample</a>) files, and this also gives the instrument the
+ capability of using a non-default standard observer. CCSS files can
+ be created using the <a href="ccxxmake.html">ccxxmake</a> tool
+ using a spectrometer as a reference.<br>
+ <br>
+ <span style="font-weight: bold;">Important Note </span>about the
+ DataColor Spyder 4 vendor display type/calibration support:<br>
+ <br>
+ This instrument does not have a full range of display type
+ calibration selections available without the vendor supplied
+ calibration data for it.<br>
+ This calibration data is not provided with Argyll, since it is not
+ available under a compatible license.<br>
+ You can use CCSS files as an alternative (see above), or as the
+ purchaser of a Spyder 4 instrument you should have received a copy
+ of the calibration data along with the instrument, and should
+ therefore be able to enable the full range of display type
+ selections in Argyll by using the <a href="oeminst.html">oeminst</a>
+ tool.<br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n</span> | <span
+ style="font-weight: bold;">l</span>&nbsp;&nbsp; &nbsp;
+ &nbsp;&nbsp; A non-refresh type display with a generic calibration
+ [Default, CB1].<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r | c</span> <span
+ style="font-weight: bold;"></span> &nbsp; &nbsp; &nbsp;&nbsp; A
+ refresh type display with a generic calibration.[CB2]<br>
+ <br>
+ The Display Selections for this instrument when the manufacturers
+ calibration information has been installed is:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">n&nbsp;&nbsp; </span><span
+ style="font-weight: bold;"></span>&nbsp;&nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp; A non-refresh type display with a generic
+ calibration [Default, CB1].<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">r</span> <span
+ style="font-weight: bold;"></span> &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp; A refresh type display with a generic
+ calibration.[CB2]<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">f &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; </span>&nbsp;&nbsp;&nbsp;&nbsp; LCD, CCFL
Backlight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2037,17 +2425,29 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- - normal gamut Liquid Crystal Display with standard Cold Cathode
- Fluorescent Lamp backlight.<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">L</span>&nbsp;
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; Wide Gamut LCD, CCFL
- Backlight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - wide gamut Liquid Crystal
- Display with Cold Cathode Fluorescent Lamps backlight.<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">e</span>
- &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; LCD, White
- LED Backlight&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - normal
- gamut Liquid Crystal Display with a White LED backlight.<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ - normal gamut Liquid Crystal Display with standard Cold Cathode
+ Fluorescent Lamp backlight.<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">L</span>&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; Wide Gamut LCD, CCFL
+ Backlight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - wide gamut Liquid Crystal
+ Display with Cold Cathode Fluorescent Lamps backlight.<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">e</span>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; LCD, White
+ LED Backlight&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - normal
+ gamut Liquid Crystal Display with a White LED backlight.<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">B</span>&nbsp;&nbsp;
@@ -2070,12 +2470,24 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; Wide Gamut LCD, RGB LED
- Backlight - wide gamut Liquid Crystal Display with RGB LED
- backlight.<br>
- &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">x</span>
- &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; LCD, CCFL
- Type 2
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; Wide Gamut LCD, RGB LED
+ Backlight - wide gamut Liquid Crystal Display with RGB LED
+ backlight.<br>
+ &nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">x</span>
+ &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; LCD, CCFL
+ Type 2
Backlight&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2098,23 +2510,6 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- - normal gamut Liquid Crystal Display with alternative Cold Cathode
- Fluorescent Lamp backlight (Laptop ?)<br>
- <br>
- The ambient light sensor can be used with the <span
- style="font-weight: bold;">Spyder4Elite</span> and <span
- style="font-weight: bold;">Spyder4Pro</span> instruments, but is
- only capable of monochrome readings.<span style="font-weight: bold;"></span><br>
- <span style="font-weight: bold;"></span><br>
- <hr style="width: 100%; height: 2px;"><a name="HCFR"></a><span
- style="font-weight: bold;" class="titre">Colorim&egrave;tre HCFR
- colorimeter<br>
- <br>
- <img alt="" src="HCFR.jpg" style="width: 203px; height: 194px;"><br>
- <br>
- </span><span style="font-weight: bold;">Availability:<br>
- <br>
- </span>The <span style="font-weight: bold;" class="titre">Colorim&egrave;tre
@@ -2126,6 +2521,34 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
+
+ - normal gamut Liquid Crystal Display with alternative Cold Cathode
+ Fluorescent Lamp backlight (Laptop ?)<br>
+ <br>
+ The ambient light sensor can be used with the <span
+ style="font-weight: bold;">Spyder4Elite</span> and <span
+ style="font-weight: bold;">Spyder4Pro</span> instruments, but is
+ only capable of monochrome readings.<span style="font-weight: bold;"></span><br>
+ <span style="font-weight: bold;"></span><br>
+ <hr style="width: 100%; height: 2px;"><a name="HCFR"></a><span
+ style="font-weight: bold;" class="titre">Colorimètre HCFR
+ colorimeter<br>
+ <br>
+ <img alt="" src="HCFR.jpg" style="width: 203px; height: 194px;"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;" class="titre">Colorimètre
+
+
+
+
+
+
+
+
+
+
@@ -2136,26 +2559,39 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- HCFR Probe</span> is a kit instrument from <span
- style="font-weight: bold;"></span> <a
- href="http://www.homecinema-fr.com/colorimetre/index_en.php">HCFR</a>.
- <br>
- <br>
- <span style="font-weight: bold;">OS X</span><br>
- <br>
- Please note the installation <a href="Installing_OSX.html#HCFR">instructions</a>.<br>
- <br>
- <span style="font-weight: bold;">Operation:</span><br>
- <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><br>
- The accuracy of this instrument does not seem to be comparable to
- the commercial instruments when used for measuring displays,
- particularly in the area of measuring dark colors, and I've seen the
- best results when used with a CRT display. It may well give good
- results in calibrating projectors, since this was what it was
- designed to do.<br>
- <br>
- The Display Selections for this instrument are:<br>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HCFR Probe</span> is a kit instrument from <span
+ style="font-weight: bold;"></span> <a
+ href="http://www.homecinema-fr.com/colorimetre/index_en.php">HCFR</a>.
+ <br>
+ <br>
+ <span style="font-weight: bold;">OS X</span><br>
+ <br>
+ Please note the installation <a href="Installing_OSX.html#HCFR">instructions</a>.<br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><br>
+ The accuracy of this instrument does not seem to be comparable to
+ the commercial instruments when used for measuring displays,
+ particularly in the area of measuring dark colors, and I've seen the
+ best results when used with a CRT display. It may well give good
+ results in calibrating projectors, since this was what it was
+ designed to do.<br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">l</span>&nbsp;&nbsp;&nbsp;&nbsp;
@@ -2178,8 +2614,20 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
- Crystal Display [Default].<br>
+
+
+
+
+
+
+
+
+
+
+
+
+ LCD display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Liquid
+ Crystal Display [Default].<br>
&nbsp;&nbsp;&nbsp; <span style="font-weight: bold;">c</span>&nbsp;&nbsp;&nbsp;
@@ -2202,13 +2650,86 @@ href="http://www.pantone.com/pages/products/product.aspx?pid=562&amp;ca=2">Huey
- CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
- Tube display.<br>
- &nbsp;&nbsp;&nbsp; <b>R</b> &nbsp; Raw&nbsp;
- Reading&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Raw sensor readings,
- used for calibration [CB1]<br>
- <br>
- <br>
- <br>
- </body>
-</html>
+
+
+
+
+
+
+
+
+
+
+
+
+ CRT display&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; A Cathode Ray
+ Tube display.<br>
+ &nbsp;&nbsp;&nbsp; <b>R</b> &nbsp; Raw&nbsp;
+ Reading&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Raw sensor readings,
+ used for calibration [CB1]<br>
+ <br>
+ <hr style="width: 100%; height: 2px;"><a name="ColorHug"></a><span
+ style="font-weight: bold;" class="titre">ColorHug<br>
+ <br>
+ <img alt="" src="ColorHug.jpg" style="width: 203px; height:
+ 194px;" height="623" width="552"><br>
+ <br>
+ </span><span style="font-weight: bold;">Availability:<br>
+ <br>
+ </span>The <span style="font-weight: bold;" class="titre">ColorHug</span>
+ is a low cost display colorimeter instrument from <span
+ style="font-weight: bold;"></span> <a
+ href="http://www.hughski.com/">Hughski</a>. <br>
+ <br>
+ <span style="font-weight: bold;">Operation:</span><br>
+ <span style="font-weight: bold;"><span style="font-weight: bold;"></span></span><br>
+ Due to the nature of its sensor, the ColorHug accuracy is quite
+ dependent on the instrument calibration matrix. A custom .CCMX will
+ greatly assist it's accuracy, although a workaround is to calibrate
+ your display using its native white point, rather than aiming for
+ some absolute white point such as D65.<br>
+ <br>
+ The Display Selections for this instrument are:<br>
+ <br>
+ &nbsp;&nbsp; <b>l</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ LCD, CCFL Backlight [Default]<br>
+ &nbsp;&nbsp; <b>c</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ CRT display<br>
+ &nbsp;&nbsp; <b>p</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Projector<br>
+ &nbsp;&nbsp; <b>e</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+ LCD, White LED Backlight<br>
+ &nbsp;&nbsp; <b>F</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Factory matrix (For Calibration) [CB1]<br>
+ &nbsp;&nbsp;<b> R</b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Raw Reading (For Factory matrix Calibration) [CB2]<br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ </body>
+</html>
diff --git a/doc/oeminst.html b/doc/oeminst.html
index 7334d8d..ffbc0f0 100644
--- a/doc/oeminst.html
+++ b/doc/oeminst.html
@@ -296,7 +296,7 @@ href="http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html">XDG
<br>
If you are going to use the same CCSS or CCMX file all the time,
then you may want to set the <a
- href="file:///D:/src/argyll/doc/Environment.html">ARGYLL_COLMTER_CAL_SPEC_SET</a>
+ href="Environment.html">ARGYLL_COLMTER_CAL_SPEC_SET</a>
environment variable.<br>
<br>
<br>
diff --git a/doc/printtarg.html b/doc/printtarg.html
index 5faab76..0d86cac 100644
--- a/doc/printtarg.html
+++ b/doc/printtarg.html
@@ -20,6 +20,7 @@
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Verbose mode</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#i">-i 20 | 22 | 41 | 51 |
@@ -34,10 +35,12 @@ DTP20,
=
+
DTP22, 41 = DTP41, 51 = DTP51, SS = SpectroScan,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
i1 = i1Pro, CM = ColorMunki</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -50,6 +53,7 @@ spacer
size
+
by factor (e.g. 0.857 or 1.5 etc.)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#A">-A scale</a><span
@@ -61,6 +65,7 @@ by
additional
+
factor (e.g. 0.857 or 1.5 etc.)</span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
@@ -75,6 +80,7 @@ additional
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Don't randomize patch location</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -87,6 +93,7 @@ image
recognition
+
(.cht) file</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#S">-S</a><span
@@ -98,6 +105,7 @@ but
don't
+
generate wide orientation strip.</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -105,6 +113,7 @@ don't
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Force colored spacers</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#b">-b</a><span
@@ -116,12 +125,14 @@ don't
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Force no spacers</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#f">-f</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Create PostScript DeviceN Color fallback</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -135,6 +146,7 @@ don't
Black colorspace encoding DeviceGray (def), DeviceCMYK,
Separation or DeviceN<br>
&nbsp;<a href="#o">-o k|n</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
CMY colorspace encoding DefiveCMYK (def), inverted DeviceRGB or
DeviceN<br style="font-family: monospace;">
</span> <span style="font-family: monospace;">&nbsp;</span><a
@@ -142,6 +154,7 @@ don't
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Output EPS compatible file<br>
&nbsp;<a href="#t">-t [res]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Output
@@ -151,6 +164,7 @@ TIFF
raster
+
file, optional res DPI (default 200)<br>
&nbsp;<a href="#T">-T [res]</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Output
@@ -160,11 +174,13 @@ TIFF
raster
+
file, optional res DPI (default 200)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;<a
href="#C">-C</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Don't use TIFF compression</span></small><br>
<small><span style="font-family: monospace;">&nbsp;<a href="#N">-N</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Use
@@ -174,10 +190,12 @@ N
channels
+
more than 4<br>
&nbsp;<a href="#D">-D</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Dither 8 bit TIFF values down from 16 bit<br>
&nbsp;<a href="#Q">-Q nbits</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Quantize
@@ -187,6 +205,7 @@ to
fit
+
in nbits<br>
</span></small><small style="font-family: monospace;">&nbsp;<span
style="text-decoration: underline;">-</span><a href="#K">K
@@ -201,6 +220,7 @@ fit
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Use given random start number</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
@@ -219,12 +239,14 @@ fit
Set
+
a page margin in mm (default 6.0 mm)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#M">-M margin</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
</span></small><small><span style="font-family: monospace;">Set a
page margin in mm and include it in TIFF</span><span
style="font-family: monospace;"></span></small><br>
@@ -232,6 +254,7 @@ Set
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Don't limit strip length</span></small><br>
<small><span style="font-family: monospace;">&nbsp;<a href="#L">-L</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Suppress
@@ -241,12 +264,19 @@ paper
clip
- border<br style="font-family: monospace;">
+
+ border</span></small><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;<a href="#U">-U</a>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Suppress CUPS cupsJobTicket: cups-disable-cmm in PS &amp;
+ EPS files</span></small><br style="font-family: monospace;">
</span><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#p">-p size</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Select page size from:</span><br style="font-family: monospace;">
<span style="font-family: monospace;"></span></small><small><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
@@ -254,17 +284,20 @@ clip
A4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
[210.0 x 297.0 mm]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
A4R&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
[297.0 x 210.0 mm]<br>
&nbsp; &nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
[297.0 x 420.0 mm] (default)<br>
&nbsp;&nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -279,18 +312,21 @@ A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
&nbsp; &nbsp;&nbsp;&nbsp; Legal&nbsp;&nbsp;&nbsp; [215.9 x 355.6
mm]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
&nbsp;&nbsp; 4x6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [101.6 x 152.4
mm]<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
11x17&nbsp;&nbsp;&nbsp;
+
[279.4 x 431.8 mm]<br style="font-family: monospace;">
</span><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#pp">-p WWWxHHH</a><span
@@ -304,6 +340,7 @@ A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Base name for input(</span><a style="font-family: monospace;"
href="File_Formats.html#.ti1">.ti1</a><span style="font-family:
monospace;">), output(</span><a style="font-family: monospace;"
@@ -333,6 +370,7 @@ A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-A:
+
</span>Normally, <b>printtarg</b> prints test patches that are the
minimum size that can be reliably and accurately read by the
instrument.&nbsp; For some media, it might be desirable to use test
@@ -385,6 +423,7 @@ A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
turn this off you probably want to <a href="chartread.html#B">disable
+
bi-directional</a> strip reading in instruments such as the i1pro.<br>
<br>
<a name="s"></a> The <b>-s</b> flag does two things. One is that it
@@ -408,6 +447,7 @@ A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
then contrasting neutral colored spacers will be used, but these
generally work less reliably than colored spacers. <a name="n"></a>The
+
<b>-n</b> flag will cause spacers to be omitted, which may still
work with smaller numbers of test values when the patch selection is
randomized, but won't work successfully when a large number of test
@@ -573,9 +613,11 @@ A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
represented in the Postscript or TIFF output. The default is to use
the DeviceGray representation (<span style="font-weight: bold;">-wg</span>),
+
but Device RGB can also be used, where the R, G &amp;B values are
all set to the same value (<span style="font-weight: bold;">-wr</span>),
+
a <span style="font-weight: bold;">White</span> separation color
can be specified (<span style="font-weight: bold;">-ws</span>), or a
DeviceN <span style="font-weight: bold;">White</span> color can be
@@ -592,6 +634,7 @@ can
also
+
be used, where the CMY values are zero, and just the K channel is
used (<span style="font-weight: bold;">-kc</span>), a <span
style="font-weight: bold;">Black</span> separation color can be
@@ -604,6 +647,7 @@ also
output. The default is to use the DeviceCMYK representation (<span
style="font-weight: bold;">-ok</span>) where the K value is always
zero, or inverted Device RGB (<span style="font-weight: bold;">-or</span>),
+
or as a 3 channel DeviceN colorsoace can be used (<span
style="font-weight: bold;">-on</span>).<br>
<br>
@@ -641,10 +685,19 @@ also
hold the chart in place, while it is being read. (Currently this is
only the Eye-One Pro).<br>
<br>
+ <a name="U"></a> The <b>-U</b> flag suppresses the CUPS
+ %cupsJobTicket: cups-disable-cmm in PS and EPS files. By default
+ this ensures that the resulting files doesn't have color management
+ applied to it. If you are creating a test chart that should be color
+ managed (perhaps because you want to use it to verify the overall
+ operation of the printing system), then you can use the <b>-U</b>
+ flag to disable this.<br>
+ <br>
<a name="p"></a> The <b>-p</b> parameter specifies the paper size.
The size can either be one of the default sizes, <a name="pp"></a>or
+
can be specified in millimeters. Limitations of the instrument may
limit the maximum number of patches in a strip. For SpectroScan, a
size of &nbsp;A4 or Letter (or smaller) should be used. Useful
diff --git a/doc/profcheck.html b/doc/profcheck.html
index ebb719b..ef0bc5b 100644
--- a/doc/profcheck.html
+++ b/doc/profcheck.html
@@ -197,7 +197,7 @@ Sort
illumination spectrum to be used as the similated instrument
illuminant, overriding the default <b>D50</b> or CIE computation
illuminant used for FWA (see <b>-i</b> below<b>). </b>See <a
- href="file:///D:/src/argyll/doc/colprof.html#f">colprof -f</a> for
+ href="colprof.html#f">colprof -f</a> for
a fuller explanation. The same value should be used as was used
during the creation of the
profile.<br>
@@ -209,7 +209,7 @@ Sort
<b>F8</b>, <b>F10</b> are a selection of standard illuminant
spectrums, with <b>D50</b> being the default. If a filename is
specified instead, it will be assumed to be an Argyll specific <a
- href="file:///D:/src/argyll/doc/File_Formats.html#.sp">.sp</a>
+ href="File_Formats.html#.sp">.sp</a>
spectrum file. If FWA compensation is used during measurement, this
illuminant will be used by default as the simulated instrument
illuminant. The same value should be used as was used during the
diff --git a/doc/refine.html b/doc/refine.html
index cfe18b9..36a0ae4 100644
--- a/doc/refine.html
+++ b/doc/refine.html
@@ -15,15 +15,16 @@
format, but only XYZ, Lab or spectral values will be used (ie. all
device space values are ignored). Typically the charts would be
printed on a target system (the one being emulated, say a printing
- press), and the proofing system (the one that is being profiled).
- The abstract profile that <span style="font-weight: bold;">refine</span>
+ press, or created using an ideal target profile such as Rec709), and
+ the proofing system (the device that is being profiled). The
+ abstract profile that <span style="font-weight: bold;">refine</span>
produces will be a correction that makes the proofing system behave
more like the target. This can then be used to recreate the proofing
systems ICC profile, or device link. By feeding a previous abstract
correction profile in as well, iterative improvement can be made to
the proofing reproduction.<br>
<br>
- <a href="verify.html">verify</a> is a useful tool to use on the two
+ <a href="colverify.html">colverify</a> is a useful tool to use on the two
test charts, to check how well the refinement is proceeding. If a
white point relative match is being created (refine -R), then use
veryify -N.<br>
@@ -32,14 +33,17 @@
[inabs] outabs<br>
&nbsp;-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
Verbose<br>
&nbsp;-c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Create
+
initial abstract correction profile<br>
&nbsp;-g&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Don't
+
impose output device gamut limit<br>
&nbsp;-r res&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set
abstract profile clut resolution (default 33)<br>
@@ -48,6 +52,7 @@ Don't
&nbsp;-R&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Aim
+
for white point relative match rather than absolute<br>
&nbsp;</small></tt><tt><small><small></small><small><small>-f
[illum]&nbsp;&nbsp;&nbsp; Use Fluorescent Whitening Agent
@@ -55,6 +60,7 @@ Aim
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
M0, M1, M2, A, C, D50 (def.), D50M2, D65, F5, F8, F10 or
file.sp]<br>
&nbsp;-i illum&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Choose
@@ -63,26 +69,33 @@ Aim
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp</small></small><br>
&nbsp;-o observ&nbsp;&nbsp;&nbsp;&nbsp; Choose CIE Observer for
spectral data:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
1931_2,
+
1964_10, S&amp;B 1955_2, J&amp;V 1978_2 (def.)<br>
&nbsp;<span style="font-style: italic;">cietarget&nbsp;</span>&nbsp;&nbsp;&nbsp;
+
Target CIE or spectral values, CGATS file (e.g. .ti3)<br>
&nbsp;<span style="font-style: italic;">ciecurrent</span>&nbsp;&nbsp;&nbsp;
+
Actual CIE or spectral values, CGATS file (e.g. .ti3)<br>
&nbsp;[<span style="font-style: italic;">outdevicc</span>]&nbsp;&nbsp;
+
Output device ICC profile to set gamut limit (not used if -g)<br>
&nbsp;[<span style="font-style: italic;">inabs</span>]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Previous
+
abstract correction ICC profile (not used if -c)<br>
&nbsp;<span style="font-style: italic;">outabs</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Created/refined
+
abstract correction ICC profile</small></tt><br>
<h3>Usage Details</h3>
<b>refine</b> provides a way of improving the profile accuracy of a
@@ -135,7 +148,7 @@ Created/refined
illumination spectrum to be used as the similated instrument
illuminant, overriding the default <b>D50</b> or CIE computation
illuminant used for FWA (see <b>-i</b> below<b>). </b>See <a
- href="file:///D:/src/argyll/doc/colprof.html#f">colprof -f</a> for
+ href="colprof.html#f">colprof -f</a> for
a fuller explanation. The same value should be used as was used
during the creation of the profile.<br>
<br>
@@ -146,7 +159,7 @@ Created/refined
standard illuminant spectrums, with <b>D50</b> being the default.
If a filename is specified instead, it will be assumed to be an
Argyll specific <a
- href="file:///D:/src/argyll/doc/File_Formats.html#.sp">.sp</a>
+ href="File_Formats.html#.sp">.sp</a>
spectrum file. If FWA compensation is used during measurement, this
illuminant will be used by default as the simulated instrument
illuminant. The same value should be used as was used during the
@@ -178,6 +191,7 @@ Created/refined
<span style="font-style: italic; font-weight: bold;">cietarget</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Is
+
the filename of the target CIE or spectral values. This is a <a
href="File_Formats.html#CGATS">CGATS</a> file (e.g. a <a
href="File_Formats.html#.ti3">.ti3</a> made using <a
@@ -198,6 +212,7 @@ Is
&nbsp;[<span style="font-style: italic; font-weight: bold;">outdevicc</span>]&nbsp;&nbsp;&nbsp;&nbsp;
If
+
the <span style="font-weight: bold;">-g</span> flag is not used,
then the output device ICC profile should be supplied here, to allow
<span style="font-weight: bold;">refine</span> to limit its
@@ -206,6 +221,7 @@ If
&nbsp;[<span style="font-weight: bold; font-style: italic;">inabs</span>]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
After
+
the first correction has been created, subsequent corrections need
to improve upon previous ones, so the previous correction profile
should be provided here. For the first correction, the <span
@@ -215,6 +231,7 @@ After
&nbsp;<span style="font-weight: bold; font-style: italic;">outabs</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
The
+
name of the created or refined abstract correction ICC profile<br>
<br>
<h3> Discussion</h3>
@@ -249,9 +266,9 @@ The
file.<br>
<br>
Lets check how well the proofing system current matches using
- verify:<br>
+ colverify:<br>
<br>
- &nbsp;&nbsp;&nbsp; verify&nbsp; reference.ti3 chart1.ti3<br>
+ &nbsp;&nbsp;&nbsp; colverify&nbsp; reference.ti3 chart1.ti3<br>
<br>
We then create our initial abstract correction fix profile <span
style="font-weight: bold;">fix1.icm</span> using refine:<br>
@@ -282,6 +299,7 @@ The
the same options as you used to create your initial <span
style="font-weight: bold;"><span style="font-weight: bold;"></span>proofer.icm&nbsp;
+
</span>or <span style="font-weight: bold;">target_proofer.icm</span>,
with the addition of the "-p fix1.icm" option to specify the
abstract correction profile be applied.<br>
@@ -292,9 +310,9 @@ The
style="font-weight: bold;">chart2.ti3</span> file.<br>
<br>
Lets check how well the proofing system matches after this first
- round of refinement using verify:<br>
+ round of refinement using colverify:<br>
<br>
- &nbsp;&nbsp;&nbsp; verify&nbsp; reference.ti3 chart2.ti3<br>
+ &nbsp;&nbsp;&nbsp; colverify&nbsp; reference.ti3 chart2.ti3<br>
<br>
<br>
<span style="font-weight: bold;"><span style="font-weight: bold;">&gt;&gt;&gt;</span></span><br>
@@ -302,6 +320,7 @@ The
<span style="font-weight: bold;"><span style="font-weight: bold;">&nbsp;</span></span>We
can
+
then start another round of improvement:<br>
<br>
We refine our previous abstract correction fix profile using
@@ -328,14 +347,15 @@ can
style="font-weight: bold;">chart3.ti3</span> file.<br>
<br>
Check again how well the proofing system matches after this first
- round of refinement using verify:<br>
+ round of refinement using colverify:<br>
<br>
- &nbsp;&nbsp;&nbsp; verify&nbsp; reference.ti3 chart3.ti3<br>
+ &nbsp;&nbsp;&nbsp; colverify&nbsp; reference.ti3 chart3.ti3<br>
<br>
Rounds of improvements can be continues by looping back to <span
style="font-weight: bold;">&gt;&gt;&gt;</span>, being careful to
increment the names of the <span style="font-weight: bold;">fixN.icm</span>,&nbsp;
+
<span style="font-weight: bold;">proofer_fixN.icm</span> or <span
style="font-weight: bold;">target_proofer_fixN.icm</span> and <span
style="font-weight: bold;">chartN.ti3</span>files. Stop when
diff --git a/doc/scanin.html b/doc/scanin.html
index db5091f..ac6ccc8 100644
--- a/doc/scanin.html
+++ b/doc/scanin.html
@@ -10,11 +10,8 @@
<h2><b>scanin/scanin</b></h2>
<h3>Summary</h3>
Convert an 8 or 16 bit per component <a
- href="File_Formats.html#TIFF">TIFF</a>
- image of a
- test chart into&nbsp;<a href="File_Formats.html#.ti3">.ti3</a>
- device
- values
+ href="File_Formats.html#TIFF">TIFF</a> image of a test chart
+ into&nbsp;<a href="File_Formats.html#.ti3">.ti3</a> device values
using automatic pattern recognition, or manual chart alignment.<br>
Performs other tasks associated with turning a TIFF raster of test
patches into numeric values. <br>
@@ -22,40 +19,37 @@
</h3>
<small><a style="font-family: monospace;" href="#_"> usage</a><span
style="font-family: monospace;">: scanin [options] input.tif
- recogin.cht
- valin.cie [diag.tif]</span><br style="font-family: monospace;">
+ recogin.cht valin.cie [diag.tif]</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; :- inputs
- 'input.tif',&nbsp; and outputs scanner
- 'input.ti3', or</span><br style="font-family: monospace;">
+ 'input.tif',&nbsp; and outputs scanner 'input.ti3', or</span><br
+ style="font-family: monospace;">
<br style="font-family: monospace;">
<a style="font-family: monospace;" href="#g"> usage</a><span
style="font-family: monospace;">: scanin -g [options] input.tif
- recogout.cht
- [diag.tif]</span><br style="font-family: monospace;">
+ recogout.cht [diag.tif]</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; :- outputs file
'recogout.cht', or</span><br style="font-family: monospace;">
<br style="font-family: monospace;">
<a style="font-family: monospace;" href="#o"> usage</a><span
style="font-family: monospace;">: scanin -o [options] input.tif
- recogin.cht
- [diag.tif]</span><br style="font-family: monospace;">
+ recogin.cht [diag.tif]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; :- outputs file
'input.val', or</span><br style="font-family: monospace;">
<br style="font-family: monospace;">
<a style="font-family: monospace;" href="#c"> usage</a><span
style="font-family: monospace;">: scanin -c [options] input.tif
- recogin.cht
- scanprofile.[icm|mpp] pbase [diag.tif]</span><br
+ recogin.cht scanprofile.[icm|mpp] pbase [diag.tif]</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; :- inputs
- pbase.ti2
- and outputs printer pbase.ti3, or</span><br style="font-family:
- monospace;">
+ pbase.ti2 and outputs printer pbase.ti3, or</span><br
+ style="font-family: monospace;">
<br style="font-family: monospace;">
<a style="font-family: monospace;" href="#r"> usage</a><span
style="font-family: monospace;">: scanin -r [options] input.tif
- recogin.cht
- pbase [diag.tif]</span><br style="font-family: monospace;">
+ recogin.cht pbase [diag.tif]</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; :- inputs
pbase.ti2+.ti3 and outputs pbase.ti3</span><br
style="font-family: monospace;">
@@ -64,18 +58,21 @@
style="font-family: monospace;" href="#g">-g</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Generate
+
a chart reference (.cht) file</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#o">-o</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Output
+
patch values in .val file</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#c">-c</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Use
+
image to measure color to convert printer pbase .ti2 to .ti3</span><span
style="font-family: monospace;"></span><br style="font-family:
monospace;">
@@ -83,19 +80,23 @@ Use
style="font-family: monospace;" href="#ca">-ca</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Same
+
as -c, but accumulates more values to pbase .ti3</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
from
+
subsequent pages</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#r">-r</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Replace
+
device values in pbase .ti3</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Default
+
is to create a scanner .ti3 file<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#F">-F
@@ -103,84 +104,98 @@ Default
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Don't
+
auto recognize, locate using four fiducual marks<br>
&nbsp;<a href="#p">-p</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Compensate
+
for perspective distortion<br style="font-family: monospace;">
</span></small><small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#a">-a</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Recognize
+
chart in normal orientation only</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Default
+
is to recognize all possible chart angles<br>
&nbsp;<a href="#m">-m</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Return
+
true mean (default is robust mean)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;<a
href="#G">-G gamma</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Approximate
-gamma
- encoding of image</span></small><br style="font-family:
+ Approximate
+ gamma encoding of image</span></small><br style="font-family:
monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#v">-v [n]</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Verbosity
+
level 0-9</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#d">-d</a><span
style="font-family: monospace;"> [ihvglLIcrsonap]&nbsp;&nbsp;
- generate
- diagnostic output (try -dipn)</span><br style="font-family:
- monospace;">
+ generate diagnostic output (try -dipn)</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#di">i</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- B&amp;W of input image</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dh">h</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- Horizontal edge detection</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dv">v</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- Vertical edge detection</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dg">g</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- Groups detected</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dl">l</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- Lines detected</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dL">L</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- All lines detected<br>
</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+
</span><span style="font-family: monospace;"><a href="#dI">I</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- lines used to improve fit<br>
</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+
</span><a style="font-family: monospace;" href="#dc">c</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- lines perspective corrected</span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
@@ -188,365 +203,251 @@ diag
style="font-family: monospace;" href="#dr">r</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- lines rotated</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#ds">s</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- sample boxes rotated</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#do">o</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- sample box outlines</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dn">n</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- sample box names</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#da">a</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
+
- sample box areas</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; </span><a
style="font-family: monospace;" href="#dp">p</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
diag
- - pixel areas sampled</span></small>
- <br>
- <small><span style="font-family: monospace;">&nbsp;
- <a href="#O">-O</a>
- outputfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Override the default output filename
- &amp; extension.</span></small><br>
+
+ - pixel areas sampled</span></small> <br>
+ <small><span style="font-family: monospace;">&nbsp; <a href="#O">-O</a>
+ outputfile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Override the
+ default output filename &amp; extension.</span></small><br>
<h3>Usage Details and Discussion</h3>
<span style="font-weight: bold;">scanin</span> is setup to deal with
- a
- raster file that has been roughly cropped to a size that contains
- the
- test chart. It's exact orientation is not important [ie. there is
- usually no need to rotate or crop the image any more finely.] The
+ a raster file that has been roughly cropped to a size that contains
+ the test chart. It's exact orientation is not important [ie. there
+ is usually no need to rotate or crop the image any more finely.] The
reference files are normally set up with the assumption that the
- edges
- of the chart are visible within the image, and if the image is
- cropped
- to exclude the chart edges, it may well not recognize the chart
- properly. It is designed to cope with a variety of resolutions, and
- will cope with some degree of noise in the scan (due to screening
- artefacts on the original, or film grain), but it isn't really
- designed
- to accept very high resolution input. For anything over 600DPI, you
- should consider down sampling the scan using a filtering downsample,
- before submitting the file to scanin. Similarly, any file with a
- large
- level of noise (due to screening or scanner artefacts) should
- consider
- down sampling the image or filtering it with some average preserving
- filter before submitting it to scanin. Examining the diagnostic
- output
- (ie. -dig and -dil) may help in determining whether noise is an
- issue.<br>
+ edges of the chart are visible within the image, and if the image is
+ cropped to exclude the chart edges, it may well not recognize the
+ chart properly. It is designed to cope with a variety of
+ resolutions, and will cope with some degree of noise in the scan
+ (due to screening artefacts on the original, or film grain), but it
+ isn't really designed to accept very high resolution input. For
+ anything over 600DPI, you should consider down sampling the scan
+ using a filtering downsample, before submitting the file to scanin.
+ Similarly, any file with a large level of noise (due to screening or
+ scanner artefacts) should consider down sampling the image or
+ filtering it with some average preserving filter before submitting
+ it to scanin. Examining the diagnostic output (ie. -dig and -dil)
+ may help in determining whether noise is an issue.<br>
<br>
There are 5 basic modes that <b>scanin</b> operates in.<br>
<ul>
<li><a name="_"></a>When no special argument is given scanin is
assumed to be parsing an input device characterization chart
- (ie. an
- IT8.7/2 chart), for the purpose of creating a <a
+ (ie. an IT8.7/2 chart), for the purpose of creating a <a
href="File_Formats.html#.ti3">.ti3</a> data file containing
the CIE test values and the corresponding RGB scanner values.
The <a href="File_Formats.html#.ti3">.ti3</a> file can then be
- used for
- creating
- an input profile using <a href="colprof.html">colprof</a>. The
- file
- arguments are: <a name="_p1"></a>The TIFF file that is to be
- processed, <a name="_p2"></a>the image recognition template
- file, <a name="_p3"></a>the CIE reference value definitions for
- the test chart
- (sometimes labeled a ".q60" file), <a name="_p4"></a>and an
- optional
- name for the image recognition
- diagnostic output. The resulting .ti3 file will have the same
- base name
- as the input TIFF file.</li>
+ used for creating an input profile using <a href="colprof.html">colprof</a>.
+ The file arguments are: <a name="_p1"></a>The TIFF file that is
+ to be processed, <a name="_p2"></a>the image recognition
+ template file, <a name="_p3"></a>the CIE reference value
+ definitions for the test chart (sometimes labeled a ".q60"
+ file), <a name="_p4"></a>and an optional name for the image
+ recognition diagnostic output. The resulting .ti3 file will have
+ the same base name as the input TIFF file.</li>
<li><a name="g"></a>If the<b> -g</b> flag is specified, then
- scanin
- is operating in a mode designed to create the necessary image
- recognition template file (<a href="File_Formats.html#.cht">.cht</a>)
- boilerplate information. Patch
- location and labeling information would need to be added
- manually to
- such
- a generated file, to make a complete and useable recognition
- template
- file. <a href="cht_format.html">CHT file format.</a> The input
- TIFF
- file in
- this situation, should be a good quality image, perhaps
- synthetically
- generated
- (rather than being scanned), and perfectly oriented, to make
- specification
- of the patch locations easier. The file arguments are: <a
- name="gp1"></a>The
- TIFF file that
- is to be processed, <a name="gp2"></a>the image recognition
- template
- file to be created, <a name="gp3"></a>and
+ scanin is operating in a mode designed to create the necessary
+ image recognition template file (<a
+ href="File_Formats.html#.cht">.cht</a>) boilerplate
+ information. Patch location and labeling information would need
+ to be added manually to such a generated file, to make a
+ complete and useable recognition template file. <a
+ href="cht_format.html">CHT file format.</a> The input TIFF
+ file in this situation, should be a good quality image, perhaps
+ synthetically generated (rather than being scanned), and
+ perfectly oriented, to make specification of the patch locations
+ easier. The file arguments are: <a name="gp1"></a>The TIFF file
+ that is to be processed, <a name="gp2"></a>the image
+ recognition template file to be created, <a name="gp3"></a>and
an optional name for the image recognition diagnostic output.</li>
<li><a name="o"></a>If the <b>-o</b> flag is used, then scanin
- will
- process the input TIFF file and produce a generic&nbsp;<a
- href="File_Formats.html#CGATS">CGATS</a>
- &nbsp;style file containing just the patch values (a <span
- style="font-weight: bold;">.val</span> file). The file
- arguments
- are: <a name="op1"></a>The TIFF file that is to be processed, <a
- name="op2"></a>the image recognition template file
- to be created, <a name="op3"></a>and an optional name for the
- image
- recognition diagnostic
- output.</li>
+ will process the input TIFF file and produce a generic&nbsp;<a
+ href="File_Formats.html#CGATS">CGATS</a> &nbsp;style file
+ containing just the patch values (a <span style="font-weight:
+ bold;">.val</span> file). The file arguments are: <a
+ name="op1"></a>The TIFF file that is to be processed, <a
+ name="op2"></a>the image recognition template file to be
+ created, <a name="op3"></a>and an optional name for the image
+ recognition diagnostic output.</li>
<li><a name="c"></a>If the <b>-c</b> flag is used, then an input
- image
- of a print test chart can be used
- in combination with a device profile, to estimate the CIE
- tristimulus
- values of the patches. This allows RGB
- input devices to be used as a crude replacement for a color
- measuring
- instrument. The icc or mpp profile has
- (presumably) been
- created by scanning an IT8.7/2 chart (or similar) through the
- RGB input
- device,
- and
- then using scanin to create the .ti3 file needed to feed to
- colprof to
- create
- the input device profile. The file arguments in -c mode are: <a
- name="cp1"></a>The
- TIFF file that
- is to be processed containing the image of a print test chart, <a
- name="cp2"></a>the image recognition template file for the
- test chart
- generated by the <a href="printtarg.html"> printtarg</a> tool,
- <a name="cp3"></a>the input device ICC or MPP profile, <a
- name="cp4"></a>the
- base
- name for the .ti2 file containing the
- test chart printer device
- values and their patch identifiers and the base name for the
- resulting
- .ti3
- file, <a name="cp5"></a>and finally an optional name for the
- image
- recognition diagnostic output.
- The resulting .ti3 file will have the same base name as the
- input TIFF
- file.
- If there is more than one page in the test chart, then scanin
- will need
- to be run multiple times, once for each scan file made from each
- test
- chart. <a name="ca"></a>The <b>-ca</b> flag combination should
- be
- used
- for all pages after the first,
- as this then adds that pages test values to the .ti3 file,
- rather than
- creating
- a .ti3 file that contains only that pages test values. If the
- incoming
- .ti2 file contains per-channel calibration
- curves, these will be passed through to the .ti3 so that
- accurate ink
- limits can be computed during profiling. </li>
+ image of a print test chart can be used in combination with a
+ device profile, to estimate the CIE tristimulus values of the
+ patches. This allows RGB input devices to be used as a crude
+ replacement for a color measuring instrument. The icc or mpp
+ profile has (presumably) been created by scanning an IT8.7/2
+ chart (or similar) through the RGB input device, and then using
+ scanin to create the .ti3 file needed to feed to colprof to
+ create the input device profile. The file arguments in -c mode
+ are: <a name="cp1"></a>The TIFF file that is to be processed
+ containing the image of a print test chart, <a name="cp2"></a>the
+ image recognition template file for the test chart generated by
+ the <a href="printtarg.html"> printtarg</a> tool, <a
+ name="cp3"></a>the input device ICC or MPP profile, <a
+ name="cp4"></a>the base name for the .ti2 file containing the
+ test chart printer device values and their patch identifiers and
+ the base name for the resulting .ti3 file, <a name="cp5"></a>and
+ finally an optional name for the image recognition diagnostic
+ output. The resulting .ti3 file will have the same base name as
+ the input TIFF file. If there is more than one page in the test
+ chart, then scanin will need to be run multiple times, once for
+ each scan file made from each test chart. <a name="ca"></a>The
+ <b>-ca</b> flag combination should be used for all pages after
+ the first, as this then adds that pages test values to the .ti3
+ file, rather than creating a .ti3 file that contains only that
+ pages test values. If the incoming .ti2 file contains
+ per-channel calibration curves, these will be passed through to
+ the .ti3 so that accurate ink limits can be computed during
+ profiling. </li>
<li><a name="r"></a>If the <span style="font-weight: bold;">-r</span>
- flag is used, then the input TIFF value
- is used as a source of device values to replace any existing
- device
- values in the given .ti3
- file. This is intended for use in the situation in which the
- device
- values
- being fed into an output device are altered in some way that is
- difficult
- to predict (ie. such as being screened and then de-screened),
- and this
- alteration
- to the device values needs to be taken into account in creating
- a
- profile
- for such a device. The file arguments in -r mode are: <a
- name="rp1"></a>The
- TIFF file that
- is to be processed containing a rasterized image of an output
- test
- chart, <a name="rp2"></a>the image recognition template file
- for the
- test
- chart generated by the <a href="printtarg.html"> printtarg</a>
- tool,&nbsp; <a name="rp3"></a>the base name for
- the .ti2 file containing the output test chart device values and
- their
- patch
+ flag is used, then the input TIFF value is used as a source of
+ device values to replace any existing device values in the given
+ .ti3 file. This is intended for use in the situation in which
+ the device values being fed into an output device are altered in
+ some way that is difficult to predict (ie. such as being
+ screened and then de-screened), and this alteration to the
+ device values needs to be taken into account in creating a
+ profile for such a device. The file arguments in -r mode are: <a
+ name="rp1"></a>The TIFF file that is to be processed
+ containing a rasterized image of an output test chart, <a
+ name="rp2"></a>the image recognition template file for the
+ test chart generated by the <a href="printtarg.html"> printtarg</a>
+ tool,&nbsp; <a name="rp3"></a>the base name for the .ti2 file
+ containing the output test chart device values and their patch
identifiers and the base name for the .ti3 file that is to have
- its
- device
- values replaced, <a name="rp4"></a>and finally an optional name
- for
- the
- image recognition diagnostic
- output.<br>
+ its device values replaced, <a name="rp4"></a>and finally an
+ optional name for the image recognition diagnostic output.<br>
</li>
</ul>
A number of flags and options are available, that are independent of
- the
- mode that scanin is in.<br>
+ the mode that scanin is in.<br>
<br>
Normally scanin will try and recognize a chart, irrespective of its
orientation. For charts that have some asymmetric patch size or
arrangement (such as an IT8.7/2, or a chart generated by <a
- href="printtarg.html"> printtarg</a>
- with the <b>-s</b> option), this is both flexible and reliable.
- Other
- charts
- may be symmetrical, and therefore having scanin figure out the
- orientation
- automatically is a problem if the recognition template does not
- contain
- expected patch values, since it will have an equal chance of
- orienting
- it incorrectly as correctly. To solve this, the <a name="a"></a><b>-a</b>
- flag can be
- used,
- and care taken to provide a raster file that is within 45 degrees of
- "no
- rotation".<br>
+ href="printtarg.html"> printtarg</a> with the <b>-s</b> option),
+ this is both flexible and reliable. Other charts may be symmetrical,
+ and therefore having scanin figure out the orientation automatically
+ is a problem if the recognition template does not contain expected
+ patch values, since it will have an equal chance of orienting it
+ incorrectly as correctly. To solve this, the <a name="a"></a><b>-a</b>
+ flag can be used, and care taken to provide a raster file that is
+ within 45 degrees of "no rotation".<br>
<br>
<a name="F"></a>Normally scanin will use automatic chart recognition
- to
- identify the location of the test patches and extract their values.
- If
- the chart <a href="cht_format.html">CHT file</a>&nbsp;
+ to identify the location of the test patches and extract their
+ values. If the chart <a href="cht_format.html">CHT file</a>&nbsp;
has four fiducial marks defined, then the chart can be manually
aligned by specifying the pixel location of the four marks as
arguments to the <span style="font-weight: bold;"><span
style="font-weight: bold;">-F</span></span> flag. The top left,
- top
- right, bottom right and bottom left fiducial marks X and Y
- co-ordinates
- should be
- specified as a single concatenated argument, separated by comma's,
- e.g:
- -F 10,20,435,22,432,239,10,239&nbsp; The coodinates may be
- fractional using a decimal point.
- Four fiducial marks allows for compensation for perspective
- distortion.<br>
+ top right, bottom right and bottom left fiducial marks X and Y
+ co-ordinates should be specified as a single concatenated argument,
+ separated by comma's, e.g: -F 10,20,435,22,432,239,10,239&nbsp; The
+ coodinates may be fractional using a decimal point. Four fiducial
+ marks allows for compensation for perspective distortion.<br>
<br>
<a name="p"></a>By default the automatic chart recognition copes
- with
- rotation, scale and stretch in the chart image, making it suitable
- for
- charts that have been scanned, or shot squarely with a camera. If a
- chart has been shot not exactly facing the camera (perhaps to avoid
- reflection, or to get more even lighting), then it will suffer from
- perspective distortion as well. The <span style="font-weight:
- bold;"><span style="font-weight: bold;">-p</span></span> flag
- enables automatic
- compensation for perspective distortion.<br>
+ with rotation, scale and stretch in the chart image, making it
+ suitable for charts that have been scanned, or shot squarely with a
+ camera. If a chart has been shot not exactly facing the camera
+ (perhaps to avoid reflection, or to get more even lighting), then it
+ will suffer from perspective distortion as well. The <span
+ style="font-weight: bold;"><span style="font-weight: bold;">-p</span></span>
+ flag enables automatic compensation for perspective distortion.<br>
<br>
<a name="m"></a>Normally scanin computes an average of the pixel
- values
- within a sample square, using a "robust" mean, that discards pixel
- values that are too far from the average ("outlier" pixel values).
- This
- is done in an attempt to discard value that are due to scanning
- artefacts such as dust, scratches etc. You can force scanin to
- return
- the true mean values for the sample squares that includes all the
- pixel
- values, by using the <span style="font-weight: bold;">-m</span>
+ values within a sample square, using a "robust" mean, that discards
+ pixel values that are too far from the average ("outlier" pixel
+ values). This is done in an attempt to discard value that are due to
+ scanning artefacts such as dust, scratches etc. You can force scanin
+ to return the true mean values for the sample squares that includes
+ all the pixel values, by using the <span style="font-weight: bold;">-m</span>
flag.<br>
<br>
<a name="G"></a>Normally scanin has reasonably robust feature
recognition, but the default assumption is that the input chart has
- an
- approximately even visual distribution of patch values, and has been
- scanned and converted to a typical gamma 2.2 corrected image,
- meaning
- that the average patch pixel value is expected to be about 50%. If
- this
- is not the case (for instance if the input chart has been scanned
- with
- linear light or "raw" encoding), then it may enhance the image
- recognition to provide the approximate gamma encoding of the image.
- For
- instance, if linear light encoding ("Raw") is used, a <span
- style="font-weight: bold;">-G</span> value of 1.0 would be
- appropriate. Values less than 2.2 should be tried if the chart is
- particularly dark, or greater than 2.2 if the chart is particularly
- light. Generally it is only necessary to provide this is there are
- problems in recognizing the chart.<br>
+ an approximately even visual distribution of patch values, and has
+ been scanned and converted to a typical gamma 2.2 corrected image,
+ meaning that the average patch pixel value is expected to be about
+ 50%. If this is not the case (for instance if the input chart has
+ been scanned with linear light or "raw" encoding), then it may
+ enhance the image recognition to provide the approximate gamma
+ encoding of the image. For instance, if linear light encoding
+ ("Raw") is used, a <span style="font-weight: bold;">-G</span> value
+ of 1.0 would be appropriate. Values less than 2.2 should be tried if
+ the chart is particularly dark, or greater than 2.2 if the chart is
+ particularly light. Generally it is only necessary to provide this
+ is there are problems in recognizing the chart.<br>
<br>
<a name="v"></a> The <b>-v</b> flag enables extra verbosity in
processing. This can aid debugging, if a chart fails to be
recognized.<br>
<br>
<a name="d"></a> The <b>-d</b> flag enables the generation of an
- image
- recognition diagnostic raster. The name of diagnostic raster can be
- specified as the last in the
- command line, or if not, will default to <span style="font-weight:
- bold;">diag.tif</span>. Various flags control what
- is written to the diagnostic
- raster.
- Note that at least one flag must be specified for a diagnostic
- raster
- to be produced.<br>
+ image recognition diagnostic raster. The name of diagnostic raster
+ can be specified as the last in the command line, or if not, will
+ default to <span style="font-weight: bold;">diag.tif</span>.
+ Various flags control what is written to the diagnostic raster. Note
+ that at least one flag must be specified for a diagnostic raster to
+ be produced.<br>
<b><a name="di"></a>i</b>&nbsp;&nbsp;&nbsp; creates a black and
- white
- version of the input raster in the diagnostic output, to be able to
- compare with the feature extraction.<br>
+ white version of the input raster in the diagnostic output, to be
+ able to compare with the feature extraction.<br>
<b><a name="dh"></a>h</b>&nbsp;&nbsp;&nbsp; will show pixels in the
input image classified as being on horizontal edges, in red.<br>
<b><a name="dv"></a>v</b>&nbsp;&nbsp;&nbsp; will show pixels in the
input image classified as being vertical edges, in green.<br>
<b><a name="dg"></a>g</b>&nbsp;&nbsp;&nbsp; will show groups of
- pixels
- that will be used
- to estimate edge lines, each group in a different color.<br>
+ pixels that will be used to estimate edge lines, each group in a
+ different color.<br>
<b><a name="dl"></a>l</b>&nbsp;&nbsp;&nbsp; will show valid lines
estimated from the vertical and horizontal pixel groups, in white.<br>
<b><a name="dL"></a>L</b>&nbsp;&nbsp;&nbsp; will show all lines
- (valid
- and invalid) estimated from the vertical and horizontal pixel
- groups,
- in white.<br>
+ (valid and invalid) estimated from the vertical and horizontal pixel
+ groups, in white.<br>
<b><a name="dI"></a>I</b> &nbsp;&nbsp; will show valid lines lines
- used
- to improve the final fit,
- in blue.<br>
+ used to improve the final fit, in blue.<br>
<b><a name="dc"></a>c</b> &nbsp;&nbsp; will show the lines with
perspective correction applied in cyan.<br>
<b><a name="dr"></a>r</b>&nbsp;&nbsp;&nbsp; will show the lines
- rotated
- to the reference
- chart orientation, in yellow.<br>
+ rotated to the reference chart orientation, in yellow.<br>
<b><a name="ds"></a>s</b>&nbsp;&nbsp;&nbsp; will show the diagnostic
sampling box edge outlines, rotated to the reference chart
- orientation,
- in orange.<br>
+ orientation, in orange.<br>
<b><a name="do"></a>o</b>&nbsp;&nbsp;&nbsp; will show all the
- sampling
- box edge outlines, in orange.<br>
+ sampling box edge outlines, in orange.<br>
<b><a name="dn"></a>n</b>&nbsp;&nbsp;&nbsp; will show the ID names
- of
- the sampling boxes, plus the diagnostic sample boxes, using a simple
- stroke font, in orange.<br>
+ of the sampling boxes, plus the diagnostic sample boxes, using a
+ simple stroke font, in orange.<br>
<b><a name="da"></a>a</b>&nbsp;&nbsp;&nbsp; will show the sampling
areas as crossed boxes, plus the diagnostic sample boxes, in orange.<br>
<b><a name="dp"></a>p</b>&nbsp;&nbsp;&nbsp; will show the sampling
@@ -555,26 +456,21 @@ diag
The combination of <b>-dipn</b> is usually a good place to start.<br>
<br>
The <a href="File_Formats.html#TIFF">TIFF</a> file can be either 8
- or
- 16 bits per color component, with 16 bit files being slower to
- process,
- but yielding more precise results.<br>
+ or 16 bits per color component, with 16 bit files being slower to
+ process, but yielding more precise results.<br>
<br>
If at all in doubt that the file has been recognized correctly, use
- the
- <span style="font-weight: bold;">-dipn</span> diagnostic flag
+ the <span style="font-weight: bold;">-dipn</span> diagnostic flag
combination, and check the resulting diagnostic raster file.<br>
[ A badly recognised image will typically result in high self fit
delta E's when used with colprof. ]<br>
<br>
<a name="O"></a>The <span style="font-weight: bold;">-O</span>
- parameter allows the
- output file name &amp; extension to be specified independently of
- the
- last tiff
- filename. Note that the full filename must be specified, including
- the
- extension.<br>
+ parameter allows the output file name &amp; extension to be
+ specified independently of the last tiff filename. This works for
+ the default, -g and -o modes. It is ignored for the -r, -c and -ca
+ modes that use a basename for .ti2 in and .ti3 output. Note that the
+ full filename must be specified, including the extension. <br>
<br>
<br>
<br>
diff --git a/doc/spec2cie.html b/doc/spec2cie.html
index 192ee64..c928f9a 100644
--- a/doc/spec2cie.html
+++ b/doc/spec2cie.html
@@ -19,7 +19,7 @@
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Verbose mode</small></tt><br>
<tt><small><small>&nbsp;<a
- href="file:///D:/src/argyll/doc/spec2cie.html#I">-I <i>illum</i></a>&nbsp;&nbsp;
+ href="spec2cie.html#I">-I <i>illum</i></a>&nbsp;&nbsp;
&nbsp;&nbsp; Override
actual instrument illuminant
in .ti3 file:<br>
@@ -31,14 +31,14 @@
(only
used in conjunction with <span style="font-weight: bold;">-f</span>)<br>
</small></small></tt><tt><small><small>&nbsp;<a
- href="file:///D:/src/argyll/doc/colprof.html#f">-f [<i>illum</i>]</a>
+ href="colprof.html#f">-f [<i>illum</i>]</a>
&nbsp;&nbsp; Use Fluorescent Whitening Agent compensation
[simulated inst. illum.:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
M0, M1, M2, A, C, D50 (def.), D50M2, D65, F5, F8, F10 or
file.sp]<br>
</small></small></tt><tt><small><small><small>&nbsp;<a
- href="file:///D:/src/argyll/doc/spec2cie.html#i">-i <i>illum</i></a>&nbsp;&nbsp;
+ href="spec2cie.html#i">-i <i>illum</i></a>&nbsp;&nbsp;
&nbsp;&nbsp; Choose illuminant for computation of CIE XYZ
from spectral data &amp; FWA:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -93,7 +93,7 @@ Measurement
bold;">-f</span>
flag. If a
filename is specified instead, it will be assumed to be an Argyll
- specific <a href="file:///D:/src/argyll/doc/File_Formats.html#.sp">.sp</a>
+ specific <a href="File_Formats.html#.sp">.sp</a>
custom spectrum file.
Illuminant details are:<br>
<br>
@@ -130,7 +130,7 @@ Measurement
selection of standard illuminant spectrums, with <b>D50</b> being
the default. If a filename is specified instead, it will be assumed
to be an Argyll specific <a
- href="file:///D:/src/argyll/doc/File_Formats.html#.sp">.sp</a>
+ href="File_Formats.html#.sp">.sp</a>
custom spectrum file. This only works if spectral data is available.
Illuminant details are:<br>
<br>
diff --git a/doc/spotread.html b/doc/spotread.html
index 0259530..aaac0a1 100644
--- a/doc/spotread.html
+++ b/doc/spotread.html
@@ -31,6 +31,9 @@
+
+
+
&nbsp; &nbsp; &nbsp; Verbose mode</span><br style="font-family:
monospace;">
<span style="font-family: monospace;"></span><span
@@ -52,6 +55,9 @@
+
+
+
&nbsp; &nbsp; &nbsp; Print spectrum for each reading.</span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
@@ -78,6 +84,9 @@
+
+
+
Set COM port, 1..4 (default 1)</span><span style="font-family:
monospace;"></span><span style="font-family: monospace;"><br
style="font-family: monospace;">
@@ -98,6 +107,9 @@
+
+
+
&nbsp; &nbsp; &nbsp; Use transmission measurement mode</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a style="
@@ -118,6 +130,9 @@
+
+
+
Use emissive measurement mode (absolute results)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#eb">-eb</a><span
@@ -137,26 +152,15 @@
+
+
+
Use display white brightness relative measurement mode<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#ew">-ew</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Use display white relative measurement mode<br>
+ Use display white point relative chromatically adjusted mode<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#p">-p</a><span
style="font-family: monospace;">
@@ -175,6 +179,9 @@
+
+
+
Use telephoto measurement mode (absolute results)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#pb">-pb</a><span
@@ -194,6 +201,9 @@
+
+
+
Use </span></small><small><span style="font-family: monospace;">projector</span></small><small><span
style="font-family: monospace;"> white brightness relative
measurement mode<br>
@@ -215,9 +225,13 @@
+
+
+
Use </span></small><small><span style="font-family: monospace;">projector</span></small><small><span
- style="font-family: monospace;"> white relative measurement mode</span></small><small><span
- style="font-family: monospace;"></span></small><br>
+ style="font-family: monospace;"> </span></small><small><span
+ style="font-family: monospace;">white point relative
+ chromatically adjusted mode</span></small><br>
<small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#a">-a</a><span
style="font-family: monospace;">
@@ -236,6 +250,9 @@
+
+
+
Use ambient measurement mode (absolute results)<br>
&nbsp;<a href="#f">-f</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -252,6 +269,9 @@
+
+
+
Use ambient flash measurement mode (absolute results)<br>
</span></small><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#y">-y X</a>
@@ -270,6 +290,9 @@
+
+
+
Display type - instrument specific list to choose from.</span></font><br>
<small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="spotread.html#I">-I illum</a><span
@@ -286,6 +309,9 @@
&nbsp;&nbsp;
M0,
+
+
+
M1, M2, A, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp</span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
@@ -319,6 +345,9 @@ D50
+
+
+
D50M2, D65, F5, F8, F10 or file.sp</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a style="
@@ -342,6 +371,9 @@ D50
+
+
+
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </span></small><small><span
style="font-family: monospace;">1931_2 </span></small><small><span
style="font-family: monospace;"> (def.)</span></small><small><span
@@ -364,6 +396,9 @@ D50
+
+
+
Set filter configuration:<br>
&nbsp;&nbsp;
n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -381,6 +416,9 @@ D50
+
+
+
None<br>
&nbsp;&nbsp;
p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -398,6 +436,9 @@ D50
+
+
+
Polarising filter<br>
&nbsp;&nbsp;
6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -415,6 +456,9 @@ D50
+
+
+
D65<br>
&nbsp;&nbsp;
u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -432,6 +476,9 @@ D50
+
+
+
U.V. Cut<br>
&nbsp;<a href="#E">-E extrafilterfile</a>&nbsp;&nbsp;&nbsp;
Apply extra filter compensation file<br>
@@ -452,6 +499,9 @@ D50
+
+
+
Display Yxy instead of Lab<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#h">-h</a>
@@ -470,6 +520,9 @@ D50
+
+
+
Display LCh instead of Lab</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;<a
href="#V">-V</a>
@@ -488,6 +541,9 @@ D50
+
+
+
Show running average and std. devation from ref.</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;<a
href="#T">-T</a>
@@ -506,6 +562,9 @@ D50
+
+
+
Display correlated color temperatures and CRI<br>
</span></font><font size="-1"><span style="font-family:
monospace;">&nbsp;<a href="#N">-N</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -523,6 +582,9 @@ D50
+
+
+
Disable initial calibration of instrument if possible</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#H">-H</a><span
@@ -546,6 +608,9 @@ D50
+
+
+
Apply Colorimeter Correction Matrix</span></font><br>
<span style="font-family: monospace;">&nbsp;<a href="#X2">-X
file.ccss</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -568,6 +633,9 @@ Samples
+
+
+
for calibration</span><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
style=" font-family: monospace;" href="#Yrn">-<font size="-1">Y</font>
@@ -579,14 +647,20 @@ Samples
+
+
+
&nbsp;&nbsp;&nbsp;&nbsp; Override refresh, non-refresh display
mode</span></font><br>
+ <tt>&nbsp;<a href="#YR">-Y R:<i>rate</i></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+ Override measured refresh rate with rate Hz</tt><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;</span><a
- style=" font-family: monospace;" href="#YA">-<font size="-1">Y</font>A</a><span
+ style=" font-family: monospace;" href="#YA">-<font size="-1">Y </font>A</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp; Use non-adaptive integration time mode
- (if available).</span></font><br>
+ &nbsp;&nbsp;&nbsp; Use non-adaptive integration time mode (if
+ available).</span></font><br>
<font size="-1"><span style="font-family: monospace;">&nbsp;<a
href="#W">-W n|h|x</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Override
@@ -611,6 +685,9 @@ none,
+
+
+
h = HW, x = Xon/Xoff</span></font><br>
<small><span style="font-family: monospace;">&nbsp;</span><a style="
font-family: monospace;" href="#D">-D [level]</a><span
@@ -633,6 +710,9 @@ none,
+
+
+
Optional file to save reading results<br style="font-family:
monospace;">
</span></font><small><span style="font-family: monospace;"></span><span
@@ -695,7 +775,9 @@ none,
<a name="ew"></a>The <span style="font-weight: bold;">-ew</span>
flag allows measuring in emissive mode using instruments that
support this mode, with the reading being relative to the white
- value read as the first reading.<br>
+ value read as the first reading using a Bradford chromatic adaption.
+ This matches the absolute &lt;-&gt; relative intent transformation
+ of Argyll ICC profiles.<br>
<br>
<a name="p"></a>The <span style="font-weight: bold;">-p</span> flag
allows measuring in telephoto mode, using instruments that support
@@ -714,7 +796,9 @@ none,
<a name="pw"></a>The <span style="font-weight: bold;">-pw</span>
flag allows measuring in telephoto mode using instruments that
support this mode, with the reading being relative to the white
- value read as the first reading.<br>
+ value read as the first reading using a Bradford chromatic adaption.
+ This matches the absolute &lt;-&gt; relative intent transformation
+ of Argyll ICC profiles.<br>
<br>
<a name="a"></a>The <span style="font-weight: bold;">-a</span> flag
allows measuring in ambient illumination mode using instruments that
@@ -749,9 +833,9 @@ none,
and how this works, see <a href="instruments.html">Operation of
particular instruments</a>. <b>3)</b> Any installed CCSS files
(if applicable), or CCMX files. These files are typically created
- using <a href="file:///D:/src/argyll/doc/ccxxmake.html">ccxxmake</a>,
+ using <a href="ccxxmake.html">ccxxmake</a>,
and installed using <a
- href="file:///D:/src/argyll/doc/oeminst.html">oeminst</a>. The
+ href="oeminst.html">oeminst</a>. The
default and Base Calibration types will be indicated in the usage.<br>
<br>
<a name="I"></a>The <b>-I</b> parameter allows specifying a
@@ -883,6 +967,9 @@ a
+
+
+
colorimeters accuracy for a particular type of display.<br>
<br>
<a name="Yrn"></a> The -<span style="font-weight: bold;">Y r </span>and
@@ -892,6 +979,9 @@ a
+
+
+
<b>-Y n</b> options overrides the refresh display mode set by the <a
href="#y">-y display type selection</a>, with <b>-Y</b><span
style="font-weight: bold;"> r</span> forcing refresh display mode,
@@ -899,6 +989,12 @@ a
instruments support a display measurement refresh mode, or the
ability to override the mode set by the display type selection.<br>
<br>
+ <a name="YR"></a> The -<span style="font-weight: bold;">Y R:<i>rate</i></span><b></b>
+ options overrides calibration of the instrument refresh rate. This
+ may be useful if the instrument supports this function and the
+ refresh rate cannot be accurately calibrated from the display
+ itself.<br>
+ <br>
<a name="YA"></a> The -<span style="font-weight: bold;">Y A</span>
option uses a non-adaptive integration time emission measurement
mode, if the instrument supports it, such as the Eye-One Pro or
@@ -975,6 +1071,10 @@ a
can be toggled on and off using the <span style="font-weight:
bold;">h</span> key.<br>
<br>
+ If the instrument supports a laser target (such as the JETI
+ specbos), then this can be toggled on &amp; off using the <b>t</b>
+ key. It will automatically be turned off at each measurement.<br>
+ <br>
If the instrument supports stored readings (ie. DTP20), then these
can be ignored using the <span style="font-weight: bold;">n</span>
key.<br>
diff --git a/doc/targen.html b/doc/targen.html
index d03416f..ee12f27 100644
--- a/doc/targen.html
+++ b/doc/targen.html
@@ -3,7 +3,7 @@
<head>
<title>targen</title>
<meta http-equiv="content-type" content="text/html;
- charset=ISO-8859-1">
+ charset=windows-1252">
<meta name="author" content="Graeme Gill">
</head>
<body>
@@ -11,65 +11,112 @@
<h3>Summary</h3>
Generate a profiling test target values&nbsp;<a
href="File_Formats.html#.ti1">.ti1</a> file. &nbsp;<b>targen</b>
- is
- used to generate the device channel test point values for grayscale,
- RGB, CMY, CMYK or N-color output or display devices.&nbsp;
+ is used to generate the device channel test point values for
+ grayscale, RGB, CMY, CMYK or N-color output or display
+ devices.&nbsp;
<h3>Usage Summary</h3>
<small><span style="font-family: monospace;">targen [options]
outfile</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#v">-v [level]</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;
+ Verbose mode [optional verbose level, 1..n]</span><br
style="font-family: monospace;">
- &nbsp;&nbsp;&nbsp;&nbsp; Verbose mode [optional
- verbose level, 1..n]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#d">-d col_comb</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; choose
colorant combination from the following:</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 0:
- Print
- grey</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0: Print grey</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;
- 1:
- Video
- grey</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp; 1: Video grey</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 2:
- Print
- RGB</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: Print RGB</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3:
- Video RGB</span><br style="font-family: monospace;">
+ &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3: Video RGB</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; &nbsp; &nbsp;
- &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 4: CMYK<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 5:
- CMY<br style="font-family: monospace;">
+ &nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4: CMYK<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 5: CMY<br style="font-family: monospace;">
</span><span style="font-family: monospace;">&nbsp;&nbsp; &nbsp;
- &nbsp;
- &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6:
- CMYK + Light CM</span><br style="font-family: monospace;">
+ &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 6: CMYK +
+ Light CM</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
- &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7: CMYK + Light CMK</span><br
- style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7:
+ CMYK + Light CMK</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
&nbsp;
@@ -79,150 +126,381 @@
CMYK
+
Red
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Blue</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp;&nbsp;
+ &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 9: CMYK +
Orange + Green</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10: CMYK +
- Light CMK + Light Light K</span><br style="font-family:
- monospace;">
+ &nbsp; &nbsp; &nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 10: CMYK + Light CMK
+ + Light Light K</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 11: CMYK +
Orange + Green + Light CM</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
- &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12: CMYK + Light
- CM + Medium CM</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 12:
+ CMYK + Light CM + Medium CM</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#D">-D colorant</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp; Add or
delete colorant from combination:</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 0:
- Additive</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ 0: Additive</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 1:
- Cyan</span><br style="font-family: monospace;">
+ 1: Cyan</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2:
Magenta</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3:
Yellow</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 4:
- Black</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4: Black</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 5:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5:
Orange</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 6:
- Red</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 6: Red</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 7:
- Green</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 7: Green</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 8:
- Blue</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8: Blue</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 9:
- White</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 9: White</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 10:
- Light
- Cyan</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10: Light Cyan</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 11:
- Light
- Magenta</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 11: Light Magenta</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 12:
- Light
- Yellow</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 12: Light Yellow</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;
- 13:
- Light
- Black</span><br style="font-family: monospace;">
+ &nbsp;&nbsp; 13: Light Black</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 14:
- Medium
- Cyan</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 14: Medium Cyan</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 15:
- Medium
- Magenta</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15: Medium Magenta</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 16:
- Medium
- Yellow</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 16: Medium Yellow</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;
- 17:
- Medium
- Black</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; 17:
+ Medium Black</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- 18:
- Light
- Light
- Black<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 18: Light
+ Light Black<br>
&nbsp;<a href="#G">-G</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Generate
- good
- optimzed
- points
- rather
- than
- Fast<br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Generate good optimzed points rather than Fast<br
+ style="font-family: monospace;">
</span><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#e">-e patches</a><span
style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp; White
- color test patches (default 4)</span><br style="font-family:
+ color test patches (default 4)</span></small><br
+ style="font-family: monospace;">
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#B">-B patches</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;
+ Black test patches (default 4 Grey/RGB, else 0)<br>
+ </span></small></span>&nbsp; <span style="font-family:
+ monospace;"></span><a style="font-family: monospace;" href="#s">-s
+
+
+
+
+
+
+
+
+
+
+
+ steps</a><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Single channel steps (default 0)</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#s">-s steps</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Single
- channel
- steps
- (default
- 0)</span><br style="font-family: monospace;">
- <span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#g">-g steps</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Gray
@@ -232,31 +510,101 @@ or
CMY
steps
(default
+
+
+
+
+
+
+
+
+
+
+
+
+
0)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#m">-m steps</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Multidimensional
- device
- space
- cube
- steps
- (default
- 2)</span><br style="font-family: monospace;">
- <span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#f">-f patches</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Add
- iterative &amp; adaptive full spread patches to total (default
- 836)<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Default
- is
- Optimised
- Farthest
- Point
- Sampling
- (OFPS)<br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Multidimensional device space cube steps (default 0)</span></small><br
+ style="font-family: monospace;">
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#b">-b steps</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+ Multidimensional body centered cubic steps (default 0)<br>
+ </span></small></span>&nbsp; <span style="font-family:
+ monospace;"></span><a style="font-family: monospace;" href="#f">-f
+
+
+
+
+
+
+
+
+
+
+
+
+ patches</a><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add iterative &amp; adaptive full spread patches to total
+ (default 836)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Default is Optimised Farthest Point Sampling (OFPS)<br
+ style="font-family: monospace;">
</span><span style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#t">-t</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -267,6 +615,19 @@ incremental
far
point
for
+
+
+
+
+
+
+
+
+
+
+
+
+
full spread</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#r">-r</a><span
@@ -278,6 +639,19 @@ device
space
random
for
+
+
+
+
+
+
+
+
+
+
+
+
+
full spread</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#R">-R</a><span
@@ -289,6 +663,19 @@ perceptual
space
random
for
+
+
+
+
+
+
+
+
+
+
+
+
+
full spread</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#q">-q</a><span
@@ -300,14 +687,26 @@ device
space-filling
quasi-random
for
+
+
+
+
+
+
+
+
+
+
+
+
+
full spread<br>
</span></small><small><span style="font-family: monospace;">&nbsp;
</span><a style="font-family: monospace;" href="#Q">-Q</a><span
style="font-family: monospace;">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;
- &nbsp; Use perceptual space-filling quasi-random for full spread</span></small><br
- style="font-family: monospace;">
+ &nbsp; &nbsp; Use perceptual space-filling quasi-random for full
+ spread</span></small><br style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#i">-i</a><span
@@ -319,6 +718,19 @@ device
space
body
centered
+
+
+
+
+
+
+
+
+
+
+
+
+
cubic grid for full spread</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp; </span><a
@@ -331,8 +743,21 @@ perceptual
space
body
centered
- cubic grid for full
- spread</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cubic grid for full spread</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#a">-a angle</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -343,14 +768,26 @@ angle
-
0.5
for
- B.C.C. grid, default -2047840407</span><br style="font-family:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ B.C.C. grid, default 0.333300</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp; </span><a
style="font-family: monospace;" href="#A">-A adaptation</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Degree
- of adaptation of OFPS 0.0 - 1.0 (default 0.1, 1.0 if -c profile
- provided)</span><br style="font-family: monospace;">
+ Degree of adaptation of OFPS 0.0 - 1.0 (default 0.1, 1.0 if -c
+ profile provided)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#t">-t</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
@@ -361,13 +798,38 @@ point
for
full
spread
- (default
- iterative)</span><br style="font-family: monospace;">
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (default iterative)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#l">-l ilimit</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Total
ink
+
+
+
+
+
+
+
+
+
+
+
+
+
limit in %(default = none, or estimated from profile)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#p">-p power</a><span
@@ -379,104 +841,127 @@ applied
to
all
device
+
+
+
+
+
+
+
+
+
+
+
+
+
values.</span></small><br style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#c">-c profile</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Optional device ICC or MPP pre-conditioning profile filename<br>
- &nbsp;<a href="#N">-N emphasis</a>&nbsp;&nbsp;&nbsp;&nbsp;
- Degree of
- neutral axis patch concentration 0-1. (default 0.50)<br
+ &nbsp;<a href="#N">-N nemphasis</a>&nbsp;&nbsp;&nbsp; Degree of
+ neutral axis patch concentration 0-1. (default 0.50)</span></small><br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;<a href="#V">-V
+ demphasis</a>&nbsp;&nbsp;&nbsp; dark region patch
+ concentration 1.0-4.0 (default 1.0 = none)</span></small><br
style="font-family: monospace;">
- </span>&nbsp;
- <a style="font-family: monospace;" href="#F">-F L,a,b,rad</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp; Filter out
- samples
- outside Lab sphere.</span><br style="font-family: monospace;">
+ </span>&nbsp; <a style="font-family: monospace;" href="#F">-F
+ L,a,b,rad</a><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+
+
+
+
+
+
+
+ Filter out samples outside Lab sphere.</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#w">-w</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Dump
- diagnostic
- outfile.wrl
- file
- (Lab
- locations)<br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dump diagnostic outfile.wrl file (Lab locations)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#W">-W</a><span
style="font-family: monospace;">
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Dump
- diagnostic
- outfile.wrl
- file
- (Device
- locations)</span></small><br style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Dump diagnostic outfile.wrl file (Device locations)</span></small><br
+ style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;</span><a
style="font-family: monospace;" href="#p1">outfile</a><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Base
- name
- for
- output(.ti1)</span></small>
- <br>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Base name for output(.ti1)</span></small> <br>
<h3>Usage Details and Discussion<br>
</h3>
The number of target patches needs to be chosen, depending on the
- media
- size, the type of device, and the quality of profile required. For
- an
- inkjet device, something like 3000 test points or more is desirable
- for high quality profiles, while 500-1000 will probably suffice for
- a
- medium quality profile. A few hundred may be sufficient for a
- preliminary profile. Well behaved printing devices (such as a
- chemical
- proof, or a high quality printing press) may produce good profiles
- with
- 1000 to 2000 test points. Well behaved RGB devices such as CRT
- monitors
- may need only a few
- hundred points, if a shaper/matrix type profile is to be produced,
- while pseudo RGB printers, or other RGB devices that a CLUT type
- profile may be used
+ media size, the type of device, and the quality of profile required.
+ For an inkjet device, something like 3000 test points or more is
+ desirable for high quality profiles, while 500-1000 will probably
+ suffice for a medium quality profile. A few hundred may be
+ sufficient for a preliminary profile. Well behaved printing devices
+ (such as a chemical proof, or a high quality printing press) may
+ produce good profiles with 1000 to 2000 test points. Well behaved
+ RGB devices such as CRT monitors may need only a few hundred points,
+ if a shaper/matrix type profile is to be produced, while pseudo RGB
+ printers, or other RGB devices that a CLUT type profile may be used
with, should probably choose somewhere between 500 and 3000 patches.
- For 'N' color profile creation,
- 3000 or more test points should probably be used.<br>
+ For 'N' color profile creation, 3000 or more test points should
+ probably be used.<br>
<br>
<a name="v"></a> The <b>-v</b> flag turns on extra verbosity when
generating patch values. Extra diagnostics and verbosity may be
available if a parameter is provided with a value greater than 1.<br>
<br>
<a name="d"></a> The <b>-d</b> parameter sets the colorspace the
- test
- values will be generated in. Video gray space is assumed to be an
- additive space, where a zero device value will be black, and a
- maximum
- device value will be white. A print gray space is assumed to be a
- subtractive space,
- in which a zero device value will be white, and a maximum device
- value
- will
- be black. If no colorspace is specified, subtractive CMYK is assumed
- as
- a default.<br>
+ test values will be generated in. Video gray space is assumed to be
+ an additive space, where a zero device value will be black, and a
+ maximum device value will be white. A print gray space is assumed to
+ be a subtractive space, in which a zero device value will be white,
+ and a maximum device value will be black. If no colorspace is
+ specified, subtractive CMYK is assumed as a default.<br>
<br>
<a name="D"></a> The <b>-D</b> parameter modifies the colorspace
- set
- by <span style="font-weight: bold;">-d</span> by allowing
- individual
- colorants to be added or subtracted from the colorspace.<br>
+ set by <span style="font-weight: bold;">-d</span> by allowing
+ individual colorants to be added or subtracted from the colorspace.<br>
<br>
<a name="G"></a> The <b>-G</b> flag changes the Incremental Far
- Point
- Distribution
- algorithm from fast to good mode. Fast mode uses a limited number of
- iterations to optimize the patch locations, while good mode strives
- for
- a more even patch distribution by using more iterations.<br>
+ Point Distribution algorithm from fast to good mode. Fast mode uses
+ a limited number of iterations to optimize the patch locations,
+ while good mode strives for a more even patch distribution by using
+ more iterations.<br>
<br>
The composition of the test patches is controlled by the following
flags and parameters:<br>
@@ -485,309 +970,286 @@ device
colored test patches, defaulting to 4 if the -e flag isn't used. The
white patches are usually very important in establishing white point
that the ICC data is made relative to, so it improves robustness to
- use
- more than a
- single point.<br>
+ use more than a single point.<br>
+ <br>
+ <a name="B"></a> The <b>-B</b> parameter sets the number of black
+ colored test patches, defaulting to 4 if the -B flag isn't used and
+ the colorspace is grey or RGB. The black point can be very important
+ for characterizing additive color spaces, so measuring more than one
+ black patch improves robustness over measuring just a single point.<br>
<br>
<a name="s"></a> The <b>-s</b> parameter sets the number of patches
in a set of per colorant wedges. The steps are evenly spaced in
- device
- space by default, and the total number of test patches will be the
- number of
- colorants
- times the value specified with the -s flag. If the <span
- style="font-weight: bold;">-p</span> parameter is provided, then,
- then the steps will be distributed according to the power value.
- e.g.
- the option <span style="font-weight: bold;">-s 5</span> will
- generate
- steps at 0.0 0.25 0.5 0.75 and 1.0, while the option <span
- style="font-weight: bold;">-s 5 -p 2.0</span> will generate steps
- at
- 0.0
- 0.0625 0.25 0.5625 and 1.0. By default, no per colorant
- test wedge values are generated. When creating a test chart for a
- device
- that will be used as a source colorspace, it is often useful to
- generated
- some per colorant wedge values.<br>
+ device space by default, and the total number of test patches will
+ be the number of colorants times the value specified with the -s
+ flag. If the <span style="font-weight: bold;">-p</span> parameter
+ is provided, then, then the steps will be distributed according to
+ the power value. e.g. the option <span style="font-weight: bold;">-s
+
+
+
+
+
+
+
+
+
+
+
+
+ 5</span> will generate steps at 0.0 0.25 0.5 0.75 and 1.0, while
+ the option <span style="font-weight: bold;">-s 5 -p 2.0</span> will
+ generate steps at 0.0 0.0625 0.25 0.5625 and 1.0. By default, no per
+ colorant test wedge values are generated. When creating a test chart
+ for a device that will be used as a source colorspace, it is often
+ useful to generated some per colorant wedge values.<br>
<br>
<a name="g"></a> The <b>-g</b> parameter sets the number of patches
in a set of combined (nominally gray) wedges. This will typically be
equal RGB or CMY values, and by default will be equally spaced steps
- in
- device
- space. If the <span style="font-weight: bold;">-p</span> parameter
- is
- provided, then,
- then the steps will be distributed according to the power value.
- e.g.
- the option <span style="font-weight: bold;">-g 5</span>
- will generate steps at 0.0 0.25 0.5 0.75 and 1.0, while the option <span
- style="font-weight: bold;">-g 5 -p 2.0</span> will generate steps
- at
- 0.0
- 0.0625 0.25 0.5625 and 1.0. By
- default, no gray combination values are generated. When creating a
- test
- chart for a device that will be used as a source colorspace, it is
- often
- useful to generated some per colorant wedge values.<br>
+ in device space. If the <span style="font-weight: bold;">-p</span>
+ parameter is provided, then, then the steps will be distributed
+ according to the power value. e.g. the option <span
+ style="font-weight: bold;">-g 5</span> will generate steps at 0.0
+ 0.25 0.5 0.75 and 1.0, while the option <span style="font-weight:
+ bold;">-g 5 -p 2.0</span> will generate steps at 0.0 0.0625 0.25
+ 0.5625 and 1.0. By default, no gray combination values are
+ generated. When creating a test chart for a device that will be used
+ as a source colorspace, it is often useful to generated some per
+ colorant wedge values.<br>
<br>
<a name="m"></a> The <b>-m</b> parameter sets the edge size of the
multidimensional grid of test values. The total number of patches of
this type will be the -m parameter value to the power of the number
- of
- colorants. The grid steps are evenly spaced in device space by
- default,
- but if the <span style="font-weight: bold;">-p</span> parameter is
- provided, then,
- then the steps will be distributed according to the power value.
- e.g.
- the option <span style="font-weight: bold;">-m 5</span>
- will generate steps at 0.0 0.25 0.5 0.75 and 1.0, while the option <span
- style="font-weight: bold;">-m 5 -p 2.0</span> will generate steps
- at
- 0.0
- 0.0625 0.25 0.5625 and 1.0. By
- default, all the device primary color combinations that fall within
- the
- ink limit are generated..<br>
- <br>
- The behavior of the <b>-e</b>, <b>-s</b>, <b>-g</b> and <b>-m</b>
- flags, is not to duplicate test values already created by a previous
- type.<br>
+ of colorants. The grid steps are evenly spaced in device space by
+ default, but if the <span style="font-weight: bold;">-p</span>
+ parameter is provided, then, then the steps will be distributed
+ according to the power value. e.g. the option <span
+ style="font-weight: bold;">-m 5</span> will generate steps at 0.0
+ 0.25 0.5 0.75 and 1.0, while the option <span style="font-weight:
+ bold;">-m 5 -p 2.0</span> will generate steps at 0.0 0.0625 0.25
+ 0.5625 and 1.0. By default, all the device primary color
+ combinations that fall within the ink limit are generated..<br>
+ <br>
+ <a name="m"></a> The <b>-b</b> parameter sets the outer edge size
+ of the multidimensional body centered grid of test values. The total
+ number of patches of this type will be the -b parameter value to the
+ power of the number of colorants plus the (number-1) to the power of
+ the number of colorants. The grid steps are evenly spaced in device
+ space by default, but if the <span style="font-weight: bold;">-p</span>
+ parameter is provided, then, then the steps will be distributed
+ according to the power value. A body centered grid is a regular grid
+ (see <b>-m</b>) with another smaller regular grid within it, at the
+ centers of the outer grid. This grid arrangement is more space
+ efficient than a regular grid (ie. for a given number of test
+ points, it fills the space better.)<br>
+ <br>
+ The behavior of the <b>-e</b>, <b>-s</b>, <b>-g</b> <b>-m </b>and
+
+
+
+
+
+
+
+
+
+
+
+
+ <b>-b</b> flags, is not to duplicate test values already created by
+ a previous type.<br>
<br>
<a name="f"></a> The <b>-f</b> parameter sets the number of full
spread test patches. Full spread patches are distributed according
- to
- the default or chosen algorithm. The default algorithm will optimize
- the point locations to minimize the distance from any point in
- device
- space, to the nearest
- sample point. This is called Optimized Farthest Point Sampling
- (OFPS) .
- This can be overridden by specifying the <b>-t. -r, -R,
- -q,
- -i or -I</b> flags. If the default OFPS algorithm is used, then
- adaptive
- test
- point distribution can be fully enabled by supplying a previous or
- typical profile with the <span style="font-weight: bold;">-c</span>
- option. The total number patches specified will
- include any
- patches
- generated using the <b>-e</b>, <b>-s</b>, <b>-g</b> and <b>-m</b>
- flags (i.e.
- full spread patches will be added to bring the total number of
- patches
- including
- those generated using the <b>-e</b>, <b>-s</b>, <b>-g</b> and <b>-m</b>
- flags
- up to the specified number). When there are more than four device
- channels,
- the full spread distribution algorithm can't deal with so many
- dimensions,
- and <b>targen</b> falls back on an incremental far point
- distribution
- algorithm
- by default, that doesn't generate such evenly spread points. This
- behaviour
- can be forced using the <b>-t</b> flag. A <a href="#Table">table</a>
- of useful total patch counts for different paper sizes is shown
- below.
+ to the default or chosen algorithm. The default algorithm will
+ optimize the point locations to minimize the distance from any point
+ in device space, to the nearest sample point. This is called
+ Optimized Farthest Point Sampling (OFPS) . This can be overridden by
+ specifying the <b>-t. -r, -R, -q, -i or -I</b> flags. If the
+ default OFPS algorithm is used, then adaptive test point
+ distribution can be fully enabled by supplying a previous or typical
+ profile with the <span style="font-weight: bold;">-c</span> option.
+ The total number patches specified will include any patches
+ generated using the <b>-e</b>, <b>-s</b>, <b>-g</b> <b>-m</b>
+ and <b>-b</b> flags (i.e. full spread patches will be added to
+ bring the total number of patches including those generated using
+ the <b>-e</b>, <b>-s</b>, <b>-g</b> <b>-m </b>and <b>-b</b>
+ flags up to the specified number). When there are more than four
+ device channels, the full spread distribution algorithm can't deal
+ with so many dimensions, and <b>targen</b> falls back on an
+ incremental far point distribution algorithm by default, that
+ doesn't generate such evenly spread points. This behaviour can be
+ forced using the <b>-t</b> flag. A <a href="#Table">table</a> of
+ useful total patch counts for different paper sizes is shown below.
Note that it's occasionally the case that the OFPS algorithm will
- fail
- to complete, or make very slow progress if the <span
+ fail to complete, or make very slow progress if the <span
style="font-weight: bold;">-c</span> profile is poor, non-smooth,
- or
- has unusual behaviour. In these cases a different algorithm should
- be
- chosen (ie. <span style="font-weight: bold;">-Q</span> or <span
- style="font-weight: bold;">-I</span>), or perhaps a smoother or
- lower
- resolution ("quality") previous profile may overcome the problem. <br>
+ or has unusual behaviour. In these cases a different algorithm
+ should be chosen (ie. <span style="font-weight: bold;">-Q</span> or
+ <span style="font-weight: bold;">-I</span>), or perhaps a smoother
+ or lower resolution ("quality") previous profile may overcome the
+ problem. <br>
<br>
<a name="t"></a> The <b>-t</b> flag overrides the default full
- spread
- test patch algorithm, and makes use of the Incremental Far Point
- Distribution
- algorithm, which incrementally searches for test points that are as
- far
- away
- as possible from any existing points. This is used as the default
- for
- dimensions
- higher than 4.<br>
+ spread test patch algorithm, and makes use of the Incremental Far
+ Point Distribution algorithm, which incrementally searches for test
+ points that are as far away as possible from any existing points.
+ This is used as the default for dimensions higher than 4.<br>
<br>
<a name="r"></a> The <b>-r</b> flag overrides the default full
- spread
- test patch algorithm, and chooses test points with an even random
- distribution in device space.<br>
+ spread test patch algorithm, and chooses test points with an even
+ random distribution in device space.<br>
<br>
<a name="R"></a> The <b>-R</b> flag overrides the default full
- spread
- test patch algorithm, and chooses test points with an even random
- distribution in perceptual space.<br>
+ spread test patch algorithm, and chooses test points with an even
+ random distribution in perceptual space.<br>
<br>
<a name="q"></a> The <b>-q</b> flag overrides the default full
- spread
- test patch algorithm, and chooses test points with a quasi-random,
- space filling distribution in device space.<br>
+ spread test patch algorithm, and chooses test points with a
+ quasi-random, space filling distribution in device space.<br>
<br>
<a name="Q"></a> The <b>-Q</b> flag overrides the default full
- spread
- test patch algorithm, and chooses test points with a quasi-random,
- space filling distribution in perceptual space.<br>
+ spread test patch algorithm, and chooses test points with a
+ quasi-random, space filling distribution in perceptual space.<br>
<br>
<a name="i"></a> The <b>-i</b> flag overrides the default full
- spread
- test patch algorithm, and chooses test points with body centered
- cubic
- distribution in device space.<br>
+ spread test patch algorithm, and chooses test points with body
+ centered cubic distribution in device space.<br>
<br>
<a name="I"></a> The <b>-I</b> flag overrides the default full
- spread
- test patch algorithm, and chooses test points with body centered
- cubic
- distribution in perceptual space.<br>
+ spread test patch algorithm, and chooses test points with body
+ centered cubic distribution in perceptual space.<br>
<br>
<a name="a"></a> The <b>-a <i>angle</i></b> parameter sets the
- overall
- angle that the body centered grid distribution has.<br>
+ overall angle that the body centered grid distribution has.<br>
<br>
<a name="A"></a> The <b>-A <i>adaptation</i></b> parameter sets
- the
- degree of adaptation to the known device characteristics, used by
- the
- default full spread OFPS algorithm. A profile
- should be provided using the <span style="font-weight: bold;">-c</span>
+ the degree of adaptation to the known device characteristics, used
+ by the default full spread OFPS algorithm. A profile should be
+ provided using the <span style="font-weight: bold;">-c</span>
parameter if <span style="font-weight: bold; font-style: italic;">adaptation</span>
- is set above a low level. By
- default the adaptation is 0.1 (low), and 1.0 (maximum) if <span
- style="font-weight: bold;">-c profile</span> is provided, but
- these
- defaults can be overridden using this option. For instance, if the <span
- style="font-weight: bold;">-c profile</span> doesn't represent the
- device behavior very well, a lower adaption than 1.0 might be
- appropriate.<br>
+ is set above a low level. By default the adaptation is 0.1 (low),
+ and 1.0 (maximum) if <span style="font-weight: bold;">-c profile</span>
+ is provided, but these defaults can be overridden using this option.
+ For instance, if the <span style="font-weight: bold;">-c profile</span>
+ doesn't represent the device behavior very well, a lower adaption
+ than 1.0 might be appropriate.<br>
<br>
<a name="l"></a> The <b>-l</b> flag and parameter sets a total ink
- limit (Total
- Area Coverage or TAC), which is adhered to for all the generated
- points. It is generally good practice to set a test chart ink limit
- at
- least 10% higher than the ink limit that will be applied when making
- the resulting profile. In the case of device cube points, this can
- generate extra test
- values that lie at the ink limit boundary. For gray wedge values,
- any
- that exceed the ink limit are omitted. Full spread test values are
- all
- generated to lie
- within the ink limit. Although it doesn't make much sense, this
- parameter has an affect on additive device spaces (such as RGB), but
- should not normally be used with such devices. The total ink limit
- value will be written to the
- .ti1 file, and carried through automatically to the .ti3 file, so
- that
- it
- can be used during profile creation. If a profile is provided using
- the
- <span style="font-weight: bold;">-c</span> flag, then this will be
- used
- to estimate an ink limit, if none is provided with the <span
- style="font-weight: bold;">-l</span> flag. Ink limits are, as far
- as
- possible, always in final calibrated device values, and the
- calibration
- curves from the profile provided to the <span style="font-weight:
- bold;">-c</span> flag will be used to estimate the
- equivalent limit in the underlying pre-calibration device space
- values
- that targen creates.<br>
+ limit (Total Area Coverage or TAC), which is adhered to for all the
+ generated points. It is generally good practice to set a test chart
+ ink limit at least 10% higher than the ink limit that will be
+ applied when making the resulting profile. In the case of device
+ cube points, this can generate extra test values that lie at the ink
+ limit boundary. For gray wedge values, any that exceed the ink limit
+ are omitted. Full spread test values are all generated to lie within
+ the ink limit. Although it doesn't make much sense, this parameter
+ has an affect on additive device spaces (such as RGB), but should
+ not normally be used with such devices. The total ink limit value
+ will be written to the .ti1 file, and carried through automatically
+ to the .ti3 file, so that it can be used during profile creation. If
+ a profile is provided using the <span style="font-weight: bold;">-c</span>
+ flag, then this will be used to estimate an ink limit, if none is
+ provided with the <span style="font-weight: bold;">-l</span> flag.
+ Ink limits are, as far as possible, always in final calibrated
+ device values, and the calibration curves from the profile provided
+ to the <span style="font-weight: bold;">-c</span> flag will be used
+ to estimate the equivalent limit in the underlying pre-calibration
+ device space values that targen creates.<br>
<br>
<a name="p"></a> The <b>-p</b> flag and parameter sets a power-like
- value
- applied to all of the device values after they are generated, <span
- style="font-weight: bold;"></span><span style="font-weight: bold;"></span>the
-spacer
-colors.
-This
-can
-be
-useful
-in
- creating calibration charts for
- very non-linearly behaved devices. A value greater than 1.0 will
- cause
- a tighter spacing of test values near device value 0.0, while a
- value
- less than 1.0 will cause a tighter spacing near device value 1.0. <span
- style="font-weight: bold;">printcal</span> will recommend a
- power-like
- value if the verbose option is used. [ <span style="font-weight:
- bold;">Note</span>
- that for Print RGB space this
- is reversed, since internally a Print RGB space is treated as a CMY
- space. ]. <span style="font-weight: bold;">Note</span> that the
- device
- model used to create the expected patch values will not take into
- account the applied power, nor will the more complex full spread
- algorithms correctly take into account the power in generating
- values
- up to the ink limits. (A power-like function is used, to avoid the
- excessive compression that a real power function would apply).<br>
+ value applied to all of the device values after they are generated,
+ <span style="font-weight: bold;"></span><span style="font-weight:
+ bold;"></span>the spacer colors. This can be useful in creating
+ calibration charts for very non-linearly behaved devices. A value
+ greater than 1.0 will cause a tighter spacing of test values near
+ device value 0.0, while a value less than 1.0 will cause a tighter
+ spacing near device value 1.0. <span style="font-weight: bold;">printcal</span>
+ will recommend a power-like value if the verbose option is used. [ <span
+ style="font-weight: bold;">Note</span> that for Print RGB space
+ this is reversed, since internally a Print RGB space is treated as a
+ CMY space. ]. <span style="font-weight: bold;">Note</span> that the
+ device model used to create the expected patch values will not take
+ into account the applied power, nor will the more complex full
+ spread algorithms correctly take into account the power in
+ generating values up to the ink limits. (A power-like function is
+ used, to avoid the excessive compression that a real power function
+ would apply).<br>
<br>
<a name="c"></a> The <b>-c</b> flag and parameter is used to
- specify
- an <a href="File_Formats.html#ICC">ICC</a> or <a
+ specify an <a href="File_Formats.html#ICC">ICC</a> or <a
href="File_Formats.html#MPP">MPP</a> pre-conditioning profile, for
estimating perceptual distances and colorspace curvature, used in
optimizing the full spread test point placement,or in creating
- perceptualy spaced distributions. Normally a previous
- profile for this or a similar device will be used, or a simpler,
- preliminary profile will be created and used. If no such profile is
- specified, a default device space model is used. Note that this
- will only have an effect if an algorithm that uses perceptual
- placement (such as <span style="font-weight: bold;">-R, -Q, -I</span>
- or the default OFPS with an
- <span style="font-weight: bold;">-A</span> value &gt; 0.0) is being
- used.<br>
- <br>
- <a name="N"></a> The <b>-N emphasis</b> parameter allows changing
- the
- degree to which the patch distribution should emphasise the neutral
- axis. Since the neutral axis is regarded as the most visually
- critical
- are of the color space, it can help maximize the quality of the
- resulting profile to place more measurement patches in this region.
- This emphasis is only effective for perceptual patch distributions,
- and
- for the default OFPS distribution if the <a href="#A">adaptation</a>
- parameter is set to a high value. It is also most effective when a <a
- href="#c">pre-conditioning</a> profile is provided, since this is
- the
- only way that neutral can be determined. The default value of 0.5
- provides an affect about twice the emphasis of the CIE94 Delta E
- formula.<br>
+ perceptualy spaced distributions. Normally a previous profile for
+ this or a similar device will be used, or a simpler, preliminary
+ profile will be created and used. If no such profile is specified, a
+ default device space model is used. Note that this will only have an
+ effect if an algorithm that uses perceptual placement (such as <span
+ style="font-weight: bold;">-R, -Q, -I</span> or the default OFPS
+ with an <span style="font-weight: bold;">-A</span> value &gt; 0.0)
+ is being used.<br>
+ <br>
+ <a name="N"></a> The <b>-N nemphasis</b> parameter allows changing
+ the degree to which the patch distribution should emphasise the
+ neutral axis. Since the neutral axis is regarded as the most
+ visually critical are of the color space, it can help maximize the
+ quality of the resulting profile to place more measurement patches
+ in this region. This emphasis is only effective for perceptual patch
+ distributions, and for the default OFPS distribution if the <a
+ href="#A">adaptation</a> parameter is set to a high value. It is
+ also most effective when a <a href="#c">pre-conditioning</a>
+ profile is provided, since this is the only way that neutral can be
+ determined. The default value of 0.5 provides an affect about twice
+ the emphasis of the CIE94 Delta E formula.<br>
+ <br>
+ <a name="V"></a> The <b>-V demphasis</b> parameter allows changing
+ the degree to which the patch distribution should emphasis dark
+ region of the device response. Display devices used for video or
+ film reproduction are typically viewed in dark viewing environments
+ with no strong white reference, and typically employ a range of
+ brightness levels in different scenes. This often means that the
+ devices dark region response is of particular importance, so
+ increasing the relative number of sample points in the dark region
+ may improved the balance of accuracy of the resulting profile for
+ video or film reproduction. This emphasis is only effective for
+ perceptual patch distributions where a <a href="targen.html#c">pre-conditioning</a>
+ profile is provided. The default value of 1.0 provides no emphasis
+ of the dark regions. A value somewhere around <b>1.5 - 2.0</b> is a
+ good place to start for video profile use. A scaled down version of
+ the -V parameter will be passed on through the .ti3 file to colprof
+ where it will set a default value for the corresponding <a
+ href="colprof.html#V">colprof -V</a> parameter.&nbsp; Note that
+ increasing the proportion of dark patches will typically lengthen
+ the time that an instrument takes to read the whole chart.
+ Emphasizing the dark region characterization will reduce the
+ accuracy of measuring and modelling the lighter regions, given a
+ fixed number of test points and profile quality/grid resolution. The
+ parameter will also be used in an analogous way to the <small><a
+ href="file:///D:/src/argyll/doc/targen.html#p">-p power</a>
+ value in changing the distribution of </small><small><a
+ href="file:///D:/src/argyll/doc/targen.html#s">-s steps</a>, </small><small><a
+ href="file:///D:/src/argyll/doc/targen.html#g">-g steps</a>, </small><small><a
+ href="file:///D:/src/argyll/doc/targen.html#m">-m steps</a></small>
+ and <small><small><a href="file:///D:/src/argyll/doc/targen.html#b">-b
+
+
+
+ steps</a></small></small> patches.<br>
<br>
<a name="F"></a> The <b>-F</b> flag and parameters is used to
- define
- an L*a*b* sphere to filter the test points through. Only test points
- within the sphere (defined by it's center and radius) will be
- written
- to the .ti1 file. This can be good for targeting supplemental test
- points at a troublesome area of a device. The accuracy of the L*a*b*
- target will be best when the <span style="font-weight: bold;">-c</span>
- option is used to specify a reasonably accurate profile for the
- device.
- Note that the actual number of points generated can be hard to
- predict,
- and will depend on the type of generation used. All means of
- generating
- points except the -f N &amp; -r, -R and -q will generate a smaller
- number of test points than expected. If the -f N &amp; -r, -R and -q
+ define an L*a*b* sphere to filter the test points through. Only test
+ points within the sphere (defined by it's center and radius) will be
+ written to the .ti1 file. This can be good for targeting
+ supplemental test points at a troublesome area of a device. The
+ accuracy of the L*a*b* target will be best when the <span
+ style="font-weight: bold;">-c</span> option is used to specify a
+ reasonably accurate profile for the device. Note that the actual
+ number of points generated can be hard to predict, and will depend
+ on the type of generation used. All means of generating points
+ except the -f N &amp; -r, -R and -q will generate a smaller number
+ of test points than expected. If the -f N &amp; -r, -R and -q
methods are used, then the target number of points will be achieved.
For this reason, the -f N -q method is probably the easiest to use.<br>
<br>
@@ -798,35 +1260,29 @@ in
strange, since the extra K dimension is compressed into the 3
dimensional L*a*b* space. <a name="W"></a>If the <span
style="font-weight: bold;">-W</span> flag is given, the plot will
- be
- in device space, with only the first 3 dimensions of each point
- being
- plotted.<br>
+ be in device space, with only the first 3 dimensions of each point
+ being plotted.<br>
<br>
<a name="p1"></a> The final parameter on the command line is the
- base
- filename for the <a href="File_Formats.html#.ti1">.ti1</a> output
- file. <b>targen</b> will add the .ti1 extension automatically.<br>
+ base filename for the <a href="File_Formats.html#.ti1">.ti1</a>
+ output file. <b>targen</b> will add the .ti1 extension
+ automatically.<br>
<br>
Some typical total patch number/paper size combinations are shown
below. These "magic" numbers are found by using <a
href="printtarg.html">printtarg</a> to compute the row length and
number of rows, and then adjusting the total number of patches to
- fill
- the last row or paper size, in an iterative fashion.<br>
+ fill the last row or paper size, in a trial and error fashion.<br>
<br>
<a name="Table"></a> &nbsp;&nbsp; &nbsp; Size (mm/Standard Name),
- &nbsp;
- No. Patches<br>
+ &nbsp; No. Patches<br>
<br>
DTP20:<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x A4&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 540<br>
&nbsp; &nbsp; &nbsp; 2 x A4 &nbsp; &nbsp; &nbsp; 1080<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp; 1620<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4&nbsp; &nbsp;
- &nbsp;&nbsp; 2160<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 1620<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4&nbsp; &nbsp; &nbsp;&nbsp; 2160<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; 1 x Letter &nbsp;&nbsp; 570<br>
&nbsp; &nbsp; &nbsp; 2 x Letter&nbsp;&nbsp; 1140<br>
@@ -844,41 +1300,27 @@ in
&nbsp; DTP41:<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x A4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;
- &nbsp;
- &nbsp; &nbsp; 375<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; 375<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 x A4 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; 750<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; 750<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 x A4 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp; 1125<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 1125<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 x A4 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp; 1500<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 1500<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;
- &nbsp; 345<br>
+ &nbsp; &nbsp; 345<br>
&nbsp; &nbsp; &nbsp; 2 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;&nbsp;
- 690<br>
+ &nbsp;&nbsp;&nbsp; 690<br>
&nbsp; &nbsp; &nbsp; 3 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;
- 1035<br>
+ &nbsp;&nbsp; 1035<br>
&nbsp; &nbsp; &nbsp; 4 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;
- 1380<br>
+ &nbsp;&nbsp; 1380<br>
<br>
&nbsp;&nbsp; &nbsp;&nbsp; 1 x A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 836<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 836<br>
&nbsp;&nbsp; &nbsp;&nbsp; 2 x A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1672<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1672<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x 11x17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp;&nbsp; 780<br>
@@ -889,55 +1331,41 @@ in
&nbsp; DTP51:<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x A4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; 266<br>
+ &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; 266<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2 x A4 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; 532<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; 532<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3 x A4 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; 798<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; 798<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4 x A4 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp; &nbsp;
- &nbsp;
- &nbsp;&nbsp; 1064<br>
+ &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 1064<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;
- 252<br>
+ &nbsp;&nbsp; 252<br>
&nbsp; &nbsp; &nbsp; 2 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;
- 504<br>
+ &nbsp;&nbsp; 504<br>
&nbsp; &nbsp; &nbsp; 3 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;
- 756<br>
+ &nbsp;&nbsp; 756<br>
&nbsp; &nbsp; &nbsp; 4 x Letter &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; 1008<br>
<br>
&nbsp;&nbsp; &nbsp;&nbsp; 1 x A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 580<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 580<br>
&nbsp;&nbsp; &nbsp;&nbsp; 2 x A3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 1160<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; 1160<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x 11x17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; 570<br>
&nbsp; &nbsp; &nbsp; 2 x 11x17 &nbsp; &nbsp; &nbsp; &nbsp;
- &nbsp;&nbsp;
- 1140<br>
+ &nbsp;&nbsp; 1140<br>
<br>
&nbsp; SpectroScan with square patches:<br>
<br>
&nbsp; &nbsp; &nbsp; 1 x A4R&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 1014<br>
&nbsp; &nbsp; &nbsp; 2 x A4R &nbsp; &nbsp; &nbsp; 2028<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4R&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp; 3042<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4R&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp; 4056<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4R&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ 3042<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4R&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
+ 4056<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; 1 x LetterR &nbsp;&nbsp; 999<br>
&nbsp; &nbsp; &nbsp; 2 x LetterR&nbsp;&nbsp; 1998<br>
@@ -948,10 +1376,10 @@ in
<br>
&nbsp; &nbsp; &nbsp; 1 x A4R&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 1170<br>
&nbsp; &nbsp; &nbsp; 2 x A4R &nbsp; &nbsp; &nbsp; 2340<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4R&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp; 3510<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4R&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp; 4680<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4R&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ 3510<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4R&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;
+ 4680<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; 1 x LetterR&nbsp;&nbsp; 1092<br>
&nbsp; &nbsp; &nbsp; 2 x LetterR&nbsp;&nbsp; 2184<br>
@@ -962,10 +1390,8 @@ in
<br>
&nbsp; &nbsp; &nbsp; 1 x A4&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 441<br>
&nbsp; &nbsp; &nbsp; 2 x A4 &nbsp; &nbsp; &nbsp;&nbsp; 882<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp; 1323<br>
- &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4&nbsp;&nbsp;&nbsp;
- &nbsp;&nbsp; 1764<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 3 x A4&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 1323<br>
+ &nbsp;&nbsp; &nbsp;&nbsp; 4 x A4&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 1764<br>
<br>
&nbsp;&nbsp;&nbsp; &nbsp; 1 x Letter &nbsp;&nbsp; 462<br>
&nbsp; &nbsp; &nbsp; 2 x Letter&nbsp;&nbsp;&nbsp; 924<br>
diff --git a/doc/tiffgamut.html b/doc/tiffgamut.html
index bc63ce7..5b67603 100644
--- a/doc/tiffgamut.html
+++ b/doc/tiffgamut.html
@@ -9,182 +9,195 @@
<body>
<h2><b>xicc/tiffgamut</b></h2>
<h3>Summary</h3>
- Create a gamut file or VRML file of the color gamut of the
- contents of a set of TIFF or JPEG image.<br>
+ Create a gamut file or VRML file of the color gamut of the contents
+ of a set of TIFF or JPEG image.<br>
<br>
<span style="font-weight: bold;">tiffgamut</span> allows creation of
- gamut files from the pixel values in a
- set of TIFF and/or JPEG raster images, as defined by an ICC profile,
- in L*a*b* or
- CIECAM02
- Jab
- colorspace, and can also represent the gamut as a VRML file. This
- can be used for visualizing and comparing the gamut of an image to
- the
- colorspace it is
- in, or a colorspace it might get transformed into, and can also be
- used
- to create an image source gamut for use with <a href="collink.html">
- collink</a>.<br>
+ gamut files from the pixel values in a set of TIFF and/or JPEG
+ raster images, as defined by an ICC profile, in L*a*b* or CIECAM02
+ Jab colorspace, and can also represent the gamut as a VRML file.
+ This can be used for visualizing and comparing the gamut of an image
+ to the colorspace it is in, or a colorspace it might get transformed
+ into, and can also be used to create an image source gamut for use
+ with <a href="collink.html"> collink</a>.<br>
<br>
<span style="font-weight: bold;">NOTE</span> that if you are
- creating
- an image gamut suitable for use with the <a href="collink.html">collink</a>
- <a href="collink.html#g">-g</a> or <a href="collink.html#G">-G</a>
- flags, or <a href="colprof.html#g">colprof
- -g</a>, use the Jab appearance space intent for appearance space
- gamut
- mappings, and the same input viewing
- conditions to be used in <span style="font-weight: bold;">collink</span>
- or <span style="font-weight: bold;">colprof</span>
- using
- the -c flag, i.e. "tiffgamut -pj -cmt sRGB.icm image.tif"<br>
+ creating an image gamut suitable for use with the <a
+ href="collink.html">collink</a> <a href="collink.html#g">-g</a>
+ or <a href="collink.html#G">-G</a> flags, or <a
+ href="colprof.html#g">colprof -g</a>, use the Jab appearance space
+ intent for appearance space gamut mappings, and the same input
+ viewing conditions to be used in <span style="font-weight: bold;">collink</span>
+ or <span style="font-weight: bold;">colprof</span> using the -c
+ flag, i.e. "tiffgamut -pj -cmt sRGB.icm image.tif"<br>
<h3>Usage Summary</h3>
<small><span style="font-family: monospace;">tiffgamut [-v level]
[profile.icm | embedded.tif/jpg] infile1.tif/jpg
[infile2.tif/jpg ...]</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-v&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
Verbose</span><br style="font-family: monospace;">
- &nbsp;
- <span style="font-family: monospace;">-d
- sres&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Surface
- resolution details 1.0 - 50.0</span><br style="font-family:
- monospace;">
+ &nbsp; <span style="font-family: monospace;">-d
+ sres&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Surface resolution
+ details 1.0 - 50.0</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-w&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
emit
+
+
VRML .wrl file as well as CGATS .gam file</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;-n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Don't
+
+
add VRML axes or white/black point</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;-k&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Add
+
+
markers for prim. &amp; sec. "cusp" points<br>
&nbsp;-f perc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Filter by
- popularity,
- perc = percent to use<br style="font-family: monospace;">
+ popularity, perc = percent to use<br style="font-family:
+ monospace;">
</span><span style="font-family: monospace;">&nbsp;-i
- intent&nbsp;&nbsp;&nbsp;&nbsp; p =
- perceptual, r = relative colorimetric,</span><br
- style="font-family: monospace;">
+ intent&nbsp;&nbsp;&nbsp;&nbsp; p = perceptual, r = relative
+ colorimetric,</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
s
+
+
= saturation, a = absolute (default), d = profile default</span></small><small><span
style="font-family: monospace;"></span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;-o
- order&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = normal
- (priority: lut &gt; matrix &gt; monochrome)</span><br
- style="font-family: monospace;">
+ order&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n = normal (priority: lut
+ &gt; matrix &gt; monochrome)</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
r
- = reverse (priority: monochrome &gt;
- matrix &gt; lut)<br>
+
+
+ = reverse (priority: monochrome &gt; matrix &gt; lut)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;</span><span
style="font-family: monospace;">-p oride</span><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; l
- =
- Lab_PCS (default), j = CIECAM02 Appearance Jab</span></small><br
+ = Lab_PCS (default), j = CIECAM02 Appearance Jab</span></small><br
style="font-family: monospace;">
<small><span style="font-family: monospace;"></span><span
style="font-family: monospace;">&nbsp;-c viewcond&nbsp;&nbsp;
- set
- appearance mode and viewing conditions for CIECAM02,</span><br
+ set appearance mode and viewing conditions for CIECAM02,</span><br
style="font-family: monospace;">
<span style="font-family: monospace;"></span><span
style="font-family: monospace;"></span></small><small><span
style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
either
+
+
an enumerated choice, or a parameter:value change</span><span
style="font-family: monospace;"></span><br style="font-family:
monospace;">
<span style="font-family: monospace;"></span></small><small><span
- style="font-family: monospace;">&nbsp;
- &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; pp - Practical Reflection
- Print
- (ISO-3664 P2)</span><br style="font-family: monospace;">
+ style="font-family: monospace;">&nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp; pp - Practical Reflection Print (ISO-3664 P2)</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
+
+
pe - Print evaluation environment (CIE 116-1995)<br>
</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
+
+
pc - Critical print evaluation environment (ISO-3664 P1)</span></small><small><span
style="font-family: monospace;"></span><span style="font-family:
monospace;"></span><br style="font-family: monospace;">
- <span style="font-family: monospace;">&nbsp;&nbsp; &nbsp;
- &nbsp; &nbsp; &nbsp; mt - Monitor in typical work environment</span><br
+ <span style="font-family: monospace;">&nbsp;&nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; mt - Monitor in typical work environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
&nbsp; mb - Monitor in bright work environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; md - Monitor in darkened work
+ &nbsp; &nbsp;&nbsp;&nbsp; md - Monitor in darkened work
environment</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; jm - Projector in dim environment</span><br
+ &nbsp; &nbsp;&nbsp;&nbsp; jm - Projector in dim environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; jd - Projector in dark environment</span><br
+ &nbsp; &nbsp;&nbsp;&nbsp; jd - Projector in dark environment</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp; &nbsp;&nbsp;
- &nbsp;&nbsp;&nbsp; pcd - Photo CD - original scene
- outdoors</span><br style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp; pcd - Photo CD - original scene outdoors</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; ob - Original scene - Bright Outdoors</span><br
+ &nbsp; &nbsp;&nbsp;&nbsp; ob - Original scene - Bright Outdoors</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
- &nbsp;
- &nbsp;&nbsp;&nbsp; cx - Cut Sheet Transparencies on a viewing
- box</span></small><br style="font-family: monospace;">
+ &nbsp; &nbsp;&nbsp;&nbsp; cx - Cut Sheet Transparencies on a
+ viewing box</span></small><br style="font-family: monospace;">
<small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
s:surround&nbsp;&nbsp;
+
+
n = auto, a = average, m = dim, d = dark,</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;
+
+
&nbsp; &nbsp;&nbsp; c = transparency (default average)</span><br
style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
w:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Adapted white point
- as XYZ (default media white)</span><br style="font-family:
- monospace;">
+
+
+ Adapted white point as XYZ (default media white)</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
w:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Adapted white point as
- x, y</span><br style="font-family: monospace;">
+
+
+ Adapted white point as x, y</span><br style="font-family:
+ monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
a:adaptation
- Adaptation luminance in
- cd.m^2
- (default 50.0)</span><br style="font-family: monospace;">
+
+
+ Adaptation luminance in cd.m^2 (default 50.0)</span><br
+ style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
b:background
+
+
Background % of image luminance (default 20)<br>
- &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; l:scenewhite Scene
- white in
- cd.m^2 if surround = auto (default 250)<br style="font-family:
- monospace;">
- </span><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; l:imagewhite Image
+ white in cd.m^2 if surround = auto (default 250)</span></small><br
+ style="font-family: monospace;">
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
f:flare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Flare
- light % of image luminance (default 1)</span><br
- style="font-family: monospace;">
+
+
+ Flare light % of image luminance (default 1)<br>
+ </span></small>&nbsp;</span><span style="font-family:
+ monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ g:glare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare light % of ambient
+ (default 1)</span><br style="font-family: monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
- &nbsp;&nbsp;
- f:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flare color as
- XYZ (default media white)</span><br style="font-family:
+ &nbsp;&nbsp; g:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color
+ as XYZ (default media white)</span><br style="font-family:
monospace;">
<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
- Flare color as x, y<br>
+
+ g:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color as
+ x, y<br>
&nbsp;-O outputfile Override the default output filename &amp;
extension.<br style="font-family: monospace;">
</span></small><br>
@@ -193,148 +206,116 @@ f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
The<b> -v</b> flag dumps out the ICC profile header information.<br>
<br>
The <b>-d</b> parameter controls the level of detail displayed in
- the
- surface. The parameter roughly corresponds to a deltaE value, so
- smaller
- values
- give greater detail. The default value is around 10, and is a good
- place
- to start. Small values may take a lot of time to generate, and will
- produce
- big files.<br>
+ the surface. The parameter roughly corresponds to a deltaE value, so
+ smaller values give greater detail. The default value is around 10,
+ and is a good place to start. Small values may take a lot of time to
+ generate, and will produce big files.<br>
<br>
The <b>-w</b> flag causes a VRML file to be produced, as well as a
gamut file.<br>
<br>
- The <b>-n</b> flag suppresses the L*a*b* axes being created in
- the
+ The <b>-n</b> flag suppresses the L*a*b* axes being created in the
VRML.<br>
<br>
The <span style="font-weight: bold;">-k</span> flag adds markers
- for
- each of the primary and secondary "cusp" points (Red, Yellow, Green,
- Cyan, Blue &amp; Magenta). No markers will be displayed if the cusps
- cannot be determined.<br>
+ for each of the primary and secondary "cusp" points (Red, Yellow,
+ Green, Cyan, Blue &amp; Magenta). No markers will be displayed if
+ the cusps cannot be determined.<br>
<br>
The <span style="font-weight: bold;">-f</span> <span
style="font-weight: bold;">perc</span> parameter turns on
- filtering of
- the raster colors. The colors from the image are clustered, and then
- sorted according to popularity, and then the <span
+ filtering of the raster colors. The colors from the image are
+ clustered, and then sorted according to popularity, and then the <span
style="font-weight: bold;">perc</span> most common percentage of
colors are used to create the gamut surface. This may be useful in
creating a source gamut mapping surface that favors the important
colors within an image, and doesn't attempt to compress the color
reproduction in order to reproduce the little used colors. A value
of <span style="font-weight: bold;">perc</span> of 90 or 80 may be
- a good place
- to start. Note that the filtering is performed independently on each
- raster image processed, with the final gamut being the union of all
- the
- filtered image gamuts.<br>
+ a good place to start. Note that the filtering is performed
+ independently on each raster image processed, with the final gamut
+ being the union of all the filtered image gamuts.<br>
<br>
The <b>-i</b> flag selects the intent transform used for a lut
- based
- profile. It also selects between relative and absolute colorimetric
- for
- non-lut base profiles. Note that anything other than colorimetric
- may
- not represent the
- native capabilities of the device. The default intent will be
- absolute
- colorimetic for L*a*b* output, and CIECAM02 appearance for Jab
- output.<br>
+ based profile. It also selects between relative and absolute
+ colorimetric for non-lut base profiles. Note that anything other
+ than colorimetric may not represent the native capabilities of the
+ device. The default intent will be absolute colorimetic for L*a*b*
+ output, and CIECAM02 appearance for Jab output.<br>
<br>
An ICC profile is allowed to contain more than the minimum number of
elements or table needed to describe a certain transform, and may
contain redundant descriptions. &nbsp;By default, LUT based table
information will be used first if present, followed by matrix/shaper
- information, and only using monochrome
- information if it is all that is present. The <b>-o</b> flag,
- reverses
- this
+ information, and only using monochrome information if it is all that
+ is present. The <b>-o</b> flag, reverses this
order.&nbsp;&nbsp;&nbsp; <br>
<br>
<span style="font-weight: bold;">-p</span>: By default the gamut
- will
- be created in L*a*b* colorspace. If&nbsp; <span style="font-weight:
- bold;">-pj</span> is selected, then CIECAM02
+ will be created in L*a*b* colorspace. If&nbsp; <span
+ style="font-weight: bold;">-pj</span> is selected, then CIECAM02
appearance space Jab will be used for the output, and the viewing
conditions will be taken into account. Jab space is what is normally
needed to be compatible with the default intents used in <a
href="colprof.html">colprof</a>. <span style="font-weight: bold;"><br>
</span>Note that the CIECAM02 output space selection by default uses
the colorimetric transform of the profile resulting in the
- appearance
- of the native device, but that the perceptual or
+ appearance of the native device, but that the perceptual or
saturation transforms may be used by selecting them using the <span
style="font-weight: bold;">-i</span> parameter, which may give a
different result with some profiles. This may be desirable if an
- image
- is to be transformed through the perceptual or saturation tables of
- a
- profile as part of a link with an Argyll generated output profile,
- since it will then represent the apparent gamut of the image when
- subject to these tables. If the absolute colorimetric intent is
- chosen
- using <span style="font-weight: bold;">-ia</span> in combinations
- with
- <span style="font-weight: bold;">-pj</span>, then&nbsp; Jab with
- a fixed white reference is used, which emulates an absolute CIECAM02
- Jab
- appearance space. <br>
+ image is to be transformed through the perceptual or saturation
+ tables of a profile as part of a link with an Argyll generated
+ output profile, since it will then represent the apparent gamut of
+ the image when subject to these tables. If the absolute colorimetric
+ intent is chosen using <span style="font-weight: bold;">-ia</span>
+ in combinations with <span style="font-weight: bold;">-pj</span>,
+ then&nbsp; Jab with a fixed white reference is used, which emulates
+ an absolute CIECAM02 Jab appearance space. <br>
<br>
The <span style="font-weight: bold;">-c</span> parameter sets the
output space to CIECAM02 appearance Jab values, and also allows
- choosing
- a set of viewing conditions, either by choosing a typical viewing
- environment, or controlling
- particular viewing condition parameters. This is only functional if
- an
- ICC profile is provided.<br>
+ choosing a set of viewing conditions, either by choosing a typical
+ viewing environment, or controlling particular viewing condition
+ parameters. This is only functional if an ICC profile is provided.<br>
<br>
The <span style="font-weight: bold;">-O</span> parameter allows the
output file name &amp; extension to be specified independently of
- the
- last tiff/jpeg
- filename. Note that the full filename must be specified, including
- the
- extension.<br>
+ the last tiff/jpeg filename. Note that the full filename must be
+ specified, including the extension.<br>
<br>
If the TIFF or JPEG files are in a device space (ie. RGB, CMYK
- etc.), then it
- is
- necessary to supply an ICC profile to translate the device space
- values
- to a CIE space value such as L*a*b* or CIECAM02 Jab space for
- creating
- a gamut surface. For the ICC profile provided it is then possible to
- select exactly what type of conversion is used. A TIFF or JPEGfile
- with an
- embedded ICC profile may be supplied as the profile argument - e.g.
- to
- get the gamut of a tiff file that contains an embedded profile use
- something like:<br>
+ etc.), then it is necessary to supply an ICC profile to translate
+ the device space values to a CIE space value such as L*a*b* or
+ CIECAM02 Jab space for creating a gamut surface. For the ICC profile
+ provided it is then possible to select exactly what type of
+ conversion is used. A TIFF or JPEGfile with an embedded ICC profile
+ may be supplied as the profile argument - e.g. to get the gamut of a
+ tiff file that contains an embedded profile use something like:<br>
<br>
&nbsp;&nbsp;&nbsp; tiffgamut image.tif image.tif<br>
<br>
- If a TIFF file is
- already in a CIE space such as CIELab or ICCLab, then it is not
- necessary to select an ICC profile,&nbsp; although a PCS to PCS
- colorspace profile may be chosen. All the TIFF and JPEG files
- must be in the same colorspace.<br>
+ To create a gamut suitable for CIECAM02&nbsp; gamut mapping space in
+ colprof or collink, something like<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; tiffgamut -ir -pj -cmt&nbsp; image.icm image.tif<br>
+ <br>
+ where the viewing conditions "mt" should the same as the source
+ conditions in colprof or collink.<br>
+ <br>
+ If a TIFF file is already in a CIE space such as CIELab or ICCLab,
+ then it is not necessary to select an ICC profile,&nbsp; although a
+ PCS to PCS colorspace profile may be chosen. All the TIFF and JPEG
+ files must be in the same colorspace.<br>
<br>
One or more TIFF and/or JPEG files may be specified, and the gamut
- is the union of
- the gamuts of each file. This is useful for creating an image
- specific
- gamut mapping that can be applied to a set of images with consistent
- results between the images. Note that the output gamut file name
- will
- by default be taken from the last TIFF or JPEG file specified, with
- the .gam
- extension added automatically. The <span style="font-weight: bold;">-O</span>
- parameter will override this default.<br>
+ is the union of the gamuts of each file. This is useful for creating
+ an image specific gamut mapping that can be applied to a set of
+ images with consistent results between the images. Note that the
+ output gamut file name will by default be taken from the last TIFF
+ or JPEG file specified, with the .gam extension added automatically.
+ The <span style="font-weight: bold;">-O</span> parameter will
+ override this default.<br>
<br>
<span style="font-weight: bold;">NOTES</span><br>
<br>
@@ -342,12 +323,9 @@ f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
and black points. For the purposes of latter gamut mapping, it is
assumed that the image should retain it's position within the
colorspace dynamic range. For an L*a*b* image, the values value
- 100,0,0
- and 0,0,0 for white and black are assumed. An image in L*a*b* should
- be
- adjusted be neutral to, and sit within the dynamic range of those
- white
- and black points.<br>
+ 100,0,0 and 0,0,0 for white and black are assumed. An image in
+ L*a*b* should be adjusted be neutral to, and sit within the dynamic
+ range of those white and black points.<br>
<br>
<br>
<span style="font-weight: bold;"></span><br>
diff --git a/doc/txt2ti3.html b/doc/txt2ti3.html
index 744a576..5d021fc 100644
--- a/doc/txt2ti3.html
+++ b/doc/txt2ti3.html
@@ -1,98 +1,112 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
-<head>
- <title>txt2ti3</title>
- <meta http-equiv="content-type"
- content="text/html; charset=ISO-8859-1">
- <meta name="author" content="Graeme Gill">
-</head>
-<body>
-<h2><b>profile/txt2ti3</b></h2>
-<h3>Summary</h3>
-<small><big>Convert
-Gretag/Logo/X-Rite or other CGATS format RGB or CMYK test chart results
-into</big></small> Argyll&nbsp;<a href="File_Formats.html#.ti3">.ti3</a>
-CGATS
-format.&nbsp;
-<h3>Usage Summary</h3>
-<small><span style="font-family: monospace;">txt2ti3 [-v] [-l limit]
-[-d] [devfile] infile [specfile] outfile</span><br
- style="font-family: monospace;">
-<br style="font-family: monospace;">
-<span style="font-family: monospace;">-2<span
- style="font-style: italic;"> &nbsp; &nbsp; &nbsp;</span>
-&nbsp;&nbsp;&nbsp;&nbsp; create a dummy .ti2 file as well.<br>
-</span></small><small><span style="font-family: monospace;">-l </span><i
- style="font-family: monospace;">limit</i><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set ink
-limit, 0
--
-400% (default max in file)<br>
--d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Set type of device as Display, not Output<br>
--i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Set type of device as Input, not Output<br
- style="font-family: monospace;">
-</span></small><small><span style="font-family: monospace;"></span><i
- style="font-family: monospace;">[devfile]</i><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; Input Device
-CMYK
-target file (typically file.txt)</span><br
- style="font-family: monospace;">
-<i style="font-family: monospace;">infile&nbsp;</i><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <head>
+ <title>txt2ti3</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=ISO-8859-1">
+ <meta name="author" content="Graeme Gill">
+ </head>
+ <body>
+ <h2><b>profile/txt2ti3</b></h2>
+ <h3>Summary</h3>
+ <small><big>Convert
+ Gretag/Logo/X-Rite or other CGATS format RGB or CMYK test chart
+ results
+ into</big></small> Argyll&nbsp;<a href="File_Formats.html#.ti3">.ti3</a>
+ CGATS
+ format.&nbsp;
+ <h3>Usage Summary</h3>
+ <small><span style="font-family: monospace;">txt2ti3 [-v] [-l limit]
+ [-d] [devfile] infile [specfile] outbase</span><br
+ style="font-family: monospace;">
+ <br style="font-family: monospace;">
+ <span style="font-family: monospace;">-2<span style="font-style:
+ italic;"> &nbsp; &nbsp; &nbsp;</span>
+ &nbsp;&nbsp;&nbsp;&nbsp; create a dummy .ti2 file as well.<br>
+ </span></small><small><span style="font-family: monospace;">-l </span><i
+ style="font-family: monospace;">limit</i><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ set ink
+ limit, 0
+ -
+ 400% (default max in file)<br>
+ -d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Set
+ type of device as Display, not Output<br>
+ -i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Set
+ type of device as Input, not Output<br style="font-family:
+ monospace;">
+ </span></small><small><span style="font-family: monospace;"></span><i
+ style="font-family: monospace;">[devfile]</i><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; Input
+ Device
+ CMYK
+ target file (typically file.txt)</span><br style="font-family:
+ monospace;">
+ <i style="font-family: monospace;">infile&nbsp;</i><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Input
-CIE, Spectral or Device &amp; Spectral file (typically file.txt)</span><br
- style="font-family: monospace;">
-<i style="font-family: monospace;">[specfile]</i><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp; Input Spectral
-file (typically file.txt)</span><br style="font-family: monospace;">
-<i style="font-family: monospace;">outbasefile</i><span
- style="font-family: monospace;">&nbsp;&nbsp; Base name for
-output</span><a style="font-family: monospace;"
- href="File_Formats.html#.ti3">.ti3</a><span
- style="font-family: monospace;"> and <a href="File_Formats.html#.ti2">.ti2</a>
-file</span></small>
-<br>
-<h3>Usage Details and Discussion</h3>
-txt2ti3 takes the Gretag/Logo/X-Rite/etc. test chart
-results, and converts them
-into Argyll&nbsp;<a href="File_Formats.html#.ti3">.ti3</a> CGATS files.<br>
-It is quite common to find profile test chart data from various
-standards bodies and industry organizations in one of these formats,
-so it is
-useful to be able to convert them for use with Argyll. ICC profiles
-created using Gretag Profile Maker also commonly contain the test chart
-results embedded in the profile, inside an ICC tag.<br>
-<br>
-A variety of different packaging of Gretag/Logo data can be accepted: <br>
-<br>
-1&nbsp;source files, consisting of a combined device value and CIE
-and/or spectral values.<br>
-2 source files, consisting of &nbsp;a file containing the device
-values, and a file containing the CIE and/or spectral values.<br>
-2 source files, consisting of a file containing the device values and
-the CIE values, and a file containing the spectral values.<br>
-3 source files, consisting of a file containing the device values, a
-file containing the CIE values, and a file containing the spectral
-values.<br>
-<br>
-X-Rite ColorPort seems to produce a single source file containing
-combined device value and CIE
-and/or spectral values.<br>
-<br>
-The Gretag/Logo test chart results format seem to change with each
-minor release of Profile Maker, so this tool may not work in all
-cases.<br>
-<br>
-The <span style="font-style: italic;">outbasefile</span> is the base
-of the output file(s), to which txt2ti3 will automatically append a
-.ti3 and .ti2 extension.<br>
-<br>
-The input files may have data that is scaled to one of three levels:
-1.0, 100.0 or 255.0, and txt2ti3 attempts to guess what the appropriate
-range is, in order to scale to Argyll's standard range 0 .. 100.0.<br>
-<br>
-<br>
-</body>
+CIE,
+ Spectral or Device &amp; Spectral file (typically file.txt)</span><br
+ style="font-family: monospace;">
+ <i style="font-family: monospace;">[specfile]</i><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp; Input
+ Spectral
+ file (typically file.txt)</span><br style="font-family:
+ monospace;">
+ <i style="font-family: monospace;">outbasefile</i><span
+ style="font-family: monospace;">&nbsp;&nbsp; Base name for
+ output</span><a style="font-family: monospace;"
+ href="File_Formats.html#.ti3">.ti3</a><span style="font-family:
+ monospace;"> and <a href="File_Formats.html#.ti2">.ti2</a>
+ file</span></small>
+ <br>
+ <h3>Usage Details and Discussion</h3>
+ txt2ti3 takes the Gretag/Logo/X-Rite/etc. test chart
+ results, and converts them
+ into Argyll&nbsp;<a href="File_Formats.html#.ti3">.ti3</a> CGATS
+ files.<br>
+ It is quite common to find profile test chart data from various
+ standards bodies and industry organizations in one of these formats,
+ so it is
+ useful to be able to convert them for use with Argyll. ICC profiles
+ created using Gretag Profile Maker also commonly contain the test
+ chart
+ results embedded in the profile, inside an ICC tag.<br>
+ <br>
+ A variety of different packaging of Gretag/Logo data can be
+ accepted: <br>
+ <br>
+ 1&nbsp;source files, consisting of a combined device value and CIE
+ and/or spectral values.<br>
+ 2 source files, consisting of &nbsp;a file containing the device
+ values, and a file containing the CIE and/or spectral values.<br>
+ 2 source files, consisting of a file containing the device values
+ and
+ the CIE values, and a file containing the spectral values.<br>
+ 3 source files, consisting of a file containing the device values, a
+ file containing the CIE values, and a file containing the spectral
+ values.<br>
+ <br>
+ X-Rite ColorPort seems to produce a single source file containing
+ combined device value and CIE
+ and/or spectral values.<br>
+ <br>
+ The Gretag/Logo test chart results format seem to change with each
+ minor release of Profile Maker, so this tool may not work in all
+ cases.<br>
+ <br>
+ The <span style="font-style: italic;">outbasefile</span> is the
+ base
+ of the output file(s), to which txt2ti3 will automatically append a
+ .ti3 and .ti2 extension.<br>
+ <br>
+ The input files may have data that is scaled to one of three levels:
+ 1.0, 100.0 or 255.0, and txt2ti3 attempts to guess what the
+ appropriate
+ range is, in order to scale to Argyll's standard range 0 .. 100.0.<br>
+ <br>
+ <br>
+ </body>
</html>
diff --git a/doc/xicclu.html b/doc/xicclu.html
index 8377c69..cf572fe 100644
--- a/doc/xicclu.html
+++ b/doc/xicclu.html
@@ -1,551 +1,838 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
-<head>
- <title>xicclu</title>
- <meta http-equiv="content-type"
- content="text/html; charset=ISO-8859-1">
- <meta name="author" content="Graeme Gill">
-</head>
-<body>
-<h2><b>xicc/xicclu</b>&nbsp; </h2>
-<h3>Summary&nbsp;<br>
-</h3>
-Lookup individual color values forward or inverted though an ICC
-profile table. <b>xicclu</b> is the analogue of the icclib tool <a
- href="icclu.html">icclu</a>, but expands the capability to reverse
-lookup the Lut tables, and displaying PCS values in CIECAM02 Jab space.
-<b>xicclu</b>
-can also be used to plot the device value composition down the neutral
-axis,
-for device profiles.<br>
-<h3>Usage Summary</h3>
-&nbsp;<small><span style="font-family: monospace;">xicclu [-</span><i
- style="font-family: monospace;">options</i><span
- style="font-family: monospace;">] profile</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#v">-v level</a><span
- style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Verbosity level 0 - 2 (default = 1)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#g">-g</a><span
- style="font-family: monospace;"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
-&nbsp; Plot slice instead of looking colors up. (Default white to black)<br>
-&nbsp;<a href="#Gs">-G s:L:a:b</a>&nbsp;&nbsp;&nbsp;&nbsp; Override
-plot slice start with Lab or Jab co-ordinate<br>
-&nbsp;<a href="#Ge">-G e:L:a:b</a>&nbsp;&nbsp;&nbsp;&nbsp; Override
-plot slice end with Lab or Jab co-ordinate<br
- style="font-family: monospace;">
-</span><span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#f">-f function</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp; f = forward, b =
-backwards, g = gamut, p = preview</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ <head>
+ <title>xicclu</title>
+ <meta http-equiv="content-type" content="text/html;
+ charset=ISO-8859-1">
+ <meta name="author" content="Graeme Gill">
+ </head>
+ <body>
+ <h2><b>xicc/xicclu</b>&nbsp; </h2>
+ <h3>Summary&nbsp;<br>
+ </h3>
+ Lookup individual color values forward or inverted though an ICC
+ profile table or CAL file. <b>xicclu</b> is the analogue of the
+ icclib tool <a href="icclu.html">icclu</a>, but expands the
+ capability to reverse lookup the Lut tables, and displaying PCS
+ values in CIECAM02 Jab space. <b>xicclu</b> can also be used to
+ plot the device value composition down the neutral axis for device
+ profiles, or CAL file contents.<br>
+ <br>
+ Few of the options that apply to ICC profiles apply to CAL files,
+ although device value options such as <b>-e</b> or <b>-E</b> will
+ work. To lookup inverted CAL values, use <b>-f b</b>.<br>
+ <h3>Usage Summary</h3>
+ &nbsp;<small><span style="font-family: monospace;">xicclu [-</span><i
+ style="font-family: monospace;">options</i><span
+ style="font-family: monospace;">] profile_or_cal</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#v">-v level</a><span
+ style="font-family: monospace;"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Verbosity level 0 - 2 (default = 1)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#g">-g</a><span
+ style="font-family: monospace;"> &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; Plot slice instead of looking colors up. (Default
+ white to black)<br>
+ &nbsp;<a href="#Gs">-G s:L:a:b</a>&nbsp;&nbsp;&nbsp;&nbsp;
+ Override plot slice start with Lab or Jab co-ordinate<br>
+ &nbsp;<a href="#Ge">-G e:L:a:b</a>&nbsp;&nbsp;&nbsp;&nbsp;
+ Override plot slice end with Lab or Jab co-ordinate<br
+ style="font-family: monospace;">
+ </span><span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#f">-f function</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp; f = forward,
+ b = backwards, g = gamut, p = preview</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if
-= inverted forward, ib = inverted backwards</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#i">-i intent</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a =
-absolute, r = relative colorimetric,</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-</span></small><small><span style="font-family: monospace;"> p =
-perceptual, </span></small><small><span style="font-family: monospace;">s
=
-saturation</span><span style="font-family: monospace;"></span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#o">-o order</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; n
-= normal (priority: lut &gt; matrix &gt; monochrome)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+ inverted forward, ib = inverted backwards</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#i">-i intent</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a
+ = absolute, r = relative colorimetric,</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+ </span></small><small><span style="font-family: monospace;"> p =
+ perceptual, </span></small><small><span style="font-family:
+ monospace;">s = saturation</span><span style="font-family:
+ monospace;"></span><br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#o">-o order</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+ n = normal (priority: lut &gt; matrix &gt; monochrome)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
r
-= reverse (priority: monochrome &gt; matrix &gt;
-lut)</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#p">-p oride</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x
-= XYZ_PCS, X = XYZ * 100, l = Lab_PCS, L = LCh, y = Yxy,<br>
-&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = CIECAM02
-Appearance Jab, J = CIECAM02 Appearance JCh<br>
-</span><span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#s">-s scale</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Scale device range 0.0 - scale rather than 0.0 - 1.0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#k">-k [zhxrlv]</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp; Black generation: z
-= zero K,</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+=
+
+
+
+
+
+ reverse (priority: monochrome &gt; matrix &gt; lut)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#p">-p oride</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+ x = XYZ_PCS, X = XYZ * 100, l = Lab_PCS, L = LCh, y = Yxy,<br>
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j =
+ CIECAM02 Appearance Jab, J = CIECAM02 Appearance JCh<br>
+ </span><span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#s">-s scale</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Scale
+
+
+
+
+
+ device range 0.0 - scale rather than 0.0 - 1.0<br>
+ </span></small><br>
+ &nbsp; <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;"><a href="#e">-e flag</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+ Video encode device input as:<br>
+ &nbsp;<a href="#E">-E flag</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+ Video decode device output as:<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ normal 0..1 full range RGB levels (default)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ (16-235)/255 "TV" RGB levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec601 YCbCr SD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec709 1125/60Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec709 1250/50Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec2020 YCbCr UHD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 "TV"
+ lev</span></small></span></small><small><span
+ style="font-family: monospace;"><br style="font-family:
+ monospace;">
+ </span> <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#k">-k [zhxrlv]</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp; Black
+ generation: z = zero K,</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-h = 0.5 K, x = max K, r = ramp K (def.)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+h
+
+
+
+
+
+ = 0.5 K, x = max K, r = ramp K (def.)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-l = extra PCS input is portion of K locus</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+l
+
+
+
+
+
+ = extra PCS input is portion of K locus</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-v = extra PCS input is K target value</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#kp">-k p stle stpo enpo enle
-shape</a><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+v
+
+
+
+
+
+ = extra PCS input is K target value</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#kp">-k p stle stpo enpo
+ enle shape</a><br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-stle: K level at White 0.0 - 1.0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+stle:
+
+
+
+
+
+ K level at White 0.0 - 1.0</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-stpo: start point of transition Wh 0.0 - Bk 1.0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+stpo:
+
+
+
+
+
+ start point of transition Wh 0.0 - Bk 1.0</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-enpo: End point of transition Wh 0.0 - Bk 1.0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+enpo:
+
+
+
+
+
+ End point of transition Wh 0.0 - Bk 1.0</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-enle: K level at Black 0.0 - 1.0</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+enle:
+
+
+
+
+
+ K level at Black 0.0 - 1.0</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-shape: 1.0 = straight, 0.0-1.0 concave, 1.0-2.0
-convex</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#kq">-k q stle0 stpo0 enpo0
-enle0 shape0 stle2 stpo2
-enpo2 enle2 shape2</a><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+shape:
+
+
+
+
+
+ 1.0 = straight, 0.0-1.0 concave, 1.0-2.0 convex</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#kq">-k q stle0 stpo0
+ enpo0 enle0 shape0 stle2 stpo2 enpo2 enle2 shape2</a><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Transfer
-extra PCS input to dual curve limits</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#K">-K parameters</a><span
- style="font-family: monospace;">&nbsp; Same as -k, but target is K
-locus rather than K value itself</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#l">-l tlimit</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set
-total ink limit, 0 - 400% (estimate by default)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#L">-L klimit</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set
-black ink limit, 0 - 100% (estimate by default)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#a">-a</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+extra
+
+
+
+
+
+ PCS input to dual curve limits</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#K">-K parameters</a><span
+ style="font-family: monospace;">&nbsp; Same as -k, but target is
+ K locus rather than K value itself</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#l">-l tlimit</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ set total ink limit, 0 - 400% (estimate by default)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#L">-L klimit</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ set black ink limit, 0 - 100% (estimate by default)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#a">-a</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
show
-actual target values if clipped<br>
-&nbsp;<a href="#b">-b</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+actual
+
+
+
+
+
+ target values if clipped<br>
+ &nbsp;<a href="#b">-b</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
use
-CAM Jab for clipping<br style="font-family: monospace;">
-</span><span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#m">-m</a><span
- style="font-family: monospace;">
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-merge output processing into clut</span><span
- style="font-family: monospace;"></span><span
- style="font-weight: bold; font-family: monospace;"></span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;</span><a
- style="font-family: monospace;" href="#c">-c viewcond</a><span
- style="font-family: monospace;">&nbsp;&nbsp;&nbsp; set viewing
-conditions
-for CIECAM02,</span><br style="font-family: monospace;">
-&nbsp;&nbsp;</small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+CAM
+
+
+
+
+
+ Jab for clipping<br style="font-family: monospace;">
+ </span><span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#m">-m</a><span
+ style="font-family: monospace;">
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ merge output processing into clut</span><span
+ style="font-family: monospace;"></span><span style="font-weight:
+ bold; font-family: monospace;"></span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;</span><a
+ style="font-family: monospace;" href="#c">-c viewcond</a><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp; set viewing
+ conditions for CIECAM02,</span><br style="font-family:
+ monospace;">
+ &nbsp;&nbsp;</small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-either an enumerated choice, or a parameter:value change</span><span
- style="font-family: monospace;"></span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;"></span></small><small><span
- style="font-family: monospace;">&nbsp;
-&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; pp - Practical Reflection Print
-(ISO-3664 P2)</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+either
+
+
+
+
+
+ an enumerated choice, or a parameter:value change</span><span
+ style="font-family: monospace;"></span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;"></span></small><small><span
+ style="font-family: monospace;">&nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp;&nbsp; pp - Practical Reflection Print (ISO-3664 P2)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-pe - Print evaluation environment (CIE 116-1995)<br>
-</span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+pe
+
+
+
+
+
+ - Print evaluation environment (CIE 116-1995)<br>
+ </span></small><small><span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;
-pc - Critical print evaluation environment (ISO-3664 P1)</span></small><small><span
- style="font-family: monospace;"></span><span
- style="font-family: monospace;"></span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp; &nbsp; &nbsp; mt - Monitor in typical work environment</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+pc
+
+
+
+
+
+ - Critical print evaluation environment (ISO-3664 P1)</span></small><small><span
+ style="font-family: monospace;"></span><span style="font-family:
+ monospace;"></span><br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp; &nbsp; &nbsp; mt - Monitor in typical work environment</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;
&nbsp;
-&nbsp; mb - Monitor in bright work environment</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp; md - Monitor in darkened work
-environment</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp; jm - Projector in dim environment</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp; jd - Projector in dark environment</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp; pcd - Photo CD - original scene
-outdoors</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp; ob - Original scene - Bright Outdoors</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp; cx - Cut Sheet Transparencies on a viewing box</span></small><small><span
- style="font-family: monospace;"></span><span
- style="font-family: monospace;"></span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+ mb - Monitor in bright work environment</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;&nbsp; md - Monitor in darkened work
+ environment</span><br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;&nbsp; jm - Projector in dim environment</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;&nbsp; jd - Projector in dark environment</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp; pcd - Photo CD - original scene outdoors</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;&nbsp; ob - Original scene - Bright Outdoors</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ &nbsp; &nbsp;&nbsp;&nbsp; cx - Cut Sheet Transparencies on a
+ viewing box</span></small><small><span style="font-family:
+ monospace;"></span><span style="font-family: monospace;"></span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
s:surround&nbsp;&nbsp;
-n = auto, a = average, m = dim, d = dark,</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+n
+
+
+
+
+
+ = auto, a = average, m = dim, d = dark,</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;
&nbsp;
-&nbsp; &nbsp;&nbsp;&nbsp; c = transparency (default average)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+
+ &nbsp;&nbsp;&nbsp; c = transparency (default average)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
w:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Adapted white point
-as XYZ (default media white, Abs: D50)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Adapted
+
+
+
+
+
+ white point as XYZ (default media white, Abs: D50)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
w:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Adapted white point as
-x, y</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Adapted
+
+
+
+
+
+ white point as x, y</span><br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
a:adaptation
-Adaptation luminance in
-cd.m^2
-(default 50.0)</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b:background Background %
-of image luminance (default 20)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+Adaptation
+
+
+
+
+
+ luminance in cd.m^2 (default 50.0)</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b:background Background % of
+ image luminance (default 20)</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;"></span></small><small><span
+ style="font-family: monospace;"><small><span style="font-family:
+ monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
f:flare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Flare
-light % of image luminance (default 1)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;
-&nbsp;
-f:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Flare color
-as XYZ (default media white, Abs: D50)</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-f:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Flare color as x, y</span><br style="font-family: monospace;">
-<br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;
-</span><a style="font-family: monospace;" href="#p1"><i>inoutfile</i></a><span
- style="font-family: monospace;"> &nbsp;&nbsp; &nbsp;&nbsp; The input
-ICC profile</span><br style="font-family: monospace;">
-<br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; The colors to
-be translated should be fed into
-standard in,</span><br style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; one input
-color per line, white space separated.</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; A line
-starting with a # will be ignored.</span><br
- style="font-family: monospace;">
-<span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; A line not
-starting with a number will terminate the
-program.</span></small>
-<br>
-<h3>Flags and Parameters</h3>
-<a name="v"></a> The <b>-v</b> parameter sets the level of verbosity.
-Default is level 1, which repeats each input value, the colorspaces of
-input and output, the type of conversion algorithm used, and if the
-result was clipped. Level 2 adds prints extra information about the
-profile before doing the conversions. Level 0 turns off all verbosity,
-just outputting the results of each conversion. Use the latter to
-capture batch output ready for further processing.<br>
-<br>
-<a name="g"></a>The <b>-g</b> flag causes a plot of the device values
-along a slice through the Lab or Jab colorspace, rather than allowing
-the interactive looking up of color
-values. By default this will be the neutral axis
-from the white point to the black point, but the start and end can be
-overridden using the <span style="font-weight: bold;">-G</span>
-parameters.
-This is useful in determining the existing black generation in a CMYK
-profile,
-or exploring the behavior of various black generation options using
-the
-<b>-k</b> parameters. The profile must be a device profile, and the PCS
-must
-be either Lab or Jab. The default plot is up the neutral axis is from
-the white to
-the black point (scale 0 to 100%), and shows the percentage of each
-device colorant. To examine a profiles B2A table black
-generation,
-use the flag <b>-fb</b> to select the B2A table, or to invert the A2B
-table,
-and be able to explore black generation behavior, use the <b>-fif</b>
-flag.
-The appropriate intent can be selected with the <b>-i</b> flag,
-&nbsp;as
-can other flags appropriate to the function selected.&nbsp; See <a
- href="#xg">example</a>.<br>
-<br>
-<a name="Gs"></a>The <span style="font-weight: bold;">-G </span><small><span
- style="font-family: monospace;"><span style="font-weight: bold;">s:L:a:b</span></span></small>
-parameter overrides the plot slice start point of white, with some
-other point specified in Lab or Jab Profile Connection Space. The
-parameter must be a single string that combines<span
- style="font-weight: bold;"> s:</span> with the three numbers separated
-by the '<span style="font-weight: bold;">:'</span> character (no
-spaces).<br>
-<br>
-<a name="Ge"></a>The <span style="font-weight: bold;">-G </span><small><span
- style="font-family: monospace;"><span style="font-weight: bold;">e:L:a:b</span></span></small>
-parameter overrides the plot slice end point of black, with some
-other point specified in Lab or Jab Profile Connection Space. The
-parameter must be a single string that combines<span
- style="font-weight: bold;"> s:</span> with the three numbers separated
-by the '<span style="font-weight: bold;">:'</span> character (no
-spaces).<br>
-<br>
-<a name="f"></a> The <b>-f</b> flag selects which type of table or
-conversion is to be used. In addition to the usual four tables that can
-be accessed in a fully populated Lut based profile, two additional
-options are available in <b>xicclu</b>. One is to invert the forward
-table, and the other is to invert the backward table. For non Lut based
-profiles, -fif is equivalent to -fb, and -fib is equivalent to -ff.
-Note that the -fib combination may not be fully supported.<br>
-<br>
-<a name="i"></a> The <b>-i</b> flag selects the intent table used for
-a lut based
-profile. It also selects between relative and absolute colorimetric for
-non-lut base profiles.<br>
-<br>
-<a name="o"></a> A profile is allowed to contain more than the minimum
-number of elements or table needed to describe a certain transform, and
-may contain redundant descriptions. &nbsp;By default, Lut based table
-information will be used first if present, followed by matrix/shaper
-information, and only using monochrome information if it is all that is
-present. The <b>-o</b> flag, reverses this order.&nbsp;&nbsp;&nbsp; <br>
-<br>
-<a name="p"></a> Normally the native PCS (Profile Connection Space) of
-a device or abstract profile is used, but the <b>-p</b> flag allows
-this to be overridden: <span style="font-weight: bold;">-px</span>:
-XYZ (scaled to 1.0), <span style="font-weight: bold;">-pX</span>: XYZ
-scaled to 100, <span style="font-weight: bold;">-pl</span>: L*a*b*, <span
- style="font-weight: bold;">-pL</span>: LCh, <span
- style="font-weight: bold;">-py</span>: Yxy space, <span
- style="font-weight: bold;">-pj</span>: CIECAM02 appearance space Jab,
-or <span style="font-weight: bold;">-pJ</span>: CIECAM02 appearance
-space JCh.<span style="font-weight: bold;"><br>
-</span>Note that the CIECAM02 output space selection by default uses
-the colorimetric table of the profile, but that the perceptual or
-saturation tables may be used by selecting them using the <span
- style="font-weight: bold;">-i</span> parameter. If the absolute
-colorimetric intent is chosen using <span style="font-weight: bold;">-ia</span>
-in combinations with <span style="font-weight: bold;">-pj</span>,
-then&nbsp; Jab with
-a fixed white reference is used, which emulates an absolute CIECAM02
-Jab
-appearance space. <br>
-<br>
-<a name="s"></a> Usually device values are processed and displayed
-using a normalized value range between 0.0 and 1.0 Sometimes other
-systems scale them to some other range (such as 100 or 255) due to an
-underlying binary representation. The <span style="font-weight: bold;">-s</span>
-flag lets you input and display such data in its normal range. For
-instance, if your device values have a range between 0 and 255, use <span
- style="font-weight: bold;">-s 255.</span><br>
-<br>
-<a name="k"></a> When inverting a CMYK profile, (ie. using the -fif
-flag), an input PCS value can have many possible CMYK solutions. To be
-able to return a unique solution, a black level (or black inking rule)
-should be chosen. The choice here reflect similar choices in black
-generation available in other tools (eg. <a href="colprof.html">colprof</a>,
-<a href="collink.html"> collink</a>), with the addition of two extra
-options.<br>
-<br>
-&nbsp;Possible arguments to the <b>-k</b> option are:<br>
-<br>
-<b> -kz</b> selects minimum black (0.0)<br>
-<b> -kh</b> selects a black value of 0.5<br>
-<b> -kx</b> selects the maximum possible black (1.0)<br>
-<b> -kr</b> selects a linear black ramp, starting at minimum black for
-highlight, and maximum black for shadow (equivalent to -kp 0 0 1 1 1).
-This is the default.<br>
-<b> -kl</b> uses an extra (fourth) value entered after the input PCS
-value, to select a black locus target between 0.0 and 1.0.<br>
-<b> -kv</b> uses an extra (fourth) value entered after the input PCS
-value, to select a black value target value between 0.0 and 1.0.<br>
-<br>
-<b><a name="kp"></a>-k p stle stpo enpo enle shape</b>&nbsp; allows an
-arbitrary black value ramp to be defined, consisting of a starting
-value (stle) for highlights, a breakpoint L value (stpo) where it
-starts to transition to the shadow level, an end breakpoint L (enpo)
-where it flattens out again, and the finishing black level (enle) for
-the shadows. There is also a curve parameter, that modifies the
-transition from stle to enle to either be concave (ie.&nbsp; the
-transition starts gradually and and finished more abruptly) using
-values 0.0-1.0, with 0.0 being most concave, or convex (the transition
-starts more abruptly but finishes gradually), using values 1.0-2.0,
-with 2.0 being the most convex.<br>
-<br>
-Typical black value generation curve with parameters something
-like: -kp 0 .05 1 .9 .8<br>
-<br>
-<tt> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0 K &nbsp; |
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;enpo<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+light
+
+
+
+
+
+ % of image luminance (default 1)<br>
+ </span></small>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ g:glare&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare light % of ambient
+ (default 1)</span><br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; &nbsp;
+ &nbsp; &nbsp; g:X:Y:Z&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Glare color
+ as XYZ (default media white, Abs: D50)</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ g:x:y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FGare color as
+ x, y</span><br style="font-family: monospace;">
+ <br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp; </span><a
+ style="font-family: monospace;" href="#p1"><i>inoutfile</i></a><span
+ style="font-family: monospace;"> &nbsp;&nbsp; &nbsp;&nbsp; The
+ input ICC profile or CAL file.</span><br style="font-family:
+ monospace;">
+ <br style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; The
+ colors to be translated should be fed into standard in,</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; one input
+ color per line, white space separated.</span><br
+ style="font-family: monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; A line
+ starting with a # will be ignored.</span><br style="font-family:
+ monospace;">
+ <span style="font-family: monospace;">&nbsp;&nbsp;&nbsp; A line
+ not starting with a number will terminate the program.</span></small>
+ <br>
+ <h3>Flags and Parameters</h3>
+ <a name="v"></a> The <b>-v</b> parameter sets the level of
+ verbosity. Default is level 1, which repeats each input value, the
+ colorspaces of input and output, the type of conversion algorithm
+ used, and if the result was clipped. Level 2 adds prints extra
+ information about the profile before doing the conversions. Level 0
+ turns off all verbosity, just outputting the results of each
+ conversion. Use the latter to capture batch output ready for further
+ processing.<br>
+ <br>
+ <a name="g"></a>The <b>-g</b> flag causes a plot of the device
+ values along a slice through the Lab or Jab colorspace, rather than
+ allowing the interactive looking up of color values. By default this
+ will be the neutral axis from the white point to the black point,
+ but the start and end can be overridden using the <span
+ style="font-weight: bold;">-G</span> parameters. This is useful in
+ determining the existing black generation in a CMYK profile, or
+ exploring the behavior of various black generation options using the
+ <b>-k</b> parameters. The profile must be a device profile, and the
+ PCS must be either Lab or Jab. The default plot is up the neutral
+ axis is from the white to the black point (scale 0 to 100%), and
+ shows the percentage of each device colorant. To examine a profiles
+ B2A table black generation, use the flag <b>-fb</b> to select the
+ B2A table, or to invert the A2B table, and be able to explore black
+ generation behavior, use the <b>-fif</b> flag. The appropriate
+ intent can be selected with the <b>-i</b> flag, &nbsp;as can other
+ flags appropriate to the function selected.&nbsp; See <a href="#xg">example</a>.<br>
+ <br>
+ If a CAL file is used, then <b>-g</b> will simply plot the each
+ channels calibration curve. It will also plot the invers curve for <b>-f
+
+ b</b>.<br>
+ <br>
+ <a name="Gs"></a>The <span style="font-weight: bold;">-G </span><small><span
+ style="font-family: monospace;"><span style="font-weight: bold;">s:L:a:b</span></span></small>
+ parameter overrides the plot slice start point of white, with some
+ other point specified in Lab or Jab Profile Connection Space. The
+ parameter must be a single string that combines<span
+ style="font-weight: bold;"> s:</span> with the three numbers
+ separated by the '<span style="font-weight: bold;">:'</span>
+ character (no spaces).<br>
+ <br>
+ <a name="Ge"></a>The <span style="font-weight: bold;">-G </span><small><span
+ style="font-family: monospace;"><span style="font-weight: bold;">e:L:a:b</span></span></small>
+ parameter overrides the plot slice end point of black, with some
+ other point specified in Lab or Jab Profile Connection Space. The
+ parameter must be a single string that combines<span
+ style="font-weight: bold;"> s:</span> with the three numbers
+ separated by the '<span style="font-weight: bold;">:'</span>
+ character (no spaces).<br>
+ <br>
+ <a name="f"></a> The <b>-f</b> flag selects which type of table or
+ conversion is to be used. In addition to the usual four tables that
+ can be accessed in a fully populated Lut based profile, two
+ additional options are available in <b>xicclu</b>. One is to invert
+ the forward table, and the other is to invert the backward table.
+ For non Lut based profiles, -fif is equivalent to -fb, and -fib is
+ equivalent to -ff. Note that the -fib combination may not be fully
+ supported.<br>
+ <br>
+ <a name="i"></a> The <b>-i</b> flag selects the intent table used
+ for a lut based profile. It also selects between relative and
+ absolute colorimetric for non-lut base profiles.<br>
+ <br>
+ <a name="o"></a> A profile is allowed to contain more than the
+ minimum number of elements or table needed to describe a certain
+ transform, and may contain redundant descriptions. &nbsp;By default,
+ Lut based table information will be used first if present, followed
+ by matrix/shaper information, and only using monochrome information
+ if it is all that is present. The <b>-o</b> flag, reverses this
+ order.&nbsp;&nbsp;&nbsp; <br>
+ <br>
+ <a name="p"></a> Normally the native PCS (Profile Connection Space)
+ of a device or abstract profile is used, but the <b>-p</b> flag
+ allows this to be overridden: <span style="font-weight: bold;">-px</span>:
+ XYZ (scaled to 1.0), <span style="font-weight: bold;">-pX</span>:
+ XYZ scaled to 100, <span style="font-weight: bold;">-pl</span>:
+ L*a*b*, <span style="font-weight: bold;">-pL</span>: LCh, <span
+ style="font-weight: bold;">-py</span>: Yxy space, <span
+ style="font-weight: bold;">-pj</span>: CIECAM02 appearance space
+ Jab, or <span style="font-weight: bold;">-pJ</span>: CIECAM02
+ appearance space JCh.<span style="font-weight: bold;"><br>
+ </span>Note that the CIECAM02 output space selection by default uses
+ the colorimetric table of the profile, but that the perceptual or
+ saturation tables may be used by selecting them using the <span
+ style="font-weight: bold;">-i</span> parameter. If the absolute
+ colorimetric intent is chosen using <span style="font-weight:
+ bold;">-ia</span> in combinations with <span style="font-weight:
+ bold;">-pj</span>, then&nbsp; Jab with a fixed white reference is
+ used, which emulates an absolute CIECAM02 Jab appearance space. <br>
+ <br>
+ <a name="s"></a> Usually device values are processed and displayed
+ using a normalized value range between 0.0 and 1.0 Sometimes other
+ systems scale them to some other range (such as 100 or 255) due to
+ an underlying binary representation. The <span style="font-weight:
+ bold;">-s</span> flag lets you input and display such data in its
+ normal range. For instance, if your device values have a range
+ between 0 and 255, use <span style="font-weight: bold;">-s 255.</span><br>
+ <br>
+ <a name="e"></a>The <b>-e</b> <i>flag</i> applies a Video encoding
+ to the input. See <a
+ href="collink.html#E"><b>-E</b></a> for
+ the list of encodings.<br>
+ <br>
+ <b><a name="E"></a></b>The <b>-E</b> <i>flag</i> applies a Video
+ encoding to the output. The possible encoding are:<br>
+ <br>
+ <small><span style="font-family: monospace;"><small><span
+ style="font-family: monospace;">&nbsp;&nbsp;&nbsp;&nbsp;
+ n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ normal RGB 0..1 full range levels (default)<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ RGB (16-235)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Rec601 YCbCr SD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Rec709 1125/60Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Rec709 1250/50Hz YCbCr HD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ 2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Rec2020 YCbCr UHD (16-235,240)/255 "TV" levels<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;
+ C&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+
+
+
+
+ Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 "TV"
+ levels<br>
+ </span></small></span></small><br>
+ <a name="k"></a> When inverting a CMYK profile, (ie. using the -fif
+ flag), an input PCS value can have many possible CMYK solutions. To
+ be able to return a unique solution, a black level (or black inking
+ rule) should be chosen. The choice here reflect similar choices in
+ black generation available in other tools (eg. <a
+ href="colprof.html">colprof</a>, <a href="collink.html"> collink</a>),
+
+
+
+
+ with the addition of two extra options.<br>
+ <br>
+ &nbsp;Possible arguments to the <b>-k</b> option are:<br>
+ <br>
+ <b> -kz</b> selects minimum black (0.0)<br>
+ <b> -kh</b> selects a black value of 0.5<br>
+ <b> -kx</b> selects the maximum possible black (1.0)<br>
+ <b> -kr</b> selects a linear black ramp, starting at minimum black
+ for highlight, and maximum black for shadow (equivalent to -kp 0 0 1
+ 1 1). This is the default.<br>
+ <b> -kl</b> uses an extra (fourth) value entered after the input PCS
+ value, to select a black locus target between 0.0 and 1.0.<br>
+ <b> -kv</b> uses an extra (fourth) value entered after the input PCS
+ value, to select a black value target value between 0.0 and 1.0.<br>
+ <br>
+ <b><a name="kp"></a>-k p stle stpo enpo enle shape</b>&nbsp; allows
+ an arbitrary black value ramp to be defined, consisting of a
+ starting value (stle) for highlights, a breakpoint L value (stpo)
+ where it starts to transition to the shadow level, an end breakpoint
+ L (enpo) where it flattens out again, and the finishing black level
+ (enle) for the shadows. There is also a curve parameter, that
+ modifies the transition from stle to enle to either be concave
+ (ie.&nbsp; the transition starts gradually and and finished more
+ abruptly) using values 0.0-1.0, with 0.0 being most concave, or
+ convex (the transition starts more abruptly but finishes gradually),
+ using values 1.0-2.0, with 2.0 being the most convex.<br>
+ <br>
+ Typical black value generation curve with parameters something like:
+ -kp 0 .05 1 .9 .8<br>
+ <br>
+ <tt> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0 K &nbsp; |
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;enpo<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;&nbsp; &nbsp; &nbsp;_______&nbsp;
-enle<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;
+
+
+
+
+
+ &nbsp; &nbsp;_______&nbsp; enle<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp; &nbsp; &nbsp;/<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;
+
+
+
+
+
+ &nbsp; &nbsp;/<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp;&nbsp; &nbsp; /<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;&nbsp;
+
+
+
+
+
+ &nbsp; /<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp; &nbsp;/<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;
+
+
+
+
+
+ &nbsp;/<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-&nbsp; /<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stle&nbsp;
-| ------/<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
-&nbsp;&nbsp;&nbsp;&nbsp; +-------------------<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0 K&nbsp;
-0.0&nbsp;&nbsp;&nbsp; stpo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0<br>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+&nbsp;
+
+
+
+
+
+ /<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ stle&nbsp; | ------/<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
+ &nbsp;&nbsp;&nbsp;&nbsp; +-------------------<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0 K&nbsp;
+ 0.0&nbsp;&nbsp;&nbsp;
+ stpo&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.0<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
White&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Black<br>
-</tt><br>
-<b><a name="kq"></a>-k q stle0 stpo0 enpo0 enle0 shape0 stle2 stpo2
-enpo2 enle2 shape2</b> is a combination of the <b>-kv</b> and <b>-kp</b>
-functionality, with the black being preserved in CMYK to CMYK linking,
-with the output black constrained to be between the first and second
-set of curve parameters.<br>
-<br>
-<a name="K"></a> <span style="font-weight: bold;">-K parameters.</span>
-Any of the <span style="font-weight: bold;">-k</span> options above
-can use the <span style="font-weight: bold;">-K</span> version, in
-which rather than a black value target being defined by the inking
-rule, a black <span style="text-decoration: underline;">locus</span>
-target is defined. For each lookup, the minimum possible black level
-and the maximum possible black level is determined, the former
-corresponding to a locus target of 0, and the latter corresponding to a
-locus target of 1. For instance, at
-the
-white point, no black will be used in the output, even if the black
-locus specifies a maximum (since the maximum amount of black that
-can be used to print white is actually zero). Similarly, at the black
-point, black may well be used, even if the black locus specifies
-zero black (since a certain amount of black is needed to achieve the
-desired density of color). <br>
-<tt> </tt><span style="text-decoration: underline;"></span><br>
-&nbsp;The <b>-g</b> flag can be used together with the <b>-fif</b>
-flag, to plot
-out the resulting black channel behaviour for various <b>-k</b>
-or <span style="font-weight: bold;">-K </span>parameter
-values.<br>
-<br>
-<b><a name="l"></a>-l</b> <i>tlimit</i>&nbsp; &nbsp;&nbsp; Sets the
-total ink limit (TAC, Total Area Coverage) for the CMYK inverse forward
-lookup, as a total percentage from 0% to 400%. If none is provided, it
-will be estimated from the profile relcolor B2A table. The ink limit
-will be in final calibrated device values if the profile includes
-calibration information.<br>
-<br>
-<b><a name="L"></a>-L</b> <i>klimit</i>&nbsp; &nbsp; Sets the black
-ink limit for the CMYK inverse forward lookup, as a total percentage
-from 0% to 100%. If none is provided, it will be estimated from the
-profile relcolor B2A table. The ink limit
-will be in final calibrated device values if the profile includes
-calibration information.<br>
-<br>
-<a name="a"></a> If the <b>-a</b> flag is used for inverse forward
-lookups, then if
-the target PCS value cannot be reproduced by the device (ie. it clips),
-then the achievable, clipped PCS value is displayed.<br>
-<br>
-<a name="b"></a> If the <b>-b</b> flag is used for inverse forward
-lookups, then out of gamut clipping will be performed in the CIECAM02
-Jab appearance colorspace, rather than L*a*b* colorspace.<br>
-<br>
-<a name="m"></a> The <b>-m</b> flag turns on an internal processing
-option, in which the per device curve lookup table processing is merged
-into the main multi-dimensional interpolation lut lookup.<br>
-<br>
-<a name="c"></a>Whenever PCS values are to be specified or displayed in
-Jab/CIECAM02
-colorspace, a set of viewing conditions will be used to determine the
-details of the conversion. The <b>-c</b> parameter allows the
-specification of the viewing conditions. Viewing conditions can be
-specified in two basic ways. One
-is to select from the list of "pre canned", enumerated viewing
-conditions, choosing one that is closest to the conditions that are
-appropriate for the media type and situation. Alternatively, the
-viewing conditions parameters can be specified in detail individually.
-If both methods are used, them the chosen enumerated condition will be
-used as a base, and its parameters will then be individually overridden.<br>
-<br>
-<a name="p1"></a> The final parameter is the name of the <a
- href="File_Formats.html#ICC">ICC</a> profile to be used. On the
-MSWindows platform a .icm extension is generally used, and on Apple or
-Unix/Linux platforms a .icc extension is often used.<br>
-<h3>Usage and Discussion</h3>
-Typical usage for an output profile might be:<br>
-<br>
-&nbsp;&nbsp;&nbsp; xicclu -ff -ip profile.icm<br>
-<br>
-Normally the program is interactive, allowing the user to type in input
-color
-values, each number separated by a space, and the resulting output
-color
-being looked up and displayed after pressing return. To batch process
-a
-group of color values, prepare a text file containing each input value
-on
-a
-separate line, and use the input indirection facilities of your command
-line
-shell to redirect this input file into the standard input of xicclu.
-The
-output can be captured to a file by redirecting standard output to a
-file.
-In most shells this would be done something like this:<br>
-<br>
-&nbsp;&nbsp;&nbsp; xicclu -ff -ip profile.icm &lt; inputvalues.txt &gt;
-outputvalues.txt<br>
-<br>
-<a name="xg"></a>When plotting the neutral axis behavior, plotting the
-existing B2A table
-behavior would typically be done something like this:<br>
-<br>
-&nbsp;&nbsp;&nbsp; xicclu -g -fb profile.icm<br>
-<br>
-Exploring possible black generation and ink limiting behavior might be
-done
-like this:<br>
-<br>
-&nbsp;&nbsp;&nbsp; xicclu -g -fif -kp 0 .1 .9 1 .5 -l230 -L95
-profile.icm<br>
-<br>
-<br>
-<br>
-<br>
-<br>
-<br>
-<br>
-</body>
+
+
+
+
+
+ Black<br>
+ </tt><br>
+ <b><a name="kq"></a>-k q stle0 stpo0 enpo0 enle0 shape0 stle2 stpo2
+ enpo2 enle2 shape2</b> is a combination of the <b>-kv</b> and <b>-kp</b>
+ functionality, with the black being preserved in CMYK to CMYK
+ linking, with the output black constrained to be between the first
+ and second set of curve parameters.<br>
+ <br>
+ <a name="K"></a> <span style="font-weight: bold;">-K parameters.</span>
+ Any of the <span style="font-weight: bold;">-k</span> options above
+ can use the <span style="font-weight: bold;">-K</span> version, in
+ which rather than a black value target being defined by the inking
+ rule, a black <span style="text-decoration: underline;">locus</span>
+ target is defined. For each lookup, the minimum possible black level
+ and the maximum possible black level is determined, the former
+ corresponding to a locus target of 0, and the latter corresponding
+ to a locus target of 1. For instance, at the white point, no black
+ will be used in the output, even if the black locus specifies a
+ maximum (since the maximum amount of black that can be used to print
+ white is actually zero). Similarly, at the black point, black may
+ well be used, even if the black locus specifies zero black (since a
+ certain amount of black is needed to achieve the desired density of
+ color). <br>
+ <tt> </tt><span style="text-decoration: underline;"></span><br>
+ &nbsp;The <b>-g</b> flag can be used together with the <b>-fif</b>
+ flag, to plot out the resulting black channel behaviour for various
+ <b>-k</b> or <span style="font-weight: bold;">-K </span>parameter
+ values.<br>
+ <br>
+ <b><a name="l"></a>-l</b> <i>tlimit</i>&nbsp; &nbsp;&nbsp; Sets the
+ total ink limit (TAC, Total Area Coverage) for the CMYK inverse
+ forward lookup, as a total percentage from 0% to 400%. If none is
+ provided, it will be estimated from the profile relcolor B2A table.
+ The ink limit will be in final calibrated device values if the
+ profile includes calibration information.<br>
+ <br>
+ <b><a name="L"></a>-L</b> <i>klimit</i>&nbsp; &nbsp; Sets the black
+ ink limit for the CMYK inverse forward lookup, as a total percentage
+ from 0% to 100%. If none is provided, it will be estimated from the
+ profile relcolor B2A table. The ink limit will be in final
+ calibrated device values if the profile includes calibration
+ information.<br>
+ <br>
+ <a name="a"></a> If the <b>-a</b> flag is used for inverse forward
+ lookups, then if the target PCS value cannot be reproduced by the
+ device (ie. it clips), then the achievable, clipped PCS value is
+ displayed.<br>
+ <br>
+ <a name="b"></a> If the <b>-b</b> flag is used for inverse forward
+ lookups, then out of gamut clipping will be performed in the
+ CIECAM02 Jab appearance colorspace, rather than L*a*b* colorspace.<br>
+ <br>
+ <a name="m"></a> The <b>-m</b> flag turns on an internal processing
+ option, in which the per device curve lookup table processing is
+ merged into the main multi-dimensional interpolation lut lookup.<br>
+ <br>
+ <a name="c"></a>Whenever PCS values are to be specified or displayed
+ in Jab/CIECAM02 colorspace, a set of viewing conditions will be used
+ to determine the details of the conversion. The <b>-c</b> parameter
+ allows the specification of the viewing conditions. Viewing
+ conditions can be specified in two basic ways. One is to select from
+ the list of "pre canned", enumerated viewing conditions, choosing
+ one that is closest to the conditions that are appropriate for the
+ media type and situation. Alternatively, the viewing conditions
+ parameters can be specified in detail individually. If both methods
+ are used, them the chosen enumerated condition will be used as a
+ base, and its parameters will then be individually overridden.<br>
+ <br>
+ <a name="p1"></a> The final parameter is the name of the <a
+ href="File_Formats.html#ICC">ICC</a> profile to be used. On the
+ MSWindows platform a .icm extension is generally used, and on Apple
+ or Unix/Linux platforms a .icc extension is often used.<br>
+ <h3>Usage and Discussion</h3>
+ Typical usage for an output profile might be:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; xicclu -ff -ip profile.icm<br>
+ <br>
+ Normally the program is interactive, allowing the user to type in
+ input color values, each number separated by a space, and the
+ resulting output color being looked up and displayed after pressing
+ return. To batch process a group of color values, prepare a text
+ file containing each input value on a separate line, and use the
+ input indirection facilities of your command line shell to redirect
+ this input file into the standard input of xicclu. The output can be
+ captured to a file by redirecting standard output to a file. In most
+ shells this would be done something like this:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; xicclu -ff -ip profile.icm &lt; inputvalues.txt
+ &gt; outputvalues.txt<br>
+ <br>
+ <a name="xg"></a>When plotting the neutral axis behavior, plotting
+ the existing B2A table behavior would typically be done something
+ like this:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; xicclu -g -fb profile.icm<br>
+ <br>
+ Exploring possible black generation and ink limiting behavior might
+ be done like this:<br>
+ <br>
+ &nbsp;&nbsp;&nbsp; xicclu -g -fif -kp 0 .1 .9 1 .5 -l230 -L95
+ profile.icm<br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ <br>
+ </body>
</html>
diff --git a/gamut/gammap.c b/gamut/gammap.c
index a9bef1e..d463755 100644
--- a/gamut/gammap.c
+++ b/gamut/gammap.c
@@ -26,9 +26,10 @@
* proportionality. Ideally there should be an intent that matches
* this, that can be selected for the colorimetric table (or perhaps be default).
*
- * It might be good to offer the black mapping method as an option (gmm_BPmap),
+ * It might be good to offer the black mapping method as an option (icx_BPmap),
* as well as offering different profile (xicc/xlut.c) black point options
* (neutral, K hue max density, CMY max density, any max density).
+ * Perhaps print RGB & CMY should default to neutral black, rather than 0,0,0 ??
*
* The gamut mapping code here and the near smooth code don't actually mesh
* very well. For instance, the black point bend approach in < V1.3.4
@@ -448,11 +449,6 @@ gammap *new_gammap(
double *mx, /* for rspl grid. */
char *diagname /* If non-NULL, write a gamut mapping diagnostic WRL */
) {
- gmm_BPmap bph = gmm_bendBP; /* Prefered algorithm */
-// gmm_BPmap bph = gmm_clipBP; /* Alternatives tried */
-// gmm_BPmap bph = gmm_BPadpt;
-// gmm_BPmap bph = gmm_noBPadpt;
-
gammap *s; /* This */
gamut *scl_gam; /* Source colorspace gamut with rotation and L mapping applied */
gamut *sil_gam; /* Source image gamut with rotation and L mapping applied */
@@ -499,12 +495,6 @@ gammap *new_gammap(
printf("Gamut map resolution: %d\n",mapres);
if (si_gam != NULL)
printf("Image gamut supplied\n");
- switch(bph) {
- case gmm_clipBP: printf("Neutral axis no-adapt extend and clip\n"); break;
- case gmm_BPadpt: printf("Neutral axis fully adapt\n"); break;
- case gmm_bendBP: printf("Neutral axis no-adapt extend and bend\n"); break;
- case gmm_noBPadpt: printf("Neutral axis no-adapt\n"); break;
- }
}
/* Allocate the object */
@@ -729,8 +719,8 @@ gammap *new_gammap(
}
/* Now decide the detail of the white and black alignment */
- if (bph == gmm_BPadpt || bph == gmm_bendBP) { /* Adapt to destination white and black */
-
+ if (gmi->bph == gmm_BPadpt || gmi->bph == gmm_bendBP) {
+ /* Adapt to destination white and black */
/* Use the fully adapted white and black points */
for (j = 0; j < 3; j++) {
@@ -738,7 +728,7 @@ gammap *new_gammap(
dr_cs_bp[j] = fabp[j];
}
- if (bph == gmm_bendBP) {
+ if (gmi->bph == gmm_bendBP) {
/* Extend the half adapted (white = dst, black = src) black point */
/* to the same L as the target (dst), to use as the initial (bent) black point */
@@ -768,7 +758,7 @@ gammap *new_gammap(
dr_cs_wp[0], dr_cs_wp[1], dr_cs_wp[2], dr_cs_bp[0], dr_cs_bp[1], dr_cs_bp[2]);
}
#endif
- if (bph == gmm_clipBP) {
+ if (gmi->bph == gmm_clipBP) {
/* Extend the target black point to accomodate the */
/* bent or clipped destination space L* range */
@@ -1114,31 +1104,12 @@ glumknf = 1.0;
{
/* We want to rotate and then map L independently of everything else, */
- /* so transform source csape & image gamuts through the rotation and L mapping */
+ /* so transform source cs & image gamuts through the rotation and L mapping */
/* before we create the surface 3D mapping from them */
/* Create L mapped versions of rotated src colorspace white/black points */
-#ifdef NEVER
- co cp;
- double t;
- int i;
-
- cp.p[0] = sr_cs_wp[0];
- s->grey->interp(s->grey, &cp);
-
- t = (cp.v[0] - sr_cs_bp[0])/(sr_cs_wp[0] - sr_cs_bp[0]);
- for (j = 0; j < 3; j++)
- sl_cs_wp[j] = sr_cs_bp[j] + t * (sr_cs_wp[j] - sr_cs_bp[j]);
-
- cp.p[0] = sr_cs_bp[0];
- s->grey->interp(s->grey, &cp);
- t = (cp.v[0] - sr_cs_wp[0])/(sr_cs_bp[0] - sr_cs_wp[0]);
- for (j = 0; j < 3; j++)
- sl_cs_bp[j] = sr_cs_wp[j] + t * (sr_cs_bp[j] - sr_cs_wp[j]);
-#else
dopartialmap1(s, sl_cs_wp, s_cs_wp);
dopartialmap1(s, sl_cs_bp, s_cs_bp);
-#endif
#ifdef VERBOSE
if (verb) {
diff --git a/gamut/gammap.h b/gamut/gammap.h
index b59e821..3bc1c8c 100644
--- a/gamut/gammap.h
+++ b/gamut/gammap.h
@@ -39,6 +39,7 @@ struct _gammap {
}; typedef struct _gammap gammap;
+#ifdef NEVER
/* Method of black point adaptation */
typedef enum {
gmm_BPadpt = 0, /* Adapt source black point to destination */
@@ -46,6 +47,7 @@ typedef enum {
gmm_bendBP = 2, /* Don't adapt black point, bend it to dest. at end */
gmm_clipBP = 3 /* Don't adapt black point, clip it to dest. at end */
} gmm_BPmap;
+#endif
/* Creator */
gammap *new_gammap(
diff --git a/gamut/gamut.c b/gamut/gamut.c
index 052b8d8..09a5110 100644
--- a/gamut/gamut.c
+++ b/gamut/gamut.c
@@ -136,6 +136,7 @@
static void triangulate(gamut *s);
static void del_gamut(gamut *s);
static gvert *expand_gamut(gamut *s, double in[3]);
+static void set_cs_bp_kp_ovrd(gamut *s, double *bk, double *kp);
static double getsres(gamut *s);
static int getisjab(gamut *s);
static int getisrast(gamut *s);
@@ -175,6 +176,7 @@ static int intersect(gamut *s, gamut *s1, gamut *s2);
static int compdstgamut(gamut *s, gamut *img, gamut *src, gamut *dst, int docomp, int doexp,
gamut *nedst, void (*cvect)(void *cntx, double *vec, double *pos), void *cntx);
static int vect_intersect(gamut *s, double *rvp, double *ip, double *p1, double *p2, gtri *t);
+static void compgawb(gamut *s);
/* in isecvol.c: */
extern double isect_volume(gamut *s1, gamut *s2);
@@ -632,6 +634,7 @@ int isRast /* Flag indicating Raster rather than colorspace */
/* Setup methods */
s->del = del_gamut;
s->expand = expand_gamut;
+ s->set_cs_bp_kp_ovrd = set_cs_bp_kp_ovrd;
s->getsres = getsres;
s->getisjab = getisjab;
s->getisrast = getisrast;
@@ -2892,6 +2895,23 @@ gamut *s
}
/* ===================================================== */
+/* Special override code (To support BT.1886 modification */
+/* ===================================================== */
+
+/* Override cs black points */
+static void set_cs_bp_kp_ovrd(gamut *s, double *bp, double *kp) {
+ if (bp != NULL) {
+ icmCpy3(s->cs_bp, bp);
+ }
+ if (kp != NULL) {
+ icmCpy3(s->cs_kp, kp);
+ }
+
+ /* recompute the gamut white/black available */
+ compgawb(s);
+}
+
+/* ===================================================== */
/* Code that makes use of the triangulation */
/* ===================================================== */
diff --git a/gamut/gamut.h b/gamut/gamut.h
index 8f9f00e..8f4645c 100644
--- a/gamut/gamut.h
+++ b/gamut/gamut.h
@@ -257,6 +257,8 @@ struct _gamut {
gvert *(*expand)(struct _gamut *s, double in[3]); /* Expand the gamut surface */
+ void (*set_cs_bp_kp_ovrd)(struct _gamut *s, double *bk, double *kp); /* Override cs black points */
+
int (*getisjab)(struct _gamut *s); /* Return the isJab flag value */
int (*getisrast)(struct _gamut *s); /* Return the isRast flag value */
diff --git a/gamut/maptest.c b/gamut/maptest.c
index 1c595b6..5fe5c42 100644
--- a/gamut/maptest.c
+++ b/gamut/maptest.c
@@ -164,7 +164,7 @@ main(int argc, char *argv[]) {
/* - - - - - - - - - - - - - - - - - - - */
/* Create the gamut mapping */
- gmi.usecas = 0;
+ gmi.usecas = 1; /* Abs. L*a*b* */
gmi.usemap = 1;
gmi.greymf = 1.0; /* Gray axis hue matching factor, 0.0 - 1.0 */
gmi.glumwcpf = 1.0; /* Grey axis luminance white compression factor, 0.0 - 1.0 */
@@ -172,6 +172,7 @@ main(int argc, char *argv[]) {
gmi.glumbcpf = 1.0; /* Grey axis luminance black compression factor, 0.0 - 1.0 */
gmi.glumbexf = 1.0; /* Grey axis luminance black expansion factor, 0.0 - 1.0 */
gmi.glumknf = 0.7; /* Gray axis luminance knee factor, 0.0 - 1.0 */
+ gmi.bph = gmm_bendBP; /* Extend and bend */
gmi.gamcpf = 1.0; /* Gamut compression factor, 0.0 - 1.0 */
if (sat)
gmi.gamexf = 1.0; /* Gamut expansion factor, 0.0 - 1.0 */
diff --git a/gamut/nearsmth.c b/gamut/nearsmth.c
index 1f48f20..a13442d 100644
--- a/gamut/nearsmth.c
+++ b/gamut/nearsmth.c
@@ -3200,7 +3200,6 @@ datao map_oh
//if (PFCOND) printf("~1 neutral axis point = %f %f %f\n", napoint[0], napoint[1], napoint[2]);
/* Compute a normalized available depth from distance */
/* to closest to neautral axis point */
- if (maxt > 1.0) /* Compression */
if ((mint > 1e-8 && maxt > -1e-8) /* G. & V. Compression */
|| ((mint < -1e-8 && maxt > -1e-8) /* G. Exp & V. comp. */
&& (fabs(mint) < (fabs(maxt) - 1e-8))))
diff --git a/h/aconfig.h b/h/aconfig.h
index 0de524f..91e43b8 100644
--- a/h/aconfig.h
+++ b/h/aconfig.h
@@ -9,8 +9,8 @@
/* minor number = 8 bits */
/* major number = 8 bits */
-#define ARGYLL_VERSION 0x01051
-#define ARGYLL_VERSION_STR "1.5.1"
+#define ARGYLL_VERSION 0x01063
+#define ARGYLL_VERSION_STR "1.6.3"
/* Maximum file path length */
#define MAXNAMEL 1024
diff --git a/h/counters.h b/h/counters.h
index 3a3e71c..e3944d9 100644
--- a/h/counters.h
+++ b/h/counters.h
@@ -51,7 +51,7 @@
} \
}
-/* After increment, expression is TRUE if counter is done */
+/* After init or increment, expression is TRUE if counter is done */
#define DC_DONE(nn) \
(nn##_e >= nn##_di)
diff --git a/icc/ClayRGB1998.icm b/icc/ClayRGB1998.icm
index 1eedf09..1c3a02e 100644
--- a/icc/ClayRGB1998.icm
+++ b/icc/ClayRGB1998.icm
Binary files differ
diff --git a/icc/EBU3213_PAL.icm b/icc/EBU3213_PAL.icm
new file mode 100644
index 0000000..54cfed7
--- /dev/null
+++ b/icc/EBU3213_PAL.icm
Binary files differ
diff --git a/icc/Jamfile b/icc/Jamfile
index abbeddb..9f27848 100644
--- a/icc/Jamfile
+++ b/icc/Jamfile
@@ -13,7 +13,9 @@ PREF_LINKFLAGS = $(LINKDEBUGFLAG) ; # Link debugging flags
Libraries = libicc ;
Executables = iccdump icclu ;
Headers = icc.h ;
-Samples = sRGB.icm ClayRGB1998.icm lab2lab.icm ;
+Samples = sRGB.icm ClayRGB1998.icm EBU3213_PAL.icm SMPTE_RP145_NTSC.icm Rec709.icm
+ Rec2020.icm SMPTE431_P3.icm ProPhoto.icm ProPhotoLin.icm lab2lab.icm ;
+# Remember to add samples to ref/afiles !
#Install
InstallBin $(DESTDIR)$(PREFIX)/bin : $(Executables) ;
@@ -36,19 +38,31 @@ LINKLIBS = libicc ;
# All utils are made from a single source file
MainsFromSources icctest.c lutest.c iccdump.c icclu.c iccrw.c ;
+# This is an example program for making a matrix display profile
+MainsFromSources mkDispProf.c ;
+
+#MainsFromSources t.c ;
+
if $(BUILD_JUNK) {
# MainsFromSources tt.c ;
MainsFromSources mksRGB.c ;
+# MainsFromSources mkscRGB.c ;
MainsFromSources mkAdobeRGB.c ;
+ MainsFromSources mkEBU3213.c ;
+ MainsFromSources mkSMPTERP145.c ;
MainsFromSources mklab2lab.c ;
+ MainsFromSources mkRec709.c ;
+ MainsFromSources mkRec2020.c ;
+ MainsFromSources mkSMPTE431_P3.c ;
+ MainsFromSources mkProPhoto.c ;
# MainsFromSources icm2ary.c ;
# Check library is compatible with C++
Main cppcheck : cppcheck.cpp ;
- # chech CIEDE2000
+ # check CIEDE2000
MainsFromSources testDE2K.c ;
#Monotonic behaviour checker
diff --git a/icc/License.txt b/icc/License.txt
index 9de79da..bd0c4f2 100644
--- a/icc/License.txt
+++ b/icc/License.txt
@@ -1,5 +1,5 @@
*************************************************************************
-Copyright (c) 1997-2009 Graeme W. Gill
+Copyright (c) 1997-2013 Graeme W. Gill
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/icc/ProPhoto.icm b/icc/ProPhoto.icm
new file mode 100644
index 0000000..3ed16cb
--- /dev/null
+++ b/icc/ProPhoto.icm
Binary files differ
diff --git a/icc/ProPhotoLin.icm b/icc/ProPhotoLin.icm
new file mode 100644
index 0000000..579b903
--- /dev/null
+++ b/icc/ProPhotoLin.icm
Binary files differ
diff --git a/icc/Readme.txt b/icc/Readme.txt
index 0ec425e..d39e9da 100644
--- a/icc/Readme.txt
+++ b/icc/Readme.txt
@@ -5,7 +5,7 @@ This version is part of Argyll V 1.50
-------------------------------------------
-Date 22 September 2012, Version 2.14
+Date 22 September 2013, Version 2.15
This distribution contains source code which implements the reading and
writing of color profile files that conform to the International Color
@@ -70,12 +70,6 @@ In summary this library provides:
system file and memory sub-systems.
* Loads Tag Types on demand to conserve memory space.
-Changes from V2.11
-
-Many changes have been made to support ArgyllCMS.
-A double memory free bug when iccdump'ing a profile
-that has duplicate tags has been fixed.
-
Package contents:
icclib.zip ZIP archive of the following files
diff --git a/icc/Rec2020.icm b/icc/Rec2020.icm
new file mode 100644
index 0000000..09d5ccf
--- /dev/null
+++ b/icc/Rec2020.icm
Binary files differ
diff --git a/icc/Rec709.icm b/icc/Rec709.icm
new file mode 100644
index 0000000..46140bd
--- /dev/null
+++ b/icc/Rec709.icm
Binary files differ
diff --git a/icc/SMPTE431_P3.icm b/icc/SMPTE431_P3.icm
new file mode 100644
index 0000000..f3861be
--- /dev/null
+++ b/icc/SMPTE431_P3.icm
Binary files differ
diff --git a/icc/SMPTE_RP145_NTSC.icm b/icc/SMPTE_RP145_NTSC.icm
new file mode 100644
index 0000000..a6ce7f1
--- /dev/null
+++ b/icc/SMPTE_RP145_NTSC.icm
Binary files differ
diff --git a/icc/afiles b/icc/afiles
index 7df3ba5..acb730e 100644
--- a/icc/afiles
+++ b/icc/afiles
@@ -20,7 +20,14 @@ icctest.c
lutest.c
mcheck.c
testDE2K.c
-makezip.ksh
+mkDispProf.c
sRGB.icm
ClayRGB1998.icm
lab2lab.icm
+EBU3213_PAL.icm
+SMPTE_RP145_NTSC.icm
+Rec709.icm
+Rec2020.icm
+SMPTE431_P3.icm
+ProPhoto.icm
+ProPhotoLin.icm
diff --git a/icc/icc.c b/icc/icc.c
index 68668d0..7dfe519 100644
--- a/icc/icc.c
+++ b/icc/icc.c
@@ -7,7 +7,7 @@
* Date: 2002/04/22
* Version: 2.15
*
- * Copyright 1997 - 2012 Graeme W. Gill
+ * Copyright 1997 - 2013 Graeme W. Gill
*
* This material is licensed with an "MIT" free use license:-
* see the License.txt file in this directory for licensing details.
@@ -51,10 +51,10 @@
#define _ICC_C_ /* Turn on implimentation code */
-#undef DEBUG_SETLUT /* Show each value being set in setting lut contents */
-#undef DEBUG_SETLUT_CLIP /* Show clipped values when setting LUT */
-#undef DEBUG_LULUT /* Show each value being looked up from lut contents */
-#undef DEBUG_LLULUT /* Debug individual lookup steps (not fully implemented) */
+#undef DEBUG_SETLUT /* [Und] Show each value being set in setting lut contents */
+#undef DEBUG_SETLUT_CLIP /* [Und] Show clipped values when setting LUT */
+#undef DEBUG_LULUT /* [Und] Show each value being looked up from lut contents */
+#undef DEBUG_LLULUT /* [Und] Debug individual lookup steps (not fully implemented) */
#include <stdio.h>
#include <stdlib.h>
@@ -127,6 +127,10 @@
#define DBLLL(xxx)
#endif
+#ifndef M_PI
+# define M_PI 3.14159265358979323846
+#endif
+
/* =========================================================== */
/* Overflow protected unsigned int arithmatic functions. */
/* These functions saturate rather than wrapping around. */
@@ -706,6 +710,12 @@ static int write_S15Fixed16Number(double d, char *p) {
return 0;
}
+static double round_S15Fixed16Number(double d) {
+ d = floor(d * 65536.0 + 0.5); /* Beware! (int)(d + 0.5) doesn't work! */
+ d = d/65536.0;
+ return d;
+}
+
/* Device coordinate as 8 bit value range 0.0 - 1.0 */
static double read_DCS8Number(char *p) {
unsigned int rv;
@@ -775,7 +785,7 @@ static void read_PCSNumber(icc *icp, icColorSpaceSignature csig, double pcs[3],
if (csig == icmSigPCSData)
csig = icp->header->pcs;
if (csig == icSigLabData) {
- if (icp->ver != 0)
+ if (icp->ver >= icmVersion4_1)
csig = icmSigLabV4Data;
else
csig = icmSigLabV2Data;
@@ -820,7 +830,7 @@ static int write_PCSNumber(icc *icp, icColorSpaceSignature csig, double pcs[3],
if (csig == icmSigPCSData)
csig = icp->header->pcs;
if (csig == icSigLabData) {
- if (icp->ver != 0)
+ if (icp->ver >= icmVersion4_1)
csig = icmSigLabV4Data;
else
csig = icmSigLabV2Data;
@@ -5374,6 +5384,257 @@ double *in /* Input array[outputChan] */
}
/* ----------------------------------------------- */
+/* Tune a single interpolated value. Based on lookup_clut functions (above) */
+
+/* Helper function to fine tune a single value interpolation */
+/* Return 0 on success, 1 if input clipping occured, 2 if output clipping occured */
+int icmLut_tune_value_nl(
+icmLut *p, /* Pointer to Lut object */
+double *out, /* Output array[inputChan] */
+double *in /* Input array[outputChan] */
+) {
+ icc *icp = p->icp;
+ int rv = 0;
+ double *gp; /* Pointer to grid cube base */
+ double co[MAX_CHAN]; /* Coordinate offset with the grid cell */
+ double *gw, GW[1 << 8]; /* weight for each grid cube corner */
+ double cout[MAX_CHAN]; /* Current output value */
+
+ if (p->inputChan <= 8) {
+ gw = GW; /* Use stack allocation */
+ } else {
+ if ((gw = (double *) icp->al->malloc(icp->al, sat_mul((1 << p->inputChan), sizeof(double)))) == NULL) {
+ sprintf(icp->err,"icmLut_lookup_clut: malloc() failed");
+ return icp->errc = 2;
+ }
+ }
+
+ /* We are using an multi-linear (ie. Trilinear for 3D input) interpolation. */
+ /* The implementation here uses more multiplies that some other schemes, */
+ /* (for instance, see "Tri-Linear Interpolation" by Steve Hill, */
+ /* Graphics Gems IV, page 521), but has less involved bookeeping, */
+ /* needs less local storage for intermediate output values, does fewer */
+ /* output and intermediate value reads, and fp multiplies are fast on */
+ /* todays processors! */
+
+ /* Compute base index into grid and coordinate offsets */
+ {
+ unsigned int e;
+ double clutPoints_1 = (double)(p->clutPoints-1);
+ int clutPoints_2 = p->clutPoints-2;
+ gp = p->clutTable; /* Base of grid array */
+
+ for (e = 0; e < p->inputChan; e++) {
+ unsigned int x;
+ double val;
+ val = in[e] * clutPoints_1;
+ if (val < 0.0) {
+ val = 0.0;
+ rv |= 1;
+ } else if (val > clutPoints_1) {
+ val = clutPoints_1;
+ rv |= 1;
+ }
+ x = (unsigned int)floor(val); /* Grid coordinate */
+ if (x > clutPoints_2)
+ x = clutPoints_2;
+ co[e] = val - (double)x; /* 1.0 - weight */
+ gp += x * p->dinc[e]; /* Add index offset for base of cube */
+ }
+ }
+ /* Compute corner weights needed for interpolation */
+ {
+ unsigned int e;
+ int i, g = 1;
+ gw[0] = 1.0;
+ for (e = 0; e < p->inputChan; e++) {
+ for (i = 0; i < g; i++) {
+ gw[g+i] = gw[i] * co[e];
+ gw[i] *= (1.0 - co[e]);
+ }
+ g *= 2;
+ }
+ }
+ /* Now compute the current output value, and distribute the correction */
+ {
+ int i;
+ unsigned int f;
+ double w, *d, ww = 0.0;
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] = 0.0;
+ for (i = 0; i < (1 << p->inputChan); i++) { /* For all other corners of cube */
+ w = gw[i]; /* Strength reduce */
+ ww += w * w; /* Sum of weights squared */
+ d = gp + p->dcube[i];
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] += w * d[f];
+ }
+
+ /* We distribute the correction needed in proportion to the */
+ /* interpolation weighting, so the biggest correction is to the */
+ /* closest vertex. */
+
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] = (out[f] - cout[f])/ww; /* Amount to distribute */
+
+ for (i = 0; i < (1 << p->inputChan); i++) { /* For all other corners of cube */
+ w = gw[i]; /* Strength reduce */
+ d = gp + p->dcube[i];
+ for (f = 0; f < p->outputChan; f++) {
+ d[f] += w * cout[f]; /* Apply correction */
+ if (d[f] < 0.0) {
+ d[f] = 0.0;
+ rv |= 2;
+ } else if (d[f] > 1.0) {
+ d[f] = 1.0;
+ rv |= 2;
+ }
+ }
+ }
+ }
+
+ if (gw != GW)
+ icp->al->free(icp->al, (void *)gw);
+ return rv;
+}
+
+/* Helper function to fine tune a single value interpolation */
+/* Return 0 on success, 1 if input clipping occured, 2 if output clipping occured */
+int icmLut_tune_value_sx(
+icmLut *p, /* Pointer to Lut object */
+double *out, /* Output array[inputChan] */
+double *in /* Input array[outputChan] */
+) {
+ int rv = 0;
+ double *gp; /* Pointer to grid cube base */
+ double co[MAX_CHAN]; /* Coordinate offset with the grid cell */
+ int si[MAX_CHAN]; /* co[] Sort index, [0] = smalest */
+ double cout[MAX_CHAN]; /* Current output value */
+
+ /* We are using a simplex (ie. tetrahedral for 3D input) interpolation. */
+ /* This method is more appropriate for XYZ/RGB/CMYK input spaces, */
+
+ /* Compute base index into grid and coordinate offsets */
+ {
+ unsigned int e;
+ double clutPoints_1 = (double)(p->clutPoints-1);
+ int clutPoints_2 = p->clutPoints-2;
+ gp = p->clutTable; /* Base of grid array */
+
+ for (e = 0; e < p->inputChan; e++) {
+ unsigned int x;
+ double val;
+ val = in[e] * clutPoints_1;
+ if (val < 0.0) {
+ val = 0.0;
+ rv |= 1;
+ } else if (val > clutPoints_1) {
+ val = clutPoints_1;
+ rv |= 1;
+ }
+ x = (unsigned int)floor(val); /* Grid coordinate */
+ if (x > clutPoints_2)
+ x = clutPoints_2;
+ co[e] = val - (double)x; /* 1.0 - weight */
+ gp += x * p->dinc[e]; /* Add index offset for base of cube */
+ }
+ }
+ /* Do insertion sort on coordinates, smallest to largest. */
+ {
+ int f, vf;
+ unsigned int e;
+ double v;
+ for (e = 0; e < p->inputChan; e++)
+ si[e] = e; /* Initial unsorted indexes */
+
+ for (e = 1; e < p->inputChan; e++) {
+ f = e;
+ v = co[si[f]];
+ vf = f;
+ while (f > 0 && co[si[f-1]] > v) {
+ si[f] = si[f-1];
+ f--;
+ }
+ si[f] = vf;
+ }
+ }
+ /* Now compute the current output value, and distribute the correction */
+ {
+ unsigned int e, f;
+ double w, ww = 0.0; /* Current vertex weight, sum of weights squared */
+ double *ogp = gp; /* Pointer to grid cube base */
+
+ w = 1.0 - co[si[p->inputChan-1]]; /* Vertex at base of cell */
+ ww += w * w; /* Sum of weights squared */
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] = w * gp[f];
+
+ for (e = p->inputChan-1; e > 0; e--) { /* Middle verticies */
+ w = co[si[e]] - co[si[e-1]];
+ ww += w * w; /* Sum of weights squared */
+ gp += p->dinc[si[e]]; /* Move to top of cell in next largest dimension */
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] += w * gp[f];
+ }
+
+ w = co[si[0]];
+ ww += w * w; /* Sum of weights squared */
+ gp += p->dinc[si[0]]; /* Far corner from base of cell */
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] += w * gp[f];
+
+ /* We distribute the correction needed in proportion to the */
+ /* interpolation weighting, so the biggest correction is to the */
+ /* closest vertex. */
+ for (f = 0; f < p->outputChan; f++)
+ cout[f] = (out[f] - cout[f])/ww; /* Amount to distribute */
+
+ gp = ogp;
+ w = 1.0 - co[si[p->inputChan-1]]; /* Vertex at base of cell */
+ for (f = 0; f < p->outputChan; f++) {
+ gp[f] += w * cout[f]; /* Apply correction */
+ if (gp[f] < 0.0) {
+ gp[f] = 0.0;
+ rv |= 2;
+ } else if (gp[f] > 1.0) {
+ gp[f] = 1.0;
+ rv |= 2;
+ }
+ }
+
+ for (e = p->inputChan-1; e > 0; e--) { /* Middle verticies */
+ w = co[si[e]] - co[si[e-1]];
+ gp += p->dinc[si[e]]; /* Move to top of cell in next largest dimension */
+ for (f = 0; f < p->outputChan; f++) {
+ gp[f] += w * cout[f]; /* Apply correction */
+ if (gp[f] < 0.0) {
+ gp[f] = 0.0;
+ rv |= 2;
+ } else if (gp[f] > 1.0) {
+ gp[f] = 1.0;
+ rv |= 2;
+ }
+ }
+ }
+
+ w = co[si[0]];
+ gp += p->dinc[si[0]]; /* Far corner from base of cell */
+ for (f = 0; f < p->outputChan; f++) {
+ gp[f] += w * cout[f]; /* Apply correction */
+ if (gp[f] < 0.0) {
+ gp[f] = 0.0;
+ rv |= 2;
+ } else if (gp[f] > 1.0) {
+ gp[f] = 1.0;
+ rv |= 2;
+ }
+ }
+ }
+ return rv;
+}
+
+
+/* ----------------------------------------------- */
/* Pseudo - Hilbert count sequencer */
/* This multi-dimensional count sequence is a distributed */
@@ -5550,35 +5811,44 @@ static int getNormFunc(
#define CLIP_MARGIN 0.005 /* Margine to allow before reporting clipping = 0.5% */
+/* NOTE that ICM_CLUT_SET_FILTER turns out to be not very useful, */
+/* as it can result in reversals. Could #ifdef out the code ?? */
+
/* Helper function to set multiple Lut tables simultaneously. */
/* Note that these tables all have to be compatible in */
/* having the same configuration and resolution. */
/* Set errc and return error number in underlying icc */
-/* Set warnc if there is clipping in the output values */
-/* 1 = input table, 2 = main clut, 3 = clut midpoin, 4 = midpoint interp, 5 = output table */
+/* Set warnc if there is clipping in the output values: */
+/* 1 = input table, 2 = main clut, 3 = clut midpoint, 4 = midpoint interp, 5 = output table */
+/* Note that clutfunc in[] value has "index under", ie: */
+/* at ((int *)in)[-chan-1], and for primary grid is simply the */
+/* grid index (ie. 5,3,8), and for the center of cells grid, is */
+/* the -index-1, ie. -6,-3,-8 */
int icmSetMultiLutTables(
- int ntables, /* Number of tables to be set, 1..n */
- icmLut **pp, /* Pointer to array of Lut objects */
- int flags, /* Setting flags */
- void *cbctx, /* Opaque callback context pointer value */
- icColorSpaceSignature insig, /* Input color space */
- icColorSpaceSignature outsig, /* Output color space */
+ int ntables, /* Number of tables to be set, 1..n */
+ icmLut **pp, /* Pointer to array of Lut objects */
+ int flags, /* Setting flags */
+ void *cbctx, /* Opaque callback context pointer value */
+ icColorSpaceSignature insig, /* Input color space */
+ icColorSpaceSignature outsig, /* Output color space */
void (*infunc)(void *cbctx, double *out, double *in),
/* Input transfer function, inspace->inspace' (NULL = default) */
/* Will be called ntables times for each input grid value */
- double *inmin, double *inmax, /* Maximum range of inspace' values */
- /* (NULL = default) */
+ double *inmin, double *inmax, /* Maximum range of inspace' values */
+ /* (NULL = default) */
void (*clutfunc)(void *cbntx, double *out, double *in),
/* inspace' -> outspace[ntables]' transfer function */
/* will be called once for each input' grid value, and */
/* ntables output values should be written consecutively */
/* to out[]. */
- double *clutmin, double *clutmax, /* Maximum range of outspace' values */
- /* (NULL = default) */
- void (*outfunc)(void *cbntx, double *out, double *in))
+ double *clutmin, double *clutmax, /* Maximum range of outspace' values */
+ /* (NULL = default) */
+ void (*outfunc)(void *cbntx, double *out, double *in),
/* Output transfer function, outspace'->outspace (NULL = deflt) */
/* Will be called ntables times on each output value */
-{
+ int *apxls_gmin, int *apxls_gmax /* If not NULL, the grid indexes not to be affected */
+ /* by ICM_CLUT_SET_APXLS, defaulting to 0..>clutPoints-1 */
+) {
icmLut *p, *pn; /* Pointer to 0'th nd tn'th Lut object */
icc *icp; /* Pointer to common icc */
int tn;
@@ -5594,6 +5864,7 @@ int icmSetMultiLutTables(
double *_iv, *iv, *ivn; /* Real index value/table value */
double imin[MAX_CHAN], imax[MAX_CHAN];
double omin[MAX_CHAN], omax[MAX_CHAN];
+ int def_apxls_gmin[MAX_CHAN], def_apxls_gmax[MAX_CHAN];
void (*ifromindex)(double *out, double *in); /* Index to input color space function */
void (*itoentry)(double *out, double *in); /* Input color space to entry function */
void (*ifromentry)(double *out, double *in); /* Entry to input color space function */
@@ -5806,6 +6077,17 @@ int icmSetMultiLutTables(
/* Allocate space for cell center value lookup */
if (flags & ICM_CLUT_SET_APXLS) {
+ if (apxls_gmin == NULL) {
+ apxls_gmin = def_apxls_gmin;
+ for (e = 0; e < p->inputChan; e++)
+ apxls_gmin[e] = 0;
+ }
+ if (apxls_gmax == NULL) {
+ apxls_gmax = def_apxls_gmax;
+ for (e = 0; e < p->inputChan; e++)
+ apxls_gmax[e] = p->clutPoints-1;
+ }
+
if ((clutTable2 = (double **) icp->al->calloc(icp->al,sizeof(double *), ntables)) == NULL) {
sprintf(icp->err,"icmLut_set_tables malloc of cube center array failed");
icp->al->free(icp->al, _iv);
@@ -5884,7 +6166,7 @@ int icmSetMultiLutTables(
ti += ii[e] * p->dinc[e]; /* Clut index */
iv[e] = ii[e]/(p->clutPoints-1.0); /* Vertex coordinates */
iv[e] = iv[e] * (imax[e] - imin[e]) + imin[e]; /* Undo expansion to 0.0 - 1.0 */
- *((int *)&iv[-((int)e)-1]) = ii[e]; /* Trick to supply grid index in iv[] */
+ *((int *)&iv[-((int)e)-1]) = ii[e]; /* Trick to supply grid index in iv[] */
}
if (flags & ICM_CLUT_SET_FILTER) {
@@ -5941,12 +6223,13 @@ int icmSetMultiLutTables(
if (clutTable2 != NULL) {
for (e = 0; e < p->inputChan; e++) {
- if (ii[e] >= (p->clutPoints-1))
- break; /* Don't lookup beyond last */
+ if (ii[e] < apxls_gmin[e]
+ || ii[e] >= apxls_gmax[e])
+ break; /* Don't lookup outside least squares area */
iv[e] = (ii[e] + 0.5)/(p->clutPoints-1.0); /* Vertex coordinates + 0.5 */
iv[e] = iv[e] * (imax[e] - imin[e]) + imin[e]; /* Undo expansion to 0.0 - 1.0 */
- *((int *)&iv[-((int)e)-1]) = ii[e]; /* Trick to supply grid index in iv[] */
- /* (Not this is only the base for +0.5) */
+ *((int *)&iv[-((int)e)-1]) = -ii[e]-1; /* Trick to supply -ve grid index in iv[] */
+ /* (Not this is only the base for +0.5 center) */
}
if (e >= p->inputChan) { /* We're not on the last row */
@@ -5995,7 +6278,7 @@ int icmSetMultiLutTables(
#define APXLS_DIFF_THRHESH 0.2
/* Deal with cell center value, aproximate least squares adjustment. */
/* Subtract some of the mean of the surrounding center values from each grid value. */
- /* Skip the edges so that things like the white point are not changed. */
+ /* Skip the range edges so that things like the white point or Video sync are not changed. */
/* Avoid modifying the value if the difference between the */
/* interpolated value and the current value is too great, */
/* and there is the possibility of different color aliases. */
@@ -6005,9 +6288,9 @@ int icmSetMultiLutTables(
int ee;
double cw = 1.0/(double)(1 << p->inputChan); /* Weight for each cube corner */
- /* For each cell center point except last row */
+ /* For each cell center point except last row because we access ii[e]+1 */
for (e = 0; e < p->inputChan; e++)
- ii[e] = 0; /* init coords */
+ ii[e] = apxls_gmin[e]; /* init coords */
/* Compute linear interpolated value from center values */
for (ee = 0; ee < p->inputChan;) {
@@ -6051,14 +6334,15 @@ int icmSetMultiLutTables(
}
pn->clutTable[ti + f] = vv;
}
+ DBGSL(("nix %s apxls ov %s\n",icmPiv(p->inputChan, ii), icmPdv(pn->outputChan, ivn)));
}
}
/* Increment coord */
for (ee = 0; ee < p->inputChan; ee++) {
- if (++ii[ee] < (p->clutPoints-2)) /* Don't go through upper edge */
+ if (++ii[ee] < (apxls_gmax[ee]-1)) /* Stop short of upper row of clutTable2 */
break; /* No carry */
- ii[ee] = 0;
+ ii[ee] = apxls_gmin[ee];
}
}
@@ -6069,6 +6353,7 @@ int icmSetMultiLutTables(
}
/* Apply any smoothing in the clipped region to the resulting clutTable */
+ /* !!! should avoid smoothing outside apxls_gmin[e] & apxls_gmax[e] region !!! */
if (clutTable3 != NULL) {
double *clutTable1; /* Copy of current unfilted values */
FCOUNT(cc, MAX_CHAN, p->inputChan); /* Surrounding counter */
@@ -6180,7 +6465,7 @@ int icmSetMultiLutTables(
free(clutTable3);
}
- /* Create the output table entry values */
+ /* Create the 1D output table entry values */
for (tn = 0; tn < ntables; tn++) {
pn = pp[tn];
for (n = 0; n < pn->outputEnt; n++) {
@@ -6239,19 +6524,21 @@ int icmSetMultiLutTables(
/* Set errc and return error number */
/* Set warnc if there is clipping in the output values */
static int icmLut_set_tables (
-icmLut *p, /* Pointer to Lut object */
-int flags, /* Setting flags */
-void *cbctx, /* Opaque callback context pointer value */
-icColorSpaceSignature insig, /* Input color space */
-icColorSpaceSignature outsig, /* Output color space */
+icmLut *p, /* Pointer to Lut object */
+int flags, /* Setting flags */
+void *cbctx, /* Opaque callback context pointer value */
+icColorSpaceSignature insig, /* Input color space */
+icColorSpaceSignature outsig, /* Output color space */
void (*infunc)(void *cbcntx, double *out, double *in),
/* Input transfer function, inspace->inspace' (NULL = default) */
-double *inmin, double *inmax, /* Maximum range of inspace' values (NULL = default) */
+double *inmin, double *inmax, /* Maximum range of inspace' values (NULL = default) */
void (*clutfunc)(void *cbctx, double *out, double *in),
/* inspace' -> outspace' transfer function */
-double *clutmin, double *clutmax, /* Maximum range of outspace' values (NULL = default) */
-void (*outfunc)(void *cbctx, double *out, double *in)
- /* Output transfer function, outspace'->outspace (NULL = deflt) */
+double *clutmin, double *clutmax, /* Maximum range of outspace' values (NULL = default) */
+void (*outfunc)(void *cbctx, double *out, double *in),
+ /* Output transfer function, outspace'->outspace (NULL = deflt) */
+int *apxls_gmin, int *apxls_gmax /* If not NULL, the grid indexes not to be affected */
+ /* by ICM_CLUT_SET_APXLS, defaulting to 0..>clutPoints-1 */
) {
struct _icmLut *pp[3];
@@ -6263,7 +6550,8 @@ void (*outfunc)(void *cbctx, double *out, double *in)
inmin, inmax,
clutfunc,
clutmin, clutmax,
- outfunc);
+ outfunc,
+ apxls_gmin, apxls_gmax);
}
/* - - - - - - - - - - - - - - - - */
@@ -6347,16 +6635,8 @@ static int icmLut_read(
p->outputChan = read_UInt8Number(bp+9);
p->clutPoints = read_UInt8Number(bp+10);
- /* Sanity check */
- if (p->inputChan > MAX_CHAN) {
- sprintf(icp->err,"icmLut_read: Can't handle > %d input channels\n",MAX_CHAN);
- return icp->errc = 1;
- }
-
- if (p->outputChan > MAX_CHAN) {
- sprintf(icp->err,"icmLut_read: Can't handle > %d output channels\n",MAX_CHAN);
- return icp->errc = 1;
- }
+ if (icp->allowclutPoints256 && p->clutPoints == 0) /* Special case */
+ p->clutPoints = 256;
/* Read 3x3 transform matrix */
for (j = 0; j < 3; j++) { /* Rows */
@@ -6375,7 +6655,7 @@ static int icmLut_read(
bp = buf+52;
}
- /* Sanity check dimensions. This protects against */
+ /* Sanity check tag size. This protects against */
/* subsequent integer overflows involving the dimensions. */
if ((size = icmLut_get_size((icmBase *)p)) == UINT_MAX
|| size > len) {
@@ -6384,12 +6664,15 @@ static int icmLut_read(
return icp->errc = 1;
}
- /* Read the input tables */
- size = (p->inputChan * p->inputEnt);
+ /* Sanity check the dimensions and resolution values agains limits, */
+ /* allocate space for them and generate internal offset tables. */
if ((rv = p->allocate((icmBase *)p)) != 0) {
icp->al->free(icp->al, buf);
return rv;
}
+
+ /* Read the input tables */
+ size = (p->inputChan * p->inputEnt);
if (p->ttype == icSigLut8Type) {
for (i = 0; i < size; i++, bp += 1)
p->inputTable[i] = read_DCS8Number(bp);
@@ -6400,10 +6683,6 @@ static int icmLut_read(
/* Read the clut table */
size = (p->outputChan * sat_pow(p->clutPoints,p->inputChan));
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
if (p->ttype == icSigLut8Type) {
for (i = 0; i < size; i++, bp += 1)
p->clutTable[i] = read_DCS8Number(bp);
@@ -6414,10 +6693,6 @@ static int icmLut_read(
/* Read the output tables */
size = (p->outputChan * p->outputEnt);
- if ((rv = p->allocate((icmBase *)p)) != 0) {
- icp->al->free(icp->al, buf);
- return rv;
- }
if (p->ttype == icSigLut8Type) {
for (i = 0; i < size; i++, bp += 1)
p->outputTable[i] = read_DCS8Number(bp);
@@ -6426,20 +6701,6 @@ static int icmLut_read(
p->outputTable[i] = read_DCS16Number(bp);
}
- /* Private: compute dimensional increment though clut */
- /* Note that first channel varies least rapidly. */
- i = p->inputChan-1;
- p->dinc[i--] = p->outputChan;
- for (; i < p->inputChan; i--)
- p->dinc[i] = p->dinc[i+1] * p->clutPoints;
-
- /* Private: compute offsets from base of cube to other corners */
- for (p->dcube[0] = 0, g = 1, j = 0; j < p->inputChan; j++) {
- for (i = 0; i < g; i++)
- p->dcube[g+i] = p->dcube[i] + p->dinc[j];
- g *= 2;
- }
-
icp->al->free(icp->al, buf);
return 0;
}
@@ -6486,10 +6747,19 @@ static int icmLut_write(
icp->al->free(icp->al, buf);
return icp->errc = rv;
}
- if ((rv = write_UInt8Number(p->clutPoints, bp+10)) != 0) {
- sprintf(icp->err,"icmLut_write: write_UInt8Number() failed");
- icp->al->free(icp->al, buf);
- return icp->errc = rv;
+
+ if (icp->allowclutPoints256 && p->clutPoints == 256) {
+ if ((rv = write_UInt8Number(0, bp+10)) != 0) {
+ sprintf(icp->err,"icmLut_write: write_UInt8Number() failed");
+ icp->al->free(icp->al, buf);
+ return icp->errc = rv;
+ }
+ } else {
+ if ((rv = write_UInt8Number(p->clutPoints, bp+10)) != 0) {
+ sprintf(icp->err,"icmLut_write: write_UInt8Number() failed");
+ icp->al->free(icp->al, buf);
+ return icp->errc = rv;
+ }
}
write_UInt8Number(0, bp+11); /* Set padding to 0 */
@@ -6678,7 +6948,9 @@ static void icmLut_dump(
}
}
-/* Allocate variable sized data elements */
+/* Sanity check the input & output dimensions, and */
+/* allocate variable sized data elements, and */
+/* generate internal dimension offset tables */
static int icmLut_allocate(
icmBase *pp
) {
@@ -6686,7 +6958,7 @@ static int icmLut_allocate(
icmLut *p = (icmLut *)pp;
icc *icp = p->icp;
- /* Sanity check */
+ /* Sanity check, so that dinc[] comp. won't fail */
if (p->inputChan < 1) {
sprintf(icp->err,"icmLut_alloc: Can't handle %d input channels\n",p->inputChan);
return icp->errc = 1;
@@ -6800,6 +7072,8 @@ static icmBase *new_icmLut(
icmLut *p;
if ((p = (icmLut *) icp->al->calloc(icp->al,1,sizeof(icmLut))) == NULL)
return NULL;
+ p->icp = icp;
+
p->ttype = icSigLut16Type;
p->refcount = 1;
p->get_size = icmLut_get_size;
@@ -6820,8 +7094,7 @@ static icmBase *new_icmLut(
/* Set method */
p->set_tables = icmLut_set_tables;
-
- p->icp = icp;
+ p->tune_value = icmLut_tune_value_sx; /* Default to most likely simplex */
/* Set matrix to reasonable default */
for (i = 0; i < 3; i++)
@@ -7941,7 +8214,7 @@ static int icmColorantTable_allocate(
if (p->count != p->_count) {
unsigned int i;
if (ovr_mul(p->count, sizeof(icmColorantTableVal))) {
- sprintf(icp->err,"icmColorantTable_alloc: count overflow (%d of %ld bytes)",p->count,sizeof(icmColorantTableVal));
+ sprintf(icp->err,"icmColorantTable_alloc: count overflow (%d of %lu bytes)",p->count,sizeof(icmColorantTableVal));
return icp->errc = 1;
}
if (p->data != NULL)
@@ -10784,10 +11057,18 @@ static int icmHeader_read(
p->cmmId = read_SInt32Number(buf + 4); /* CMM for profile */
tt = read_UInt8Number(buf + 8); /* Raw major version number */
p->majv = (tt >> 4) * 10 + (tt & 0xf); /* Integer major version number */
- icp->ver = p->majv > 3 ? 1 : 0; /* Set major version flag in icc */
- tt = read_UInt8Number(buf + 9); /* Raw minor/bug fix version numbers */
+ tt = read_UInt8Number(buf + 9); /* Raw minor & bug fix version numbers */
p->minv = (tt >> 4); /* Integer minor version number */
p->bfv = (tt & 0xf); /* Integer bug fix version number */
+ if (p->majv < 3) { /* Set version class */
+ if (p->minv >= 4)
+ icp->ver = icmVersion2_4;
+ else if (p->minv >= 3)
+ icp->ver = icmVersion2_3;
+ else
+ icp->ver = icmVersionDefault;
+ } else
+ icp->ver = icmVersion4_1;
p->deviceClass = (icProfileClassSignature)
read_SInt32Number(buf + 12); /* Type of profile */
p->colorSpace = (icColorSpaceSignature)
@@ -10814,13 +11095,13 @@ static int icmHeader_read(
}
p->creator = read_SInt32Number(buf + 80); /* Profile creator */
- for (tt = 0; tt < 16; tt++)
- p->id[tt] = icp->ver ? read_UInt8Number(buf + 84 + tt) : 0; /* Profile ID */
+ for (tt = 0; tt < 16; tt++) /* Profile ID */
+ p->id[tt] = icp->ver >= icmVersion4_1 ? read_UInt8Number(buf + 84 + tt) : 0;
icp->al->free(icp->al, buf);
#ifndef ENABLE_V4
- if (icp->ver) {
+ if (icp->ver >= icmVersion4_1) {
sprintf(icp->err,"icmHeader_read: ICC V4 not supported!");
return icp->errc = 1;
}
@@ -10869,6 +11150,7 @@ static int icmHeader_write(
icp->al->free(icp->al, buf);
return icp->errc = 1;
}
+ // ~~~ Hmm. We're not checking ->ver is >= corresponding header version number ~~
tt = ((p->majv/10) << 4) + (p->majv % 10);
if ((rv = write_UInt8Number(tt, buf + 8)) != 0) { /* Raw major version number */
sprintf(icp->err,"icmHeader_write: Uint8Number major version");
@@ -10946,7 +11228,7 @@ static int icmHeader_write(
icp->al->free(icp->al, buf);
return icp->errc = rv;
}
- if (doid == 0 && icp->ver) { /* ID is V4.0+ feature */
+ if (doid == 0 && icp->ver >= icmVersion4_1) { /* ID is V4.0+ feature */
for (tt = 0; tt < 16; tt++) {
if ((rv = write_UInt8Number(p->id[tt], buf + 84 + tt)) != 0) { /* Profile ID */
sprintf(icp->err,"icmHeader_write: UInt8Number creator");
@@ -10992,7 +11274,7 @@ static void icmHeader_dump(
op->gprintf(op," Rndrng Intnt = %s\n", string_RenderingIntent(p->renderingIntent));
op->gprintf(op," Illuminant = %s\n", string_XYZNumber_and_Lab(&p->illuminant));
op->gprintf(op," Creator = %s\n", tag2str(p->creator)); /* ~~~ */
- if (p->icp->ver) { /* V4.0+ feature */
+ if (p->icp->ver >= icmVersion4_1) { /* V4.0+ feature */
for (i = 0; i < 16; i++) { /* Check if ID has been set */
if (p->id[i] != 0)
break;
@@ -11369,10 +11651,15 @@ static int check_icc_legal(
/* Found entry, so now check that all the required tags are present. */
for (j = 0; tagchecktable[i].tags[j] != icMaxEnumType; j++) {
if (p->find_tag(p, tagchecktable[i].tags[j]) != 0) { /* Not present! */
+#ifdef NEVER
+ printf("icc_check_legal: deviceClass %s is missing required tag %s", tag2str(sig), tag2str(tagchecktable[i].tags[j]));
+#endif
if (tagchecktable[i].chans == -200
|| tagchecktable[i].chans == -dchans) { /* But can try next table */
break;
}
+ /* ~~99 Hmm. Should report all possible missing tags from */
+ /* previous failed tables ~~~999 */
sprintf(p->err,"icc_check_legal: deviceClass %s is missing required tag %s",
tag2str(sig), tag2str(tagchecktable[i].tags[j]));
return p->errc = 1;
@@ -11776,7 +12063,7 @@ static int icc_write_x(
/* If V4.0+, Compute the MD5 id for the profile. */
/* We do this by writing to a fake icmFile */
- if (p->ver) {
+ if (p->ver >= icmVersion4_1) {
icmMD5 *md5 = NULL;
icmFile *ofp, *dfp = NULL;
@@ -11796,13 +12083,13 @@ static int icc_write_x(
ofp = p->fp;
p->fp = dfp;
- /* Dumy write the header */
+ /* Dummy write the header */
if ((rv = p->header->write(p->header, 0, 1)) != 0) {
p->al->free(p->al, buf);
return rv;
}
- /* Dumy write the tag table */
+ /* Dummy write the tag table */
if ( p->fp->seek(p->fp, 128) != 0
|| p->fp->write(p->fp, buf, 1, len) != len) {
sprintf(p->err,"icc_write: seek() or write() failed");
@@ -11810,7 +12097,7 @@ static int icc_write_x(
return p->errc = 1;
}
- /* Dumy write all the tag element data */
+ /* Dummy write all the tag element data */
/* (We invert meaning of touched here) */
for (i = 0; i < p->count; i++) { /* For all the tag element data */
if (p->data[i].objp->touched == 0)
@@ -12197,8 +12484,8 @@ static icmBase *icc_read_tag_ix(
}
/* Read the tag element data of the first matching, and return a pointer to the object */
-/* Returns NULL if error - icc->errc will contain: */
-/* 2 if not found */
+/* Returns NULL if error - icc->errc will contain: */
+/* 2 if not found */
/* Doesn't read uknown type tags */
static icmBase *icc_read_tag(
icc *p,
@@ -12222,7 +12509,7 @@ static icmBase *icc_read_tag(
}
/* Read the tag element data of the first matching, and return a pointer to the object */
-/* Returns NULL if error.
+/* Returns NULL if error. */
/* Returns an icmSigUnknownType object if the tag type isn't handled by a specific object. */
/* NOTE: we don't handle tag duplication - you'll always get the first in the file. */
static icmBase *icc_read_tag_any(
@@ -12651,6 +12938,25 @@ static void Lut_Luv2Lut(double *out, double *in) {
}
/* - - - - - - - - - - - - - - - - */
+/* Convert YCbCr to Lut number */
+/* We are assuming full range here. foot/head scaling */
+/* should be done outside the icc profile. */
+
+/* Convert Lut table index/value to YCbCr */
+static void Lut_Lut2YCbCr(double *out, double *in) {
+ out[0] = in[0]; /* Y */
+ out[1] = in[1] - 0.5; /* Cb */
+ out[2] = in[2] - 0.5; /* Cr */
+}
+
+/* Convert YCbCr to Lut table index/value */
+static void Lut_YCbCr2Lut(double *out, double *in) {
+ out[0] = in[0]; /* Y */
+ out[1] = in[1] + 0.5; /* Cb */
+ out[2] = in[2] + 0.5; /* Cr */
+}
+
+/* - - - - - - - - - - - - - - - - */
/* Default N component conversions */
static void Lut_N(double *out, double *in, int nc) {
for (--nc; nc >= 0; nc--)
@@ -12749,7 +13055,6 @@ static void Lut_15(double *out, double *in) {
/* Function table - match conversions to color spaces. */
/* Anything not here, we don't know how to convert. */
-/* (ie. YCbCr) */
static struct {
icColorSpaceSignature csig;
void (*fromLut)(double *out, double *in); /* from Lut index/entry */
@@ -12764,6 +13069,7 @@ static struct {
{icmSigLV2Data, Lut_Lut2LV2_16, Lut_L2LutV2_16 },
{icmSigLV4Data, Lut_Lut2LV4_16, Lut_L2LutV4_16 },
{icSigLuvData, Lut_Lut2Luv, Lut_Luv2Lut },
+ {icSigYCbCrData, Lut_Lut2YCbCr, Lut_YCbCr2Lut },
{icSigYxyData, Lut_3, Lut_3 },
{icSigRgbData, Lut_3, Lut_3 },
{icSigGrayData, Lut_1, Lut_1 },
@@ -12837,7 +13143,7 @@ static int getNormFunc(
if (tagType == icSigLut16Type) /* Lut16 retains legacy encoding */
csig = icmSigLabV2Data;
else { /* Other tag types use version specific encoding */
- if (icp->ver)
+ if (icp->ver >= icmVersion4_1)
csig = icmSigLabV4Data;
else
csig = icmSigLabV2Data;
@@ -12870,7 +13176,6 @@ static int getNormFunc(
/* Function table - match ranges to color spaces. */
/* Anything not here, we don't know how to convert. */
-/* (ie. YCbCr) */
/* Hmm. we're not handling Lab8 properly ?? ~~~8888 */
static struct {
icColorSpaceSignature csig;
@@ -12889,7 +13194,7 @@ static struct {
{icmSigLV4Data, 1, { 0.0 }, { 100.0 } },
{icSigLuvData, 0, { 0.0, -128.0, -128.0 },
{ 100.0, 127.0 + 255.0/256.0, 127.0 + 255.0/256.0 } },
- {icSigYCbCrData, 1, { 0.0 }, { 1.0 } }, /* ??? */
+ {icSigYCbCrData, 0, { 0.0, -0.5, -0.5 }, { 1.0, 0.5, 0.5 } }, /* Full range */
{icSigYxyData, 1, { 0.0 }, { 1.0 } }, /* ??? */
{icSigRgbData, 1, { 0.0 }, { 1.0 } },
{icSigGrayData, 1, { 0.0 }, { 1.0 } },
@@ -12940,7 +13245,7 @@ static int getRange(
if (tagType == icSigLut16Type) /* Lut16 retains legacy encoding */
csig = icmSigLabV2Data;
else { /* Other tag types use version specific encoding */
- if (icp->ver)
+ if (icp->ver >= icmVersion4_1)
csig = icmSigLabV4Data;
else
csig = icmSigLabV2Data;
@@ -12974,8 +13279,8 @@ static int getRange(
return 0;
}
-/* ============================================= */
-/* Misc. support functions. */
+/* =============================================================== */
+/* Misc. support functions. */
/* Clamp a 3 vector to be +ve */
void icmClamp3(double out[3], double in[3]) {
@@ -12998,6 +13303,20 @@ void icmSub3(double out[3], double in1[3], double in2[3]) {
out[2] = in1[2] - in2[2];
}
+/* Divide two 3 vectors, out = in1/in2 */
+void icmDiv3(double out[3], double in1[3], double in2[3]) {
+ out[0] = in1[0]/in2[0];
+ out[1] = in1[1]/in2[1];
+ out[2] = in1[2]/in2[2];
+}
+
+/* Multiply two 3 vectors, out = in1 * in2 */
+void icmMul3(double out[3], double in1[3], double in2[3]) {
+ out[0] = in1[0] * in2[0];
+ out[1] = in1[1] * in2[1];
+ out[2] = in1[2] * in2[2];
+}
+
/* - - - - - - - - - - - - - - - - - - - - - - - - */
/* Set a 3x3 matrix to unity */
@@ -13307,6 +13626,18 @@ void icmBlend3(double out[3], double in0[3], double in1[3], double bf) {
out[2] = (1.0 - bf) * in0[2] + bf * in1[2];
}
+/* Clip a vector to the range 0.0 .. 1.0 */
+void icmClip3(double out[3], double in[3]) {
+ int j;
+ for (j = 0; j < 3; j++) {
+ out[j] = in[j];
+ if (out[j] < 0.0)
+ out[j] = 0.0;
+ else if (out[j] > 1.0)
+ out[j] = 1.0;
+ }
+}
+
/* Normalise a 3 vector to the given length. Return nz if not normalisable */
int icmNormalize3(double out[3], double in[3], double len) {
double tt = sqrt(in[0] * in[0] + in[1] * in[1] + in[2] * in[2]);
@@ -13681,6 +14012,74 @@ double icmPlaneDist3(double eq[4], double p[3]) {
}
/* - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Given 2 2D points, compute a plane equation. */
+/* The normal will be right handed given the order of the points */
+/* The plane equation will be the 2 normal components and the constant. */
+/* Return nz if any points are cooincident or co-linear */
+int icmPlaneEqn2(double eq[3], double p0[2], double p1[2]) {
+ double ll, v1[3];
+
+ /* Compute vectors along edge */
+ v1[0] = p1[0] - p0[0];
+ v1[1] = p1[1] - p0[1];
+
+ /* Normal to vector */
+ eq[0] = v1[1];
+ eq[1] = -v1[0];
+
+ /* Normalise the equation */
+ ll = sqrt(eq[0] * eq[0] + eq[1] * eq[1]);
+ if (ll < 1e-10) {
+ return 1;
+ }
+ eq[0] /= ll;
+ eq[1] /= ll;
+
+ /* Compute the plane equation constant */
+ eq[2] = - (eq[0] * p0[0])
+ - (eq[1] * p0[1]);
+
+ return 0;
+}
+
+/* Given a 2D point and a plane equation, return the signed */
+/* distance from the plane. The distance will be +ve if the point */
+/* is to the right of the plane formed by two points in order */
+double icmPlaneDist2(double eq[3], double p[2]) {
+ double rv;
+
+ rv = eq[0] * p[0]
+ + eq[1] * p[1]
+ + eq[2];
+
+ return rv;
+}
+
+/* Given two infinite 2D lines define by 4 points, compute the intersection. */
+/* Return nz if there is no intersection (lines are parallel) */
+int icmLineIntersect2(double res[2], double p1[2], double p2[2], double p3[2], double p4[2]) {
+ /* Compute by determinants */
+ double x1y2_y1x2 = p1[0] * p2[1] - p1[1] * p2[0];
+ double x3y4_y3x4 = p3[0] * p4[1] - p3[1] * p4[0];
+ double x1_x2 = p1[0] - p2[0];
+ double y1_y2 = p1[1] - p2[1];
+ double x3_x4 = p3[0] - p4[0];
+ double y3_y4 = p3[1] - p4[1];
+ double num; /* Numerator */
+
+ num = x1_x2 * y3_y4 - y1_y2 * x3_x4;
+
+ if (fabs(num) < 1e-10)
+ return 1;
+
+ res[0] = (x1y2_y1x2 * x3_x4 - x1_x2 * x3y4_y3x4)/num;
+ res[1] = (x1y2_y1x2 * y3_y4 - y1_y2 * x3y4_y3x4)/num;
+
+ return 0;
+}
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - */
/* CIE Y (range 0 .. 1) to perceptual CIE 1976 L* (range 0 .. 100) */
double
icmY2L(double val) {
@@ -13778,7 +14177,7 @@ void icmLCh2Lab(double *out, double *in) {
out[2] = C * sin(h);
}
-/* Lab to LCh */
+/* Lab to LCh (general to polar, works with Luv too) */
void icmLab2LCh(double *out, double *in) {
double C, h;
@@ -13883,9 +14282,6 @@ extern ICCLIB_API void icmLuv2XYZ(icmXYZNumber *w, double *out, double *in) {
out[2] = Z;
}
-/* NOTE :- none of the following seven have been protected */
-/* against arithmmetic issues (ie. for black) */
-
/* CIE XYZ to perceptual CIE 1976 UCS diagram Yu'v'*/
/* (Yu'v' is a better chromaticity space than Yxy) */
extern ICCLIB_API void icmXYZ21976UCS(double *out, double *in) {
@@ -13893,8 +14289,15 @@ extern ICCLIB_API void icmXYZ21976UCS(double *out, double *in) {
double den, u, v;
den = (X + 15.0 * Y + 3.0 * Z);
- u = (4.0 * X) / den;
- v = (9.0 * Y) / den;
+
+ if (den < 1e-9) {
+ Y = 0.0;
+ u = 4.0/19.0;
+ v = 9.0/19.0;
+ } else {
+ u = (4.0 * X) / den;
+ v = (9.0 * Y) / den;
+ }
out[0] = Y;
out[1] = u;
@@ -13909,8 +14312,12 @@ extern ICCLIB_API void icm1976UCS2XYZ(double *out, double *in) {
u = in[1];
v = in[2];
- X = ((9.0 * u * Y)/(4.0 * v));
- Z = -(((20.0 * v + 3.0 * u - 12.0) * Y)/(4.0 * v));
+ if (v < 1e-9) {
+ X = Y = Z = 0.0;
+ } else {
+ X = ((9.0 * u * Y)/(4.0 * v));
+ Z = -(((20.0 * v + 3.0 * u - 12.0) * Y)/(4.0 * v));
+ }
out[0] = X;
out[1] = Y;
@@ -13922,10 +14329,18 @@ extern ICCLIB_API void icm1976UCS2XYZ(double *out, double *in) {
/* in computing color temperatures.) */
extern ICCLIB_API void icmXYZ21960UCS(double *out, double *in) {
double X = in[0], Y = in[1], Z = in[2];
- double u, v;
+ double den, u, v;
- u = (4.0 * X) / (X + 15.0 * Y + 3.0 * Z);
- v = (6.0 * Y) / (X + 15.0 * Y + 3.0 * Z);
+ den = (X + 15.0 * Y + 3.0 * Z);
+
+ if (den < 1e-9) {
+ Y = 0.0;
+ u = 4.0/19.0;
+ v = 6.0/19.0;
+ } else {
+ u = (4.0 * X) / den;
+ v = (6.0 * Y) / den;
+ }
out[0] = Y;
out[1] = u;
@@ -13940,8 +14355,12 @@ extern ICCLIB_API void icm1960UCS2XYZ(double *out, double *in) {
u = in[1];
v = in[2];
- X = ((3.0 * u * Y)/(2.0 * v));
- Z = -(((10.0 * v + u - 4.0) * Y)/(2.0 * v));
+ if (v < 1e-9) {
+ X = Y = Z = 0.0;
+ } else {
+ X = ((3.0 * u * Y)/(2.0 * v));
+ Z = -(((10.0 * v + u - 4.0) * Y)/(2.0 * v));
+ }
out[0] = X;
out[1] = Y;
@@ -13989,6 +14408,7 @@ extern ICCLIB_API void icm1964WUV2XYZ(icmXYZNumber *w, double *out, double *in)
}
/* CIE CIE1960 UCS to perceptual CIE 1964 WUV (U*V*W*) */
+/* (This is used in computing CRI) */
extern ICCLIB_API void icm1960UCS21964WUV(icmXYZNumber *w, double *out, double *in) {
double W, U, V;
double wucs[3];
@@ -14006,6 +14426,7 @@ extern ICCLIB_API void icm1960UCS21964WUV(icmXYZNumber *w, double *out, double *
}
/* - - - - - - - - - - - - - - - - - - - - - - - - */
+/* NOTE :- that these values are for the 1931 standard observer */
/* available D50 Illuminant */
icmXYZNumber icmD50 = { /* Profile illuminant - D50 */
@@ -14041,6 +14462,7 @@ double icmD65_100_ary3[3] = { /* Profile illuminant - D65, scaled to 100 */
95.05, 100.00, 108.90
};
+
/* Default black point */
icmXYZNumber icmBlack = {
0.0000, 0.0000, 0.0000
@@ -14126,7 +14548,7 @@ double icmCIE94sq(double Lab0[3], double Lab1[3]) {
c12 = sqrt(c1 * c2); /* Symetric chromanance */
/* delta chromanance squared */
- dc = c2 - c1;
+ dc = c1 - c2;
dcsq = dc * dc;
}
@@ -14137,8 +14559,8 @@ double icmCIE94sq(double Lab0[3], double Lab1[3]) {
double sc, sh;
/* Weighting factors for delta chromanance & delta hue */
- sc = 1.0 + 0.048 * c12;
- sh = 1.0 + 0.014 * c12;
+ sc = 1.0 + 0.045 * c12;
+ sh = 1.0 + 0.015 * c12;
return dlsq + dcsq/(sc * sc) + dhsq/(sh * sh);
}
}
@@ -14286,7 +14708,7 @@ double icmCIE2K(double *Lab0, double *Lab1) {
}
/* Return the CIEDE2000 Delta E color difference measure for two XYZ values */
-extern ICCLIB_API double icmXYZCIE2K(icmXYZNumber *w, double *in0, double *in1) {
+ICCLIB_API double icmXYZCIE2K(icmXYZNumber *w, double *in0, double *in1) {
double lab0[3], lab1[3];
icmXYZ2Lab(w, lab0, in0);
@@ -14295,12 +14717,15 @@ extern ICCLIB_API double icmXYZCIE2K(icmXYZNumber *w, double *in0, double *in1)
}
+
/* - - - - - - - - - - - - - - - - - - - - - - - - */
/* Chromatic adaptation transform utility */
/* Return a 3x3 chromatic adaptation matrix */
/* Use icmMulBy3x3(dst, mat, src) */
+/* NOTE that to transform primaries they */
+/* must be mat[XYZ][RGB] format! */
void icmChromAdaptMatrix(
- int flags, /* Use bradford, Transform given matrix flags */
+ int flags, /* Use Bradford, Transform given matrix flags */
icmXYZNumber d_wp, /* Destination white point */
icmXYZNumber s_wp, /* Source white point */
double mat[3][3] /* Destination matrix */
@@ -14376,7 +14801,7 @@ int icmRGBprim2matrix(
icmXYZNumber red, /* Red colorant */
icmXYZNumber green, /* Green colorant */
icmXYZNumber blue, /* Blue colorant */
- double mat[3][3] /* Destination matrix */
+ double mat[3][3] /* Destination matrix[RGB][XYZ] */
) {
double tmat[3][3];
double t[3];
@@ -14409,19 +14834,73 @@ int icmRGBprim2matrix(
/* Now formulate the transform matrix */
mat[0][0] = red.X * t[0];
- mat[0][1] = green.X * t[1];
- mat[0][2] = blue.X * t[2];
- mat[1][0] = red.Y * t[0];
+ mat[1][0] = green.X * t[1];
+ mat[2][0] = blue.X * t[2];
+ mat[0][1] = red.Y * t[0];
mat[1][1] = green.Y * t[1];
- mat[1][2] = blue.Y * t[2];
- mat[2][0] = red.Z * t[0];
- mat[2][1] = green.Z * t[1];
+ mat[2][1] = blue.Y * t[2];
+ mat[0][2] = red.Z * t[0];
+ mat[1][2] = green.Z * t[1];
mat[2][2] = blue.Z * t[2];
return 0;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Pre-round RGB device primary values to ensure that */
+/* the sum of the quantized primaries is the same as */
+/* the quantized sum. */
+void quantizeRGBprimsS15Fixed16(
+ double mat[3][3] /* matrix[RGB][XYZ] */
+) {
+ int i, j;
+ double sum[3];
+
+// printf("D50 = %f %f %f\n",icmD50.X, icmD50.Y, icmD50.Z);
+
+ /* Compute target sum of primary XYZ */
+ for (i = 0; i < 3; i++) {
+ sum[i] = 0.0;
+ for (j = 0; j < 3; j++)
+ sum[i] += mat[j][i];
+ }
+// printf("Sum = %f %f %f\n",sum[0], sum[1], sum[2]);
+
+ /* Pre-quantize the primary XYZ's, and then ensure that the */
+ /* sum of the quantized values is the quantized sum by assigning */
+ /* the rounding error to the largest component. */
+ for (i = 0; i < 3; i++) {
+ int bix = 0;
+ double bval = -1e9;
+
+ /* locate the largest and quantize each component */
+ for (j = 0; j < 3; j++) {
+ if (fabs(mat[j][i]) > bval) { /* Locate largest */
+ bix = j;
+ bval = fabs(mat[j][i]);
+ }
+ mat[j][i] = round_S15Fixed16Number(mat[j][i]);
+ }
+
+ /* Compute the value the largest has to be */
+ /* to ensure that sum of the quantized values is */
+ /* equal to the quantized sum */
+ for (j = 0; j < 3; j++) {
+ if (j == bix)
+ continue;
+ sum[i] -= mat[j][i];
+ }
+ mat[bix][i] = round_S15Fixed16Number(sum[i]);
+
+ /* Check the sum of the quantized values */
+// sum[i] = 0.0;
+// for (j = 0; j < 3; j++)
+// sum[i] += mat[j][i];
+ }
+// printf("Q Sum = %f %f %f\n",sum[0], sum[1], sum[2]);
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - */
/* Some PCS utility functions */
/* Clip Lab, while maintaining hue angle. */
@@ -14525,7 +15004,426 @@ int icmClipXYZ(double out[3], double in[3]) {
return 1;
}
-/* - - - - - - - - - - - - - - - - - - - - - - - - */
+/* --------------------------------------------------------------- */
+/* Some video specific functions */
+
+/* Convert Lut table index/value to YPbPr */
+/* (Same as Lut_Lut2YPbPr() ) */
+void icmLut2YPbPr(double *out, double *in) {
+ out[0] = in[0]; /* Y */
+ out[1] = in[1] - 0.5; /* Cb */
+ out[2] = in[2] - 0.5; /* Cr */
+}
+
+/* Convert YPbPr to Lut table index/value */
+/* (Same as Lut_YPbPr2Lut() ) */
+void icmYPbPr2Lut(double *out, double *in) {
+ out[0] = in[0]; /* Y */
+ out[1] = in[1] + 0.5; /* Cb */
+ out[2] = in[2] + 0.5; /* Cr */
+}
+
+/* Convert Rec601 RGB' into YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+/* [From the Rec601 spec. ] */
+void icmRec601_RGBd_2_YPbPr(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 0.299 * in[0] + 0.587 * in[1] + 0.114 * in[2];
+
+ tt[1] = -0.299 /1.772 * in[0]
+ + -0.587 /1.772 * in[1]
+ + (1.0-0.114)/1.772 * in[2];
+
+ tt[2] = (1.0-0.299)/1.402 * in[0]
+ + -0.587 /1.402 * in[1]
+ + -0.114 /1.402 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec601 YPbPr to RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+/* [Inverse of above] */
+void icmRec601_YPbPr_2_RGBd(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 1.000000000 * in[0] + 0.000000000 * in[1] + 1.402000000 * in[2];
+ tt[1] = 1.000000000 * in[0] + -0.344136286 * in[1] + -0.714136286 * in[2];
+ tt[2] = 1.000000000 * in[0] + 1.772000000 * in[1] + 0.000000000 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+
+/* Convert Rec709 1150/60/2:1 RGB' into YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+/* [From the Rec709 specification] */
+void icmRec709_RGBd_2_YPbPr(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 0.2126 * in[0] + 0.7152 * in[1] + 0.0722 * in[2];
+
+ tt[1] = 0.5389 * -0.2126 * in[0]
+ + 0.5389 * -0.7152 * in[1]
+ + 0.5389 * (1.0-0.0722) * in[2];
+
+ tt[2] = 0.6350 * (1.0-0.2126) * in[0]
+ + 0.6350 * -0.7152 * in[1]
+ + 0.6350 * -0.0722 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec709 1150/60/2:1 YPbPr to RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+/* [Inverse of above] */
+void icmRec709_YPbPr_2_RGBd(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 1.000000000 * in[0] + 0.000000000 * in[1] + 1.574803150 * in[2];
+ tt[1] = 1.000000000 * in[0] + -0.187327487 * in[1] + -0.468125209 * in[2];
+ tt[2] = 1.000000000 * in[0] + 1.855631843 * in[1] + 0.000000000 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec709 1250/50/2:1 RGB' into YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+/* [From the Rec709 specification] */
+void icmRec709_50_RGBd_2_YPbPr(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 0.299 * in[0] + 0.587 * in[1] + 0.114 * in[2];
+
+ tt[1] = 0.564 * -0.299 * in[0]
+ + 0.564 * -0.587 * in[1]
+ + 0.564 * (1.0-0.114) * in[2];
+
+ tt[2] = 0.713 * (1.0-0.299) * in[0]
+ + 0.713 * -0.587 * in[1]
+ + 0.713 * -0.114 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec709 1250/50/2:1 YPbPr to RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+/* [Inverse of above] */
+void icmRec709_50_YPbPr_2_RGBd(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 1.000000000 * in[0] + 0.000000000 * in[1] + 1.402524544 * in[2];
+ tt[1] = 1.000000000 * in[0] + -0.344340136 * in[1] + -0.714403473 * in[2];
+ tt[2] = 1.000000000 * in[0] + 1.773049645 * in[1] + 0.000000000 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+
+/* Convert Rec2020 RGB' into Non-constant liminance YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+/* [From the Rec2020 specification] */
+void icmRec2020_NCL_RGBd_2_YPbPr(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 0.2627 * in[0] + 0.6780 * in[1] + 0.0593 * in[2];
+
+ tt[1] = 1/1.8814 * -0.2627 * in[0]
+ + 1/1.8814 * -0.6780 * in[1]
+ + 1/1.8814 * (1.0-0.0593) * in[2];
+
+ tt[2] = 1/1.4746 * (1.0-0.2627) * in[0]
+ + 1/1.4746 * -0.6780 * in[1]
+ + 1/1.4746 * -0.0593 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec2020 Non-constant liminance YPbPr into RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+/* [Inverse of above] */
+void icmRec2020_NCL_YPbPr_2_RGBd(double out[3], double in[3]) {
+ double tt[3];
+
+ tt[0] = 1.000000000 * in[0] + 0.000000000 * in[1] + 1.474600000 * in[2];
+ tt[1] = 1.000000000 * in[0] + -0.164553127 * in[1] + -0.571353127 * in[2];
+ tt[2] = 1.000000000 * in[0] + 1.881400000 * in[1] + 0.000000000 * in[2];
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec2020 RGB' into Constant liminance YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+/* [From the Rec2020 specification] */
+void icmRec2020_CL_RGBd_2_YPbPr(double out[3], double in[3]) {
+ int i;
+ double tt[3];
+
+ /* Convert RGB' to RGB */
+ for (i = 0; i < 3; i++) {
+ if (in[i] < (4.5 * 0.0181))
+ tt[i] = in[i]/4.5;
+ else
+ tt[i] = pow((in[i] + 0.0993)/1.0993, 1.0/0.45);
+ }
+
+ /* Y value */
+ tt[0] = 0.2627 * tt[0] + 0.6780 * tt[1] + 0.0593 * tt[2];
+
+ /* Y' value */
+ if (tt[0] < 0.0181)
+ tt[0] = tt[0] * 4.5;
+ else
+ tt[0] = 1.0993 * pow(tt[0], 0.45) - 0.0993;
+
+ tt[1] = in[2] - tt[0];
+ if (tt[1] <= 0.0)
+ tt[1] /= 1.9404;
+ else
+ tt[1] /= 1.5816;
+
+ tt[2] = in[0] - tt[0];
+ if (tt[2] <= 0.0)
+ tt[2] /= 1.7184;
+ else
+ tt[2] /= 0.9936;
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+/* Convert Rec2020 Constant liminance YPbPr into RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+/* [Inverse of above] */
+void icmRec2020_CL_YPbPr_2_RGBd(double out[3], double in[3]) {
+ int i;
+ double tin[3], tt[3];
+
+ /* Y' */
+ tin[0] = in[0];
+
+ /* B' - Y' */
+ if (in[1] <= 0.0)
+ tin[1] = 1.9404 * in[1];
+ else
+ tin[1] = 1.5816 * in[1];
+
+ /* R' - Y' */
+ if (in[2] <= 0.0)
+ tin[2] = 1.7184 * in[2];
+ else
+ tin[2] = 0.9936 * in[2];
+
+
+ /* R' */
+ tt[0] = tin[2] + tin[0];
+
+ /* Y' */
+ tt[1] = tin[0];
+
+ /* B' */
+ tt[2] = tin[1] + tin[0];
+
+ /* Convert RYB' to RYB */
+ for (i = 0; i < 3; i++) {
+ if (tt[i] < (4.5 * 0.0181))
+ tin[i] = tt[i]/4.5;
+ else
+ tin[i] = pow((tt[i] + 0.0993)/1.0993, 1.0/0.45);
+ }
+
+ /* G */
+ tt[1] = (tin[1] - 0.2627 * tin[0] - 0.0593 * tin[2])/0.6780;
+
+ /* G' */
+ if (tt[1] < 0.0181)
+ tt[1] = tt[1] * 4.5;
+ else
+ tt[1] = 1.0993 * pow(tt[1], 0.45) - 0.0993;
+
+ out[0] = tt[0];
+ out[1] = tt[1];
+ out[2] = tt[2];
+}
+
+
+/* Convert Rec601/Rec709/Rec2020 YPbPr to YCbCr Video range. */
+/* input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, */
+/* output 16/255 .. 235/255, 16/255 .. 240/255, 16/255 .. 240/255 */
+void icmRecXXX_YPbPr_2_YCbCr(double out[3], double in[3]) {
+ out[0] = ((235.0 - 16.0) * in[0] + 16.0)/255.0;
+ out[1] = ((128.0 - 16.0) * 2.0 * in[1] + 128.0)/255.0;
+ out[2] = ((128.0 - 16.0) * 2.0 * in[2] + 128.0)/255.0;
+}
+
+/* Convert Rec601/Rec709/Rec2020 Video YCbCr to YPbPr range. */
+/* input 16/255 .. 235/255, 16/255 .. 240/255, 16/255 .. 240/255 */
+/* output 0..1, -0.5 .. 0.5, -0.5 .. 0.5, */
+void icmRecXXX_YCbCr_2_YPbPr(double out[3], double in[3]) {
+ out[0] = (255.0 * in[0] - 16.0)/(235.0 - 16.0);
+ out[1] = (255.0 * in[1] - 128.0)/(2.0 * (128.0 - 16.0));
+ out[2] = (255.0 * in[2] - 128.0)/(2.0 * (128.0 - 16.0));
+}
+
+/* Convert full range RGB to Video range 16..235 RGB */
+void icmRGB_2_VidRGB(double out[3], double in[3]) {
+ out[0] = ((235.0 - 16.0) * in[0] + 16.0)/255.0;
+ out[1] = ((235.0 - 16.0) * in[1] + 16.0)/255.0;
+ out[2] = ((235.0 - 16.0) * in[2] + 16.0)/255.0;
+}
+
+/* Convert Video range 16..235 RGB to full range RGB */
+/* Return nz if outside RGB range */
+void icmVidRGB_2_RGB(double out[3], double in[3]) {
+ out[0] = (255.0 * in[0] - 16.0)/(235.0 - 16.0);
+ out[1] = (255.0 * in[1] - 16.0)/(235.0 - 16.0);
+ out[2] = (255.0 * in[2] - 16.0)/(235.0 - 16.0);
+}
+
+/* =============================================================== */
+/* PS 3.14-2009, Digital Imaging and Communications in Medicine */
+/* (DICOM) Part 14: Grayscale Standard Display Function */
+
+/* JND index value 1..1023 to L 0.05 .. 3993.404 cd/m^2 */
+static double icmDICOM_fwd_nl(double jnd) {
+ double a = -1.3011877;
+ double b = -2.5840191e-2;
+ double c = 8.0242636e-2;
+ double d = -1.0320229e-1;
+ double e = 1.3646699e-1;
+ double f = 2.8745620e-2;
+ double g = -2.5468404e-2;
+ double h = -3.1978977e-3;
+ double k = 1.2992634e-4;
+ double m = 1.3635334e-3;
+ double jj, num, den, rv;
+
+ jj = jnd = log(jnd);
+
+ num = a;
+ den = 1.0;
+ num += c * jj;
+ den += b * jj;
+ jj *= jnd;
+ num += e * jj;
+ den += d * jj;
+ jj *= jnd;
+ num += g * jj;
+ den += f * jj;
+ jj *= jnd;
+ num += m * jj;
+ den += h * jj;
+ jj *= jnd;
+ den += k * jj;
+
+ rv = pow(10.0, num/den);
+
+ return rv;
+}
+
+/* JND index value 1..1023 to L 0.05 .. 3993.404 cd/m^2 */
+double icmDICOM_fwd(double jnd) {
+
+ if (jnd < 0.5)
+ jnd = 0.5;
+ if (jnd > 1024.0)
+ jnd = 1024.0;
+
+ return icmDICOM_fwd_nl(jnd);
+}
+
+/* L 0.05 .. 3993.404 cd/m^2 to JND index value 1..1023 */
+/* This is not super accurate - typically to 0.03 .. 0.1 jne. */
+static double icmDICOM_bwd_apx(double L) {
+ double A = 71.498068;
+ double B = 94.593053;
+ double C = 41.912053;
+ double D = 9.8247004;
+ double E = 0.28175407;
+ double F = -1.1878455;
+ double G = -0.18014349;
+ double H = 0.14710899;
+ double I = -0.017046845;
+ double rv, LL;
+
+ if (L < 0.049982) { /* == jnd 0.5 */
+ return 0.5;
+ }
+ if (L > 4019.354716) /* == jnd 1024 */
+ L = 4019.354716;
+
+ LL = L = log10(L);
+ rv = A;
+ rv += B * LL;
+ LL *= L;
+ rv += C * LL;
+ LL *= L;
+ rv += D * LL;
+ LL *= L;
+ rv += E * LL;
+ LL *= L;
+ rv += F * LL;
+ LL *= L;
+ rv += G * LL;
+ LL *= L;
+ rv += H * LL;
+ LL *= L;
+ rv += I * LL;
+
+ return rv;
+}
+
+/* L 0.05 .. 3993.404 cd/m^2 to JND index value 1..1023 */
+/* Polish the aproximate solution twice using Newton's itteration */
+double icmDICOM_bwd(double L) {
+ double rv, Lc, prv, pLc, de;
+ int i;
+
+ if (L < 0.045848) /* == jnd 0.5 */
+ L = 0.045848;
+ if (L > 4019.354716) /* == jnd 1024 */
+ L = 4019.354716;
+
+ /* Approx solution */
+ rv = icmDICOM_bwd_apx(L);
+
+ /* Compute aprox derivative */
+ Lc = icmDICOM_fwd_nl(rv);
+
+ prv = rv + 0.01;
+ pLc = icmDICOM_fwd_nl(prv);
+
+ do {
+ de = (rv - prv)/(Lc - pLc);
+ prv = rv;
+ rv -= (Lc - L) * de;
+ pLc = Lc;
+ Lc = icmDICOM_fwd_nl(rv);
+ } while (fabs(Lc - L) > 1e-8);
+
+ return rv;
+}
+
+
+/* =============================================================== */
/* Object for computing RFC 1321 MD5 checksums. */
/* Derived from Colin Plumb's 1993 public domain code. */
@@ -16169,25 +17067,25 @@ double *in /* Vector of input values */
icmLut *lut = p->lut;
double temp[MAX_CHAN];
- DBGLL(("icmLuLut_lookup: in = %s\n", icmPdv(p->inputChan, in)));
+ DBGLL(("icmLuLut_lookup: in = %s\n", icmPdv(p->lut->inputChan, in)));
rv |= p->in_abs(p,temp,in); /* Possible absolute conversion */
- DBGLL(("icmLuLut_lookup: in_abs = %s\n", icmPdv(p->inputChan, temp)));
+ DBGLL(("icmLuLut_lookup: in_abs = %s\n", icmPdv(p->lut->inputChan, temp)));
if (p->usematrix) {
rv |= lut->lookup_matrix(lut,temp,temp);/* If XYZ, multiply by non-unity matrix */
- DBGLL(("icmLuLut_lookup: matrix = %s\n", icmPdv(p->inputChan, temp)));
+ DBGLL(("icmLuLut_lookup: matrix = %s\n", icmPdv(p->lut->inputChan, temp)));
}
p->in_normf(temp, temp); /* Normalize for input color space */
- DBGLL(("icmLuLut_lookup: norm = %s\n", icmPdv(p->inputChan, temp)));
+ DBGLL(("icmLuLut_lookup: norm = %s\n", icmPdv(p->lut->inputChan, temp)));
rv |= lut->lookup_input(lut,temp,temp); /* Lookup though input tables */
- DBGLL(("icmLuLut_lookup: input = %s\n", icmPdv(p->inputChan, temp)));
+ DBGLL(("icmLuLut_lookup: input = %s\n", icmPdv(p->lut->inputChan, temp)));
rv |= p->lookup_clut(lut,out,temp); /* Lookup though clut tables */
- DBGLL(("icmLuLut_lookup: clut = %s\n", icmPdv(p->outputChan, out)));
+ DBGLL(("icmLuLut_lookup: clut = %s\n", icmPdv(p->lut->outputChan, out)));
rv |= lut->lookup_output(lut,out,out); /* Lookup though output tables */
- DBGLL(("icmLuLut_lookup: output = %s\n", icmPdv(p->outputChan, out)));
+ DBGLL(("icmLuLut_lookup: output = %s\n", icmPdv(p->lut->outputChan, out)));
p->out_denormf(out,out); /* Normalize for output color space */
- DBGLL(("icmLuLut_lookup: denorm = %s\n", icmPdv(p->outputChan, out)));
+ DBGLL(("icmLuLut_lookup: denorm = %s\n", icmPdv(p->lut->outputChan, out)));
rv |= p->out_abs(p,out,out); /* Possible absolute conversion */
- DBGLL(("icmLuLut_lookup: out_abse = %s\n", icmPdv(p->outputChan, out)));
+ DBGLL(("icmLuLut_lookup: out_abse = %s\n", icmPdv(p->lut->outputChan, out)));
return rv;
}
@@ -16891,8 +17789,10 @@ icc_new_icmLuLut(
if (use_sx) {
p->lookup_clut = p->lut->lookup_clut_sx;
+ p->lut->tune_value = icmLut_tune_value_sx;
} else {
p->lookup_clut = p->lut->lookup_clut_nl;
+ p->lut->tune_value = icmLut_tune_value_nl;
}
}
#else /* Development code */
@@ -17665,7 +18565,7 @@ icmAlloc *al /* Memory allocator */
if ((p = (icc *) al->calloc(al, 1,sizeof(icc))) == NULL) {
return NULL;
}
- p->ver = 0; /* default is V2 profile */
+ p->ver = icmVersionDefault; /* default is V2.2.0 profile */
p->al = al; /* Heap allocator */
diff --git a/icc/icc.h b/icc/icc.h
index 7c3a65b..ba66581 100644
--- a/icc/icc.h
+++ b/icc/icc.h
@@ -8,7 +8,7 @@
* Date: 1999/11/29
* Version: 2.15
*
- * Copyright 1997 - 2012 Graeme W. Gill
+ * Copyright 1997 - 2013 Graeme W. Gill
*
* This material is licensed with an "MIT" free use license:-
* see the License.txt file in this directory for licensing details.
@@ -30,8 +30,8 @@
/* Version of icclib release */
-#define ICCLIB_VERSION 0x020016
-#define ICCLIB_VERSION_STR "2.16"
+#define ICCLIB_VERSION 0x020017
+#define ICCLIB_VERSION_STR "2.17"
#undef ENABLE_V4 /* V4 is not fully implemented */
@@ -778,8 +778,20 @@ struct _icmLut {
/* inspace' -> outspace' transfer function */
double *clutmin, double *clutmax, /* Maximum range of outspace' values */
/* (NULL = default) */
- void (*outfunc)(void *cbntx, double *out, double *in));
+ void (*outfunc)(void *cbntx, double *out, double *in),
/* Output transfer function, outspace'->outspace (NULL = deflt) */
+ int *apxls_gmin, int *apxls_gmax /* If not NULL, the grid indexes not to be affected */
+ /* by ICM_CLUT_SET_APXLS, defaulting to 0..>clutPoints-1 */
+ );
+
+ /* Helper function to fine tune a single value interpolation */
+ /* Return 0 on success, 1 if input clipping occured, 2 if output clipping occured */
+ /* To guarantee the optimal function, an icmLuLut needs to be create. */
+ /* The default will be to assume simplex interpolation will be used. */
+ int (*tune_value) (
+ struct _icmLut *p, /* Pointer to Lut object */
+ double *out, /* Target value */
+ double *in); /* Input value */
}; typedef struct _icmLut icmLut;
@@ -792,27 +804,29 @@ struct _icmLut {
/* If ICM_CLUT_SET_FILTER is set, the per grid node filtering radius */
/* is returned in clutfunc out[-1], out[-2] etc for each table */
int icmSetMultiLutTables(
- int ntables, /* Number of tables to be set, 1..n */
- struct _icmLut **p, /* Pointer to Lut object */
- int flags, /* Setting flags */
- void *cbctx, /* Opaque callback context pointer value */
- icColorSpaceSignature insig, /* Input color space */
- icColorSpaceSignature outsig, /* Output color space */
+ int ntables, /* Number of tables to be set, 1..n */
+ struct _icmLut **p, /* Pointer to Lut object */
+ int flags, /* Setting flags */
+ void *cbctx, /* Opaque callback context pointer value */
+ icColorSpaceSignature insig, /* Input color space */
+ icColorSpaceSignature outsig, /* Output color space */
void (*infunc)(void *cbctx, double *out, double *in),
/* Input transfer function, inspace->inspace' (NULL = default) */
/* Will be called ntables times each input grid value */
- double *inmin, double *inmax, /* Maximum range of inspace' values */
- /* (NULL = default) */
+ double *inmin, double *inmax, /* Maximum range of inspace' values */
+ /* (NULL = default) */
void (*clutfunc)(void *cbntx, double *out, double *in),
/* inspace' -> outspace[ntables]' transfer function */
/* will be called once for each input' grid value, and */
/* ntables output values should be written consecutively */
/* to out[]. */
- double *clutmin, double *clutmax, /* Maximum range of outspace' values */
- /* (NULL = default) */
- void (*outfunc)(void *cbntx, double *out, double *in)
+ double *clutmin, double *clutmax, /* Maximum range of outspace' values */
+ /* (NULL = default) */
+ void (*outfunc)(void *cbntx, double *out, double *in),
/* Output transfer function, outspace'->outspace (NULL = deflt) */
/* Will be called ntables times on each output value */
+ int *apxls_gmin, int *apxls_gmax /* If not NULL, the grid indexes not to be affected */
+ /* by ICM_CLUT_SET_APXLS, defaulting to 0..>clutPoints-1 */
);
/* - - - - - - - - - - - - - - - - - - - - - */
@@ -1487,6 +1501,8 @@ struct _icc {
int errc; /* Error code */
int warnc; /* Warning code */
+ int allowclutPoints256; /* Non standard - allow 256 res cLUT */
+
/* Private: ? */
icmAlloc *al; /* Heap allocator */
int del_al; /* NZ if heap allocator should be deleted */
@@ -1652,135 +1668,9 @@ extern ICCLIB_API unsigned int icmCSSig2nchan(icColorSpaceSignature sig);
/* 1 if it is a colorant based colorspace, and 2 if it is not a colorant based space */
extern ICCLIB_API unsigned int icmCSSig2chanNames( icColorSpaceSignature sig, char *cvals[]);
-
-/* Simple macro to transfer an array to an XYZ number */
-#define icmAry2XYZ(xyz, ary) ((xyz).X = (ary)[0], (xyz).Y = (ary)[1], (xyz).Z = (ary)[2])
-
-/* And the reverse */
-#define icmXYZ2Ary(ary, xyz) ((ary)[0] = (xyz).X, (ary)[1] = (xyz).Y, (ary)[2] = (xyz).Z)
-
-/* Simple macro to transfer an XYZ number to an XYZ number */
-#define icmXYZ2XYZ(d_xyz, s_xyz) ((d_xyz).X = (s_xyz).X, (d_xyz).Y = (s_xyz).Y, \
- (d_xyz).Z = (s_xyz).Z)
-
-/* Simple macro to transfer an 3array to 3array */
-/* Hmm. Same as icmCpy3 */
-#define icmAry2Ary(d_ary, s_ary) ((d_ary)[0] = (s_ary)[0], (d_ary)[1] = (s_ary)[1], \
- (d_ary)[2] = (s_ary)[2])
-
-/* CIE Y (range 0 .. 1) to perceptual CIE 1976 L* (range 0 .. 100) */
-double icmY2L(double val);
-
-/* Perceptual CIE 1976 L* (range 0 .. 100) to CIE Y (range 0 .. 1) */
-double icmL2Y(double val);
-
-/* CIE XYZ to perceptual Lab */
-extern ICCLIB_API void icmXYZ2Lab(icmXYZNumber *w, double *out, double *in);
-
-/* Perceptual Lab to CIE XYZ */
-extern ICCLIB_API void icmLab2XYZ(icmXYZNumber *w, double *out, double *in);
-
-/* LCh to Lab */
-extern ICCLIB_API void icmLCh2Lab(double *out, double *in);
-
-/* Lab to LCh */
-extern ICCLIB_API void icmLab2LCh(double *out, double *in);
-
-/* XYZ to Yxy */
-extern ICCLIB_API void icmXYZ2Yxy(double *out, double *in);
-
-/* Yxy to XYZ */
-extern ICCLIB_API void icmYxy2XYZ(double *out, double *in);
-
-/* CIE XYZ to perceptual Luv */
-extern ICCLIB_API void icmXYZ2Luv(icmXYZNumber *w, double *out, double *in);
-
-/* Perceptual Luv to CIE XYZ */
-extern ICCLIB_API void icmLuv2XYZ(icmXYZNumber *w, double *out, double *in);
-
-
-/* NOTE :- none of the following seven have been protected */
-/* against arithmmetic issues (ie. for black) */
-
-/* CIE XYZ to perceptual CIE 1976 UCS diagram Yu'v'*/
-/* (Yu'v' is a better chromaticity space than Yxy) */
-extern ICCLIB_API void icmXYZ21976UCS(double *out, double *in);
-
-/* Perceptual CIE 1976 UCS diagram Yu'v' to CIE XYZ */
-extern ICCLIB_API void icm1976UCS2XYZ(double *out, double *in);
-
-/* CIE XYZ to perceptual CIE 1960 UCS */
-/* (This was obsoleted by the 1976UCS, but is still used */
-/* in computing color temperatures.) */
-extern ICCLIB_API void icmXYZ21960UCS(double *out, double *in);
-
-/* Perceptual CIE 1960 UCS to CIE XYZ */
-extern ICCLIB_API void icm1960UCS2XYZ(double *out, double *in);
-
-/* CIE XYZ to perceptual CIE 1964 WUV (U*V*W*) */
-/* (This is obsolete but still used in computing CRI) */
-extern ICCLIB_API void icmXYZ21964WUV(icmXYZNumber *w, double *out, double *in);
-
-/* Perceptual CIE 1964 WUV (U*V*W*) to CIE XYZ */
-extern ICCLIB_API void icm1964WUV2XYZ(icmXYZNumber *w, double *out, double *in);
-
-/* CIE CIE1960 UCS to perceptual CIE 1964 WUV (U*V*W*) */
-extern ICCLIB_API void icm1960UCS21964WUV(icmXYZNumber *w, double *out, double *in);
-
-
-/* The standard D50 illuminant value */
-extern icmXYZNumber icmD50;
-extern icmXYZNumber icmD50_100; /* Scaled to 100 */
-double icmD50_ary3[3]; /* As an array */
-double icmD50_100_ary3[3]; /* Scaled to 100 as an array */
-
-/* The standard D65 illuminant value */
-extern icmXYZNumber icmD65;
-extern icmXYZNumber icmD65_100; /* Scaled to 100 */
-double icmD65_ary3[3]; /* As an array */
-double icmD65_100_ary3[3]; /* Scaled to 100 as an array */
-
-/* The default black value */
-extern icmXYZNumber icmBlack;
-
-
-/* Initialise a pseudo-hilbert grid counter, return total usable count. */
-extern ICCLIB_API unsigned psh_init(psh *p, int di, unsigned int res, int co[]);
-
-/* Reset the counter */
-extern ICCLIB_API void psh_reset(psh *p);
-
-/* Increment pseudo-hilbert coordinates */
-/* Return non-zero if count rolls over to 0 */
-extern ICCLIB_API int psh_inc(psh *p, int co[]);
-
-
-/* RGB primaries to device to RGB->XYZ transform matrix */
-/* Return non-zero if matrix would be singular */
-int icmRGBprim2matrix(
- icmXYZNumber white, /* White point */
- icmXYZNumber red, /* Red colorant */
- icmXYZNumber green, /* Green colorant */
- icmXYZNumber blue, /* Blue colorant */
- double mat[3][3] /* Destination matrix */
-);
-
-/* Chromatic Adaption transform utility */
-/* Return a 3x3 chromatic adaption matrix */
-/* Use icmMulBy3x3(dst, mat, src) */
-
-#define ICM_CAM_BRADFORD 0x0001 /* Use Bradford sharpened response space */
-#define ICM_CAM_MULMATRIX 0x0002 /* Transform the given matrix */
-
-void icmChromAdaptMatrix(
- int flags, /* Flags as defined below */
- icmXYZNumber d_wp, /* Destination white point */
- icmXYZNumber s_wp, /* Source white point */
- double mat[3][3] /* Destination matrix */
-);
-
/* - - - - - - - - - - - - - - */
-/* Set a 3 vector */
+
+/* Set a 3 vector to the same value */
#define icmSet3(d_ary, s_val) ((d_ary)[0] = (s_val), (d_ary)[1] = (s_val), \
(d_ary)[2] = (s_val))
@@ -1801,6 +1691,16 @@ void icmSub3(double out[3], double in1[3], double in2[3]);
#define ICMSUB3(o, i, j) ((o)[0] = (i)[0] - (j)[0], (o)[1] = (i)[1] - (j)[1], (o)[2] = (i)[2] - (j)[2])
+/* Divide two 3 vectors, out = in1/in2 */
+void icmDiv3(double out[3], double in1[3], double in2[3]);
+
+#define ICMDIV3(o, i, j) ((o)[0] = (i)[0]/(j)[0], (o)[1] = (i)[1]/(j)[1], (o)[2] = (i)[2]/(j)[2])
+
+/* Multiply two 3 vectors, out = in1 * in2 */
+void icmMul3(double out[3], double in1[3], double in2[3]);
+
+#define ICMMUL3(o, i, j) ((o)[0] = (i)[0] * (j)[0], (o)[1] = (i)[1] * (j)[1], (o)[2] = (i)[2] * (j)[2])
+
/* Compute the dot product of two 3 vectors */
double icmDot3(double in1[3], double in2[3]);
@@ -1822,10 +1722,13 @@ double icmNorm3(double in[3]);
/* Scale a 3 vector by the given ratio */
void icmScale3(double out[3], double in[3], double rat);
+#define ICMSCALE3(o, i, j) ((o)[0] = (i)[0] * (j), (o)[1] = (i)[1] * (j), (o)[2] = (i)[2] * (j))
+
/* Compute a blend between in0 and in1 */
void icmBlend3(double out[3], double in0[3], double in1[3], double bf);
-#define ICMSCALE3(o, i, j) ((o)[0] = (i)[0] * (j), (o)[1] = (i)[1] * (j), (o)[2] = (i)[2] * (j))
+/* Clip a vector to the range 0.0 .. 1.0 */
+void icmClip3(double out[3], double in[3]);
/* Normalise a 3 vector to the given length. Return nz if not normalisable */
int icmNormalize3(double out[3], double in[3], double len);
@@ -1922,9 +1825,128 @@ double icmPlaneDist3(double eq[4], double p[3]);
/* - - - - - - - - - - - - - - - - - - - - - - - */
+/* Given 2 2D points, compute a plane equation. */
+/* The normal will be right handed given the order of the points */
+/* The plane equation will be the 2 normal components and the constant. */
+/* Return nz if any points are cooincident or co-linear */
+int icmPlaneEqn2(double eq[3], double p0[2], double p1[2]);
+
+/* Given a 2D point and a plane equation, return the signed */
+/* distance from the plane */
+double icmPlaneDist2(double eq[3], double p[2]);
+
+/* Given two infinite 2D lines define by two pairs of points, compute the intersection. */
+/* Return nz if there is no intersection (lines are parallel) */
+int icmLineIntersect2(double res[2], double p1[2], double p2[2], double p3[2], double p4[2]);
+
/* Multiply 2 array by 2x2 transform matrix */
void icmMulBy2x2(double out[2], double mat[2][2], double in[2]);
+/* - - - - - - - - - - - - - - */
+
+/* Simple macro to transfer an array to an XYZ number */
+#define icmAry2XYZ(xyz, ary) ((xyz).X = (ary)[0], (xyz).Y = (ary)[1], (xyz).Z = (ary)[2])
+
+/* And the reverse */
+#define icmXYZ2Ary(ary, xyz) ((ary)[0] = (xyz).X, (ary)[1] = (xyz).Y, (ary)[2] = (xyz).Z)
+
+/* Simple macro to transfer an XYZ number to an XYZ number */
+#define icmXYZ2XYZ(d_xyz, s_xyz) ((d_xyz).X = (s_xyz).X, (d_xyz).Y = (s_xyz).Y, \
+ (d_xyz).Z = (s_xyz).Z)
+
+/* Simple macro to transfer an 3array to 3array */
+/* Hmm. Same as icmCpy3 */
+#define icmAry2Ary(d_ary, s_ary) ((d_ary)[0] = (s_ary)[0], (d_ary)[1] = (s_ary)[1], \
+ (d_ary)[2] = (s_ary)[2])
+
+/* CIE Y (range 0 .. 1) to perceptual CIE 1976 L* (range 0 .. 100) */
+double icmY2L(double val);
+
+/* Perceptual CIE 1976 L* (range 0 .. 100) to CIE Y (range 0 .. 1) */
+double icmL2Y(double val);
+
+/* CIE XYZ to perceptual Lab */
+extern ICCLIB_API void icmXYZ2Lab(icmXYZNumber *w, double *out, double *in);
+
+/* Perceptual Lab to CIE XYZ */
+extern ICCLIB_API void icmLab2XYZ(icmXYZNumber *w, double *out, double *in);
+
+/* LCh to Lab */
+extern ICCLIB_API void icmLCh2Lab(double *out, double *in);
+
+/* Lab to LCh */
+extern ICCLIB_API void icmLab2LCh(double *out, double *in);
+
+/* XYZ to Yxy */
+extern ICCLIB_API void icmXYZ2Yxy(double *out, double *in);
+
+/* Yxy to XYZ */
+extern ICCLIB_API void icmYxy2XYZ(double *out, double *in);
+
+/* CIE XYZ to perceptual Luv */
+extern ICCLIB_API void icmXYZ2Luv(icmXYZNumber *w, double *out, double *in);
+
+/* Perceptual Luv to CIE XYZ */
+extern ICCLIB_API void icmLuv2XYZ(icmXYZNumber *w, double *out, double *in);
+
+
+/* CIE XYZ to perceptual CIE 1976 UCS diagram Yu'v'*/
+/* (Yu'v' is a better chromaticity space than Yxy) */
+extern ICCLIB_API void icmXYZ21976UCS(double *out, double *in);
+
+/* Perceptual CIE 1976 UCS diagram Yu'v' to CIE XYZ */
+extern ICCLIB_API void icm1976UCS2XYZ(double *out, double *in);
+
+
+/* CIE XYZ to perceptual CIE 1960 UCS */
+/* (This was obsoleted by the 1976UCS, but is still used */
+/* in computing color temperatures.) */
+extern ICCLIB_API void icmXYZ21960UCS(double *out, double *in);
+
+/* Perceptual CIE 1960 UCS to CIE XYZ */
+extern ICCLIB_API void icm1960UCS2XYZ(double *out, double *in);
+
+
+/* CIE XYZ to perceptual CIE 1964 WUV (U*V*W*) */
+/* (This is obsolete but still used in computing CRI) */
+extern ICCLIB_API void icmXYZ21964WUV(icmXYZNumber *w, double *out, double *in);
+
+/* Perceptual CIE 1964 WUV (U*V*W*) to CIE XYZ */
+extern ICCLIB_API void icm1964WUV2XYZ(icmXYZNumber *w, double *out, double *in);
+
+/* CIE CIE1960 UCS to perceptual CIE 1964 WUV (U*V*W*) */
+extern ICCLIB_API void icm1960UCS21964WUV(icmXYZNumber *w, double *out, double *in);
+
+
+/* NOTE :- that these values are for the 1931 standard observer */
+
+/* The standard D50 illuminant value */
+extern icmXYZNumber icmD50;
+extern icmXYZNumber icmD50_100; /* Scaled to 100 */
+extern double icmD50_ary3[3]; /* As an array */
+extern double icmD50_100_ary3[3]; /* Scaled to 100 as an array */
+
+/* The standard D65 illuminant value */
+extern icmXYZNumber icmD65;
+extern icmXYZNumber icmD65_100; /* Scaled to 100 */
+extern double icmD65_ary3[3]; /* As an array */
+extern double icmD65_100_ary3[3]; /* Scaled to 100 as an array */
+
+
+/* The default black value */
+extern icmXYZNumber icmBlack;
+
+
+/* Initialise a pseudo-hilbert grid counter, return total usable count. */
+extern ICCLIB_API unsigned psh_init(psh *p, int di, unsigned int res, int co[]);
+
+/* Reset the counter */
+extern ICCLIB_API void psh_reset(psh *p);
+
+/* Increment pseudo-hilbert coordinates */
+/* Return non-zero if count rolls over to 0 */
+extern ICCLIB_API int psh_inc(psh *p, int co[]);
+
/* - - - - - - - - - - - - - - - - - - - - - - - */
/* Return the normal Delta E given two Lab values */
@@ -1956,6 +1978,7 @@ extern ICCLIB_API double icmCIE2Ksq(double *in0, double *in1);
/* Return the CIEDE2000 Delta E color difference measure for two XYZ values */
extern ICCLIB_API double icmXYZCIE2K(icmXYZNumber *w, double *in0, double *in1);
+
/* - - - - - - - - - - - - - - - - - - - - - - - */
/* Clip Lab, while maintaining hue angle. */
/* Return nz if clipping occured */
@@ -1966,6 +1989,122 @@ int icmClipLab(double out[3], double in[3]);
int icmClipXYZ(double out[3], double in[3]);
/* - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* RGB primaries to device to RGB->XYZ transform matrix */
+/* Return non-zero if matrix would be singular */
+int icmRGBprim2matrix(
+ icmXYZNumber white, /* White point */
+ icmXYZNumber red, /* Red colorant */
+ icmXYZNumber green, /* Green colorant */
+ icmXYZNumber blue, /* Blue colorant */
+ double mat[3][3] /* Destination matrix[RGB[XYZ] */
+);
+
+/* Chromatic Adaption transform utility */
+/* Return a 3x3 chromatic adaption matrix */
+/* Use icmMulBy3x3(dst, mat, src) */
+
+#define ICM_CAM_BRADFORD 0x0001 /* Use Bradford sharpened response space */
+#define ICM_CAM_MULMATRIX 0x0002 /* Transform the given matrix */
+ /* NOTE that to transform primaries they */
+ /* must be mat[XYZ][RGB] format! */
+
+void icmChromAdaptMatrix(
+ int flags, /* Flags as defined below */
+ icmXYZNumber d_wp, /* Destination white point */
+ icmXYZNumber s_wp, /* Source white point */
+ double mat[3][3] /* Destination matrix */
+);
+
+/* Pre-round RGB device primary values to ensure that */
+/* the sum of the quantized primaries is the same as */
+/* the quantized sum. */
+void quantizeRGBprimsS15Fixed16(
+ double mat[3][3] /* matrix[RGB][XYZ] */
+);
+
+/* - - - - - - - - - - - - - - */
+/* Video functions */
+
+/* Convert Lut table index/value to YCbCr */
+void icmLut2YCbCr(double *out, double *in);
+
+/* Convert YCbCr to Lut table index/value */
+void icmYCbCr2Lut(double *out, double *in);
+
+
+/* Convert Rec601 RGB' into YPbPr, (== "full range YCbCr") */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+void icmRec601_RGBd_2_YPbPr(double out[3], double in[3]);
+
+/* Convert Rec601 YPbPr to RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+void icmRec601_YPbPr_2_RGBd(double out[3], double in[3]);
+
+
+/* Convert Rec709 1150/60/2:1 RGB' into YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+void icmRec709_RGBd_2_YPbPr(double out[3], double in[3]);
+
+/* Convert Rec709 1150/60/2:1 YPbPr to RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+void icmRec709_YPbPr_2_RGBd(double out[3], double in[3]);
+
+/* Convert Rec709 1250/50/2:1 RGB' into YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+void icmRec709_50_RGBd_2_YPbPr(double out[3], double in[3]);
+
+/* Convert Rec709 1250/50/2:1 YPbPr to RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+void icmRec709_50_YPbPr_2_RGBd(double out[3], double in[3]);
+
+
+/* Convert Rec2020 RGB' into Non-constant liminance YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+void icmRec2020_NCL_RGBd_2_YPbPr(double out[3], double in[3]);
+
+/* Convert Rec2020 Non-constant liminance YPbPr into RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+void icmRec2020_NCL_YPbPr_2_RGBd(double out[3], double in[3]);
+
+/* Convert Rec2020 RGB' into Constant liminance YPbPr, or "full range YCbCr" */
+/* where input 0..1, output 0..1, -0.5 .. 0.5, -0.5 .. 0.5 */
+void icmRec2020_CL_RGBd_2_YPbPr(double out[3], double in[3]);
+
+/* Convert Rec2020 Constant liminance YPbPr into RGB' (== "full range YCbCr") */
+/* where input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, output 0.0 .. 1 */
+void icmRec2020_CL_YPbPr_2_RGBd(double out[3], double in[3]);
+
+
+/* Convert Rec601/709/2020 YPbPr to YCbCr range. */
+/* input 0..1, -0.5 .. 0.5, -0.5 .. 0.5, */
+/* output 16/255 .. 235/255, 16/255 .. 240/255, 16/255 .. 240/255 */
+void icmRecXXX_YPbPr_2_YCbCr(double out[3], double in[3]);
+
+/* Convert Rec601/709/2020 YCbCr to YPbPr range. */
+/* input 16/255 .. 235/255, 16/255 .. 240/255, 16/255 .. 240/255 */
+/* output 0..1, -0.5 .. 0.5, -0.5 .. 0.5, */
+void icmRecXXX_YCbCr_2_YPbPr(double out[3], double in[3]);
+
+
+/* Convert full range RGB to Video range 16..235 RGB */
+void icmRGB_2_VidRGB(double out[3], double in[3]);
+
+/* Convert Video range 16..235 RGB to full range RGB */
+void icmVidRGB_2_RGB(double out[3], double in[3]);
+
+/* ---------------------------------------------------------- */
+/* PS 3.14-2009, Digital Imaging and Communications in Medicine */
+/* (DICOM) Part 14: Grayscale Standard Display Function */
+
+/* JND index value 1..1023 to L 0.05 .. 3993.404 cd/m^2 */
+double icmDICOM_fwd(double jnd);
+
+/* L 0.05 .. 3993.404 cd/m^2 to JND index value 1..1023 */
+double icmDICOM_bwd(double L);
+
+
+/* ---------------------------------------------------------- */
/* Print an int vector to a string. */
/* Returned static buffer is re-used every 5 calls. */
char *icmPiv(int di, int *p);
@@ -1981,8 +2120,8 @@ char *icmPfv(int di, float *p);
/* Print an 0..1 range XYZ as a D50 Lab string */
/* Returned static buffer is re-used every 5 calls. */
char *icmPLab(double *p);
+/* - - - - - - - - - - - - - - - - - - - - - - - */
-/* ---------------------------------------------------------- */
#ifdef __cplusplus
}
diff --git a/icc/iccdump.c b/icc/iccdump.c
index aaf14f0..76959e7 100644
--- a/icc/iccdump.c
+++ b/icc/iccdump.c
@@ -182,6 +182,9 @@ main(int argc, char *argv[]) {
if ((rv = icco->read(icco,fp,offset)) != 0)
error ("%d, %s",rv,icco->err);
+ if (icco->header->cmmId == str2tag("argl"))
+ icco->allowclutPoints256 = 1;
+
if (ntag_names > 0) {
int i;
for (i = 0; i < ntag_names; i++) {
diff --git a/icc/icclu.c b/icc/icclu.c
index ea32da0..80126da 100644
--- a/icc/icclu.c
+++ b/icc/icclu.c
@@ -245,6 +245,9 @@ main(int argc, char *argv[]) {
if ((rv = icco->read(icco,fp,0)) != 0)
error ("%d, %s",rv,icco->err);
+ if (icco->header->cmmId == str2tag("argl"))
+ icco->allowclutPoints256 = 1;
+
if (verb > 1) {
icmFile *op;
if ((op = new_icmFileStd_fp(stdout)) == NULL)
@@ -286,7 +289,7 @@ main(int argc, char *argv[]) {
continue;
}
/* For each input number */
- for (bp = buf-1, nbp = buf, i = 0; i < MAX_CHAN; i++) {
+ for (nbp = buf, i = 0; i < MAX_CHAN; i++) {
bp = nbp;
in[i] = oin[i] = strtod(bp, &nbp);
if (nbp == bp)
@@ -310,19 +313,7 @@ main(int argc, char *argv[]) {
}
if (repYxy && ins == icSigYxyData) {
- double Y = in[0];
- double x = in[1];
- double y = in[2];
- double z = 1.0 - x - y;
- double sum;
- if (y < 1e-6) {
- in[0] = in[1] = in[2] = 0.0;
- } else {
- sum = Y/y;
- in[0] = x * sum;
- in[1] = Y;
- in[2] = z * sum;
- }
+ icmYxy2XYZ(in, in);
}
/* Do conversion */
@@ -342,17 +333,7 @@ main(int argc, char *argv[]) {
}
if (repYxy && outs == icSigYxyData) {
- double X = out[0];
- double Y = out[1];
- double Z = out[2];
- double sum = X + Y + Z;
- if (sum < 1e-6) {
- out[0] = out[1] = out[2] = 0.0;
- } else {
- out[0] = Y;
- out[1] = X/sum;
- out[2] = Y/sum;
- }
+ icmXYZ2Yxy(out, out);
}
/* If device data and scale */
diff --git a/icc/icctest.c b/icc/icctest.c
index 97a3f62..e7534fb 100644
--- a/icc/icctest.c
+++ b/icc/icctest.c
@@ -111,6 +111,7 @@ main(
if (md5_test() != 0)
error ("MD5 checksum routine is faulty");
+
/* Outer loop does a number of file write/reads, */
/* in order to exercise random tests, and to test file offsets. */
@@ -199,8 +200,6 @@ main(
offset = rand_int(0,72789);
}
- printf("\nTest completed OK\n");
-
return 0;
}
@@ -325,9 +324,9 @@ int doit(
/* Values that are not normally set. Set them to non-defaults for testing */
wh->cmmId = str2tag("tst3");
- wh->majv = 3; /* Default version 2.1.0 */
- wh->minv = 2;
- wh->bfv = 1;
+ wh->majv = 2; /* Default version 2.1.0 */
+ wh->minv = 1;
+ wh->bfv = 0;
wh->date.year = rand_int(1900,3000); /* Defaults to current date */
wh->date.month = rand_int(1,12);
wh->date.day = rand_int(1,31);
diff --git a/icc/lab2lab.icm b/icc/lab2lab.icm
index fe518e6..0b8a4b3 100644
--- a/icc/lab2lab.icm
+++ b/icc/lab2lab.icm
Binary files differ
diff --git a/icc/log.txt b/icc/log.txt
index 97435b6..7c4bd83 100644
--- a/icc/log.txt
+++ b/icc/log.txt
@@ -1,7 +1,13 @@
Change History: (See ArgyllCMS log.txt too)
- 2.15
+ 2.16
+ Clean up cLUT read code to make sanity checking
+ more explicit and remove redundant code.
+
+ Added special mode that interprets cLUT res of 0 as 256
+ for MadVR testing.
+
Change icc->read_tag() to only succeed if the tag type is
known, since the standard expectation of a non NULL
return type is that it is of a known type. Added new
diff --git a/icc/lutest.c b/icc/lutest.c
index e43fbc5..9bf127f 100644
--- a/icc/lutest.c
+++ b/icc/lutest.c
@@ -1995,13 +1995,15 @@ main(
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigRgbData, /* Input color space */
- icSigXYZData, /* Output color space */
- RGB_RGBp, /* Input transfer function, RGB->RGB' (NULL = default) */
- NULL, NULL, /* Use default Maximum range of RGB' values */
- RGBp_XYZp, /* RGB' -> XYZ' transfer function */
- xyzmin, xyzmax, /* Make XYZ' range 0.0 - 1.0 for better precision */
- XYZp_XYZ) != 0) /* Output transfer function, XYZ'->XYZ (NULL = deflt) */
+ icSigRgbData, /* Input color space */
+ icSigXYZData, /* Output color space */
+ RGB_RGBp, /* Input transfer function, RGB->RGB' (NULL = default) */
+ NULL, NULL, /* Use default Maximum range of RGB' values */
+ RGBp_XYZp, /* RGB' -> XYZ' transfer function */
+ xyzmin, xyzmax, /* Make XYZ' range 0.0 - 1.0 for better precision */
+ XYZp_XYZ, /* Output transfer function, XYZ'->XYZ (NULL = deflt) */
+ NULL, NULL
+ ) != 0)
error("Setting 16 bit RGB->XYZ Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
/* 16 bit dev -> pcs lut - link intent 0 to intent 1 */
@@ -2126,13 +2128,15 @@ main(
#endif
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigXYZData, /* Input color space */
- icSigRgbData, /* Output color space */
- XYZ_XYZp, /* Input transfer function, XYZ->XYZ' (NULL = default) */
- xyzmin, xyzmax, /* Make XYZ' range 0.0 - 1.0 for better precision */
- XYZp_RGBp, /* XYZ' -> RGB' transfer function */
- rgbmin, rgbmax, /* Make RGB' range 0.0 - 1.333 for less clip rounding */
- RGBp_RGB) != 0) /* Output transfer function, RGB'->RGB (NULL = deflt) */
+ icSigXYZData, /* Input color space */
+ icSigRgbData, /* Output color space */
+ XYZ_XYZp, /* Input transfer function, XYZ->XYZ' (NULL = default) */
+ xyzmin, xyzmax, /* Make XYZ' range 0.0 - 1.0 for better precision */
+ XYZp_RGBp, /* XYZ' -> RGB' transfer function */
+ rgbmin, rgbmax, /* Make RGB' range 0.0 - 1.333 for less clip rounding */
+ RGBp_RGB, /* Output transfer function, RGB'->RGB (NULL = deflt) */
+ NULL, NULL
+ ) != 0)
error("Setting 16 bit XYZ->RGB Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -2181,13 +2185,14 @@ main(
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigXYZData, /* Input color space */
- icSigGrayData, /* Output color space */
- XYZ_XYZp, /* Input transfer function, XYZ->XYZ' (NULL = default) */
- xyzmin, xyzmax, /* Make XYZ' range 0.0 - 1.0 for better precision */
- XYZp_BDIST, /* XYZ' -> Boundary Distance transfer function */
- NULL, NULL, /* Default range from clut to output table */
- BDIST_GAMMUT /* Boundary Distance -> Out of gamut distance */
+ icSigXYZData, /* Input color space */
+ icSigGrayData, /* Output color space */
+ XYZ_XYZp, /* Input transfer function, XYZ->XYZ' (NULL = default) */
+ xyzmin, xyzmax, /* Make XYZ' range 0.0 - 1.0 for better precision */
+ XYZp_BDIST, /* XYZ' -> Boundary Distance transfer function */
+ NULL, NULL, /* Default range from clut to output table */
+ BDIST_GAMMUT, /* Boundary Distance -> Out of gamut distance */
+ NULL, NULL
) != 0)
error("Setting 16 bit XYZ->Gammut Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -2559,13 +2564,14 @@ main(
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigRgbData, /* Input color space */
- icSigLabData, /* Output color space */
- RGB_RGBp, /* Input transfer function, RGB->RGB' (NULL = default) */
- NULL, NULL, /* Use default Maximum range of RGB' values */
- RGBp_Labp, /* RGB' -> Lab' transfer function */
- NULL, NULL, /* Use default Maximum range of Lab' values */
- Labp_Lab /* Linear output transform Lab'->Lab */
+ icSigRgbData, /* Input color space */
+ icSigLabData, /* Output color space */
+ RGB_RGBp, /* Input transfer function, RGB->RGB' (NULL = default) */
+ NULL, NULL, /* Use default Maximum range of RGB' values */
+ RGBp_Labp, /* RGB' -> Lab' transfer function */
+ NULL, NULL, /* Use default Maximum range of Lab' values */
+ Labp_Lab, /* Linear output transform Lab'->Lab */
+ NULL, NULL
) != 0)
error("Setting 16 bit RGB->Lab Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -2643,13 +2649,15 @@ main(
#endif
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigLabData, /* Input color space */
- icSigRgbData, /* Output color space */
- Lab_Labp, /* Linear input transform Lab->Lab' */
- NULL, NULL, /* Use default Lab' range */
- Labp_RGBp, /* Lab' -> RGB' transfer function */
- rgbmin, rgbmax, /* Make RGB' range 0.0 - 1.333 for less clip rounding */
- RGBp_RGB) != 0) /* Output transfer function, RGB'->RGB (NULL = deflt) */
+ icSigLabData, /* Input color space */
+ icSigRgbData, /* Output color space */
+ Lab_Labp, /* Linear input transform Lab->Lab' */
+ NULL, NULL, /* Use default Lab' range */
+ Labp_RGBp, /* Lab' -> RGB' transfer function */
+ rgbmin, rgbmax, /* Make RGB' range 0.0 - 1.333 for less clip rounding */
+ RGBp_RGB, /* Output transfer function, RGB'->RGB (NULL = deflt) */
+ NULL, NULL
+ ) != 0)
error("Setting 16 bit Lab->RGB Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -2690,13 +2698,14 @@ main(
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigLabData, /* Input color space */
- icSigGrayData, /* Output color space */
- Lab_Labp, /* Linear input transform Lab->Lab' */
- NULL, NULL , /* Default Lab' range */
- Labp_BDIST, /* Lab' -> Boundary Distance transfer function */
- NULL, NULL, /* Default range from clut to output table */
- BDIST_GAMMUT /* Boundary Distance -> Out of gamut distance */
+ icSigLabData, /* Input color space */
+ icSigGrayData, /* Output color space */
+ Lab_Labp, /* Linear input transform Lab->Lab' */
+ NULL, NULL, /* Default Lab' range */
+ Labp_BDIST, /* Lab' -> Boundary Distance transfer function */
+ NULL, NULL, /* Default range from clut to output table */
+ BDIST_GAMMUT, /* Boundary Distance -> Out of gamut distance */
+ NULL, NULL
) != 0)
error("Setting 16 bit Lab->Gammut Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -3065,13 +3074,14 @@ main(
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigRgbData, /* Input color space */
- icSigLabData, /* Output color space */
- RGB_RGBp, /* Input transfer function, RGB->RGB' (NULL = default) */
- NULL, NULL, /* Use default Maximum range of RGB' values */
- RGBp_Labp, /* RGB' -> Lab' transfer function */
- NULL, NULL, /* Use default Maximum range of Lab' values */
- Labp_Lab /* Linear output transform Lab'->Lab */
+ icSigRgbData, /* Input color space */
+ icSigLabData, /* Output color space */
+ RGB_RGBp, /* Input transfer function, RGB->RGB' (NULL = default) */
+ NULL, NULL, /* Use default Maximum range of RGB' values */
+ RGBp_Labp, /* RGB' -> Lab' transfer function */
+ NULL, NULL, /* Use default Maximum range of Lab' values */
+ Labp_Lab, /* Linear output transform Lab'->Lab */
+ NULL, NULL
) != 0)
error("Setting 8 bit RGB->Lab Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -3149,13 +3159,15 @@ main(
#endif
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigLabData, /* Input color space */
- icSigRgbData, /* Output color space */
- Lab_Labp, /* Linear input transform Lab->Lab' */
- NULL, NULL, /* Use default Lab' range */
- Labp_RGBp, /* Lab' -> RGB' transfer function */
- rgbmin, rgbmax, /* Make RGB' range 0.0 - 1.333 for less clip rounding */
- RGBp_RGB) != 0) /* Output transfer function, RGB'->RGB (NULL = deflt) */
+ icSigLabData, /* Input color space */
+ icSigRgbData, /* Output color space */
+ Lab_Labp, /* Linear input transform Lab->Lab' */
+ NULL, NULL, /* Use default Lab' range */
+ Labp_RGBp, /* Lab' -> RGB' transfer function */
+ rgbmin, rgbmax, /* Make RGB' range 0.0 - 1.333 for less clip rounding */
+ RGBp_RGB, /* Output transfer function, RGB'->RGB (NULL = deflt) */
+ NULL, NULL
+ ) != 0)
error("Setting 8 bit Lab->RGB Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
@@ -3196,13 +3208,14 @@ main(
/* Use helper function to do the hard work. */
if (wo->set_tables(wo, ICM_CLUT_SET_EXACT, NULL,
- icSigLabData, /* Input color space */
- icSigGrayData, /* Output color space */
- Lab_Labp, /* Linear input transform Lab->Lab' */
- NULL, NULL , /* Default Lab' range */
- Labp_BDIST, /* Lab' -> Boundary Distance transfer function */
- NULL, NULL, /* Default range from clut to output table */
- BDIST_GAMMUT /* Boundary Distance -> Out of gamut distance */
+ icSigLabData, /* Input color space */
+ icSigGrayData, /* Output color space */
+ Lab_Labp, /* Linear input transform Lab->Lab' */
+ NULL, NULL , /* Default Lab' range */
+ Labp_BDIST, /* Lab' -> Boundary Distance transfer function */
+ NULL, NULL, /* Default range from clut to output table */
+ BDIST_GAMMUT, /* Boundary Distance -> Out of gamut distance */
+ NULL, NULL
) != 0)
error("Setting 16 bit Lab->Gammut Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
}
diff --git a/icc/makezip.ksh b/icc/makezip.ksh
deleted file mode 100644
index f06efa4..0000000
--- a/icc/makezip.ksh
+++ /dev/null
@@ -1,6 +0,0 @@
-# Create icclib source distribution
-#jam
-#zip nt_iccdump.zip iccdump.exe
-#zip nt_icclu.zip icclu.exe
-rm icclib.zip
-zip -9 -ll icclib.zip Readme.txt License.txt todo.txt log.txt Jamfile Makefile Makefile.WNT Makefile.IBMNT Makefile.UNIX Makefile.OSX icc.c iccstd.c icc.h iccV42.h iccdump.c icclu.c iccrw.c icctest.c lutest.c
diff --git a/icc/mcheck.c b/icc/mcheck.c
index 9000650..54811c3 100644
--- a/icc/mcheck.c
+++ b/icc/mcheck.c
@@ -155,7 +155,7 @@ main(
error ("%d, %s",rd_icco->errc, rd_icco->err);
}
/* Get details of conversion */
- luo->spaces(luo, &ins, &inn, &outs, NULL, &alg, NULL, NULL, NULL);
+ luo->spaces(luo, &ins, &inn, &outs, NULL, &alg, NULL, NULL, NULL, NULL);
if (alg != icmLutType) {
error("Expecting Lut based profile");
diff --git a/icc/mkDispProf.c b/icc/mkDispProf.c
new file mode 100644
index 0000000..bc70154
--- /dev/null
+++ b/icc/mkDispProf.c
@@ -0,0 +1,331 @@
+
+
+/*
+ * Create an ICC V2.4 compatible matrix display profile.
+ *
+ * Author: Graeme W. Gill
+ * Date: 8/2/2008
+ * Version: 1.00
+ *
+ * Copyright 2006 - 2014 Graeme W. Gill
+ *
+ * This material is licensed with an "MIT" free use license:-
+ * see the License.txt file in this directory for licensing details.
+ *
+ * Based on icc/lutest.c
+ */
+
+
+/*
+ * TTBD:
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include "icc.h"
+
+void error(char *fmt, ...), warning(char *fmt, ...);
+
+void usage(void) {
+ fprintf(stderr,"Create a Matrix Display ICC profile\n");
+ fprintf(stderr,"Author: Graeme W. Gill\n");
+ fprintf(stderr,"usage: mkDispProf [-v level] outfile\n");
+ fprintf(stderr," -v Verbose\n");
+ exit(1);
+}
+
+/* sRGB like device gamma encoded value to linear value 0.0 .. 1.0 */
+static double gdv2dv(double iv) {
+ double ov;
+
+ if (iv < 0.04045)
+ ov = iv/12.92;
+ else
+ ov = pow((iv + 0.055)/1.055, 2.4);
+ return ov;
+}
+
+int
+main(
+int argc,
+char *argv[]
+) {
+ int fa,nfa;
+ char out_name[1000];
+ icmFile *wr_fp;
+ icc *wr_icco;
+ int rv = 0;
+ int verb = 0;
+
+ if (argc < 2)
+ usage();
+
+ /* 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 */
+ }
+ }
+ }
+
+ if (argv[fa][1] == '?')
+ usage();
+
+ /* Verbosity */
+ else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
+ verb = 1;
+ }
+
+ else
+ usage();
+ }
+ else
+ break;
+ }
+
+ if (fa >= argc || argv[fa][0] == '-') usage();
+ strcpy(out_name,argv[fa]);
+
+ /* ---------------------------------------- */
+ /* Create a matrix/shaper based XYZ profile */
+ /* ---------------------------------------- */
+
+ /* Open up the file for writing */
+ if ((wr_fp = new_icmFileStd_name(out_name,"w")) == NULL)
+ error ("Write: Can't open file '%s'",out_name);
+
+ if ((wr_icco = new_icc()) == NULL)
+ error ("Write: Creation of ICC object failed");
+
+ /* Add all the tags required */
+
+ /* The header: */
+ {
+ icmHeader *wh = wr_icco->header;
+
+ /* Values that must be set before writing */
+ wh->deviceClass = icSigDisplayClass;
+ wh->colorSpace = icSigRgbData; /* It's RGB space */
+ wh->pcs = icSigXYZData;
+ wh->renderingIntent = icPerceptual;
+
+ /* Values that should be set before writing */
+ wh->manufacturer = str2tag("????");
+ wh->model = str2tag("????");
+ }
+ /* Profile Description Tag: */
+ {
+ icmTextDescription *wo;
+ char *dst;
+
+ dst = "sRGB like Matrix Display profile";
+ if ((wo = (icmTextDescription *)wr_icco->add_tag(
+ wr_icco, icSigProfileDescriptionTag, icSigTextDescriptionType)) == NULL)
+ error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);
+
+ wo->size = strlen(dst)+1; /* Allocated and used size of desc, inc null */
+ wo->scCode = 0;
+ wo->scSize = strlen(dst)+1;
+ if (wo->scSize > 67)
+ error("Description scriptCode string longer than 67");
+ wo->allocate((icmBase *)wo);/* Allocate space */
+ strcpy(wo->desc, dst); /* Copy the string in */
+ strcpy((char *)wo->scDesc, dst); /* Copy the string in */
+ }
+ /* Copyright Tag: */
+ {
+ icmText *wo;
+ char *crt = "Copyright tag goes here";
+ if ((wo = (icmText *)wr_icco->add_tag(
+ wr_icco, icSigCopyrightTag, icSigTextType)) == NULL)
+ error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);
+
+ wo->size = strlen(crt)+1; /* Allocated and used size of text, inc null */
+ wo->allocate((icmBase *)wo);/* Allocate space */
+ strcpy(wo->data, crt); /* Copy the text in */
+ }
+
+ /* Could add other relevant tags here, such as:
+
+ Device Manufacturers Description Tag
+ Device Model Description Tag
+ Device technology Tag
+ Viewing conditions Description Tag
+ Viewing conditions
+ Display Luminance Tag
+ Measurement information Tag
+
+ etc.
+ */
+
+ /* Setup the primaries */
+ {
+ /* Compute primaries as XYZ */
+ icmXYZNumber wrgb[4] = { /* Primaries in Yxy from the standard */
+ { 1.0, 0.3127, 0.3290 }, /* White */
+ { 1.0, 0.6400, 0.3300 }, /* Red */
+ { 1.0, 0.3000, 0.6000 }, /* Green */
+ { 1.0, 0.1500, 0.0600 } /* Blue */
+ };
+ double mat[3][3];
+ int i;
+
+ /* Convert Yxy to XYZ */
+ for (i = 0; i < 4; i++) {
+ double v[3];
+
+ icmXYZ2Ary(v, wrgb[i]);
+ icmYxy2XYZ(v, v);
+ icmAry2XYZ(wrgb[i], v);
+ }
+
+ /* Convert XYZ to normalised 3x3 matrix */
+ icmRGBprim2matrix(wrgb[0], wrgb[1], wrgb[2], wrgb[3], mat);
+
+#ifdef NEVER /* Dump XYZ of matrix */
+ printf("sRGB: XYZ\n");
+ printf("{ %f, %f, %f }, /* Red */\n"
+ "{ %f, %f, %f }, /* Green */\n"
+ "{ %f, %f, %f }, /* Blue */\n"
+ "{ %f, %f, %f } /* White */\n",
+ mat[0][0], mat[0][1], mat[0][2],
+ mat[1][0], mat[1][1], mat[1][2],
+ mat[2][0], mat[2][1], mat[2][2],
+ wrgb[0].X, wrgb[0].Y, wrgb[0].Z);
+#endif
+
+ /* White Point Tag: */
+ {
+ icmXYZArray *wo;
+
+ if ((wo = (icmXYZArray *)wr_icco->add_tag(
+ wr_icco, icSigMediaWhitePointTag, icSigXYZArrayType)) == NULL)
+ error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);
+
+ wo->size = 1;
+ wo->allocate((icmBase *)wo); /* Allocate space */
+ wo->data[0].X = wrgb[0].X;
+ wo->data[0].Y = wrgb[0].Y;
+ wo->data[0].Z = wrgb[0].Z;
+ }
+ /* Black Point Tag: */
+ {
+ icmXYZArray *wo;
+
+ if ((wo = (icmXYZArray *)wr_icco->add_tag(
+ wr_icco, icSigMediaBlackPointTag, icSigXYZArrayType)) == NULL)
+ error("add_tag failed: %d, %s",wr_icco->errc,wr_icco->err);
+
+ wo->size = 1;
+ wo->allocate((icmBase *)wo); /* Allocate space */
+ wo->data[0].X = 0.00;
+ wo->data[0].Y = 0.00;
+ wo->data[0].Z = 0.00;
+ }
+ /* Red, Green and Blue Colorant Tags: */
+ {
+ icmXYZArray *wor, *wog, *wob;
+ double fromAbs[3][3];
+ double d50m[3][3];
+
+ /* Convert to D50 adapated */
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, wrgb[0], fromAbs);
+ icmMulBy3x3(d50m[0], fromAbs, mat[0]);
+ icmMulBy3x3(d50m[1], fromAbs, mat[1]);
+ icmMulBy3x3(d50m[2], fromAbs, mat[2]);
+
+ /* Make sure rounding doesn't wreck white point */
+ quantizeRGBprimsS15Fixed16(d50m);
+
+ if ((wor = (icmXYZArray *)wr_icco->add_tag(
+ wr_icco, icSigRedColorantTag, icSigXYZArrayType)) == NULL)
+ error("add_tag failed: %d, %s",rv,wr_icco->err);
+ if ((wog = (icmXYZArray *)wr_icco->add_tag(
+ wr_icco, icSigGreenColorantTag, icSigXYZArrayType)) == NULL)
+ error("add_tag failed: %d, %s",rv,wr_icco->err);
+ if ((wob = (icmXYZArray *)wr_icco->add_tag(
+ wr_icco, icSigBlueColorantTag, icSigXYZArrayType)) == NULL)
+ error("add_tag failed: %d, %s",rv,wr_icco->err);
+
+ wor->size = wog->size = wob->size = 1;
+ wor->allocate((icmBase *)wor); /* Allocate space */
+ wog->allocate((icmBase *)wog);
+ wob->allocate((icmBase *)wob);
+ wor->data[0].X = d50m[0][0]; wor->data[0].Y = d50m[0][1]; wor->data[0].Z = d50m[0][2];
+ wog->data[0].X = d50m[1][0]; wog->data[0].Y = d50m[1][1]; wog->data[0].Z = d50m[1][2];
+ wob->data[0].X = d50m[2][0]; wob->data[0].Y = d50m[2][1]; wob->data[0].Z = d50m[2][2];
+ }
+ }
+ /* Red, Green and Blue Gamma Curve Tags: */
+ {
+ icmCurve *wor, *wog, *wob;
+ int i;
+
+ if ((wor = (icmCurve *)wr_icco->add_tag(
+ wr_icco, icSigRedTRCTag, icSigCurveType)) == NULL)
+ error("add_tag failed: %d, %s",rv,wr_icco->err);
+ wor->flag = icmCurveSpec;
+ wor->size = 1024;
+ wor->allocate((icmBase *)wor); /* Allocate space */
+ for (i = 0; i < wor->size; i++)
+ wor->data[i] = gdv2dv(i/(wor->size-1.0));
+
+ /* Link other channels to the red */
+ if ((wog = (icmCurve *)wr_icco->link_tag(
+ wr_icco, icSigGreenTRCTag, icSigRedTRCTag)) == NULL)
+ error("link_tag failed: %d, %s",rv,wr_icco->err);
+ if ((wob = (icmCurve *)wr_icco->link_tag(
+ wr_icco, icSigBlueTRCTag, icSigRedTRCTag)) == NULL)
+ error("link_tag failed: %d, %s",rv,wr_icco->err);
+ }
+
+ /* Write the file out */
+ if ((rv = wr_icco->write(wr_icco,wr_fp,0)) != 0)
+ error ("Write file: %d, %s",rv,wr_icco->err);
+
+ wr_icco->del(wr_icco);
+ wr_fp->del(wr_fp);
+
+ return 0;
+}
+
+/* ------------------------------------------------ */
+/* Basic printf type error() and warning() routines */
+
+void
+error(char *fmt, ...) {
+ va_list args;
+
+ fprintf(stderr,"mkDispProf: Error - ");
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit (-1);
+}
+
+void
+warning(char *fmt, ...) {
+ va_list args;
+
+ fprintf(stderr,"mkDispProf: Warning - ");
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+}
diff --git a/icc/sRGB.icm b/icc/sRGB.icm
index db0355f..5491330 100644
--- a/icc/sRGB.icm
+++ b/icc/sRGB.icm
Binary files differ
diff --git a/imdi/cctiff.c b/imdi/cctiff.c
index 1f3eb9e..bb6ee0d 100644
--- a/imdi/cctiff.c
+++ b/imdi/cctiff.c
@@ -17,6 +17,10 @@
/* TTBD:
+ Should special case jpeg noop used to embed profile
+ in output, using jpeg_read_coefficients()/jpeg_write_coefficients()
+ rather than jpeg_start_decompress(), jpeg_read_scanlines() etc.
+
Should make -d option default to the last device
profile.
@@ -469,7 +473,7 @@ char **inknames /* Return ASCII inknames if non NULL */
return 0; /* Not CMYK */
case icSigCmykData:
if (inknames != NULL) {
- *inknames = NULL; /* No inknames */
+ *inknames = NULL; /* No inknames - it's coded */
*len = 0;
}
return INKSET_CMYK;
@@ -629,7 +633,7 @@ static void l2y_curve(double *out, double *in, int isXYZ) {
/* Callbacks used to initialise imdi */
-/* Information needed from a single profile */
+/* Information needed from a single profile or calibration */
struct _profinfo {
char name[MAXNAMEL+1];
icc *c; /* If non-NULL, ICC profile. */
@@ -984,6 +988,7 @@ main(int argc, char *argv[]) {
int alpha = 0; /* Use alpha for extra planes */
int ignoremm = 0; /* Ignore any colorspace mismatches */
int nodesc = 0; /* Don't append or set the description */
+ int copydct = 0; /* For jpeg->jpeg with no changes, copy DCT cooeficients */
int i, j, rv = 0;
/* TIFF file info */
@@ -1238,10 +1243,10 @@ main(int argc, char *argv[]) {
}
}
- /* The last two "profiles" are actually the input and output TIFF filenames */
+ /* The last two "profiles" are actually the input and output TIFF/JPEG filenames */
/* Unwind them */
if (su.nprofs < 2)
- usage("Not enough arguments to specify input and output TIFF files");
+ usage("Not enough arguments to specify input and output TIFF/JPEG files");
strncpy(out_name,su.profs[--su.nprofs].name, MAXNAMEL); out_name[MAXNAMEL] = '\000';
strncpy(in_name,su.profs[--su.nprofs].name, MAXNAMEL); in_name[MAXNAMEL] = '\000';
@@ -1250,13 +1255,13 @@ main(int argc, char *argv[]) {
su.lclut = su.last = su.nprofs-1;
if (check && (!doimdi || !dofloat))
- error("Can't do check unless both integera and float processing are enabled");
+ error("Can't do check unless both integeral and float processing are enabled");
/*
Logic required:
- Discover input TIFF colorspace and set as (ICC) "next_space"
+ Discover input TIFF/JPEG colorspace and set as (ICC) "next_space"
Set any special input space encoding transform (ie. device, Lab flavour)
For each profile:
@@ -1396,6 +1401,8 @@ main(int argc, char *argv[]) {
jpeg_stdio_src(&rj, rf);
jpeg_save_markers(&rj, JPEG_COM, 0xFFFF);
+ for (i = 0; i < 16; i++)
+ jpeg_save_markers(&rj, JPEG_APP0 + i, 0xFFFF);
/* we'll longjmp on error */
jpeg_read_header(&rj, TRUE);
@@ -1488,9 +1495,6 @@ main(int argc, char *argv[]) {
if (dojpg < 0)
dojpg = 1;
- /* ~~ Should determine deafult jpgq from tables of this file */
-
- jpeg_start_decompress(&rj);
}
@@ -1585,7 +1589,7 @@ main(int argc, char *argv[]) {
error("Last colorspace %s from file '%s' doesn't match input space %s of profile %s",
icm2str(icmColorSpaceSignature,last_colorspace),
last_cs_file,
- icm2str(icmColorSpaceSignature,su.profs[i].h->colorSpace),
+ icm2str(icmColorSpaceSignature,su.profs[i].ins),
su.profs[i].name);
last_dim = icmCSSig2nchan(su.profs[i].outs);
@@ -1680,10 +1684,13 @@ main(int argc, char *argv[]) {
if (no_pmtc > 1) { /* Need to choose a photometric */
if (ochoice < 1 || ochoice > no_pmtc ) {
- printf("Possible Output Encodings for output colorspace %s are:\n",
- icm2str(icmColorSpaceSignature,last_colorspace));
- for (i = 0; i < no_pmtc; i++)
- printf("%d: %s%s\n",i+1, Photometric2str(pmtc[i]), i == 0 ? " (Default)" : "");
+ if (su.verb) {
+ printf("Possible Output Encodings for output colorspace %s are:\n",
+ icm2str(icmColorSpaceSignature,last_colorspace));
+ for (i = 0; i < no_pmtc; i++)
+ printf("%d: %s%s\n",i+1, Photometric2str(pmtc[i]), i == 0 ? " (Default)" : "");
+ printf("Using default\n\n");
+ }
ochoice = 1;
}
wphotometric = pmtc[ochoice-1];
@@ -1710,13 +1717,14 @@ main(int argc, char *argv[]) {
int inlen;
char *inames = NULL;
- if (c == NULL
- || ((ct = (icmColorantTable *)c->read_tag(c, icSigColorantTableOutTag)) == NULL
- && (ct = (icmColorantTable *)c->read_tag(c, icSigColorantTableTag)) == NULL)
- || ct->count != wsamplesperpixel
+ iset = ColorSpaceSignature2TiffInkset(su.outs, &inlen, &inames);
+
+ /* Use ICC profile ink names if they are available */
+ if (c != NULL
+ && ((ct = (icmColorantTable *)c->read_tag(c, icSigColorantTableOutTag)) != NULL
+ || (ct = (icmColorantTable *)c->read_tag(c, icSigColorantTableTag)) != NULL)
+ && ct->count != wsamplesperpixel
) {
- iset = ColorSpaceSignature2TiffInkset(su.outs, &inlen, &inames);
- } else {
int i;
char *cp;
inlen = 0;
@@ -1732,11 +1740,12 @@ main(int argc, char *argv[]) {
cp += slen;
}
*cp = '\000';
- iset = INKSET_MULTIINK;
}
- if (iset != 0xffff && inlen > 0 && inames != NULL) {
+ if (iset != 0xffff) {
TIFFSetField(wh, TIFFTAG_INKSET, iset);
- if (inames != NULL) {
+ /* An inknames tage confuses Photoshop with standard spaces */
+ if ((iset == INKSET_MULTIINK || iset == 0) /* N color or CMY */
+ && inlen > 0 && inames != NULL) {
TIFFSetField(wh, TIFFTAG_INKNAMES, inlen, inames);
}
}
@@ -1834,87 +1843,12 @@ main(int argc, char *argv[]) {
if (wj.write_Adobe_marker)
su.oinv = 1;
-
- jpeg_start_compress(&wj, TRUE);
-
- /* Perhaps the description could be more informative ? */
- if (rdesc != NULL) {
- if ((wdesc = malloc(sizeof(char) * (strlen(rdesc) + strlen(ddesc) + 2))) == NULL)
- error("malloc failed on new desciption string");
-
- strcpy(wdesc, rdesc);
- if (nodesc == 0 && su.nprofs > 0) {
- strcat(wdesc, " ");
- strcat(wdesc, ddesc);
- }
- jpeg_write_marker(&wj, JPEG_COM, (const JOCTET *)wdesc, strlen(wdesc)+1);
- } else if (nodesc == 0 && su.nprofs > 0) {
- if ((wdesc = strdup(ddesc)) == NULL)
- error("malloc failed on new desciption string");
- jpeg_write_marker(&wj, JPEG_COM, (const JOCTET *)wdesc, strlen(wdesc)+1);
- }
}
/* - - - - - - - - - - - - - - - */
- /* Setup any destination embedded profile */
- if (dst_pname[0] != '\000') {
- icmFile *fp; /* Read fp for the profile */
- unsigned char *buf;
- int size;
-
- if ((deicc = read_embedded_icc(dst_pname)) == NULL)
- error("Unable to open profile for destination embedding '%s'",dst_pname);
-
- /* Check that it is compatible with the destination raster file */
- if (deicc->header->deviceClass != icSigColorSpaceClass
- && deicc->header->deviceClass != icSigInputClass
- && deicc->header->deviceClass != icSigDisplayClass
- && deicc->header->deviceClass != icSigOutputClass) {
- error("Destination embedded profile is wrong device class for embedding");
- }
-
- if (deicc->header->colorSpace != su.outs
- || (deicc->header->pcs != icSigXYZData
- && deicc->header->pcs != icSigLabData)) {
- error("Destination embedded profile colorspaces don't match TIFF");
- }
-
- if ((fp = deicc->get_rfp(deicc)) == NULL)
- error("Failed to be able to read destination embedded profile");
-
- if ((size = fp->get_size(fp)) == 0)
- error("Failed to be able to get size of destination embedded profile");
-
- if ((buf = malloc(size)) == NULL)
- error("malloc failed on destination embedded profile size %d",size);
-
- if (fp->seek(fp,0))
- error("rewind on destination embedded profile failed");
-
- if (fp->read(fp, buf, 1, size) != size)
- error("reading destination embedded profile failed");
-
- /* (For iccv4 we would now fp->del(fp) because we got a reference) */
-
- if (wh != NULL) {
- if (TIFFSetField(wh, TIFFTAG_ICCPROFILE, size, buf) == 0)
- error("setting TIFF embedded ICC profile field failed");
- } else {
- if (setjmp(jpeg_werr.env)) {
- jpeg_destroy_compress(&wj);
- error("setting JPEG embedded ICC profile marker failed");
- }
- write_icc_profile(&wj, buf, size);
- }
-
- free(buf);
- deicc->del(deicc);
- }
-
- /* - - - - - - - - - - - - - - - */
- if ((su.fclut <= su.lclut
- && (su.profs[su.fclut].natpcs == icSigXYZData) && (su.profs[su.fclut].alg == icmMatrixFwdType))
- || su.profs[su.fclut].ins == icSigXYZData) {
+ if (su.fclut <= su.lclut
+ && ((su.profs[su.fclut].natpcs == icSigXYZData && su.profs[su.fclut].alg == icmMatrixFwdType)
+ || su.profs[su.fclut].ins == icSigXYZData)) {
su.ilcurve = 1; /* Index CLUT with L* curve rather than Y */
}
@@ -1923,9 +1857,9 @@ main(int argc, char *argv[]) {
su.icombine = 1; /* CIE can't be conveyed through 0..1 domain lookup */
}
- if ((su.fclut <= su.lclut
- && (su.profs[su.lclut].natpcs == icSigXYZData && su.profs[su.lclut].alg == icmMatrixBwdType))
- || (su.profs[su.lclut].outs == icSigXYZData)) {
+ if (su.fclut <= su.lclut
+ && ((su.profs[su.lclut].natpcs == icSigXYZData && su.profs[su.lclut].alg == icmMatrixBwdType)
+ || su.profs[su.lclut].outs == icSigXYZData)) {
su.olcurve = 1; /* Interpolate in L* space rather than Y */
}
@@ -1933,6 +1867,11 @@ main(int argc, char *argv[]) {
su.ocombine = 1; /* CIE can't be conveyed through 0..1 domain lookup */
}
+ /* Decide if jpeg should decompress & compress */
+ if (rf != NULL && wf != NULL && su.nprofs == 0) {
+ copydct = 1;
+ }
+
/* - - - - - - - - - - - - - - - */
/* Report the connection sequence details */
@@ -1944,6 +1883,8 @@ main(int argc, char *argv[]) {
} else {
printf("Input raster file '%s' is JPEG\n",in_name);
printf("Input JPEG file original colorspace is %s\n",JPEG_cspace2str(rj.jpeg_color_space));
+ if (copydct)
+ printf("JPEG copy will be lossless\n");
}
printf("Input raster file ICC colorspace is %s\n",icm2str(icmColorSpaceSignature,su.ins));
printf("Input raster file is %d x %d pixels\n",su.width, su.height);
@@ -1953,6 +1894,7 @@ main(int argc, char *argv[]) {
printf("There are %d profiles/calibrations in the sequence:\n\n",su.nprofs);
+
for (i = su.first; i <= su.last; i++) {
if (su.profs[i].c != NULL) {
icmFile *op;
@@ -2119,164 +2061,251 @@ main(int argc, char *argv[]) {
}
}
+ /* NOTE :- the legal of jpeg calls is rather tricky.... */
- /* - - - - - - - - - - - - - - - */
- /* Process colors to translate */
- /* (Should fix this to process a group of lines at a time ?) */
+ if (!copydct) { /* Do this before writing description */
+ if (rf)
+ jpeg_start_decompress(&rj);
+ if (wf)
+ jpeg_start_compress(&wj, TRUE);
+ }
- for (y = 0; y < height; y++) {
- tdata_t *obuf;
+ if (wf != NULL) {
+ /* Perhaps the description could be more informative ? */
+ if (rdesc != NULL) {
+ if ((wdesc = malloc(sizeof(char) * (strlen(rdesc) + strlen(ddesc) + 2))) == NULL)
+ error("malloc failed on new desciption string");
+
+ strcpy(wdesc, rdesc);
+ if (nodesc == 0 && su.nprofs > 0) {
+ strcat(wdesc, " ");
+ strcat(wdesc, ddesc);
+ }
+ jpeg_write_marker(&wj, JPEG_COM, (const JOCTET *)wdesc, strlen(wdesc)+1);
+ } else if (nodesc == 0 && su.nprofs > 0) {
+ if ((wdesc = strdup(ddesc)) == NULL)
+ error("malloc failed on new desciption string");
+ jpeg_write_marker(&wj, JPEG_COM, (const JOCTET *)wdesc, strlen(wdesc)+1);
+ }
+ }
- /* Read in the next line */
- if (rh) {
- if (TIFFReadScanline(rh, inbuf, y, 0) < 0)
- error ("Failed to read TIFF line %d",y);
+ if (copydct) { /* Lossless JPEG copy - copy image data */
+ jvirt_barray_ptr *coefas;
+ jpeg_saved_marker_ptr marker;
+
+ coefas = jpeg_read_coefficients(&rj);
+ jpeg_copy_critical_parameters(&rj, &wj);
+ jpeg_write_coefficients(&wj, coefas);
+
+// We don't copy these normally.
+// for (marker = rj.marker_list; marker != NULL; marker = marker->next) {
+// jpeg_write_marker(&wj, marker->marker, marker->data, marker->data_length);
+ }
+
+ /* Setup any destination embedded profile */
+ if (dst_pname[0] != '\000') {
+ icmFile *fp; /* Read fp for the profile */
+ unsigned char *buf;
+ int size;
+
+ if ((deicc = read_embedded_icc(dst_pname)) == NULL)
+ error("Unable to open profile for destination embedding '%s'",dst_pname);
+
+ /* Check that it is compatible with the destination raster file */
+ if (deicc->header->deviceClass != icSigColorSpaceClass
+ && deicc->header->deviceClass != icSigInputClass
+ && deicc->header->deviceClass != icSigDisplayClass
+ && deicc->header->deviceClass != icSigOutputClass) {
+ error("Destination embedded profile is wrong device class for embedding");
+ }
+
+ if (deicc->header->colorSpace != su.outs
+ || (deicc->header->pcs != icSigXYZData
+ && deicc->header->pcs != icSigLabData)) {
+ error("Destination embedded profile colorspaces don't match TIFF");
+ }
+
+ if ((fp = deicc->get_rfp(deicc)) == NULL)
+ error("Failed to be able to read destination embedded profile");
+
+ if ((size = fp->get_size(fp)) == 0)
+ error("Failed to be able to get size of destination embedded profile");
+
+ if ((buf = malloc(size)) == NULL)
+ error("malloc failed on destination embedded profile size %d",size);
+
+ if (fp->seek(fp,0))
+ error("rewind on destination embedded profile failed");
+
+ if (fp->read(fp, buf, 1, size) != size)
+ error("reading destination embedded profile failed");
+
+ /* (For iccv4 we would now fp->del(fp) because we got a reference) */
+
+ if (wh != NULL) {
+ if (TIFFSetField(wh, TIFFTAG_ICCPROFILE, size, buf) == 0)
+ error("setting TIFF embedded ICC profile field failed");
} else {
- jpeg_read_scanlines(&rj, (JSAMPARRAY)&inbuf, 1);
- if (su.iinv) {
- unsigned char *cp, *ep = (unsigned char *)inbuf + inbpix;
- for (cp = (unsigned char *)inbuf; cp < ep; cp++)
- *cp = ~*cp;
+ if (setjmp(jpeg_werr.env)) {
+ jpeg_destroy_compress(&wj);
+ error("setting JPEG embedded ICC profile marker failed");
}
+ write_icc_profile(&wj, buf, size);
}
- if (doimdi && su.nprofs > 0) {
- /* Do fast conversion */
- s->interp(s, (void **)outp, 0, (void **)inp, su.id, width);
- }
-
- if (dofloat || su.nprofs == 0) {
- /* Do floating point conversion into the hprecbuf[] */
- for (x = 0; x < width; x++) {
- int i;
- double in[MAX_CHAN], out[MAX_CHAN];
-
+ free(buf);
+ deicc->del(deicc);
+ }
+
+ if (!copydct) {
+
+ /* We're not doing a lossless copy */
+
+
+ /* - - - - - - - - - - - - - - - */
+ /* Process colors to translate */
+ /* (Should fix this to process a group of lines at a time ?) */
+
+ for (y = 0; y < height; y++) {
+ tdata_t *obuf;
+
+ /* Read in the next line */
+ if (rh) {
+ if (TIFFReadScanline(rh, inbuf, y, 0) < 0)
+ error ("Failed to read TIFF line %d",y);
+ } else {
+ jpeg_read_scanlines(&rj, (JSAMPARRAY)&inbuf, 1);
+ if (su.iinv) {
+ unsigned char *cp, *ep = (unsigned char *)inbuf + inbpix;
+ for (cp = (unsigned char *)inbuf; cp < ep; cp++)
+ *cp = ~*cp;
+ }
+ }
+
+ if (doimdi && su.nprofs > 0) {
+ /* Do fast conversion */
+ s->interp(s, (void **)outp, 0, (void **)inp, su.id, width);
+ }
+
+ if (dofloat || su.nprofs == 0) {
+ /* Do floating point conversion into the hprecbuf[] */
+ for (x = 0; x < width; x++) {
+ int i;
+ double in[MAX_CHAN], out[MAX_CHAN];
+
//printf("\n");
- if (bitspersample == 8) {
- for (i = 0; i < su.id; i++) {
- int v = ((unsigned char *)inbuf)[x * su.id + i];
+ if (bitspersample == 8) {
+ for (i = 0; i < su.id; i++) {
+ int v = ((unsigned char *)inbuf)[x * su.id + i];
//printf("~1 8 bit pixel value chan %d = %d\n",i,v);
- if (su.isign_mask & (1 << i)) /* Treat input as signed */
- v = (v & 0x80) ? v - 0x80 : v + 0x80;
+ if (su.isign_mask & (1 << i)) /* Treat input as signed */
+ v = (v & 0x80) ? v - 0x80 : v + 0x80;
//printf("~1 8 bit after treat as signed chan %d = %d\n",i,v);
- in[i] = v/255.0;
+ in[i] = v/255.0;
//printf("~1 8 bit fp chan %d value = %f\n",i,in[i]);
- }
- } else {
- for (i = 0; i < su.id; i++) {
- int v = ((unsigned short *)inbuf)[x * su.id + i];
+ }
+ } else {
+ for (i = 0; i < su.id; i++) {
+ int v = ((unsigned short *)inbuf)[x * su.id + i];
//printf("~1 16 bit pixel value chan %d = %d\n",i,v);
- if (su.isign_mask & (1 << i)) /* Treat input as signed */
- v = (v & 0x8000) ? v - 0x8000 : v + 0x8000;
+ if (su.isign_mask & (1 << i)) /* Treat input as signed */
+ v = (v & 0x8000) ? v - 0x8000 : v + 0x8000;
//printf("~1 16 bit after treat as signed chan %d = %d\n",i,v);
- in[i] = v/65535.0;
+ in[i] = v/65535.0;
//printf("~1 16 bit fp chan %d value = %f\n",i,in[i]);
+ }
}
- }
- if (su.nprofs > 0) {
- /* Apply the reference conversion */
- input_curves((void *)&su, out, in);
+ if (su.nprofs > 0) {
+ /* Apply the reference conversion */
+ input_curves((void *)&su, out, in);
//for (i = 0; i < su.id; i++) printf("~1 after input curve chan %d = %f\n",i,out[i]);
- md_table((void *)&su, out, out);
+ md_table((void *)&su, out, out);
//for (i = 0; i < su.od; i++) printf("~1 after md table chan %d = %f\n",i,out[i]);
- output_curves((void *)&su, out, out);
+ output_curves((void *)&su, out, out);
//for (i = 0; i < su.od; i++) printf("~1 after output curve chan %d = %f\n",i,out[i]);
- } else {
- for (i = 0; i < su.od; i++)
- out[i] = in[i];
- }
+ } else {
+ for (i = 0; i < su.od; i++)
+ out[i] = in[i];
+ }
- if (bitspersample == 8) {
- for (i = 0; i < su.od; i++) {
- int v = (int)(out[i] * 255.0 + 0.5);
+ if (bitspersample == 8) {
+ for (i = 0; i < su.od; i++) {
+ int v = (int)(out[i] * 255.0 + 0.5);
//printf("~1 8 bit chan %d = %d\n",i,v);
- if (v < 0)
- v = 0;
- else if (v > 255)
- v = 255;
+ if (v < 0)
+ v = 0;
+ else if (v > 255)
+ v = 255;
//printf("~1 8 bit after clip curve chan %d = %d\n",i,v);
- if (su.osign_mask & (1 << i)) /* Treat input as offset */
- v = (v & 0x80) ? v - 0x80 : v + 0x80;
+ if (su.osign_mask & (1 << i)) /* Treat input as offset */
+ v = (v & 0x80) ? v - 0x80 : v + 0x80;
//printf("~1 8 bit after treat as offset chan %d = %d\n",i,v);
- ((unsigned char *)hprecbuf)[x * su.od + i] = v;
- }
- } else {
- for (i = 0; i < su.od; i++) {
- int v = (int)(out[i] * 65535.0 + 0.5);
+ ((unsigned char *)hprecbuf)[x * su.od + i] = v;
+ }
+ } else {
+ for (i = 0; i < su.od; i++) {
+ int v = (int)(out[i] * 65535.0 + 0.5);
//printf("~1 16 bit chan %d = %d\n",i,v);
- if (v < 0)
- v = 0;
- else if (v > 65535)
- v = 65535;
+ if (v < 0)
+ v = 0;
+ else if (v > 65535)
+ v = 65535;
//printf("~1 16 bit after clip curve chan %d = %d\n",i,v);
- if (su.osign_mask & (1 << i)) /* Treat input as offset */
- v = (v & 0x8000) ? v - 0x8000 : v + 0x8000;
+ if (su.osign_mask & (1 << i)) /* Treat input as offset */
+ v = (v & 0x8000) ? v - 0x8000 : v + 0x8000;
//printf("~1 16 bit after treat as offset chan %d = %d\n",i,v);
- ((unsigned short *)hprecbuf)[x * su.od + i] = v;
+ ((unsigned short *)hprecbuf)[x * su.od + i] = v;
+ }
}
}
- }
- if (check) {
- /* Compute the errors */
- for (x = 0; x < (width * su.od); x++) {
- int err;
- if (bitspersample == 8)
- err = ((unsigned char *)outbuf)[x] - ((unsigned char *)hprecbuf)[x];
- else
- err = ((unsigned short *)outbuf)[x] - ((unsigned short *)hprecbuf)[x];
- if (err < 0)
- err = -err;
- if (err > mxerr)
- mxerr = err;
- avgerr += (double)err;
- avgcount++;
+ if (check) {
+ /* Compute the errors */
+ for (x = 0; x < (width * su.od); x++) {
+ int err;
+ if (bitspersample == 8)
+ err = ((unsigned char *)outbuf)[x] - ((unsigned char *)hprecbuf)[x];
+ else
+ err = ((unsigned short *)outbuf)[x] - ((unsigned short *)hprecbuf)[x];
+ if (err < 0)
+ err = -err;
+ if (err > mxerr)
+ mxerr = err;
+ avgerr += (double)err;
+ avgcount++;
+ }
}
}
- }
-
- if (dofloat || su.nprofs == 0) /* Use the results of the f.p. conversion */
- obuf = hprecbuf;
- else
- obuf = outbuf;
-
- if (wh != NULL) {
- if (TIFFWriteScanline(wh, obuf, y, 0) < 0)
- error ("Failed to write TIFF line %d",y);
- } else {
- if (su.oinv) {
- unsigned char *cp, *ep = (unsigned char *)obuf + outbpix;
- for (cp = (unsigned char *)obuf; cp < ep; cp++)
- *cp = ~(*cp);
+
+ if (dofloat || su.nprofs == 0) /* Use the results of the f.p. conversion */
+ obuf = hprecbuf;
+ else
+ obuf = outbuf;
+
+ if (wh != NULL) {
+ if (TIFFWriteScanline(wh, obuf, y, 0) < 0)
+ error ("Failed to write TIFF line %d",y);
+ } else {
+ if (su.oinv) {
+ unsigned char *cp, *ep = (unsigned char *)obuf + outbpix;
+ for (cp = (unsigned char *)obuf; cp < ep; cp++)
+ *cp = ~(*cp);
+ }
+ jpeg_write_scanlines(&wj, (JSAMPARRAY)&obuf, 1);
}
- jpeg_write_scanlines(&wj, (JSAMPARRAY)&obuf, 1);
}
- }
-
- if (check) {
- printf("Worst error = %d bits, average error = %f bits\n", mxerr, avgerr/avgcount);
- if (bitspersample == 8)
- printf("Worst error = %f%%, average error = %f%%\n",
- mxerr/2.55, avgerr/(2.55 * avgcount));
- else
- printf("Worst error = %f%%, average error = %f%%\n",
- mxerr/655.35, avgerr/(655.35 * avgcount));
- }
+ if (check) {
+ printf("Worst error = %d bits, average error = %f bits\n", mxerr, avgerr/avgcount);
+ if (bitspersample == 8)
+ printf("Worst error = %f%%, average error = %f%%\n",
+ mxerr/2.55, avgerr/(2.55 * avgcount));
+ else
+ printf("Worst error = %f%%, average error = %f%%\n",
+ mxerr/655.35, avgerr/(655.35 * avgcount));
+ }
- /* Release buffers and close files */
- if (rh != NULL) {
- if (inbuf != NULL)
- _TIFFfree(inbuf);
- TIFFClose(rh); /* Close Input file */
- } else {
- jpeg_finish_decompress(&rj);
- jpeg_destroy_decompress(&rj);
- if (inbuf != NULL)
- free(inbuf);
- if (fclose(rf))
- error("Error closing JPEG input file '%s'\n",in_name);
}
if (wh != NULL) {
@@ -2296,6 +2325,20 @@ main(int argc, char *argv[]) {
error("Error closing output file '%s'\n",out_name);
}
+ /* Release buffers and close files */
+ if (rh != NULL) {
+ if (inbuf != NULL)
+ _TIFFfree(inbuf);
+ TIFFClose(rh); /* Close Input file */
+ } else {
+ jpeg_finish_decompress(&rj);
+ jpeg_destroy_decompress(&rj);
+ if (inbuf != NULL)
+ free(inbuf);
+ if (fclose(rf))
+ error("Error closing JPEG input file '%s'\n",in_name);
+ }
+
/* Done with lookup object */
if (s != NULL)
s->del(s);
diff --git a/link/collink.c b/link/collink.c
index 6c40efd..3bb93b7 100644
--- a/link/collink.c
+++ b/link/collink.c
@@ -1,4 +1,6 @@
+/* Version with Lab bt.1886 */
+
/*
* collink
*
@@ -22,6 +24,7 @@
*
* Abstract link support intent doesn't work properly for anything
* other than absolute. This should really be fixed.
+ *
*/
/* NOTES:
@@ -51,7 +54,6 @@
The source profile per channel curve plus
a Y to L* curve it's a Matrix profile.
-
Colorspace representations are a bit of a mess. It's hard to know what space
color is in at any point, and difficult to transform to match
some other element. Putting the different colorspace support within
@@ -96,6 +98,8 @@
#undef NEUTKDEBUG /* print info about neutral L -> K mapping */
+#undef LINTERP_OR /* Use simple extrapolation of Video encoded overrage values */
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -104,12 +108,12 @@
#include <math.h>
#include "copyright.h"
#include "aconfig.h"
+#include "counters.h"
#include "numlib.h"
#include "icc.h"
#include "xicc.h"
#include "gamut.h"
#include "gammap.h"
-// ~~~99
#include "vrml.h"
void usage(char *diag, ...) {
@@ -140,6 +144,8 @@ void usage(char *diag, ...) {
fprintf(stderr," -F Special :- Force all colors to be K only output\n");
fprintf(stderr," -fcmy Special :- Force 100%% C,M or Y only to stay pure \n");
fprintf(stderr," -p absprof Include abstract profile in link\n");
+ fprintf(stderr," -a file.cal Apply calibration curves to link output and append linear\n");
+ fprintf(stderr," -H file.cal Append calibration curves to 3dlut\n");
fprintf(stderr," -s Simple Mode (default)\n");
fprintf(stderr," -g [src.gam] Gamut Mapping Mode [optional source image gamut]\n");
fprintf(stderr," -G [src.gam] Gamut Mapping Mode using inverse outprofile A2B\n");
@@ -176,10 +182,11 @@ void usage(char *diag, ...) {
fprintf(stderr," w:x:y Adapted white point as x, y\n");
fprintf(stderr," a:adaptation Adaptation luminance in cd.m^2 (default 50.0)\n");
fprintf(stderr," b:background Background %% of image luminance (default 20)\n");
- fprintf(stderr," l:scenewhite Scene white in cd.m^2 if surround = auto (default 250)\n");
- fprintf(stderr," f:flare Flare light %% of image luminance (default 1)\n");
- fprintf(stderr," f:X:Y:Z Flare color as XYZ (default media white)\n");
- fprintf(stderr," f:x:y Flare color as x, y\n");
+ fprintf(stderr," l:imagewhite Image white in cd.m^2 if surround = auto (default 250)\n");
+ fprintf(stderr," f:flare Flare light %% of image luminance (default 0)\n");
+ fprintf(stderr," g:glare Flare light %% of ambient (default 1)\n");
+ fprintf(stderr," g:X:Y:Z Flare color as XYZ (default media white, Abs: D50)\n");
+ fprintf(stderr," g:x:y Flare color as x, y\n");
fprintf(stderr," -t tlimit set source total ink limit, 0 - 400%% (estimate by default)\n");
fprintf(stderr," -T klimit set source black ink limit, 0 - 100%% (estimate by default)\n");
fprintf(stderr," Inverse outprofile A2B Options:\n");
@@ -193,11 +200,56 @@ void usage(char *diag, ...) {
fprintf(stderr," -K parameters Same as -k, but target is K locus rather than K value itself\n");
fprintf(stderr," -l tlimit set destination total ink limit, 0 - 400%% (estimate by default)\n");
fprintf(stderr," -L klimit set destination black ink limit, 0 - 100%% (estimate by default)\n");
+ fprintf(stderr," -3 flag Create \"3DLut\" output file as well as devlink\n");
+ fprintf(stderr," e eeColor .txt file\n");
+ fprintf(stderr," m MadVR .3dlut\t file\n");
+ fprintf(stderr," -I b Apply BT.1886-like mapping with effective gamma 2.2 to input\n");
+ fprintf(stderr," -I b:g.g Apply BT.1886-like mapping with effective gamma g.g to input\n");
+ fprintf(stderr," -I B Apply BT.1886 mapping with technical gamma 2.4 to input\n");
+ fprintf(stderr," -I B:g.g Apply BT.1886 mapping with technical gamma g.g to input\n");
+ fprintf(stderr," -e flag Video encode input as:\n");
+ fprintf(stderr," -E flag Video encode output as:\n");
+ fprintf(stderr," n normal 0..1 full range RGB levels (default)\n");
+ fprintf(stderr," t (16-235)/255 \"TV\" RGB levels\n");
+ fprintf(stderr," 6 Rec601 YCbCr SD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 7 Rec709 1125/60Hz YCbCr HD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 5 Rec709 1250/50Hz YCbCr HD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 2 Rec2020 YCbCr UHD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," C Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," x xvYCC Rec601 YCbCr Rec709 Prims. SD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," X xvYCC Rec709 YCbCr Rec709 Prims. HD (16-235,240)/255 \"TV\" levels\n");
fprintf(stderr," -P Create gamut gammap.wrl diagostic\n");
exit(1);
}
/* ------------------------------------------- */
+
+#ifdef NEVER
+/* If video encoding is being used, the edge of the video range */
+/* may not fall on a gid boundary, leading to innacuracies */
+/* in black, white, or the saturated colors. */
+/* To fix this, we notice which gid values just get clipped */
+/* by the video encoding, and after the grid is complete, */
+/* do a fixup pass to set the grid value to that needed */
+/* to make the edge value perferct. */
+
+/* For the eeColor wich has a fixed grod res. of 65, */
+/* the Luminance range 16-235 lands perfectly on a grid point, */
+/* and the CbCr maximum value of 240 missed by 1/256, */
+/* so we haven't yet implemented this fixup */
+
+/* Instead we are just tweaking the cLUT values of the black */
+/* point to avoid any error at this critical value. */
+
+typedef struct {
+ int clip; /* Clip mask */
+ int ix[MXDI]; /* Index of the grid point that was clipped */
+ double in[MXDI]; /* grid value that was clipped */
+ double out[MXDO]; /* clipped value */
+} edgepoints;
+#endif
+
+/* ------------------------------------------- */
/* structures to support icc calbacks */
/* Information needed from a profile */
@@ -205,6 +257,7 @@ struct _profinfo {
/* Setup parameters */
icRenderingIntent intent; /* Selected ICC rendering intent */
icxViewCond vc; /* Viewing Condition for CAM */
+ int vc_set; /* vc may not be default (for verb) */
int inking; /* k inking algorithm, 0 = input, 1 = min, */
/* 2 = 0.5, 3 = max, 4 = ramp, 5 = curve, 6 = dual curve */
/* 7 = outpupt profile K value */
@@ -222,6 +275,21 @@ struct _profinfo {
int nocurve; /* NZ to not use device curve in per channel curve */
int lcurve; /* 1 to apply a Y like to L* curve for XYZ Matrix profiles */
/* 2 to apply a Y to L* curve for XYZ space */
+ int tvenc; /* 0 = full range RGB, 1 = RGB Video Level encoding, */
+ /* 2 = Rec601 YCbCr encoding, 3 = Rec709 1150/60/2:1 YCbCr encoding */
+ /* 4 = Rec709 1250/50/2:1 YCbCr encoding */
+ /* 5 = Rec2020 Non-constant Luminance YCbCr encoding */
+ /* 6 = Rec2020 Constant Luminance YCbCr encoding */
+ /* 7 = xvYCC with Rec601 YCbCr encoding with Rec709 primaries */
+ /* 8 = xvYCC with Rec709 YCbCr encoding with Rec709 primaries */
+ /* (We save Video YCbCr as "RGB" space ICC profile) */
+ int bt1886; /* 1 to apply BT.1886 black point & effective gamma to input */
+ /* 2 to apply BT.1886 black point & technical gamma to input */
+ double egamma; /* effective gamma to ain for */
+ double tgamma; /* technical gamma to ain for */
+ bt1886_info bt; /* BT.1886 adjustment info */
+ double rgb_bk[3]; /* Linear light input RGB black to bend to */
+ double bt_bk[3]; /* Input profile bt.1886 modified black point in gamut map space */
double wp[3]; /* Lab/Jab white point for profile used by wphack & xyzscale */
icxLuBase *b2aluo; /* B2A lookup for inking == 7 */
}; typedef struct _profinfo profinfo;
@@ -238,6 +306,7 @@ struct _clink {
int src_kbp; /* nz = Use K only black point as src gamut black point */
int dst_kbp; /* nz = Use K only black point as dst gamut black point */
int dst_cmymap; /* masks C = 1, M = 2, Y = 4 to force 100% cusp map */
+ int tdlut; /* nz = 3DLut output, 1 = eeColor format, 2 = MadVR format */
icColorSpaceSignature pcsor; /* PCS to use between in & out profiles */
@@ -256,6 +325,10 @@ struct _clink {
xicc *abs_xicc;
icxLuBase *abs_luo; /* NULL if none */
+ int addcal; /* 1 = apply cal to 3dLut and set linear cal1 */
+ /* 2 = set cal1 to cal */
+ xcal *cal; /* Calibration to apply, NULL if none */
+
/* (We current assume that xyzscale can't be used with gmi) */
double xyzscale; /* < 1.0 if Y is to be scaled in destination XYZ space */
double swxyz[3]; /* Source white point in XYZ */
@@ -264,6 +337,8 @@ struct _clink {
gammap *map; /* Gamut mapping */
gammap *Kmap; /* Gamut mapping K in to K out nhack == 2 and K in to K out */
+// edgepoints *epl; /* Edge point list for fixups when in.tvenc */
+ /* we need 2 * di * gres ^ (di-1) entries max. */
/* Per profile setup information */
profinfo in;
@@ -334,6 +409,130 @@ static void l2y_curve(double *out, double *in, int isXYZ) {
}
/* ------------------------------------------- */
+
+/* Clip a value to the RGB Video range 16..235 RGB */
+/* Return a bit mask of the channels that have clipped */
+/* Clip the incoming value clip[] in place */
+/* Return the uncliped value in unclipped[] */
+/* Return the full value in the clip direction in full[] */
+static int clipVidRGB(double full[3], double unclipped[3], double clip[3]) {
+ int i, os = 0;
+ for (i = 0; i < 3; i++) {
+ unclipped[i] = clip[i];
+ if (clip[i] < (16.0/255.0)) {
+ clip[i] = (16.0/255.0);
+ full[i] = 0.0;
+ os |= (1 << i);
+ } else if (clip[i] > (235.0/255.0)) {
+ clip[i] = (235.0/255.0);
+ full[i] = 1.0;
+ os |= (1 << i);
+ }
+ }
+ return os;
+}
+
+/* Clip a value to the YCbCr range range 16..235, 16..240 */
+/* Return a bit mask of the channels that have clipped */
+/* Clip the incoming value clip[] in place */
+/* Return the uncliped value in unclipped[] */
+/* Return the full value in the clip direction in full[] */
+static int clipYCrCb(double full[3], double unclipped[3], double clip[3]) {
+ int os = 0;
+
+ unclipped[0] = clip[0];
+ if (clip[0] < (16.0/255.0)) {
+ clip[0] = (16.0/255.0);
+ full[0] = 0.0;
+ os |= 1;
+ } else if (clip[0] > (235.0/255.0)) {
+ clip[0] = (235.0/255.0);
+ full[0] = 1.0;
+ os |= 1;
+ }
+
+ unclipped[1] = clip[1];
+ if (clip[1] < (16.0/255.0)) {
+ clip[1] = (16.0/255.0);
+ full[1] = 0.0;
+ os |= 2;
+ } else if (clip[1] > (240.0/255.0)) {
+ clip[1] = (240.0/255.0);
+ full[1] = 1.0;
+ os |= 2;
+ }
+
+ unclipped[2] = clip[2];
+ if (clip[2] < (16.0/255.0)) {
+ clip[2] = (16.0/255.0);
+ full[2] = 0.0;
+ os |= 4;
+ } else if (clip[2] > (240.0/255.0)) {
+ clip[2] = (240.0/255.0);
+ full[2] = 1.0;
+ os |= 4;
+ }
+
+ return os;
+}
+
+/* Clip a value to the xvYCC range range 16..235, 0..255 */
+/* (We should clip CbCr to 1..254 range, but unless we are using */
+/* a 256 res cLUT, this would mess up the mapping at the edges.) */
+/* Return a bit mask of the channels that have clipped */
+/* Clip the incoming value clip[] in place */
+/* Return the uncliped value in unclipped[] */
+/* Return the full value in the clip direction in full[] */
+static int clip_xvYCC(double full[3], double unclipped[3], double clip[3]) {
+ int os = 0;
+
+ unclipped[0] = clip[0];
+ if (clip[0] < (16.0/255.0)) {
+ clip[0] = (16.0/255.0);
+ full[0] = 0.0;
+ os |= 1;
+ } else if (clip[0] > (235.0/255.0)) {
+ clip[0] = (235.0/255.0);
+ full[0] = 1.0;
+ os |= 1;
+ }
+
+ unclipped[1] = clip[1];
+ unclipped[2] = clip[2];
+
+ return os;
+}
+
+/* Apply the Rec709 power curve to extended values using symetry */
+static void xvYCC_fwd_curve(double *out, double *in) {
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ if (fabs(in[i]) <= 0.081)
+ out[i] = in[i]/4.5;
+ else {
+ if (in[i] < 0.0)
+ out[i] = -pow((0.099 + -in[i])/1.099, 1.0/0.45);
+ else
+ out[i] = pow((0.099 + in[i])/1.099, 1.0/0.45);
+ }
+ }
+}
+
+/* Apparently xvYCC601 uses the Rec709 primaries */
+
+/* Convert RGB to D50 Rec709 RGB */
+static void xvYCC_fwd_matrix(double *out, double *in) {
+ double mat[3][3] = {
+ { 0.436029, 0.385099, 0.143072 },
+ { 0.222438, 0.716942, 0.060621 },
+ { 0.013897, 0.097076, 0.713926 }
+ };
+
+ icmMulBy3x3(out, mat, in);
+}
+
+/* ======================================================= */
/* Functions called back in setting up the transform table */
#ifdef DEBUGC
@@ -346,6 +545,10 @@ static int tt = 0;
void devi_devip(void *cntx, double *out, double *in) {
int rv = 0;
clink *p = (clink *)cntx;
+ int i, clip = 0;
+ double uc[3]; /* Unclipped values (Video) */
+ double cin[3]; /* clipped input value (Video) */
+ double full[3]; /* Full value in clip direction (Video) */
#ifdef DEBUGC
if (in[0] == 1.0 && in[1] == 1.0 && in[2] == 1.0 && in[3])
@@ -356,30 +559,46 @@ void devi_devip(void *cntx, double *out, double *in) {
#ifdef DEBUGC
DEBUGC
#endif
- printf("DevIn->DevIn' got %f %f %f %f\n",in[0], in[1], in[2], in[3]); fflush(stdout);
+ printf("DevIn->DevIn' got %s\n",icmPdv(p->in.chan, in));
#endif
- if (p->in.nocurve) { /* Don't use profile per channel curves */
- int i;
- for (i = 0; i < p->in.chan; i++)
- out[i] = in[i];
- } else { /* Use input profile per channel curves */
+ for (i = 0; i < p->in.chan; i++)
+ out[i] = in[i];
+
+ if (!p->in.nocurve) { /* Using profile per channel curves */
+
+ /* Video encoding decode */
+ if (p->in.tvenc == 1) { /* Video 16-235 range */
+ clip = clipVidRGB(full, uc, out);
+ icmCpy3(cin, out);
+ icmVidRGB_2_RGB(out, out);
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("After TVdecode:\n",icmPdv(p->in.chan, out));
+#endif
+
+ } else if (p->in.tvenc >= 2) { /* YCbCr */
+ error("Can't use input curves with YCbCr input encoding");
+ }
+
switch(p->in.alg) {
case icmMonoFwdType: {
icxLuMono *lu = (icxLuMono *)p->in.luo; /* Safe to coerce */
- rv |= lu->fwd_curve(lu, out, in);
+ rv |= lu->fwd_curve(lu, out, out);
break;
}
case icmMatrixFwdType: {
icxLuMatrix *lu = (icxLuMatrix *)p->in.luo; /* Safe to coerce */
- rv |= lu->fwd_curve(lu, out, in);
+ rv |= lu->fwd_curve(lu, out, out);
break;
}
case icmLutType: {
icxLuLut *lu = (icxLuLut *)p->in.luo; /* Safe to coerce */
/* Since not PCS, in_abs and matrix cannot be valid, */
/* so input curve on own is ok to use. */
- rv |= lu->input(lu, out, in);
+ rv |= lu->input(lu, out, out);
break;
}
default:
@@ -387,18 +606,41 @@ void devi_devip(void *cntx, double *out, double *in) {
}
if (rv >= 2)
error("icc lookup failed: %d, %s",p->in.c->errc,p->in.c->err);
+
+ /* Create linear interpolation from clip to full range */
+ if (clip && p->in.tvenc) {
+ for (i = 0; i < 3; i++) {
+ if (clip & (1 << i)) {
+ out[i] = out[i] + (uc[i] - cin[i])/(full[i] - cin[i]) * (full[i] - out[i]);
+ }
+ }
+ }
}
if (p->in.lcurve) { /* Apply Y to L* */
-//printf("~1 y2l_curve got %f %f %f, isXYZ %d\n",in[0],in[1],in[2],p->in.lcurve == 2);
y2l_curve(out, out, p->in.lcurve == 2);
}
+ /* eeColor cLUT is fake 65^3 - only 64^3 is usable. This affects */
+ /* full range and xvYCC RGB, so map inputs to cLUT to only use 64^3 */
+ if (p->tdlut == 1) {
+ if (p->in.tvenc == 0) { /* Full range */
+ for (i = 0; i < p->in.chan; i++)
+ out[i] = out[i] * (p->clutres-2.0)/(p->clutres-1.0);
+
+ /* This isn't actually usable, because the eeColor does its own YCbCr conversion */
+ } else if (p->in.tvenc == 7 || p->in.tvenc == 8) { /* xvYCC */
+ out[0] = out[0];
+ out[1] = (out[1] * (p->clutres-3.0) + 1.0)/(p->clutres-1.0); /* Keep symetrical */
+ out[2] = (out[2] * (p->clutres-3.0) + 1.0)/(p->clutres-1.0);
+ }
+ }
+
#ifdef DEBUG
#ifdef DEBUGC
DEBUGC
#endif
- printf("DevIn->DevIn' ret %f %f %f %f\n",out[0], out[1], out[2], in[3]); fflush(stdout);
+ printf("DevIn->DevIn' ret %s\n",icmPdv(p->in.chan, out));
#endif
}
@@ -406,6 +648,7 @@ void devi_devip(void *cntx, double *out, double *in) {
/* - - - - - - - - - - - - */
/* clut, DevIn' -> DevOut' */
void devip_devop(void *cntx, double *out, double *in) {
+ double oin[MAX_CHAN]; /* original input values */
double win[MAX_CHAN]; /* working input values */
double pcsv[MAX_CHAN]; /* PCS intermediate value, pre-gamut map */
double pcsvm[MAX_CHAN]; /* PCS intermediate value, post-gamut map */
@@ -416,14 +659,89 @@ void devip_devop(void *cntx, double *out, double *in) {
int cmytrig = 0; /* CMY output hack triggered */
int i, rv = 0;
clink *p = (clink *)cntx;
+ int clip = 0; /* clip mask (Video) */
+ double cin[3]; /* clipped input value (Video) */
+ double uc[3]; /* Unclipped values (Video) */
+ double full[3]; /* Full value in clip direction (Video) */
#ifdef DEBUG
#ifdef DEBUGC
DEBUGC
#endif
- printf("DevIn'->DevOut' got %f %f %f %f\n",in[0], in[1], in[2], in[3]); fflush(stdout);
+ printf("DevIn'->DevOut' got %s\n",icmPdv(p->in.chan, in));
#endif
+ /* Make a copy so we can modify it and are not affected when we write */
+ /* to out when out == in */
+ for (i = 0; i < p->in.chan; i++)
+ win[i] = oin[i] = in[i];
+
+ /* eeColor cLUT is fake 65^3 - only 64^3 is usable. This affects */
+ /* full range and xvYCC RGB, so un-map inputs to cLUT to only use 64^3 */
+ if (p->tdlut == 1) {
+ if (p->in.tvenc == 0) {
+ for (i = 0; i < p->in.chan; i++)
+ win[i] = win[i] * (p->clutres-1.0)/(p->clutres-2.0);
+
+ /* This isn't actually usable, because the eeColor does its own YCbCr conversion */
+ } else if (p->in.tvenc == 7 || p->in.tvenc == 8) { /* xvYCC */
+ win[0] = win[0];
+ win[1] = (win[1] * (p->clutres-1.0) - 1.0)/(p->clutres-3.0);
+ win[2] = (win[2] * (p->clutres-1.0) - 1.0)/(p->clutres-3.0);
+ }
+ }
+
+ if (p->in.nocurve) { /* Not using profile per channel curves */
+ /* Video encoding decode */
+ if (p->in.tvenc == 1) { /* Video 16-235 range */
+ clip = clipVidRGB(full, uc, win);
+ icmCpy3(cin, win);
+ icmVidRGB_2_RGB(win, win);
+ } else if (p->in.tvenc == 2) { /* Rec601 YCbCr */
+ clip = clipYCrCb(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec601_YPbPr_2_RGBd(win, win);
+ } else if (p->in.tvenc == 3) { /* Rec709 1150/60/2:1 YCbCr */
+ clip = clipYCrCb(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec709_YPbPr_2_RGBd(win, win);
+ } else if (p->in.tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ clip = clipYCrCb(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec709_50_YPbPr_2_RGBd(win, win);
+ } else if (p->in.tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr encoding */
+ clip = clipYCrCb(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec2020_NCL_YPbPr_2_RGBd(win, win);
+ } else if (p->in.tvenc == 6) { /* Rec2020 Constant Luminance YCbCr encoding */
+ clip = clipYCrCb(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec2020_CL_YPbPr_2_RGBd(win, win);
+ } else if (p->in.tvenc == 7) { /* SD xvYCC with Rec601 YCbCr encoding */
+ clip = clip_xvYCC(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec601_YPbPr_2_RGBd(win, win);
+ } else if (p->in.tvenc == 8) { /* HD xvYCC with Rec709 YCbCr encoding */
+ clip = clip_xvYCC(full, uc, win);
+ icmCpy3(cin, win);
+ icmRecXXX_YCbCr_2_YPbPr(win, win);
+ icmRec709_YPbPr_2_RGBd(win, win);
+ }
+
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("After TVdecode: %s\n",icmPdv(p->in.chan, win));
+#endif
+ }
+
#ifdef ENKHACK
/* Handle neutral recognition/output K only hack */
/* (see discussion at top of file for generalization of this idea) */
@@ -436,30 +754,30 @@ void devip_devop(void *cntx, double *out, double *in) {
/* input space device values here. It also made sure that there are at */
/* least 3 input channels. */
- if (fabs(in[0] - in[1]) < thr
- && fabs(in[1] - in[2]) < thr
- && fabs(in[2] - in[0]) < thr)
+ if (fabs(win[0] - win[1]) < thr
+ && fabs(win[1] - win[2]) < thr
+ && fabs(win[2] - win[0]) < thr)
ntrig = 1; /* K only output triggered flag */
} else if (p->nhack == 2) {
double maxcmy; /* Comute a degree of source "K onlyness" */
double maxcmyk;
- maxcmy = in[0]; /* Compute minimum of CMY */
- if (in[1] > maxcmy)
- maxcmy = in[1];
- if (in[2] > maxcmy)
- maxcmy = in[2];
+ maxcmy = win[0]; /* Compute minimum of CMY */
+ if (win[1] > maxcmy)
+ maxcmy = win[1];
+ if (win[2] > maxcmy)
+ maxcmy = win[2];
maxcmyk = maxcmy; /* Compute minimum of all inks */
- if (in[3] > maxcmyk)
- maxcmyk = in[3];
+ if (win[3] > maxcmyk)
+ maxcmyk = win[3];
-//printf("~1 maxcmy = %f, maxcmyk = %f, in[3] = %f\n",maxcmy,maxcmyk,in[3]);
- if (in[3] <= 0.0 || maxcmy > in[3]) {
+//printf("~1 maxcmy = %f, maxcmyk = %f, win[3] = %f\n",maxcmy,maxcmyk,win[3]);
+ if (win[3] <= 0.0 || maxcmy > win[3]) {
konlyness = 0.0;
} else {
- konlyness = (in[3] - maxcmy)/in[3];
+ konlyness = (win[3] - maxcmy)/win[3];
}
/* As we approach no colorant, blend towards no Konlyness */
@@ -467,9 +785,9 @@ void devip_devop(void *cntx, double *out, double *in) {
konlyness *= maxcmyk/0.2;
/* We want to see if the input colors are exactly K only. */
- if (in[0] < thr
- && in[1] < thr
- && in[2] < thr)
+ if (win[0] < thr
+ && win[1] < thr
+ && win[2] < thr)
ntrig = 1; /* K only output triggered flag */
#ifdef DEBUG
#ifdef DEBUGC
@@ -485,46 +803,36 @@ void devip_devop(void *cntx, double *out, double *in) {
double thr = (0.5)/(p->clutres-1.0); /* Match threshold */
if (p->cmyhack & 1) {
- if (in[0] > (1.0 - thr)
- && in[1] < thr
- && in[2] < thr
- && (p->in.chan < 4 || in[3] < thr))
+ if (win[0] > (1.0 - thr)
+ && win[1] < thr
+ && win[2] < thr
+ && (p->in.chan < 4 || win[3] < thr))
cmytrig |= 1;
}
if (p->cmyhack & 2) {
- if (in[0] < thr
- && in[1] > (1.0 - thr)
- && in[2] < thr
- && (p->in.chan < 4 || in[3] < thr))
+ if (win[0] < thr
+ && win[1] > (1.0 - thr)
+ && win[2] < thr
+ && (p->in.chan < 4 || win[3] < thr))
cmytrig |= 2;
}
if (p->cmyhack & 4) {
- if (in[0] < thr
- && in[1] < thr
- && in[2] > (1.0 - thr)
- && (p->in.chan < 4 || in[3] < thr))
+ if (win[0] < thr
+ && win[1] < thr
+ && win[2] > (1.0 - thr)
+ && (p->in.chan < 4 || win[3] < thr))
cmytrig |= 4;
}
}
#endif /* ENKHACK */
if (p->in.lcurve) { /* Apply L* to Y */
- l2y_curve(win, in, p->in.lcurve == 2);
-#ifdef DEBUG
-#ifdef DEBUGC
- DEBUGC
-#endif
- printf("win[] set to L* value %f %f %f %f\n",win[0], win[1], win[2], win[3]); fflush(stdout);
-#endif
-
- } else {
- for (i = 0; i < p->in.chan; i++)
- win[i] = in[i];
+ l2y_curve(win, win, p->in.lcurve == 2);
#ifdef DEBUG
#ifdef DEBUGC
- DEBUGC
+ DEBUGC
#endif
- printf("win[] set to in[] value %f %f %f %f\n",win[0], win[1], win[2], win[3]); fflush(stdout);
+ printf("win[] set to L* value %s\n",icmPdv(p->in.chan, win));
#endif
}
@@ -544,13 +852,38 @@ void devip_devop(void *cntx, double *out, double *in) {
}
case icmMatrixFwdType: {
icxLuMatrix *lu = (icxLuMatrix *)p->in.luo; /* Safe to coerce */
+ icmLuMatrix *plu = (icmLuMatrix *)lu->plu; /* Safe to coerce */
if (p->in.nocurve) { /* No explicit curve, so do implicit here */
- rv |= lu->fwd_curve(lu, pcsv, win);
- rv |= lu->fwd_matrix(lu, pcsv, pcsv);
+
+ if (p->in.tvenc == 7 || p->in.tvenc == 8) { /* xvYCC */
+ xvYCC_fwd_curve(pcsv, win); /* Allow for overrange values */
+ xvYCC_fwd_matrix(pcsv, pcsv); /* Rec709 primaries */
+ } else {
+ rv |= lu->fwd_curve(lu, pcsv, win);
+ rv |= lu->fwd_matrix(lu, pcsv, pcsv);
+ }
} else {
- rv |= lu->fwd_matrix(lu, pcsv, win);
+ if (p->in.tvenc == 7 || p->in.tvenc == 8) /* xvYCC */
+ xvYCC_fwd_matrix(pcsv, pcsv); /* Rec709 primaries */
+ else
+ rv |= lu->fwd_matrix(lu, pcsv, win);
}
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("After matrix PCS' XYZ %s Lab %s\n",icmPdv(p->in.chan, pcsv), icmPLab(pcsv));
+#endif
+ if (p->in.bt1886) {
+ bt1886_apply(&p->in.bt, plu, pcsv, pcsv);
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("After bt1886 PCS' XYZ %s Lab %s\n",icmPdv(p->in.chan, pcsv), icmPLab(pcsv));
+#endif
+ }
rv |= lu->fwd_abs(lu, pcsv, pcsv);
break;
}
@@ -625,7 +958,7 @@ void devip_devop(void *cntx, double *out, double *in) {
#ifdef DEBUGC
DEBUGC
#endif
- printf("PCS before map %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); fflush(stdout);
+ printf("PCS before map %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]);
#endif
if (p->wphack) {
@@ -693,7 +1026,7 @@ void devip_devop(void *cntx, double *out, double *in) {
#ifdef DEBUGC
DEBUGC
#endif
- printf("PCS after Y scale %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]); fflush(stdout);
+ printf("PCS after Y scale %f %f %f\n",pcsv[0], pcsv[1], pcsv[2]);
#endif
}
@@ -737,7 +1070,7 @@ void devip_devop(void *cntx, double *out, double *in) {
#ifdef DEBUGC
DEBUGC
#endif
- printf("PCS after map %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]); fflush(stdout);
+ printf("PCS after map %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]);
#endif
} else {
pcsvm[0] = pcsv[0];
@@ -766,7 +1099,7 @@ void devip_devop(void *cntx, double *out, double *in) {
#ifdef DEBUGC
DEBUGC
#endif
- printf("PCS after abstract %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]); fflush(stdout);
+ printf("PCS after abstract %f %f %f\n",pcsvm[0], pcsvm[1], pcsvm[2]);
#endif
}
@@ -931,14 +1264,99 @@ void devip_devop(void *cntx, double *out, double *in) {
error("icc lookup failed: %d, %s",p->in.c->errc,p->in.c->err);
}
- if (p->out.lcurve) /* Apply Y to L* */
+ if (p->cal != NULL && p->addcal == 1 && p->out.nocurve) {
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("DevOut' before cal curve %s\n\n",icmPdv(p->out.chan, out));
+#endif
+ p->cal->interp(p->cal, out, out);
+ }
+
+ if (p->out.lcurve) { /* Apply Y to L* */
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("DevOut' before y2l_curve %s\n\n",icmPdv(p->out.chan, out));
+#endif
y2l_curve(out, out, p->out.lcurve == 2);
+ }
+ /* Video encoding encode */
+ if (p->out.tvenc) {
#ifdef DEBUG
#ifdef DEBUGC
DEBUGC
#endif
- printf("DevIn'->DevOut' ret %f %f %f %f\n\n",out[0], out[1], out[2], out[3]); fflush(stdout);
+ printf("DevOut' before TVenc %s\n\n",icmPdv(p->out.chan, out));
+#endif
+ for (i = 0; i < p->out.chan; i++) {
+ if (out[i] < 0.0)
+ out[i] = 0.0;
+ else if (out[i] > 1.0)
+ out[i] = 1.0;
+ }
+ if (p->out.tvenc == 1) { /* Video 16-235 range */
+ icmRGB_2_VidRGB(out, out);
+ } else if (p->out.tvenc == 2) { /* Rec601 YCbCr */
+ icmRec601_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ } else if (p->out.tvenc == 3) { /* Rec709 1150/60/2:1 YCbCr */
+ icmRec709_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ } else if (p->out.tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ icmRec709_50_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ } else if (p->out.tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr encoding */
+ icmRec2020_NCL_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ } else if (p->out.tvenc == 6) { /* Rec2020 Constant Luminance YCbCr encoding */
+ icmRec2020_CL_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ }
+
+#ifdef NEVER
+ else if (p->out.tvenc == 7) { /* SD xvYCC with Rec601 YCbCr encoding */
+ icmRec601_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ } else if (p->out.tvenc == 8) { /* HD xvYCC with Rec709 YCbCr encoding */
+ icmRec709_RGBd_2_YPbPr(out, out);
+ icmRecXXX_YPbPr_2_YCbCr(out, out);
+ }
+#endif /* NEVER */
+ }
+
+ /* Create linear interpolation from clip to full range */
+ if (clip && p->out.tvenc) {
+ for (i = 0; i < 3; i++) {
+ if (clip & (1 << i)) {
+#ifdef LINTERP_OR
+ /* Linear interpolate overrange to full */
+//printf("~1 clip[%d] = out %f + (uc %f - cin %f)/(full %f - cin %f) * (full %f - out %f) = ",
+//i, out[i], uc[i], cin[i], full[i], cin[i], full[i], out[i]);
+ out[i] = out[i] + (uc[i] - cin[i])/(full[i] - cin[i]) * (full[i] - out[i]);
+//printf("%f\n",out[i]);
+#else
+ double ifull = 1.0 - full[i]; /* Opposite limit to full */
+
+ /* Do simple extrapolation (Not perfect though) */
+ out[i] = ifull + (out[i] - ifull) * (uc[i] - ifull)/(cin[i] - ifull);
+
+ if (out[i] < 0.0 || out[i] > 1.0 /* clip */
+ || fabs(uc[i] - full[i]) < 1e-6) /* or input is at sync level */
+ out[i] = full[i];
+#endif
+ }
+ }
+ }
+
+#ifdef DEBUG
+#ifdef DEBUGC
+ DEBUGC
+#endif
+ printf("DevIn'->DevOut' ret %s\n\n",icmPdv(p->out.chan, out));
#endif
@@ -958,23 +1376,35 @@ void devip_devop(void *cntx, double *out, double *in) {
void devop_devo(void *cntx, double *out, double *in) {
int rv = 0;
clink *p = (clink *)cntx;
- int i;
+ int i, clip = 0;
+ double uc[3]; /* Unclipped values (Video) */
+ double cin[3]; /* clipped input value (Video) */
+ double full[3]; /* Full value in clip direction (Video) */
#ifdef DEBUG
#ifdef DEBUGC
DEBUGC
#endif
- printf("DevOut'->DevOut got %f %f %f %f\n",in[0], in[1], in[2], in[4]); fflush(stdout);
+ printf("DevOut'->DevOut got %s\n",icmPdv(p->out.chan, in));
#endif
for (i = 0; i < p->out.chan; i++)
out[i] = in[i];
- if (p->out.lcurve) /* Apply L* to Y */
+ if (p->out.lcurve) /* Apply L* to Y */
l2y_curve(out, out, p->out.lcurve == 2);
if (p->out.nocurve == 0) { /* Using per channel curves */
+ /* Video encoding decode */
+ if (p->out.tvenc == 1) { /* Video 16-235 range */
+ clip = clipVidRGB(full, uc, out);
+ icmCpy3(cin, out);
+ icmVidRGB_2_RGB(out, out);
+ } else if (p->out.tvenc >= 2) { /* YCbCr */
+ error("Can't use output curves with YCbCr output encoding");
+ }
+
switch(p->out.alg) {
case icmMonoBwdType: {
icxLuMono *lu = (icxLuMono *)p->out.luo; /* Safe to coerce */
@@ -1004,16 +1434,35 @@ void devop_devo(void *cntx, double *out, double *in) {
}
if (rv >= 2)
error("icc lookup failed: %d, %s",p->in.c->errc,p->in.c->err);
+
+ if (p->cal != NULL && p->addcal == 1) {
+ p->cal->interp(p->cal, out, out);
+ }
+
+ /* Video encoding encode */
+ if (p->out.tvenc == 1) { /* Video 16-235 range */
+ icmRGB_2_VidRGB(out, out);
+ }
+
+ /* Create linear interpolation from clip to full range */
+ if (clip && p->out.tvenc) {
+ for (i = 0; i < 3; i++) {
+ if (clip & (1 << i)) {
+ out[i] = out[i] + (uc[i] - cin[i])/(full[i] - cin[i]) * (full[i] - out[i]);
+ }
+ }
+ }
}
#ifdef DEBUG
#ifdef DEBUGC
DEBUGC
#endif
- printf("DevOut'->DevOut ret %f %f %f %f\n",out[0], out[1], out[2], out[3]); fflush(stdout);
+ printf("DevOut'->DevOut ret %s\n",icmPdv(p->out.chan, out));
#endif
#ifdef DEBUGC
tt = 0;
#endif
+//printf("DevOut'->DevOut ret %s\n",icmPdv(p->out.chan, out));
}
/* ------------------------------------------- */
@@ -1114,19 +1563,29 @@ static double xyzoptfunc(void *cntx, double *v) {
/* ------------------------------------------- */
+int write_eeColor1DinputLuts(clink *li, char *tdlut_name);
+int write_eeColor3DLut(icc *icc, char *fname);
+int write_eeColor1DoutputLuts(clink *li, char *tdlut_name);
+
+int write_MadVR_3DLut(clink *li, icc *icc, char *fname);
+
int
main(int argc, char *argv[]) {
int fa, nfa, mfa; /* argument we're looking at */
char in_name[MAXNAMEL+1];
char sgam_name[MAXNAMEL+1] = "\000"; /* Source gamut name */
char abs_name[MAXNAMEL+1] = "\000"; /* Abstract profile name */
+ char cal_name[MAXNAMEL+1] = "\000"; /* Calibration filename */
char out_name[MAXNAMEL+1];
char link_name[MAXNAMEL+1];
+ char tdlut_name[MAXNAMEL+1];
int verify = 0; /* Do verify pass */
int outinkset = 0; /* The user specfied an output inking */
int intentset = 0; /* The user specified an intent */
int vcset = 0; /* Viewing conditions were set by user */
int modeset = 0; /* The gamut mapping mode was set by the user */
+ int addcal = 0; /* 1 = Incorporate cal. curves in 3dLUT and set linear cal1 */
+ /* 2 = Set 3dLut cal1 to calibration curves */
int rv = 0;
icxViewCond ivc, ovc; /* Viewing Condition Overrides for in and out profiles */
int ivc_e = -1, ovc_e = -1; /* Enumerated viewing condition */
@@ -1147,7 +1606,7 @@ main(int argc, char *argv[]) {
li.count = 0;
li.last = -1;
li.mode = 0; /* Default simple link mode */
- li.quality = 1; /* Medium quality */
+ li.quality = -1; /* Not set */
li.clutres = 0; /* No resolution override */
li.nhack = 0;
li.cmyhack = 0; /* Mask for 100% purity through mapping of CMY */
@@ -1166,6 +1625,9 @@ main(int argc, char *argv[]) {
li.in.locus = 0; /* Default K value target */
li.in.nocurve = 0; /* Preserve device linearisation curve */
li.in.lcurve = 0; /* Don't apply a Y to L* curve after device curve */
+ li.in.tvenc = -1;
+ li.in.egamma = 2.2; /* Default effective gamma */
+ li.in.tgamma = 2.4; /* Default technical gamma */
li.out.intent = icmDefaultIntent; /* Default */
li.out.ink.tlimit = -1.0; /* Default no total limit */
li.out.ink.klimit = -1.0; /* Default no black limit */
@@ -1178,6 +1640,7 @@ main(int argc, char *argv[]) {
li.out.locus = 0; /* Default K value target */
li.out.nocurve = 0; /* Preserve device linearisation curve */
li.out.lcurve = 0; /* Don't apply an L* to Y curve before device curve */
+ li.out.tvenc = -1;
li.out.b2aluo = NULL; /* B2A lookup for inking == 7 */
xicc_enum_gmapintent(&li.gmi, icxDefaultGMIntent, NULL); /* Set default overall intent */
@@ -1189,7 +1652,8 @@ main(int argc, char *argv[]) {
ivc.Yb = -1.0;
ivc.Lv = -1.0;
ivc.Yf = -1.0;
- ivc.Fxyz[0] = -1.0; ivc.Fxyz[1] = -1.0; ivc.Fxyz[2] = -1.0;
+ ivc.Yg = -1.0;
+ ivc.Gxyz[0] = -1.0; ivc.Gxyz[1] = -1.0; ivc.Gxyz[2] = -1.0;
ovc.Ev = -1;
ovc.Wxyz[0] = -1.0; ovc.Wxyz[1] = -1.0; ovc.Wxyz[2] = -1.0;
@@ -1197,7 +1661,8 @@ main(int argc, char *argv[]) {
ovc.Yb = -1.0;
ovc.Lv = -1.0;
ovc.Yf = -1.0;
- ovc.Fxyz[0] = -1.0; ovc.Fxyz[1] = -1.0; ovc.Fxyz[2] = -1.0;
+ ovc.Yg = -1.0;
+ ovc.Gxyz[0] = -1.0; ovc.Gxyz[1] = -1.0; ovc.Gxyz[2] = -1.0;
if (argc < 4)
usage("Too few arguments, got %d expect at least 3",argc-1);
@@ -1262,13 +1727,14 @@ main(int argc, char *argv[]) {
verify = 1;
/* Disable profile per channel curve use in device link output */
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
+ else if (argv[fa][1] == 'n') {
li.in.nocurve = 1;
li.out.nocurve = 1;
}
/* Hack to force input neutrals to K only output */
- else if (argv[fa][1] == 'f' || argv[fa][1] == 'F') {
+ else if (argv[fa][1] == 'f'
+ || argv[fa][1] == 'F') {
if (argv[fa][1] == 'f') {
if (na != NULL) { /* XXXK -> XXXK hack */
@@ -1299,7 +1765,7 @@ main(int argc, char *argv[]) {
}
/* Quality */
- else if (argv[fa][1] == 'q' || argv[fa][1] == 'Q') {
+ else if (argv[fa][1] == 'q') {
fa = nfa;
if (na == NULL) usage("Quality flag (-q) needs an argument");
switch (na[0]) {
@@ -1328,22 +1794,33 @@ main(int argc, char *argv[]) {
}
/* CLUT resolution override */
- else if (argv[fa][1] == 'r' || argv[fa][1] == 'R') {
+ else if (argv[fa][1] == 'r') {
int rr;
fa = nfa;
if (na == NULL) usage("Resolution flag (-r) needs an argument");
rr = atoi(na);
- if (rr < 1 || rr > 255) usage("Resolution flag (-r) argument out of range (%d)",rr);
+ if (rr < 1 || rr > 256) usage("Resolution flag (-r) argument out of range (%d)",rr);
li.clutres = rr;
}
/* Abstract profile */
else if (argv[fa][1] == 'p') {
- if (na == NULL) usage("Expected abstract profile filename after -a");
+ if (na == NULL) usage("Expected abstract profile filename after -p");
fa = nfa;
strncpy(abs_name,na,MAXNAMEL); abs_name[MAXNAMEL] = '\000';
}
+ /* Calibration curves */
+ else if (argv[fa][1] == 'a'
+ || argv[fa][1] == 'H') {
+ if (na == NULL) usage("Expected calibration filename after -%c",argv[fa][1]);
+ strncpy(cal_name,na,MAXNAMEL); cal_name[MAXNAMEL] = '\000';
+ addcal = 1;
+ if (argv[fa][1] == 'H')
+ addcal = 2;
+ fa = nfa;
+ }
+
/* Simple mode */
else if (argv[fa][1] == 's') {
li.mode = 0;
@@ -1351,7 +1828,8 @@ main(int argc, char *argv[]) {
}
/* Maping mode */
- else if (argv[fa][1] == 'g' || argv[fa][1] == 'G') {
+ else if (argv[fa][1] == 'g'
+ || argv[fa][1] == 'G') {
li.mode = 1;
if (argv[fa][1] == 'G') {
li.mode = 2;
@@ -1365,7 +1843,7 @@ main(int argc, char *argv[]) {
}
/* White point hack */
- else if (argv[fa][1] == 'w' || argv[fa][1] == 'W') {
+ else if (argv[fa][1] == 'w') {
li.wphack = 1;
if (na != NULL) { // To a particular white point
fa = nfa;
@@ -1376,7 +1854,7 @@ main(int argc, char *argv[]) {
}
}
/* Input profile Intent or Mapping mode intent */
- else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
+ else if (argv[fa][1] == 'i') {
fa = nfa;
if (na == NULL) usage("Input intent flag (-i) needs an argument");
/* Record it for simple mode */
@@ -1407,7 +1885,7 @@ main(int argc, char *argv[]) {
}
/* Output profile Intent */
- else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
+ else if (argv[fa][1] == 'o') {
fa = nfa;
if (na == NULL) usage("Output intent flag (-o) needs an argument");
switch (na[0]) {
@@ -1433,18 +1911,17 @@ main(int argc, char *argv[]) {
}
/* Viewing conditions */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'C'
- || argv[fa][1] == 'd' || argv[fa][1] == 'D') {
+ else if (argv[fa][1] == 'c' || argv[fa][1] == 'd') {
icxViewCond *vc;
- if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
+ if (argv[fa][1] == 'c') {
vc = &ivc;
} else {
vc = &ovc;
}
fa = nfa;
- if (na == NULL) usage("Viewing conditions flag (-[cd]) needs an argument");
+ if (na == NULL) usage("Viewing conditions flag (-%c) needs an argument",argv[fa][1]);
#ifdef NEVER
if (na[0] >= '0' && na[0] <= '9') {
if (vc == &ivc)
@@ -1464,7 +1941,7 @@ main(int argc, char *argv[]) {
}
} else if (na[0] == 's' || na[0] == 'S') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]s) missing ':'");
+ usage("Viewing conditions (-%cs) missing ':'",argv[fa][1]);
if (na[2] == 'n' || na[2] == 'N') {
vc->Ev = vc_none; /* Automatic */
} else if (na[2] == 'a' || na[2] == 'A') {
@@ -1476,7 +1953,7 @@ main(int argc, char *argv[]) {
} else if (na[2] == 'c' || na[2] == 'C') {
vc->Ev = vc_cut_sheet;
} else
- usage("Viewing condition (-[cd]) unrecognised surround '%c'",na[2]);
+ usage("Viewing condition (-%c) unrecognised surround '%c'",argv[fa][1],na[2]);
} else if (na[0] == 'w' || na[0] == 'W') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
@@ -1484,36 +1961,41 @@ main(int argc, char *argv[]) {
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
vc->Wxyz[0] = x; vc->Wxyz[1] = y;
} else
- usage("Viewing condition (-[cd]w) unrecognised white point '%s'",na+1);
+ usage("Viewing condition (-%cw) unrecognised white point '%s'",argv[fa][1],na+1);
} else if (na[0] == 'a' || na[0] == 'A') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]a) missing ':'");
+ usage("Viewing conditions (-ca) missing ':'");
vc->La = atof(na+2);
} else if (na[0] == 'b' || na[0] == 'B') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]b) missing ':'");
+ usage("Viewing conditions (-cb) missing ':'");
vc->Yb = atof(na+2)/100.0;
} else if (na[0] == 'l' || na[0] == 'L') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]l) missing ':'");
+ usage("Viewing conditions (-l) missing ':'");
vc->Lv = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ if (na[1] != ':')
+ usage("Viewing conditions (-cf) missing ':'");
+ vc->Yf = atof(na+2);
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc->Fxyz[0] = x; vc->Fxyz[1] = y; vc->Fxyz[2] = z;
+ vc->Gxyz[0] = x; vc->Gxyz[1] = y; vc->Gxyz[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc->Fxyz[0] = x; vc->Fxyz[1] = y;
+ vc->Gxyz[0] = x; vc->Gxyz[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
vc->Yf = x/100.0;
} else
- usage("Viewing condition (-[cd]f) unrecognised flare '%s'",na+1);
+ usage("Viewing condition (-%cf) unrecognised flare '%s'",argv[fa][1],na+1);
} else
- usage("Viewing condition (-[cd]) unrecognised sub flag '%c'",na[0]);
+ usage("Viewing condition (-%c) unrecognised sub flag '%c'",argv[fa][1],na[0]);
vcset = 1; /* Viewing conditions were set by user */
}
/* Inking rule */
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
+ else if (argv[fa][1] == 'k'
+ || argv[fa][1] == 'K') {
fa = nfa;
if (na == NULL) usage("Inking rule flag (-k) needs an argument");
if (argv[fa][1] == 'k')
@@ -1648,6 +2130,88 @@ main(int argc, char *argv[]) {
li.mode = 2;
}
+ /* 3DLut output */
+ else if (argv[fa][1] == '3') {
+ fa = nfa;
+ if (na == NULL) usage("3dLut format flag (-3) needs an argument");
+ switch (na[0]) {
+ case 'e':
+ li.tdlut = 1;
+ break;
+ case 'm':
+ li.tdlut = 2;
+ break;
+ default:
+ usage("3DLut format (-3) argument '%s' not recognised",na);
+ }
+ }
+
+ /* Intent modifier */
+ else if (argv[fa][1] == 'I') {
+ double gamma = 0.0;
+ fa = nfa;
+ if (na == NULL) usage("Intent modifier flag (-I) needs an argument");
+
+ switch (na[0]) {
+ case 'b':
+ li.in.bt1886 = 1;
+ if (sscanf(na+1,":%lf",&gamma) == 1)
+ li.in.egamma = gamma;
+ break;
+ case 'B':
+ li.in.bt1886 = 2;
+ if (sscanf(na+1,":%lf",&gamma) == 1)
+ li.in.tgamma = gamma;
+ break;
+ default:
+ if (gamma == 0.0)
+ usage("Intent modifier (-I) argument '%s' not recognised",na);
+ }
+ }
+
+ /* Video RGB in and out encoding */
+ else if (argv[fa][1] == 'e'
+ || argv[fa][1] == 'E') {
+ int enc;
+ if (na == NULL) usage("Video encoding flag (-%c) needs an argument",argv[fa][1]);
+ switch (na[0]) {
+ case 'n': /* Normal */
+ enc = 0;
+ break;
+ case 't': /* TV 16 .. 235 */
+ enc = 1;
+ break;
+ case '6': /* Rec601 YCbCr */
+ enc = 2;
+ break;
+ case '7': /* Rec709 1150/60/2:1 YCbCr (HD) */
+ enc = 3;
+ break;
+ case '5': /* Rec709 1250/50/2:1 YCbCr (HD) */
+ enc = 4;
+ break;
+ case '2': /* Rec2020 Non-constant Luminance YCbCr (UHD) */
+ enc = 5;
+ break;
+ case 'C': /* Rec2020 Constant Luminance YCbCr (UHD) */
+ enc = 6;
+ break;
+ case 'x': /* xvYCC Rec601 YCbCr encoding (SD) */
+ enc = 7;
+ break;
+ case 'X': /* xvYCC Rec709 YCbCr encoding (HD) */
+ enc = 8;
+ break;
+ default:
+ usage("Video encoding (-E) argument not recognised");
+ }
+ if (argv[fa][1] == 'e')
+ li.in.tvenc = enc;
+ else
+ li.out.tvenc = enc;
+ fa = nfa;
+ }
+
/* Gammut mapping diagnostic plots */
else if (argv[fa][1] == 'P')
li.gamdiag = 1;
@@ -1667,9 +2231,52 @@ main(int argc, char *argv[]) {
if (fa >= argc || argv[fa][0] == '-') usage("Missing result profile");
strncpy(link_name,argv[fa++],MAXNAMEL); link_name[MAXNAMEL] = '\000';
+ if (li.tdlut) {
+ char *xl;
+ if (li.tdlut == 1) { /* eeColor */
+ strncpy(tdlut_name,link_name,MAXNAMEL-4); tdlut_name[MAXNAMEL-4] = '\000';
+ if ((xl = strrchr(tdlut_name, '.')) == NULL) /* Figure where extention is */
+ xl = tdlut_name + strlen(tdlut_name);
+ strcpy(xl,".txt");
+
+ if (li.clutres > 255) usage("Resolution flag (-r) argument out of range (%d)",li.clutres);
+
+ if (li.clutres == 0)
+ li.clutres = 65;
+
+ } else if (li.tdlut == 2) { /* MadVR */
+ strncpy(tdlut_name,link_name,MAXNAMEL-6); tdlut_name[MAXNAMEL-6] = '\000';
+ if ((xl = strrchr(tdlut_name, '.')) == NULL) /* Figure where extention is */
+ xl = tdlut_name + strlen(tdlut_name);
+ strcpy(xl,".3dlut");
+
+ if (li.clutres == 0)
+ li.clutres = 65; /* This is good for video encoding levels */
+ }
+ } else {
+ if (li.clutres > 255) usage("Resolution flag (-r) argument out of range (%d)",li.clutres);
+ }
+
+ if (li.in.tvenc < 0)
+ li.in.tvenc = 0;
+ if (li.out.tvenc < 0)
+ li.out.tvenc = 0;
+
+ /* Need to allow spec. of gamut/matrix for xvYCC & bt.1886 */
+ if (li.out.tvenc == 7 || li.out.tvenc == 8) { /* xvYCC */
+ usage("xvYCC output encoding is not supported");
+ }
+
if (xpi.profDesc == NULL)
xpi.profDesc = link_name; /* Default description */
+ if (li.quality < 0) { /* Not set by user */
+ if (li.tdlut)
+ li.quality = 2; /* Use high quality gamut mapping */
+ else
+ li.quality = 1; /* Default to medium quality */
+ }
+
if (li.verb)
printf("Got options\n");
@@ -1677,13 +2284,84 @@ main(int argc, char *argv[]) {
#ifndef ENKHACK /* Enable K hack code */
warning("!!!!!! linkl/collink.c ENKHACK not enabled !!!!!!");
#endif
+
+ /* - - - - - - - - - - - - - - - - - - - */
+ /* Set some implied flags for bt1886 */
+
+ if (li.in.bt1886) {
+ if (li.mode == 0) { /* Simple mode */
+ if (li.in.intent == icmDefaultIntent) {
+ warning("Setting BT.1886 input intent to Relative Colorimetric");
+ li.in.intent = icRelativeColorimetric;
+ } else if (li.in.intent != icRelativeColorimetric
+ && li.in.intent != icAbsoluteColorimetric) {
+ warning("BT.1886 in simple link mode is intended to work with a colorimetric in intent");
+ }
+
+ if (li.out.intent == icmDefaultIntent) {
+ warning("Setting BT.1886 output intent to Relative Colorimetric");
+ li.out.intent = icRelativeColorimetric;
+ } else if (li.out.intent != icRelativeColorimetric
+ && li.out.intent != icAbsoluteColorimetric) {
+ warning("BT.1886 in simple link mode is intended to work with a colorimetric in intent");
+ }
+ } else {
+ if (!intentset) {
+ warning("Setting BT.1886 intent to Relative Colorimetric");
+ if (xicc_enum_gmapintent(&li.gmi, icxNoGMIntent, "r") == -999)
+ error("Internal - intent 'r' isn't recognised");
+ }
+
+#ifdef NEVER
+ if (li.gmi.glumbcpf != 0.0 || li.gmi.glumbexf != 0.0) {
+ warning("Gamut mapping will do black point mapping, so BT.1886 black point mapping will be disabled");
+ li.in.bt1886 = 2; /* Disable black point adjustment */
+ }
+#endif
+ }
+ }
+
+ /* Set some implied flags for 3dLuts */
+ if (li.tdlut) {
+
+ /* eeColor format. Currently we assume no input or output curves, */
+ /* even though it's technically possible to use them */
+ if (li.tdlut == 1) {
+
+ if (li.in.nocurve == 0) {
+ warning("Disabling input curves for eeColor 3DLut creation");
+ li.in.nocurve = 1;
+ }
+ if (li.out.nocurve == 0) {
+ warning("Disabling output curves for eeColor 3DLut creation");
+ li.out.nocurve = 1;
+ }
+
+ if (li.in.tvenc != li.out.tvenc)
+ warning("eeColor usually needs same input & output encoding");
+ }
+
+ /* MadVR format. It doesn't support in and out per channel curves */
+ else if (li.tdlut == 2) {
+
+ if (li.in.nocurve == 0) {
+ warning("Disabling input curves for MadVR 3DLut creation");
+ li.in.nocurve = 1;
+ }
+ if (li.out.nocurve == 0) {
+ warning("Disabling output curves for MadVR 3DLut creation");
+ li.out.nocurve = 1;
+ }
+ }
+ }
+
/* - - - - - - - - - - - - - - - - - - - */
/* Sanity checking/defaulting of options */
/* Deal with options that need link mode -g */
if (li.mode < 1
&& (li.in.intent == icMaxEnumIntent /* User set a smart linking intent */
- || vcset /* Viewing conditions were set by user */
+ || vcset /* Viewing conditions were set by user */
|| li.wphack)) {
if (modeset) {
if (li.in.intent == icMaxEnumIntent)
@@ -1916,6 +2594,20 @@ main(int argc, char *argv[]) {
&& li.out.h->deviceClass != icSigColorSpaceClass) /* For sRGB etc. */
error("Output profile isn't a device profile");
+ /* Grab the calibration if requested */
+ if (addcal) {
+ if ((li.cal = new_xcal()) == NULL)
+ error("new_xcal failed");
+
+ if ((li.cal->read(li.cal, cal_name)) != 0)
+ error("%s",li.cal->err);
+
+ li.addcal = addcal;
+
+ /* (Don't use vcgt in output profile, because it may include tv encoding, */
+ /* and we don't currently have a way of detecting this */
+ }
+
/* Wrap with an expanded icc */
if ((li.out.x = new_xicc(li.out.c)) == NULL)
error ("Creation of output profile xicc failed");
@@ -1990,15 +2682,18 @@ main(int argc, char *argv[]) {
xicc *x;
icxViewCond *v, *vc;
int es;
+ int *set;
if (i == 0) {
v = &ivc; /* Override parameters */
vc = &li.in.vc; /* Target parameters */
+ set = &li.in.vc_set;
es = ivc_e;
x = li.in.x; /* xicc */
} else {
v = &ovc; /* Override parameters */
vc = &li.out.vc; /* Target parameters */
+ set = &li.out.vc_set;
es = ovc_e;
x = li.out.x; /* xicc */
}
@@ -2012,14 +2707,18 @@ main(int argc, char *argv[]) {
if (es != -1) {
if (xicc_enum_viewcond(x, vc, es, NULL, 0, NULL) == -999)
error ("%d, %s",x->errc, x->err);
+ *set = 1;
}
/* Then any individual paramaters */
- if (v->Ev >= 0)
+ if (v->Ev >= 0) {
vc->Ev = v->Ev;
+ *set = 1;
+ }
if (v->Wxyz[0] >= 0.0 && v->Wxyz[1] > 0.0 && v->Wxyz[2] >= 0.0) {
/* Normalise XYZ to current media white */
vc->Wxyz[0] = v->Wxyz[0]/v->Wxyz[1] * vc->Wxyz[1];
vc->Wxyz[2] = v->Wxyz[2]/v->Wxyz[1] * vc->Wxyz[1];
+ *set = 1;
}
if (v->Wxyz[0] >= 0.0 && v->Wxyz[1] >= 0.0 && v->Wxyz[2] < 0.0) {
/* Convert Yxy to XYZ */
@@ -2028,27 +2727,42 @@ main(int argc, char *argv[]) {
double z = 1.0 - x - y;
vc->Wxyz[0] = x/y * vc->Wxyz[1];
vc->Wxyz[2] = z/y * vc->Wxyz[1];
+ *set = 1;
}
- if (v->La >= 0.0)
+ if (v->La >= 0.0) {
vc->La = v->La;
- if (v->Yb >= 0.0)
+ *set = 1;
+ }
+ if (v->Yb >= 0.0) {
vc->Yb = v->Yb;
- if (v->Lv >= 0.0)
+ *set = 1;
+ }
+ if (v->Lv >= 0.0) {
vc->Lv = v->Lv;
- if (v->Yf >= 0.0)
+ *set = 1;
+ }
+ if (v->Yf >= 0.0) {
vc->Yf = v->Yf;
- if (v->Fxyz[0] >= 0.0 && v->Fxyz[1] > 0.0 && v->Fxyz[2] >= 0.0) {
+ *set = 1;
+ }
+ if (v->Yg >= 0.0) {
+ vc->Yg = v->Yg;
+ *set = 1;
+ }
+ if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] > 0.0 && v->Gxyz[2] >= 0.0) {
/* Normalise XYZ to current media white */
- vc->Fxyz[0] = v->Fxyz[0]/v->Fxyz[1] * vc->Fxyz[1];
- vc->Fxyz[2] = v->Fxyz[2]/v->Fxyz[1] * vc->Fxyz[1];
+ vc->Gxyz[0] = v->Gxyz[0]/v->Gxyz[1] * vc->Gxyz[1];
+ vc->Gxyz[2] = v->Gxyz[2]/v->Gxyz[1] * vc->Gxyz[1];
+ *set = 1;
}
- if (v->Fxyz[0] >= 0.0 && v->Fxyz[1] >= 0.0 && v->Fxyz[2] < 0.0) {
+ if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] >= 0.0 && v->Gxyz[2] < 0.0) {
/* Convert Yxy to XYZ */
- double x = v->Fxyz[0];
- double y = v->Fxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ double x = v->Gxyz[0];
+ double y = v->Gxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc->Fxyz[0] = x/y * vc->Fxyz[1];
- vc->Fxyz[2] = z/y * vc->Fxyz[1];
+ vc->Gxyz[0] = x/y * vc->Gxyz[1];
+ vc->Gxyz[2] = z/y * vc->Gxyz[1];
+ *set = 1;
}
}
@@ -2068,11 +2782,11 @@ main(int argc, char *argv[]) {
/* the intents and pcsor appropriately. */
if (li.mode > 0) {
- if ((li.gmi.usecas & 0xff) != 0) {
+ if ((li.gmi.usecas & 0xff) >= 0x2) {
li.pcsor = icxSigJabData; /* Use CAM as PCS */
isJab = 1;
- if ((li.gmi.usecas & 0xff) == 0x2) { /* Absolute Appearance space */
+ if ((li.gmi.usecas & 0xff) == 0x3) { /* Absolute Appearance space */
double mxw;
li.in.intent = li.out.intent = li.abs_intent = icxAbsAppearance;
@@ -2090,13 +2804,16 @@ main(int argc, char *argv[]) {
/* Set the output vc to be the same as the input */
li.out.vc = li.in.vc; /* Structure copy */
- } else {
+ } else { /* usecas & ff == 0x2 */
/* Not Abs Appearance space */
li.in.intent = li.out.intent = li.abs_intent = icxAppearance;
}
} else {
- /* Not Appearance space */
- li.in.intent = li.out.intent = li.abs_intent = icAbsoluteColorimetric;
+ /* Not Appearance space - use L*a*b* */
+ if ((li.gmi.usecas & 0xff) == 0)
+ li.in.intent = li.out.intent = li.abs_intent = icRelativeColorimetric;
+ else
+ li.in.intent = li.out.intent = li.abs_intent = icAbsoluteColorimetric;
}
}
@@ -2114,13 +2831,15 @@ main(int argc, char *argv[]) {
fl |= ICX_MERGE_CLUT;
#endif
-#ifdef NEVER
- printf("~1 input space flags = 0x%x\n",fl);
- printf("~1 input space intent = %s\n",icx2str(icmRenderingIntent,li.in.intent));
- printf("~1 input space pcs = %s\n",icx2str(icmColorSpaceSignature,li.pcsor));
- printf("~1 input space viewing conditions =\n"); xicc_dump_viewcond(&li.in.vc);
- printf("~1 input space inking =\n"); xicc_dump_inking(&li.in.ink);
-#endif
+ if (li.verb && li.mode > 0) {
+// printf("Input space flags = 0x%x\n",fl);
+// printf("Input space intent = %s\n",icx2str(icmRenderingIntent,li.in.intent));
+// printf("Input space pcs = %s\n",icx2str(icmColorSpaceSignature,li.pcsor));
+ if (li.in.vc_set || li.out.vc_set)
+ printf("Input space viewing conditions =\n"), xicc_dump_viewcond(&li.in.vc);
+// printf("Input space inking =\n"); xicc_dump_inking(&li.in.ink);
+ }
+
if ((li.in.luo = li.in.x->get_luobj(li.in.x, fl, icmFwd, li.in.intent,
li.pcsor, icmLuOrdNorm, &li.in.vc, &li.in.ink)) == NULL) {
error("get xlookup object failed: %d, %s",li.in.x->errc,li.in.x->err);
@@ -2151,6 +2870,7 @@ main(int argc, char *argv[]) {
&& (li.in.alg == icmMatrixFwdType || li.in.alg == icmMatrixBwdType
|| li.in.csp == icSigXYZData)) {
li.in.lcurve = 1; /* Use Y to L* and L* to Y for input */
+
if (li.in.csp == icSigXYZData) {
li.in.lcurve = 2; /* Use real Y to L* and L* to Y for input */
li.in.nocurve = 1; /* Don't trust the curve that comes with it */
@@ -2218,6 +2938,10 @@ main(int argc, char *argv[]) {
/* Get native PCS space */
li.out.luo->lutspaces(li.out.luo, &natpcs, NULL, NULL, NULL, NULL);
+ /* Get details of overall conversion */
+ li.out.luo->spaces(li.out.luo, NULL, NULL, &li.out.csp, &li.out.chan, &li.out.alg,
+ NULL, NULL, NULL);
+
} else { /* Using inverse A2B Lut for output conversion */
fl = flb;
@@ -2230,13 +2954,14 @@ main(int argc, char *argv[]) {
if (li.verb)
printf("Loading output inverse A2B table\n");
-#ifdef NEVER
- printf("~1 output space flags = 0x%x\n",fl);
- printf("~1 output space intent = %s\n",icx2str(icmRenderingIntent,li.out.intent));
- printf("~1 output space pcs = %s\n",icx2str(icmColorSpaceSignature,li.pcsor));
- printf("~1 output space viewing conditions =\n"); xicc_dump_viewcond(&li.out.vc);
- printf("~1 output space inking =\n"); xicc_dump_inking(&li.out.ink);
-#endif
+ if (li.verb) {
+// printf("Output space flags = 0x%x\n",fl);
+// printf("Output space intent = %s\n",icx2str(icmRenderingIntent,li.out.intent));
+// printf("Output space pcs = %s\n",icx2str(icmColorSpaceSignature,li.pcsor));
+ if (li.in.vc_set || li.out.vc_set)
+ printf("Output space viewing conditions =\n"), xicc_dump_viewcond(&li.out.vc);
+// printf("Output space inking =\n"); xicc_dump_inking(&li.out.ink);
+ }
if ((li.out.luo = li.out.x->get_luobj(li.out.x, fl, icmFwd,
li.out.intent, li.pcsor, icmLuOrdNorm, &li.out.vc,
@@ -2404,7 +3129,7 @@ main(int argc, char *argv[]) {
if (li.out.nocurve == 0 && natpcs == icSigXYZData
&& (li.out.alg == icmMatrixFwdType || li.out.alg == icmMatrixBwdType
|| li.out.csp == icSigXYZData)) {
- li.out.lcurve = 1; /* Use Y to L* and L* to Y for output */
+ li.out.lcurve = 1; /* Use Y to L* and L* to Y for output */
if (li.out.csp == icSigXYZData) {
li.out.lcurve = 2; /* Use real Y to L* and L* to Y for output */
li.out.nocurve = 1; /* Don't trust the curve that comes with it */
@@ -2415,6 +3140,138 @@ main(int argc, char *argv[]) {
}
/* - - - - - - - - - - - - - - - - - - - */
+ /* Sanity checking */
+
+ if (li.cal != NULL) {
+ if (li.cal->colspace != li.out.csp) {
+ error("Calibration space %s doesn't match output profile %s",
+ icm2str(icmColorSpaceSignature, li.cal->colspace),
+ icm2str(icmColorSpaceSignature, li.out.csp));
+ }
+ }
+
+ if (li.tdlut) {
+
+ /* eeColor format. */
+ if (li.tdlut == 1) {
+
+ if (li.in.csp != icSigRgbData)
+ error("Input profile must be RGB to output eeColor 3DLut");
+
+ if (li.out.csp != icSigRgbData)
+ error("Output profile must be RGB to output eeColor 3DLut");
+ }
+
+ /* MadVR format. */
+ else if (li.tdlut == 2) {
+
+ if (li.in.csp != icSigRgbData)
+ error("Input profile must be RGB to output MadVR 3DLut");
+
+ if (li.out.csp != icSigRgbData)
+ error("Output profile must be RGB to output MadVR 3DLut");
+ }
+
+ if (li.in.tvenc) {
+ if (li.in.csp != icSigRgbData)
+ error("Input profile must be RGB to use video encoding option");
+ }
+ if (li.out.tvenc) {
+ if (li.out.csp != icSigRgbData)
+ error("Output profile must be RGB to use video encoding option");
+ }
+ }
+
+ /* Do sanity check and setup for BT.1886 gamma mapping */
+ if (li.in.bt1886) {
+ bt1886_setnop(&li.in.bt);
+ }
+ if (li.in.bt1886 == 1 || li.in.bt1886 == 2) { /* If doing BT.1886 black point mapping */
+ icxLuBase *oluo; /* Output fwd lookup */
+ icxLuMatrix *lu; /* Input profile lookup */
+ icmLuMatrix *plu; /* Input profile lookup */
+ double bp[3], rgb[3];
+
+ /* Check input profile is an RGB matrix profile */
+ if (li.in.alg != icmMatrixFwdType
+ || li.in.csp != icSigRgbData)
+ error("BT.1886 mode only works with an RGB matrix input profile");
+
+ lu = (icxLuMatrix *)li.in.luo; /* Safe to coerce - we have checked it's matrix. */
+ plu = (icmLuMatrix *)lu->plu;
+
+ if ((oluo = li.out.x->get_luobj(li.out.x, ICX_CLIP_NEAREST, icmFwd, icRelativeColorimetric,
+ icSigXYZData, icmLuOrdNorm, &li.out.vc, &li.out.ink)) == NULL) {
+ error("get xlookup object failed: %d, %s",li.out.x->errc,li.out.x->err);
+ }
+ /* We're assuming that the input space has a perfect black point... */
+
+ /* Lookup the ouput black point in XYZ PCS.*/
+ bp[0] = bp[1] = bp[2] = 0.0;
+ oluo->lookup(oluo, bp, bp);
+
+ if (li.in.bt1886 == 1) { /* Using effective gamma */
+ li.in.tgamma = xicc_tech_gamma(li.in.egamma, bp[1]);
+ if (li.verb)
+ printf("Technical gamma %f used to achieve effective gamma %f\n",li.in.tgamma, li.in.egamma);
+ } else {
+ if (li.verb)
+ printf("Using technical gamma %f\n",li.in.tgamma);
+ }
+
+ bt1886_setup(&li.in.bt, bp, li.in.tgamma);
+
+ if (li.verb) {
+ printf("bt1886 target out black rel XYZ = %f %f %f, Lab %f %f %f\n",
+ bp[0],bp[1],bp[2], li.in.bt.outL, li.in.bt.tab[0], li.in.bt.tab[1]);
+ printf("bt1886 Y input offset = %f\n", li.in.bt.ingo);
+ printf("bt1886 Y output scale = %f\n", li.in.bt.outsc);
+ }
+
+ /* Check black point now produced by input profile with bt.1886 adjustment */
+ rgb[0] = rgb[1] = rgb[2] = 0.0;
+ lu->fwd_curve(lu, rgb, rgb);
+ lu->fwd_matrix(lu, rgb, rgb);
+ bt1886_apply(&li.in.bt, plu, rgb, rgb);
+ if (li.verb) printf("bt1886 check input black point rel. XYZ %f %f %f\n", rgb[0],rgb[1],rgb[2]);
+ /* Convert XYZ black point to gamut mapping space */
+ lu->fwd_abs(lu, li.in.bt_bk, bp);
+ if (li.verb) printf("bt1886 check input black point PCS %f %f %f\n", li.in.bt_bk[0],li.in.bt_bk[1],li.in.bt_bk[2]);
+
+ oluo->del(oluo);
+
+ if (li.verb) {
+ int no = 21;
+
+ /* Overral rendering curve from video in to output target */
+ printf("BT.1886 overall rendering\n");
+ for (i = 0; i < no; i++) {
+ double v = i/(no-1.0), vv;
+ double vi[3], vo[3], Lab[3];
+ double loglog = 0.0;
+
+ if (v <= 0.081)
+ vv = v/4.5;
+ else
+ vv = pow((0.099 + v)/1.099, 1.0/0.45);
+
+ vi[0] = vv * 0.9642; /* To D50 XYZ */
+ vi[1] = vv * 1.0000;
+ vi[2] = vv * 0.8249;
+
+ bt1886_apply(&li.in.bt, plu, vo, vi); /* BT.1886 mapping */
+
+ icmXYZ2Lab(&icmD50, Lab, vo);
+
+ if (v > 1e-9 && vo[1] > 1e-9 && fabs(v - 1.0) > 1e-9)
+ loglog = log(vo[1])/log(v);
+
+ printf(" In %5.1f%% -> XYZ in %f -> bt.1886 %f, log/log %.3f, Lab %f %f %f \n",v * 100.0,vi[1],vo[1], loglog, Lab[0], Lab[1], Lab[2]);
+ }
+ }
+ }
+
+ /* - - - - - - - - - - - - - - - - - - - */
/* Setup the gamut mapping */
// ~~~~ need to account for possible abstract profile after source !!!!
// ~~~~ also need to fix tiffgamut to allow for abstract profile !!!!
@@ -2466,6 +3323,14 @@ main(int argc, char *argv[]) {
if ((csgam = li.in.luo->get_gamut(li.in.luo, sgres)) == NULL)
error ("%d, %s",li.in.x->errc, li.in.x->err);
+ /* If BT.1886 has modified the effective input space black point, */
+ /* change the black point in the source gamut to match. (Note that */
+ /* this doesn't fix the source gamut surface itself, but should */
+ /* make sure that the gamut mapping black point mapping works properly.) */
+ if (li.in.bt1886 == 1) {
+ csgam->set_cs_bp_kp_ovrd(csgam, li.in.bt_bk, li.in.bt_bk);
+ }
+
/* Grab a given source image gamut. */
if (sgam_name[0] != '\000') { /* Optional source gamut - ie. from an images */
@@ -2579,8 +3444,16 @@ main(int argc, char *argv[]) {
/* Values that must be set before writing */
wh->deviceClass = icSigLinkClass; /* We are creating a link ! */
- wh->colorSpace = li.in.h->colorSpace; /* Input profile device space */
- wh->pcs = li.out.h->colorSpace; /* Output profile device space */
+ if (li.in.tvenc >= 2) {
+ wh->colorSpace = icSigYCbCrData; /* Use YCbCr encoding */
+ } else {
+ wh->colorSpace = li.in.h->colorSpace; /* Input profile device space */
+ }
+ if (li.out.tvenc >= 2) {
+ wh->pcs = icSigYCbCrData; /* Use YCbCr encoding */
+ } else {
+ wh->pcs = li.out.h->colorSpace; /* Output profile device space */
+ }
if (li.mode > 0) {
wh->renderingIntent = li.gmi.icci; /* Closest ICC intent */
} else {
@@ -2897,6 +3770,8 @@ main(int argc, char *argv[]) {
/* 16 bit input device -> output device lut: */
{
int inputEnt, outputEnt, clutPoints;
+ int *apxls_min = NULL, *apxls_max = NULL;
+ int tapxls_min[MAX_CHAN], tapxls_max[MAX_CHAN];
icmLut *wo;
/* Setup the cLUT resolutions */
@@ -2933,7 +3808,7 @@ main(int argc, char *argv[]) {
break;
case 3:
if (li.quality >= 3)
- clutPoints = 52;
+ clutPoints = 53;
else if (li.quality == 2)
clutPoints = 33;
else if (li.quality == 1)
@@ -2945,7 +3820,7 @@ main(int argc, char *argv[]) {
if (li.quality >= 3)
clutPoints = 33;
else if (li.quality == 2)
- clutPoints = 18;
+ clutPoints = 17;
else if (li.quality == 1)
clutPoints = 9;
else
@@ -2953,15 +3828,15 @@ main(int argc, char *argv[]) {
break;
case 5:
if (li.quality >= 3)
- clutPoints = 18;
+ clutPoints = 17;
else if (li.quality == 2)
- clutPoints = 16;
+ clutPoints = 15;
else
clutPoints = 9;
break;
case 6:
if (li.quality >= 3)
- clutPoints = 12;
+ clutPoints = 13;
else if (li.quality == 2)
clutPoints = 9;
else
@@ -2969,7 +3844,7 @@ main(int argc, char *argv[]) {
break;
case 7:
if (li.quality >= 3)
- clutPoints = 8;
+ clutPoints = 9;
else if (li.quality == 2)
clutPoints = 7;
else
@@ -3004,6 +3879,47 @@ main(int argc, char *argv[]) {
if (out_curve_res > outputEnt)
outputEnt = out_curve_res;
+ /* Sanity checking */
+ if (li.in.tvenc >= 2) { /* YCbCr encoded input */
+ if ((clutPoints & 1) == 0)
+ warning("Making grid resolution is even - this is not ideal for YCbCr input");
+ }
+ if (li.in.tvenc != 0 && clutPoints != 65 && clutPoints != 129 && clutPoints != 256)
+ warning("Video or YCbCr encoded inputs will work best with grid res. of 65 (got %d)",clutPoints);
+ if (li.tdlut == 1) { /* eeColor encoded input */
+ if (clutPoints != 65)
+ warning("eeColor 3DLut needs grid resolution of 65 (got %d)",clutPoints);
+ inputEnt = 1024;
+ outputEnt = 4096; /* Ideally 8192 */
+
+ } else if (li.tdlut == 2) {
+ if (clutPoints != 65 && clutPoints != 129 && clutPoints != 256)
+ warning("MadVR 3DLut will work best with grid resolution of 65 (got %d)",clutPoints);
+ inputEnt = 1024; /* Not used */
+ outputEnt = 1024; /* Not used */
+ }
+
+ /* Limits are grid indexes that should not be adjusted by SET_APXLS */
+ /* Grid index is not adjusted if it's within 10% of device value limits */
+ if (li.in.tvenc == 1) { /* Video encoded */
+ apxls_min = tapxls_min;
+ apxls_max = tapxls_max;
+ for (i = 0; i < li.in.chan; i++) {
+ apxls_min[i] = (int)(16.0/255.0 * (clutPoints-1.0) + 0.9);
+ apxls_max[i] = (int)(235.0/255.0 * (clutPoints-1.0) + 0.1);
+ }
+ } else if (li.in.tvenc >= 2) { /* YCbCr encoded */
+ apxls_min = tapxls_min;
+ apxls_max = tapxls_max;
+ for (i = 0; i < li.in.chan; i++) {
+ apxls_min[i] = (int)(16.0/255.0 * (clutPoints-1.0) + 0.9);
+ if (i == 0)
+ apxls_max[i] = (int)(235.0/255.0 * (clutPoints-1.0) + 0.1);
+ else
+ apxls_max[i] = (int)(240.0/255.0 * (clutPoints-1.0) + 0.1);
+ }
+ }
+
/* Link Lut = AToB0 */
if ((wo = (icmLut *)wr_icc->add_tag(
@@ -3018,6 +3934,11 @@ main(int argc, char *argv[]) {
wo->clutPoints = clutPoints;
wo->outputEnt = outputEnt;
+ if (clutPoints == 256) { /* MadVR special */
+ wr_icc->allowclutPoints256 = 1;
+ warning("Creating non-standard 256 res. cLUT ICC profile !!!!");
+ }
+
if (wo->allocate((icmBase *)wo) != 0) /* Allocate space */
error("allocate failed: %d, %s",wr_icc->errc,wr_icc->err);
@@ -3033,29 +3954,55 @@ main(int argc, char *argv[]) {
if (li.verb)
printf("Filling in Lut table\n");
#ifdef DEBUG_ONE
-#define DBGNO 1 /* Up to 10 */
+#define DBGNO 3 /* Up to 10 */
#ifndef NEVER
/* Test a single given rgb/cmyk -> cmyk value */
{
double in[10][MAX_CHAN];
double out[MAX_CHAN];
- in[0][0] = 1.0;
- in[0][1] = 1.0;
- in[0][2] = 1.0;
+// in[0][0] = 0.2;
+// in[0][1] = 0.2;
+// in[0][2] = 0.8;
+
+// in[0][0] = 0.5;
+// in[0][1] = 0.5;
+// in[0][2] = 0.5;
+
+// in[0][0] = ((235-16)/255.0 * 0.5) + 16/255.0;
+// in[0][1] = ((235-16)/255.0 * 0.5) + 16/255.0;
+// in[0][2] = ((235-16)/255.0 * 0.5) + 16/255.0;
+
+// in[0][3] = 0.0;
+
+// in[0][0] = 16.0/255.0;
+// in[0][1] = 16.0/255.0;
+// in[0][2] = 16.0/255.0;
+// in[0][3] = 0.0;
+
+ in[0][0] = 3.0/64.0;
+ in[0][1] = 3.0/64.0;
+ in[0][2] = 3.0/64.0;
in[0][3] = 0.0;
- in[1][0] = 1.0;
- in[1][1] = 1.0;
- in[1][2] = 1.0;
+ in[1][0] = 4.0/64.0;
+ in[1][1] = 4.0/64.0;
+ in[1][2] = 4.0/64.0;
in[1][3] = 0.0;
+ in[2][0] = 5.0/64.0;
+ in[2][1] = 5.0/64.0;
+ in[2][2] = 5.0/64.0;
+ in[2][3] = 0.0;
+
for (i = 0; i < DBGNO; i++) {
- printf("Input %f %f %f %f\n",in[i][0], in[i][1], in[i][2], in[i][3]);
+ printf("Input %f %f %f %*\n",in[i][0], in[i][1], in[i][2], in[i][3]);
devi_devip((void *)&li, out, in[i]);
+ printf("Input' %f %f %f %*\n",out[0], out[1], out[2], out[3]);
devip_devop((void *)&li, out, out);
+ printf("Out'' %f %f %f %*\n",out[0], out[1], out[2], out[3]);
devop_devo((void *)&li, out, out);
- printf("Output %f %f %f %f\n\n",out[0], out[1], out[2], out[3]);
+ printf("Out %f %f %f %*\n\n",out[0], out[1], out[2], out[3]);
}
}
#endif /* NEVER */
@@ -3069,8 +4016,13 @@ main(int argc, char *argv[]) {
;
li.total = itotal;
/* Allow for extra lookups due to ICM_CLUT_SET_APXLS */
- for (itotal = 1, ui = 0; ui < li.in.chan; ui++, itotal *= (clutPoints-1))
- ;
+ if (apxls_min != NULL && apxls_max != NULL) {
+ for (itotal = 1, ui = 0; ui < li.in.chan; ui++)
+ itotal *= (apxls_max[ui] - apxls_min[ui]);
+ } else {
+ for (itotal = 1, ui = 0; ui < li.in.chan; ui++)
+ itotal *= (clutPoints-1);
+ }
li.total += itotal;
li.count = 0;
printf(" 0%%"); fflush(stdout);
@@ -3086,7 +4038,8 @@ main(int argc, char *argv[]) {
NULL, NULL, /* Use default input colorspace range */
devip_devop, /* devi' -> devo' transfer function */
NULL, NULL, /* Default output colorspace range */
- devop_devo /* Output transfer tables, devo'->devo */
+ devop_devo, /* Output transfer tables, devo'->devo */
+ apxls_min, apxls_max /* Limit APXLS to inside colorspace */
) != 0) {
error("Setting 16 bit Lut failed: %d, %s",wr_icc->errc,wr_icc->err);
}
@@ -3107,13 +4060,88 @@ main(int argc, char *argv[]) {
if (li.verb && li.wphack && li.wphacked > 1)
printf("Warning :- white point hack trigger more than once! (%d)\n",li.wphacked);
+ /* Special case black point correction when we are usng TV encoding */
+ /* and the black probably doesn't lie on a grid point. */
+ /* This probably only works if we can have "-ve" output values */
+ /* by virtue of the output being tv encoded too. */
+ if (li.in.tvenc) {
+ icmLut *lut;
+ double ival[MXDO]; /* Black input value */
+ double oval[MXDO]; /* Correct output value for black */
+
+ if ((lut = (icmLut *)wr_icc->read_tag(wr_icc, icSigAToB0Tag)) == NULL)
+ error("unableto locate A2B tag: %d, %s",wr_icc->errc,wr_icc->err);
+
+ ival[0] = ival[1] = ival[2] = 0.0; /* RGB black input */
+
+ /* Encode input value */
+ if (li.out.tvenc == 1) { /* Video 16-235 range */
+ icmRGB_2_VidRGB(ival, ival);
+ } else if (li.out.tvenc == 2) { /* Rec601 YCbCr */
+ icmRec601_RGBd_2_YPbPr(ival, ival);
+ icmRecXXX_YPbPr_2_YCbCr(ival, ival);
+ } else if (li.out.tvenc == 3) { /* Rec709 1150/60/2:1 YCbCr */
+ icmRec709_RGBd_2_YPbPr(ival, ival);
+ icmRecXXX_YPbPr_2_YCbCr(ival, ival);
+ } else if (li.out.tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ icmRec709_50_RGBd_2_YPbPr(ival, ival);
+ icmRecXXX_YPbPr_2_YCbCr(ival, ival);
+ } else if (li.out.tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr encoding */
+ icmRec2020_NCL_RGBd_2_YPbPr(ival, ival);
+ icmRecXXX_YPbPr_2_YCbCr(ival, ival);
+ } else if (li.out.tvenc == 6) { /* Rec2020 Constant Luminance YCbCr encoding */
+ icmRec2020_CL_RGBd_2_YPbPr(ival, ival);
+ icmRecXXX_YPbPr_2_YCbCr(ival, ival);
+ }
+
+//printf("input value %f %f %f\n",ival[0], ival[1], ival[2]);
+ lut->lookup_clut_sx(lut, oval, ival);
+//printf("before tune out %f %f %f\n",oval[0], oval[1], oval[2]);
+
+ /* Lookup the cLUT input value */
+ devi_devip((void *)&li, ival, ival);
+
+ /* Look up black output value we want */
+ devip_devop((void *)&li, oval, ival);
+
+//printf("bp tune target %f %f %f\n",oval[0], oval[1], oval[2]);
+
+ // ~~~~9999 should do a lookup to set sx/nl type corrctly
+ rv = lut->tune_value(lut, oval, ival);
+// rv = icmLut_tune_value_sx(lut, oval, ival);
+// rv = icmLut_tune_value_nl(lut, oval, ival);
+
+ if (rv != 0)
+ warning("Fine tuning video black failed - clipping");
+
+// lut->lookup_clut_sx(lut, oval, ival);
+//printf("after sx out %f %f %f\n",oval[0], oval[1], oval[2]);
+
+// lut->lookup_clut_nl(lut, oval, ival);
+//printf("after nl out %f %f %f\n",oval[0], oval[1], oval[2]);
+ }
+
if (li.verb)
printf("Writing out file\n");
/* Write the file out */
if ((rv = wr_icc->write(wr_icc,wr_fp,0)) != 0)
error ("Write file: %d, %s",rv,wr_icc->err);
-
+
+ /* eeColor format */
+ if (li.tdlut == 1) {
+ write_eeColor1DinputLuts(&li, tdlut_name);
+ if (write_eeColor3DLut(wr_icc, tdlut_name))
+ error ("Write file '%s' failed",tdlut_name);
+ write_eeColor1DoutputLuts(&li, tdlut_name);
+ }
+
+ /* MadVR format */
+ else if (li.tdlut == 2) {
+ if (write_MadVR_3DLut(&li, wr_icc, tdlut_name))
+ error ("Write file '%s' failed",tdlut_name);
+ }
+
wr_icc->del(wr_icc);
wr_fp->del(wr_fp);
@@ -3276,6 +4304,9 @@ main(int argc, char *argv[]) {
li.abs_icc->del(li.abs_icc);
li.abs_fp->del(li.abs_fp);
}
+ if (li.cal != NULL) {
+ li.cal->del(li.cal);
+ }
li.in.luo->del(li.in.luo);
li.in.x->del(li.in.x);
@@ -3290,9 +4321,420 @@ main(int argc, char *argv[]) {
return 0;
}
+/* ===================================================================== */
+/* Write a eeColor 1DLut input LUT files */
+/* Return nz on error */
+int write_eeColor1DinputLuts(clink *li, char *tdlut_name) {
+ char fname[MAXNAMEL+1+20], *xl;
+ int i, j, k;
+
+ for (j = 0; j < 3; j++) {
+ icmFile *fp;
+ double in[3], out[3];
+
+ strncpy(fname,tdlut_name,MAXNAMEL-1); fname[MAXNAMEL-1] = '\000';
+ if ((xl = strrchr(fname, '.')) == NULL) /* Figure where extention is */
+ xl = fname + strlen(fname);
+
+ if (j == 0)
+ strcpy(xl,"-first1dred.txt");
+ else if (j == 1)
+ strcpy(xl,"-first1dgreen.txt");
+ else
+ strcpy(xl,"-first1dblue.txt");
+
+ if ((fp = new_icmFileStd_name(fname,"w")) == NULL)
+ error ("write_eeColor1DinputLuts: Can't open file '%s'",fname);
+
+ for (i = 0; i < 1024; i++) {
+ for (k = 0; k < 3; k++)
+ in[k] = i/(1024-1.0);
+ devi_devip((void *)li, out, in);
+ fp->gprintf(fp,"%.6f\n",out[j]);
+ }
+
+ if (fp->del(fp))
+ error ("write_eeColor1DinputLuts to '%s' failed",fname);
+ }
+ return 0;
+}
+
+#ifdef NEVER
+
+/* Write a eeColor 3DLut file */
+/* Return nz on error */
+/* (We delve inside the icc structure, so don't use this code) */
+int write_eeColor3DLut(icc *icc, char *fname) {
+ icmLut *lut;
+ icmFile *fp;
+
+ if ((lut = (icmLut *)icc->read_tag(icc, icSigAToB0Tag)) == NULL)
+ error("write_eeColor3DLut: unableto locate A2B tag: %d, %s",icc->errc,icc->err);
+
+ /* Open up the 3dlut file for writing */
+ if ((fp = new_icmFileStd_name(fname,"w")) == NULL)
+ error ("write_eeColor3DLut: Can't open file '%s'",fname);
+
+ {
+ int i, j, k;
+ DCOUNT(gc, MAX_CHAN, lut->inputChan, 0, 0, lut->clutPoints);
+ int ord[3] = { 1, 0, 2 }; /* Channel order, fastest to slowest, G, R, B */
+ DC_INIT(gc);
+ while (!DC_DONE(gc)) {
+ int ix;
+
+ ix = 0;
+ for (i = 0; i < lut->inputChan; i++) {
+ ix += lut->dinc[ord[i]] * gc[i];
+ }
+
+ /* Hmm. We're assuming that the eeColor is smart enough */
+ /* to map the floating point values to the maximum */
+ /* video encoded range, ie 255 * (bits - 8). */
+ /* It's not clear if "bits" is 8, 10 or 12, or if */
+ /* it actually works this way though. */
+
+ /* It's also not clear what it does for full range input, */
+ /* if anything. Ie. it may just map that to 255 * (bits - 8) too. */
+
+ /* There are two sets of RGB values. One is (suposedly)
+ the "calibrated white point" and one "the native white point".
+ It's hard to guess what this is.
+ */
+
+ for (i = 0; i < lut->inputChan; i++) {
+ fp->gprintf(fp," %.6f",lut->clutTable[ix + i]);
+ }
+ for (i = 0; i < lut->outputChan; i++) {
+ fp->gprintf(fp," %.6f",lut->clutTable[ix + i]);
+ }
+
+ fp->gprintf(fp,"\n");
+
+ DC_INC(gc);
+ }
+ }
+ if (fp->del(fp))
+ error ("write_eeColor3DLut: write to '%s' failed",fname);
+ return 0;
+}
+
+#else
+
+/* Write a eeColor 3DLut file by doing a lookup for each node. */
+/* Return nz on error */
+int write_eeColor3DLut(icc *icc, char *fname) {
+ icmLuBase *luo;
+ icmLuLut *lut;
+ int i, j, k;
+ DCOUNT(gc, MAX_CHAN, 3, 0, 0, 65);
+ int ord[3]; /* Input channel order, fastest to slowest */
+ icmFile *fp;
+
+ /* Get a conversion object. We assume it is of the right type, being a link */
+ if ((luo = icc->get_luobj(icc, icmFwd, icmDefaultIntent, icmSigDefaultData, icmLuOrdNorm))
+ == NULL)
+ error("write_eeColor3DLut: get luobj failed: %d, %s",icc->errc,icc->err);
+
+ /* Cast to Lut lookup - safe because that's all that collink does */
+ lut = (icmLuLut *)luo;
+
+ /* Open up the 3dlut file for writing */
+ if ((fp = new_icmFileStd_name(fname,"w")) == NULL)
+ error ("write_eeColor3DLut: Can't open file '%s'",fname);
+
+ DC_INIT(gc);
+
+ ord[0] = 1; ord[1] = 0; ord[2] = 2; /* Fastest to slowest G R B */
+
+ while (!DC_DONE(gc)) {
+ double in[3], out[3];
+
+ /* Hmm. If we knew how the eeColor quantized the incoming video values, */
+ /* we could do the same quantization here for better accuracy. */
+ /* It's hard to guess given the unknown 8/10/12 bit nature of it. */
+ for (i = 0; i < 3; i++)
+ in[ord[i]] = gc[i]/64.0;
+
+ if (lut->clut(lut, out, in) > 1)
+ error ("write_eeColor3DLut: %d, %s",icc->errc,icc->err);
+
+//printf("~1 %f %f %f -> %f %f %f\n", in[0], in[1], in[2], out[0], out[1], out[2]);
+
+ for (i = 0; i < 3; i++)
+ fp->gprintf(fp," %.6f",out[i]);
+ for (i = 0; i < 3; i++)
+ fp->gprintf(fp," %.6f",out[i]);
+
+ fp->gprintf(fp,"\n");
+
+ DC_INC(gc);
+ }
+ if (fp->del(fp))
+ error ("write_eeColor3DLut: write to '%s' failed",fname);
+ return 0;
+}
+#endif
+
+/* Write a eeColor 1DLut output LUT files */
+/* Return nz on error */
+int write_eeColor1DoutputLuts(clink *li, char *tdlut_name) {
+ char fname[MAXNAMEL+1+20], *xl;
+ int i, j, k;
+
+ for (j = 0; j < 3; j++) {
+ icmFile *fp;
+ double in[3], out[3];
+
+ strncpy(fname,tdlut_name,MAXNAMEL-1); fname[MAXNAMEL-1] = '\000';
+ if ((xl = strrchr(fname, '.')) == NULL) /* Figure where extention is */
+ xl = fname + strlen(fname);
+
+ if (j == 0)
+ strcpy(xl,"-second1dred.txt");
+ else if (j == 1)
+ strcpy(xl,"-second1dgreen.txt");
+ else
+ strcpy(xl,"-second1dblue.txt");
+
+ if ((fp = new_icmFileStd_name(fname,"w")) == NULL)
+ error ("write_eeColor1DoutputLuts: Can't open file '%s'",fname);
+
+ for (i = 0; i < 8192; i++) {
+ for (k = 0; k < 3; k++)
+ in[k] = i/(8192-1.0);
+ devop_devo((void *)li, out, in);
+ fp->gprintf(fp,"%.6f\n",out[j]);
+ }
+
+ if (fp->del(fp))
+ error ("write_eeColor1DoutputLuts to '%s' failed",fname);
+ }
+ return 0;
+}
+
+/* ===================================================================== */
+/* Write MadVR 3dlut file */
+
+/* Return nz on error */
+int write_MadVR_3DLut(clink *li, icc *icc, char *fname) {
+ icmFile *fp;
+ ORD8 *h;
+ int of, hoff, clutsize;
+ int dov2 = 0;
+ double rgbw[4][3] = { /* RGB + White Yxy */
+ { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 },
+ { 1.0, 1.0, 1.0 }
+ };
+ int i;
+
+ icmLuBase *luo;
+
+ /* Get an absolute conversion object to lookup primaries */
+ if ((luo = li->in.c->get_luobj(li->in.c, icmFwd, icAbsoluteColorimetric, icmSigDefaultData, icmLuOrdNorm))
+ == NULL)
+ error ("write_MadVR_3DLut: %d, %s",icc->errc, icc->err);
+
+ for (i = 0; i < 4; i++) {
+ if (luo->lookup(luo, rgbw[i], rgbw[i]) > 1)
+ error ("write_MadVR_3DLut: %d, %s",icc->errc,icc->err);
+
+ icmXYZ2Yxy(rgbw[i], rgbw[i]);
+ }
+
+ luo->del(luo);
+
+ /* Get a conversion object. We assume it is of the right type */
+ if ((luo = icc->get_luobj(icc, icmFwd, icmDefaultIntent, icmSigDefaultData, icmLuOrdNorm))
+ == NULL)
+ error ("write_MadVR_3DLut: %d, %s",icc->errc, icc->err);
+
+ /* Open up the 3dlut file for writing */
+ if ((fp = new_icmFileStd_name(fname,"w")) == NULL)
+ error("write_MadVR_3DLut: Can't open file '%s'",fname);
+
+ /* Create the 3dlutheader */
+ if ((h = (ORD8 *)calloc(0x4000, sizeof(ORD8))) == NULL)
+ error("write_MadVR_3DLut: failed to calloc 16384 bytes");
+
+ of = 0;
+ if (dov2) {
+ h[0] = '3'; h[1] = 'D'; h[2] = 'L'; h[3] = '2'; of += 4; /* Signature */
+ } else {
+ h[0] = '3'; h[1] = 'D'; h[2] = 'L'; h[3] = 'T'; of += 4; /* Signature */
+ }
+ write_ORD32_le(1, h + of); of += 4; /* File format version */
+ strncpy((char *)h+of, "ArgyllCMS collink", 31); of += 32; /* Creation program */
+ write_ORD64_le(ARGYLL_VERSION, h + of); of += 8; /* Program version */
+ write_ORD32_le(8, h + of); of += 4; /* input bit depth */
+ write_ORD32_le(8, h + of); of += 4;
+ write_ORD32_le(8, h + of); of += 4;
+ write_ORD32_le(li->in.tvenc >= 2 ? 1 : 0, h + of); of += 4; /* Input BGR or cCbCr enc */
+ if (dov2)
+ write_ORD32_le(li->in.tvenc != 0 ? 1 : 0, h + of), of += 4; /* Range */
+ write_ORD32_le(16, h + of); of += 4; /* Output bit depth */
+ write_ORD32_le(li->out.tvenc >= 2 ? 1 : 0, h + of); of += 4; /* Output BGR or YCbCr encoding */
+ if (dov2)
+ write_ORD32_le(li->out.tvenc != 0 ? 1 : 0, h + of), of += 4; /* Range */
+ write_ORD32_le(0x200, h + of); of += 4; /* Bytes to parameters */
+ hoff = 0x200;
+ hoff += sprintf((char *)h+hoff, "Input_Primaries %f %f %f %f %f %f %f %f\r\n", /* For V0.66+ */
+ rgbw[0][1], rgbw[0][2], rgbw[1][1], rgbw[1][2],
+ rgbw[2][1], rgbw[2][2], rgbw[3][1], rgbw[3][2]);
+// hoff += sprintf((char *)h+hoff, "Input_Transfer_Function 1.0 0.0 0.45454545454545454545454545454545 0.0");
+
+ if (li->in.tvenc == 0)
+ hoff += sprintf((char *)h+hoff, "Input_Range 0 255\r\n");
+ else
+ hoff += sprintf((char *)h+hoff, "Input_Range 16 235\r\n");
+ if (li->out.tvenc == 0)
+ hoff += sprintf((char *)h+hoff, "Output_Range 0 255\r\n");
+ else
+ hoff += sprintf((char *)h+hoff, "Output_Range 16 235\r\n");
+ write_ORD32_le(hoff - 0x200 + 1, h + of); of += 4; /* Bytes of parameter data + nul */
+ write_ORD32_le(0x4000, h + of); of += 4; /* Bytes to clut data */
+ write_ORD32_le(0, h + of); of += 4; /* No compression */
+ clutsize = (1 << (3 * 8)) * 3 * 2;
+ write_ORD32_le(clutsize, h + of); of += 4; /* Compressed clut size */
+ write_ORD32_le(clutsize, h + of); of += 4; /* Uncompressed clut size */
+
+ if (li->verb)
+ printf("Writing 3dLut\n");
+
+ /* Write the 3dlutheader */
+ if (fp->write(fp, h, 1, 0x4000) != 0x4000)
+ error ("write_MadVR_3DLut: write header failed");
+
+ /* Write the clut data */
+ {
+ int i, j, k;
+ DCOUNT(gc, MAX_CHAN, 3, 0, 0, 256);
+ int ord[3]; /* Input channel order, fastest to slowest */
+ ORD8 buf[3 * 2];
+
+ DC_INIT(gc);
+
+ if (li->in.tvenc >= 2) { /* YCbCr fastest to slowest is Y Cb Cr */
+ ord[0] = 0; ord[1] = 1; ord[2] = 2; /* Y Cb Cr */
+
+ } else { /* RGB fastest to slowest is B G R */
+ ord[0] = 2; ord[1] = 1; ord[2] = 0; /* B G R */
+ }
+
+ while (!DC_DONE(gc)) {
+ double in[3], out[3];
+ int iout[3];
+
+ for (i = 0; i < 3; i++)
+ in[ord[i]] = gc[i]/255.0;
+
+ if (luo->lookup(luo, out, in) > 1)
+ error ("write_MadVR_3DLut: %d, %s",icc->errc,icc->err);
+
+//printf("~1 %f %f %f -> %f %f %f\n", in[0], in[1], in[2], out[0], out[1], out[2]);
+
+ if (li->in.tvenc == 7 || li->in.tvenc == 8) { /* xvYCC */
+ for (i = 1; i < 3; i++) { /* Force 'sync' entry values on CbCr*/
+ if (gc[i] == 0) {
+ out[i] = 0.0;
+ } else if (gc[i] == 255) {
+ out[i] = 1.0;
+ }
+ }
+ }
+
+ if (li->out.tvenc == 0) { /* Full range 16 bits */
+ iout[0] = (int)(out[0] * 0xffff + 0.5);
+ iout[1] = (int)(out[1] * 0xffff + 0.5);
+ iout[2] = (int)(out[2] * 0xffff + 0.5);
+
+ } else { /* TV encoding - shifted by 8 bits */
+ iout[0] = (int)(out[0] * 0xff00 + 0.5);
+ iout[1] = (int)(out[1] * 0xff00 + 0.5);
+ iout[2] = (int)(out[2] * 0xff00 + 0.5);
+
+ }
+
+ if (li->out.tvenc >= 2) { /* YCbCr order is YCbCr */
+ write_ORD16_le(iout[0], buf + 0);
+ write_ORD16_le(iout[1], buf + 2);
+ write_ORD16_le(iout[2], buf + 4);
+
+ } else { /* RGB order is BGR */
+ write_ORD16_le(iout[2], buf + 0);
+ write_ORD16_le(iout[1], buf + 2);
+ write_ORD16_le(iout[0], buf + 4);
+ }
+
+ if (fp->write(fp, buf, 1, 6) != 6)
+ error ("write_MadVR_3DLut: write clut data failed");
+
+ DC_INC(gc);
+ }
+ }
+
+ /* Append a cal1 table to the 3dlut. */
+ /* This can be used to ensure that the Graphics Card VideoLuts */
+ /* are correctly setup to match what the 3dLut is expecting. */
+
+ /* Note that the calibration is full range, never TV encoded output values */
+
+ /* Format is (little endian):
+ 4 byte magic number 'cal1'
+ 4 byte version = 1
+ 4 byte number per channel entries = 256
+ 4 byte bytes per entry = 2
+ [3][256] 2 byte entry values. Tables are in RGB order
+ */
+ if (li->cal != NULL) {
+ ORD8 buf[4 * 4 + 3 * 256 * 2], *of = buf;
+ ORD32 magic, vers, entries, depth;
+ unsigned int val;
+ int i, j;
+
+ if (li->verb)
+ printf("Appending %scalibration curves\n", li->addcal == 2 ? "" : "linear");
+
+ magic = ('c')
+ + ('a' << 8)
+ + ('l' << 16)
+ + ('1' << 24);
+ write_ORD32_le(magic, of); of += 4; /* Magic number */
+
+ vers = 1;
+ write_ORD32_le(vers, of); of += 4; /* Format version */
+
+ entries = 256;
+ write_ORD32_le(entries, of); of += 4; /* Number of entries per channel */
+
+ depth = 2;
+ write_ORD32_le(depth, of); of += 4; /* Depth per entry in bytes */
+
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < 256; i++) {
+ double v = i/255.0;
+
+ if (li->addcal == 2)
+ v = li->cal->interp_ch(li->cal, j, v);
+ val = (int)(v * 65535.0 + 0.5);
+ write_ORD16_le(val, of); of += 2;
+ }
+ }
+ if (fp->write(fp, buf, 1, sizeof(buf)) != sizeof(buf))
+ error ("write_MadVR_3DLut: write cal1 data failed");
+ }
+
+ if (fp->del(fp))
+ error ("write_MadVR_3DLut: write to '%s' failed",fname);
+ luo->del(luo);
+
+ return 0;
+}
diff --git a/log.txt b/log.txt
index 13f6bad..ce1a4d1 100644
--- a/log.txt
+++ b/log.txt
@@ -2,6 +2,310 @@
Argyll CMS change log
=====================
+Version 1.6.3 (26 January 2014)
+-------------
+
+* Added icc/mkDispProf.c sample code
+
+* Added ProPhoto.icm and ProPhotoLin.icm to ref profiles.
+
+* Fix bug in xicclu -py conversion.
+
+* Added code to minimize ICC rounding error on matrix profile white point
+ accuracy. Re-generated all reference profiles with this change.
+
+* Changed i1d3 driver to completely ignore any EEPROM checksum
+ errors for non "A-01" rev. instruments.
+
+* Made transplot handle RGB->RGB device link.
+
+* Removed colprof -y option. Use "profcheck -v2" instead, as it is
+ more developed.
+
+* Fixed bug in dispcal - it was not using the final measurement
+ pass to update the calibration curves.
+
+* Fixed bug in spotread, dispcal & dispread for CCSS capable instruments
+ where refresh display types was being ignored if a custom observer
+ was used, and/or the custom observer as being ignored, and/or
+ a CCMX was being ignored.
+ Changed instlib semantics for inst_opt_set_ccss_obs :-
+ this is now set immediately, and applied also to any subsequent
+ set_disptype() or col_cal_spec_set().
+
+* Renamed verify to colverify to avoid clash with MSWin program
+ of the same name. Made it print the patch location for -v2
+ if it is present in the file.
+
+* Changed targen to ensure that -V and -p options effects are reflected
+ in the resulting expected CIE values of the .ti1 file.
+
+* Changed targen so that -V parameter also affects single channel,
+ grey wedge, grid & body centered grid point distribution.
+
+* Changed colprof to deal with variable grid distribution
+ in a more neuanced way, to reduce overshoot artifacts
+ when the -V parameter is used.
+
+* Changed colprof to used a power_like function for the
+ grid distribution shape from the -V parameter, so as
+ to avoid issues with a power curve infinte slope near zero.
+
+* Changed colprof to used a scaled down value of the targen -V
+ parameter as the default for its -V parameter. Documentation
+ now recommends more moderate values for -V.
+
+* Added a special case to collink for RGB video input encoding
+ to (attempt) to fine tune the black point to compensate
+ for it (probably) not falling on a cLUT grid point. & out encoding
+
+* Tweaked dispcal to try and improve accuracy of black
+ point calibration.
+
+* Switch dispread to use NoClamp readings, so that
+ average black point value is not biased.
+
+* Fixed bug introduced into 1.6.2 oeminst that prevents .ccss files
+ being installed.
+
+
+Version 1.6.2 - (19th November 2013)
+-------------
+
+* Added "dark region emphasis" -V parameter to targen and colprof,
+ in an attempt to improve the accuracy of display profiles intended
+ for use with video. This should improve the subsequent black
+ point accuracy of the profile.
+
+* Fixed bug and tweaked dispcal black point optimization to
+ err on the black side. Added -v3 for even more debugging information.
+
+* Changed i1d3 driver to be more forgiving of EEProm checksum
+ calculation, so that it works with the latest release "A-02" rev.
+ i1 display pro & colormunki display instruments.
+
+* Improved robustness of i1d3 driver in recovering from errors.
+
+* Fixed race condition bug in OS X HID driver. This
+ fixes occassional problem with i1d3, and also solves
+ problem with the ColorHug on OS X. ColorHug is now fully supported.
+
+* Fixed problem with TV encoded output and dispread -E -k/-K
+ (Thanks to Florian Hoch).
+
+* Fixed minor bug in DE94 in icclib.
+
+* Fixed major bug in illumread - result was being corrupted.
+
+* Fixed "edges don't match" bug in printarg when -iCM -h -s/-S used.
+
+* Fix bug in -H flag in ccxxmake, chartread, dispcal, dispread,
+ illumread & spotread so that it works once again.
+
+Version 1.6.1 (30th September 2013)
+-------------
+
+* Fix bug in "average -m"
+
+* Fix oeminst to work with a wider range of i1d3 install
+ files.
+
+* Fix bug introduced into ColorMunki (spectro) reflective
+ measurement that created discrepancies between spot
+ and strip measurement mode. Changed short wavelength
+ handling to be more like the manufacturers driver in
+ duplicating values, reduced reflective strip reading
+ scan rate to 55Hz to reduce reflective electrical interference
+ error.
+
+* Fix bug introduced into DTP94 driver when running on OS X.
+
+* Add valid (but unsigned) .cat files for MSWin libusb-win32 driver
+ installation. This seems to remove the need to disable diver signature
+ enforcement, and makes it possible to install on Win8.1
+
+* Fix MadVR test pattern access to look for 64 bit .dll if it's been
+ compiled as 64 bit, otherwise API will fail.
+
+* Change instlib API to honour the inst_mode_highres flag in set_mode().
+ Note that this means that High Res. mode state will be set by whatever
+ the last set_mode() or get_set_opt(inst_opt_highres/inst_opt_stdre) was.
+
+
+Version 1.6.0 (16th August 2013)
+-------------
+
+* Fixed crash in ucmm/ucmm.c when loading certain profiles
+ using dispwin (thanks to Torok Edwin).
+
+* Fixed JETI specbos 1201 handling so that all refresh mode
+ support is disabled, since it is not supported by this instrument.
+
+* Changed collink video level extended range handling to do a simple
+ extrapolation rather than linearly interpolated to the sync. values.
+
+* Added extra options to fakeread & verify to support Video verification.
+
+* Changed spotread -ew mode to be Bradford chromatic transform
+ rather than XYZ scaling, to better match Argyll ICC abs. vs. rel.
+
+* Added support to xicclu to lookup colors though CAL files, both
+ forward and backwards. Will also plot CAL file contents using -g.
+
+* Changed frequency calibration test pattern to be 80% white, to
+ avoid some situations where 100% does not exhibit refresh flicker.
+ Added warning for spotread when refresh calibration is expected.
+
+* Added -Y R:rate option to spotread, dispcal, dispread & ccxxmake
+ to allow setting a chosen display refresh rate. This can be used
+ with the Colormunki display, as well as situations in which refresh rate
+ measurement is not reliable.
+
+* Added 't' interactive command to specbos to toggle laser target
+ for JETI specbos.
+
+* Turned off B2A table clip map smoothing, as it seems to introduce
+ reversals for some data sets, and provides little benefit.
+
+* Changed dispwin & other display test patch programs on Linux/X11
+ to use XRandR V1.3 XRRGetScreenResourcesCurrent() if available,
+ to avoid flickering and blackouts on some displays.
+
+* Linux profile installation will use colord if libcolordcompat.so
+ is present on system.
+
+* Changed dispwin to use XRandR V1.3 XRRGetScreenResourcesCurrent()
+ rather than XRRGetScreenResources() if available.
+
+* Added MadVR test patch support to dispwin, dispcal, dispread
+ and ccxxmake.
+
+* For those instruments that support it, made ambient readings
+ honour refresh mode measurements, to improve repeatability
+ when measuring regularly flickering light sources.
+ (specbos, i1d3, i1disp).
+
+* Made allowance for non standard ICC cLUT resolution of 256
+ for special case of MadVR device links.
+
+* Tweaked colprof display profile creation to give more weight
+ to samples near the black point, in an attempt to improve
+ the black point accuracy.
+
+* Added default 4 black patches in targen for Grey & RGB spaces, -B option
+ to specify the number of black patches.
+
+* Fixed gamut mapping intent "rl" to really use relative L*a*b*
+
+* Add Rec2020 YCbCr encoding support (both types) to collink and xicclu.
+ Added experimental xvYCC encoding support to collink.
+
+* Add Rec2020 profile.
+
+* By default printtarg will create PS and EPS files with a CUPS
+ job ticket to disable color management. Use the -U flag to disable this.
+
+* !!! Changed instlib API ambient XYZ and spectral units to Lux. In prevous versions
+ of instlib they were Lux/pi. !!!
+
+* Changed spotread so that it won't fall back to emissive spot mode if
+ an ambient reading is requested.
+
+* Fixed bug in xicclu for Yxy input.
+
+* Added display update delay calibration support to i1pro and munki (just like
+ i1disp3), to improve measurement times.
+
+* Changed dispcal & dispread so that they wait up to 0.5 seconds when reading dark
+ patches after light ones to allow for display fall time. Added a patch order
+ optimisation for display patch sets in targen to minimze the extra time.
+
+* Added MadVR Video calibration support.
+
+* Added eeColor Video calibration support.
+
+* Changed dispwin daemon loader mode from -E to -X.
+ Added -E option to encode test patch colors in Video 16-235 range.
+
+* Changed dispcal verify option from -E to -z.
+ Added -E option to encode test patch colors in Video 16-235 range.
+
+* Added -E option to to dispread to encode test patch colors in Video 16-235 range.
+
+* Changed enumerated viewing conditions for new Flare/Glare settings,
+ changed all to Flareless to improve dark image behaviour, while
+ retaining Glare modelling. Tweaked brightness and ambient values.
+
+* Changed CIECAM02 Flare model to distinguish between Flare from
+ the image itself, and Glare from ambient light. This allows
+ scaling Glare with ambient automatically.
+
+* Fix bug in cicam02 in V1.5.0 that causes some mapping
+ problems in the red for collink -ir or -ila.
+
+* Changed cctiff so that it does lossless JPEG copy
+ when there is no color transformation. This makes it
+ more useful for embedding a profile.
+
+* Fix xicclu so that it works with device links.
+
+* Add -Et and -E7 option to xicclu to help with testing
+ Video calibration device links.
+
+* Made sure that MSWin test colors are not color managed.
+ This may affect Vista, Win7 and Win8.
+
+* Changed spectro/dispwin.c so that null transform
+ color matching is used for displaying test patches
+ on OS X >= 10.6. This should fix calibrating/profiling
+ secondary displays on > OS X 10.6. Note that the 32 bit 10.4
+ binary will still have problems on > OS X 10.6.
+
+* Improved i1pro hi-res mode to improve accuracy.
+
+* Added JETI specbos 1211/1201 instrument support.
+
+* Fix some corner case bugs in imdi/cctiff when handling
+ a calibration file colorspace mismatch, and the zero
+ color transformation case.
+
+* Tweak B2A cLUT clipping behaviour slighly, to reduce L* delta E.
+
+* Added Body Centered Cubic grid option to targen.
+
+* Added -Yn flag to dispcal and dispread, which skips asking
+ the user to place the instrument on the measuring spot.
+
+* Fixed bug in shaper/matrix profile curves that caused
+ random bumpy black behaviour (shaper curve optimization local minumum problem).
+
+* Increased default smoothing for XYZ cLUT profiles, to make
+ their smoothness comparable to L*a*b* cLUT profiles.
+
+* Improve robustness of i1d3 display update measurement code.
+
+* Don't add colorant tag to .tiff files in cctiff unless
+ it is a non-standard space, as Photoshop will barf
+ on such files.
+
+* Added support for applying calibration curves in collink.
+
+* Added a Rec709.icm HDTV, EBU3213_PAL and SMPTE_RP145_NTSC profiles to samples.
+
+* Fix ColorHug driver so that it is backwards compatible with FW 1.1.8
+
+* Fix bug with Spyder not being able to break out of
+ dispcal adjustment loop.
+
+* Fix bug in xicc/xicclu, -K flag not being recognised.
+
+* Fix bug in xicc/xmatrix.c introduced in V1.5 that prevents
+ matrix only profiles from being created.
+
+* Using libusb is now deprecated in favour of native USB.
+
+* Added some prelinary BSD USB driver support. [incomplete]
+
Version 1.5.1 (8th March 2013)
-------------
@@ -1001,7 +1305,7 @@ Version 1.1.1 (21 February 2010)
in the input .tif file.
* Change spotread so that it takes spectral readings by
- default so that FWA comensation readings can be used.
+ default so that FWA compensation readings can be used.
* Changed link/collink to apply Y to L* curve if the input or output
space is XYZ. Fixed the Y to L* scaling to make sure it only
diff --git a/makepackagebin.sh b/makepackagebin.sh
index 64a1d12..1b8db28 100644
--- a/makepackagebin.sh
+++ b/makepackagebin.sh
@@ -103,10 +103,10 @@ else if [ X$OSTYPE = "Xdarwin10.0" \
USBBINFILES="binfiles.osx"
USETAR=true
else if [ X$OSTYPE = "Xlinux-gnu" ] ; then
- if [[ "$MACHTYPE" =~ x86_64-.*-linux-gnu ]] ; then
+ if [[ "$MACHTYPE" = x86_64-*-linux-gnu ]] ; then
echo "We're on Linux x86_64!"
PACKAGE=Argyll_V${VERSION}_linux_x86_64_bin.tgz
- else if [[ "$MACHTYPE" =~ i.86-.*-linux-gnu ]] ; then
+ else if [[ "$MACHTYPE" = *86-*-linux-gnu ]] ; then
echo "We're on Linux x86!"
PACKAGE=Argyll_V${VERSION}_linux_x86_bin.tgz
fi
diff --git a/numlib/numsup.c b/numlib/numsup.c
index 7648a62..a28dcd2 100644
--- a/numlib/numsup.c
+++ b/numlib/numsup.c
@@ -293,6 +293,7 @@ a1log *new_a1log(
a1loge(g_log, 1, "new_a1log: malloc of a1log failed, calling exit(1)\n");
exit(1);
}
+ log->refc = 1;
log->verb = verb;
log->debug = debug;
@@ -327,7 +328,7 @@ a1log *new_a1log_d(a1log *log) {
/* Returns NULL */
a1log *del_a1log(a1log *log) {
if (log != NULL) {
- if (--log->refc <= 0) {
+ if (--log->refc == 0) {
#ifdef NT
DeleteCriticalSection(&log->lock);
#endif
@@ -518,6 +519,55 @@ error(char *fmt, ...) {
/******************************************************************/
+/* Suplimental allcation functions */
+/******************************************************************/
+
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t)(-1))
+#endif
+
+/* a * b */
+static size_t ssat_mul(size_t a, size_t b) {
+ size_t c;
+
+ if (a == 0 || b == 0)
+ return 0;
+
+ if (a > (SIZE_MAX/b))
+ return SIZE_MAX;
+ else
+ return a * b;
+}
+
+/* reallocate and clear new allocation */
+void *recalloc( /* Return new address */
+void *ptr, /* Current address */
+size_t cnum, /* Current number and unit size */
+size_t csize,
+size_t nnum, /* New number and unit size */
+size_t nsize
+) {
+ int ind = 0;
+ size_t ctot, ntot;
+
+ if (ptr == NULL)
+ return calloc(nnum, nsize);
+
+ if ((ntot = ssat_mul(nnum, nsize)) == SIZE_MAX)
+ return NULL; /* Overflow */
+
+ if ((ctot = ssat_mul(cnum, csize)) == SIZE_MAX)
+ return NULL; /* Overflow */
+
+ ptr = realloc(ptr, ntot);
+
+ if (ptr != NULL && ntot > ctot)
+ memset((char *)ptr + ctot, 0, ntot - ctot); /* Clear the new region */
+
+ return ptr;
+}
+
+/******************************************************************/
/* Numerical Recipes Vector/Matrix Support functions */
/******************************************************************/
/* Note the z suffix versions return zero'd vectors/matricies */
@@ -1537,3 +1587,284 @@ char *ctime_64(const INR64 *timer) {
return rv;
}
+
+/*******************************************/
+/* Native to/from byte buffer functions */
+/*******************************************/
+
+/* No overflow detection is done - */
+/* numbers are clipped or truncated. */
+
+/* be = Big Endian */
+/* le = Little Endian */
+
+/* - - - - - - - - */
+/* Unsigned 8 bit */
+
+unsigned int read_ORD8(ORD8 *p) {
+ unsigned int rv;
+ rv = ((unsigned int)p[0]);
+ return rv;
+}
+
+void write_ORD8(unsigned int d, ORD8 *p) {
+ if (d > 0xff)
+ d = 0xff;
+ p[0] = (ORD8)(d);
+}
+
+/* - - - - - - - - */
+/* Signed 8 bit */
+
+int read_INR8(ORD8 *p) {
+ int rv;
+ rv = (int)(INR8)p[0];
+ return rv;
+}
+
+void write_INR8(int d, ORD8 *p) {
+ if (d > 0x7f)
+ d = 0x7f;
+ else if (d < -0x80)
+ d = -0x80;
+ p[0] = (ORD8)(d);
+}
+
+/* - - - - - - - - */
+/* Unsigned 16 bit */
+
+unsigned int read_ORD16_be(ORD8 *p) {
+ unsigned int rv;
+ rv = (((unsigned int)p[0]) << 8)
+ + (((unsigned int)p[1]));
+ return rv;
+}
+
+unsigned int read_ORD16_le(ORD8 *p) {
+ unsigned int rv;
+ rv = (((unsigned int)p[0]))
+ + (((unsigned int)p[1]) << 8);
+ return rv;
+}
+
+void write_ORD16_be(unsigned int d, ORD8 *p) {
+ if (d > 0xffff)
+ d = 0xffff;
+ p[0] = (ORD8)(d >> 8);
+ p[1] = (ORD8)(d);
+}
+
+void write_ORD16_le(unsigned int d, ORD8 *p) {
+ if (d > 0xffff)
+ d = 0xffff;
+ p[0] = (ORD8)(d);
+ p[1] = (ORD8)(d >> 8);
+}
+
+/* - - - - - - - - */
+/* Signed 16 bit */
+
+int read_INR16_be(ORD8 *p) {
+ int rv;
+ rv = (((int)(INR8)p[0]) << 8)
+ + (((int)p[1]));
+ return rv;
+}
+
+int read_INR16_le(ORD8 *p) {
+ int rv;
+ rv = (((int)p[0]))
+ + (((int)(INR8)p[1]) << 8);
+ return rv;
+}
+
+void write_INR16_be(int d, ORD8 *p) {
+ if (d > 0x7fff)
+ d = 0x7fff;
+ else if (d < -0x8000)
+ d = -0x8000;
+ p[0] = (ORD8)(d >> 8);
+ p[1] = (ORD8)(d);
+}
+
+void write_INR16_le(int d, ORD8 *p) {
+ if (d > 0x7fff)
+ d = 0x7fff;
+ else if (d < -0x8000)
+ d = -0x8000;
+ p[0] = (ORD8)(d);
+ p[1] = (ORD8)(d >> 8);
+}
+
+/* - - - - - - - - */
+/* Unsigned 32 bit */
+
+unsigned int read_ORD32_be(ORD8 *p) {
+ unsigned int rv;
+ rv = (((unsigned int)p[0]) << 24)
+ + (((unsigned int)p[1]) << 16)
+ + (((unsigned int)p[2]) << 8)
+ + (((unsigned int)p[3]));
+ return rv;
+}
+
+unsigned int read_ORD32_le(ORD8 *p) {
+ unsigned int rv;
+ rv = (((unsigned int)p[0]))
+ + (((unsigned int)p[1]) << 8)
+ + (((unsigned int)p[2]) << 16)
+ + (((unsigned int)p[3]) << 24);
+ return rv;
+}
+
+void write_ORD32_be(unsigned int d, ORD8 *p) {
+ p[0] = (ORD8)(d >> 24);
+ p[1] = (ORD8)(d >> 16);
+ p[2] = (ORD8)(d >> 8);
+ p[3] = (ORD8)(d);
+}
+
+void write_ORD32_le(unsigned int d, ORD8 *p) {
+ p[0] = (ORD8)(d);
+ p[1] = (ORD8)(d >> 8);
+ p[2] = (ORD8)(d >> 16);
+ p[3] = (ORD8)(d >> 24);
+}
+
+/* - - - - - - - - */
+/* Signed 32 bit */
+
+int read_INR32_be(ORD8 *p) {
+ int rv;
+ rv = (((int)(INR8)p[0]) << 24)
+ + (((int)p[1]) << 16)
+ + (((int)p[2]) << 8)
+ + (((int)p[3]));
+ return rv;
+}
+
+int read_INR32_le(ORD8 *p) {
+ int rv;
+ rv = (((int)p[0]))
+ + (((int)p[1]) << 8)
+ + (((int)p[2]) << 16)
+ + (((int)(INR8)p[3]) << 24);
+ return rv;
+}
+
+void write_INR32_be(int d, ORD8 *p) {
+ p[0] = (ORD8)(d >> 24);
+ p[1] = (ORD8)(d >> 16);
+ p[2] = (ORD8)(d >> 8);
+ p[3] = (ORD8)(d);
+}
+
+void write_INR32_le(int d, ORD8 *p) {
+ p[0] = (ORD8)(d);
+ p[1] = (ORD8)(d >> 8);
+ p[2] = (ORD8)(d >> 16);
+ p[3] = (ORD8)(d >> 24);
+}
+
+/* - - - - - - - - */
+/* Unsigned 64 bit */
+
+ORD64 read_ORD64_be(ORD8 *p) {
+ ORD64 rv;
+ rv = (((ORD64)p[0]) << 56)
+ + (((ORD64)p[1]) << 48)
+ + (((ORD64)p[2]) << 40)
+ + (((ORD64)p[3]) << 32)
+ + (((ORD64)p[4]) << 24)
+ + (((ORD64)p[5]) << 16)
+ + (((ORD64)p[6]) << 8)
+ + (((ORD64)p[7]));
+ return rv;
+}
+
+ORD64 read_ORD64_le(ORD8 *p) {
+ ORD64 rv;
+ rv = (((ORD64)p[0]))
+ + (((ORD64)p[1]) << 8)
+ + (((ORD64)p[2]) << 16)
+ + (((ORD64)p[3]) << 24)
+ + (((ORD64)p[4]) << 32)
+ + (((ORD64)p[5]) << 40)
+ + (((ORD64)p[6]) << 48)
+ + (((ORD64)p[7]) << 56);
+ return rv;
+}
+
+void write_ORD64_be(ORD64 d, ORD8 *p) {
+ p[0] = (ORD8)(d >> 56);
+ p[1] = (ORD8)(d >> 48);
+ p[2] = (ORD8)(d >> 40);
+ p[3] = (ORD8)(d >> 32);
+ p[4] = (ORD8)(d >> 24);
+ p[5] = (ORD8)(d >> 16);
+ p[6] = (ORD8)(d >> 8);
+ p[7] = (ORD8)(d);
+}
+
+void write_ORD64_le(ORD64 d, ORD8 *p) {
+ p[0] = (ORD8)(d);
+ p[1] = (ORD8)(d >> 8);
+ p[2] = (ORD8)(d >> 16);
+ p[3] = (ORD8)(d >> 24);
+ p[4] = (ORD8)(d >> 32);
+ p[5] = (ORD8)(d >> 40);
+ p[6] = (ORD8)(d >> 48);
+ p[7] = (ORD8)(d >> 56);
+}
+
+/* - - - - - - - - */
+/* Signed 64 bit */
+
+INR64 read_INR64_be(ORD8 *p) {
+ INR64 rv;
+ rv = (((INR64)(INR8)p[0]) << 56)
+ + (((INR64)p[1]) << 48)
+ + (((INR64)p[2]) << 40)
+ + (((INR64)p[3]) << 32)
+ + (((INR64)p[4]) << 24)
+ + (((INR64)p[5]) << 16)
+ + (((INR64)p[6]) << 8)
+ + (((INR64)p[7]));
+ return rv;
+}
+
+INR64 read_INR64_le(ORD8 *p) {
+ INR64 rv;
+ rv = (((INR64)p[0]))
+ + (((INR64)p[1]) << 8)
+ + (((INR64)p[2]) << 16)
+ + (((INR64)p[3]) << 24)
+ + (((INR64)p[4]) << 32)
+ + (((INR64)p[5]) << 40)
+ + (((INR64)p[6]) << 48)
+ + (((INR64)(INR8)p[7]) << 56);
+ return rv;
+}
+
+void write_INR64_be(INR64 d, ORD8 *p) {
+ p[0] = (ORD8)(d >> 56);
+ p[1] = (ORD8)(d >> 48);
+ p[2] = (ORD8)(d >> 40);
+ p[3] = (ORD8)(d >> 32);
+ p[4] = (ORD8)(d >> 24);
+ p[5] = (ORD8)(d >> 16);
+ p[6] = (ORD8)(d >> 8);
+ p[7] = (ORD8)(d);
+}
+
+void write_INR64_le(INR64 d, ORD8 *p) {
+ p[0] = (ORD8)(d);
+ p[1] = (ORD8)(d >> 8);
+ p[2] = (ORD8)(d >> 16);
+ p[3] = (ORD8)(d >> 24);
+ p[4] = (ORD8)(d >> 32);
+ p[5] = (ORD8)(d >> 40);
+ p[6] = (ORD8)(d >> 48);
+ p[7] = (ORD8)(d >> 56);
+}
+
diff --git a/numlib/numsup.h b/numlib/numsup.h
index 7db7676..b949379 100644
--- a/numlib/numsup.h
+++ b/numlib/numsup.h
@@ -41,6 +41,8 @@
/* This really needs checking for each different platform. */
/* Using C99 and MSC covers a lot of cases, */
/* and the fallback default is pretty reliable with modern compilers and machines. */
+/* Note that MSWin is LLP64 == 32 bit long, while OS X/Linux is LP64 == 64 bit long. */
+/* so long shouldn't really be used in any code.... */
/* (duplicated in icc.h) */
#if (__STDC_VERSION__ >= 199901L) /* C99 */
@@ -97,7 +99,7 @@
#else /* !_MSC_VER */
/* The following works on a lot of modern systems, including */
-/* LP64 model 64 bit modes */
+/* LLP64 and LP64 models, but won't work with ILP64 which needs int32 */
#define INR8 signed char /* 8 bit signed */
#define INR16 signed short /* 16 bit signed */
@@ -185,7 +187,7 @@
struct _a1log {
int refc; /* Reference count */
- char *tag; /* Optional tag name */
+ char *tag; /* Optional tag name */
int verb; /* Current verbosity level (public) */
int debug; /* Current debug level (public) */
@@ -277,6 +279,17 @@ extern char cr_char;
/* =========================================================== */
+/* reallocate and clear new allocation */
+void *recalloc( /* Return new address */
+void *ptr, /* Current address */
+size_t cnum, /* Current number and unit size */
+size_t csize,
+size_t nnum, /* New number and unit size */
+size_t nsize
+);
+
+/* =========================================================== */
+
/* Numerical recipes vector/matrix support functions */
/* Note that the index arguments are the inclusive low and high values */
@@ -372,6 +385,59 @@ char *ctime_32(const INR32 *timer);
/* A static buffer is used. There is no \n at the end */
char *ctime_64(const INR64 *timer);
+/*******************************************/
+/* Native to/from byte buffer functions */
+/*******************************************/
+
+/* No overflow detection is done - numbers are clipped */
+
+/* be = Big Endian */
+/* le = Little Endian */
+
+/* Unsigned 8 bit */
+unsigned int read_ORD8(ORD8 *p);
+void write_ORD8(unsigned int d, ORD8 *p);
+
+/* Signed 8 bit */
+int read_INR8(ORD8 *p);
+void write_INR8(int d, ORD8 *p);
+
+/* Unsigned 16 bit */
+unsigned int read_ORD16_be(ORD8 *p);
+unsigned int read_ORD16_le(ORD8 *p);
+void write_ORD16_be(unsigned int d, ORD8 *p);
+void write_ORD16_le(unsigned int d, ORD8 *p);
+
+/* Signed 16 bit */
+int read_INR16_be(ORD8 *p);
+int read_INR16_le(ORD8 *p);
+void write_INR16_be(int d, ORD8 *p);
+void write_INR16_le(int d, ORD8 *p);
+
+/* Unsigned 32 bit */
+unsigned int read_ORD32_be(ORD8 *p);
+unsigned int read_ORD32_le(ORD8 *p);
+void write_ORD32_be(unsigned int d, ORD8 *p);
+void write_ORD32_le(unsigned int d, ORD8 *p);
+
+/* Signed 32 bit */
+int read_INR32_be(ORD8 *p);
+int read_INR32_le(ORD8 *p);
+void write_INR32_be(int d, ORD8 *p);
+void write_INR32_le(int d, ORD8 *p);
+
+/* Unsigned 64 bit */
+ORD64 read_ORD64_be(ORD8 *p);
+ORD64 read_ORD64_le(ORD8 *p);
+void write_ORD64_be(ORD64 d, ORD8 *p);
+void write_ORD64_le(ORD64 d, ORD8 *p);
+
+/* Signed 64 bit */
+INR64 read_INR64_be(ORD8 *p);
+INR64 read_INR64_le(ORD8 *p);
+void write_INR64_be(INR64 d, ORD8 *p);
+void write_INR64_le(INR64 d, ORD8 *p);
+
#ifdef __cplusplus
}
#endif
diff --git a/plot/plot.c b/plot/plot.c
index c5ca910..bfd40ce 100644
--- a/plot/plot.c
+++ b/plot/plot.c
@@ -76,6 +76,7 @@ static int gcolors[MXGPHS][3] = {
struct _plot_info {
void *cx; /* Other Context */
+ int flags; /* Flags */
int dowait; /* Wait for user key if > 0, wait for n secs if < 0 */
double ratio; /* Aspect ratio of window, X/Y */
@@ -108,8 +109,13 @@ struct _plot_info {
/* Global to transfer info to window callback */
static plot_info pd;
+#define PLOTF_NONE 0x0000
+#define PLOTF_GRAPHCROSSES 0x0001 /* Plot crosses at each point on the graphs */
+#define PLOTF_VECCROSSES 0x0002 /* Plot crosses at the end of x1,y1 -> x2,y2 */
+
/* Declaration of superset */
static int do_plot_imp(
+ int flags,
double xmin, double xmax, double ymin, double ymax, /* Bounding box */
double ratio, /* Aspect ratio of window, X/Y */
int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
@@ -173,7 +179,8 @@ int n) {
if ((ymax - ymin) == 0.0)
ymax += 0.5, ymin -= 0.5;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, 1,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, 1.0, 1,
x, NULL, yy, NULL, n,
NULL, NULL, NULL, NULL, 0,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -244,7 +251,8 @@ int m) {
if ((ymax - ymin) == 0.0)
ymax += 0.5, ymin -= 0.5;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, 1,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, 1.0, 1,
x, NULL, yy, NULL, n,
x4, y4, NULL, NULL, m ,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -318,7 +326,8 @@ double ratio
ymin = pymin;
}
- return do_plot_imp(xmin, xmax, ymin, ymax, ratio, dowait,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, ratio, dowait,
x, NULL, yy, NULL, n,
NULL, NULL, NULL, NULL, 0,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -379,7 +388,8 @@ int n) { /* Number of values */
if ((ymax - ymin) == 0.0)
ymax += 0.5, ymin -= 0.5;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, 1,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, 1.0, 1,
x, NULL, yy, NULL, n,
NULL, NULL, NULL, NULL, n ,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -457,7 +467,8 @@ int m) {
if ((ymax - ymin) == 0.0)
ymax += 0.5, ymin -= 0.5;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, 1,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, 1.0, 1,
x, NULL, yy, NULL, n,
xp, yp, NULL, NULL, m,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -531,7 +542,8 @@ int zero /* Flag - make sure zero is in y range */
if ((ymax - ymin) == 0.0)
ymax += 0.5, ymin -= 0.5;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, 1,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, 1.0, 1,
x, NULL, yy, NULL, n,
NULL, NULL, NULL, NULL, n ,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -617,7 +629,8 @@ int m) {
if ((ymax - ymin) == 0.0)
ymax += 0.5, ymin -= 0.5;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, 1,
+ return do_plot_imp(PLOTF_NONE,
+ xmin, xmax, ymin, ymax, 1.0, 1,
x, NULL, yy, NULL, n,
xp, yp, NULL, NULL, m,
NULL, NULL, NULL, NULL, NULL, 0);
@@ -652,13 +665,14 @@ int m /* Number of points */
yy[0] = y1;
yy[1] = y2;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, dowait,
+ return do_plot_imp(PLOTF_VECCROSSES,
+ xmin, xmax, ymin, ymax, 1.0, dowait,
x1, x2, yy, NULL, n,
x3, y3, mcols, mtext, m,
NULL, NULL, NULL, NULL, NULL, 0);
}
-/* Plot a bunch of vectors + optional crosses + optional vectors*/
+/* Plot a bunch of vectors & crosses + optional crosses + optional vectors*/
/* return 0 on success, -1 on error */
int do_plot_vec2(
double xmin,
@@ -672,11 +686,11 @@ double *y2,
char **ntext, /* text annotation at cross */
int n, /* Number of vectors */
int dowait,
-double *x3, /* m extra point */
+double *x3, /* m extra crosses */
double *y3,
-plot_col *mcols,/* point colors */
-char **mtext, /* text annotation */
-int m, /* Number of points */
+plot_col *mcols,/* cross colors */
+char **mtext, /* text annotation at cross */
+int m, /* Number of crosses */
double *x4, /* o vector start */
double *y4,
double *x5, /* o vector end */
@@ -693,11 +707,13 @@ int o /* Number of vectors */
yy[0] = y1;
yy[1] = y2;
- return do_plot_imp(xmin, xmax, ymin, ymax, 1.0, dowait,
+ return do_plot_imp(PLOTF_VECCROSSES,
+ xmin, xmax, ymin, ymax, 1.0, dowait,
x1, x2, yy, ntext, n,
x3, y3, mcols, mtext, m,
x4, y4, x5, y5, ocols, o);
}
+
/* ********************************** NT version ********************** */
#ifdef NT
@@ -791,13 +807,15 @@ DWORD WINAPI plot_message_thread(LPVOID lpParameter) {
/* return 0 on success, -1 on error */
/* Hybrid Graph uses x1 : y1, y2, y3, y4, y5, y6 for up to 6 graph curves + */
/* optional diagonal crosses at x7, y7 in yellow (x2 == NULL). */
-/* Vector uses x1, y1 to x2, y2 as a vector with a diagonal cross at x2, y2 all in black, */
-/* with annotation ntext at the cross, */
-/* plus a diagonal cross at x7, y7 in yellow. The color for x7, y7 can be overidden by an */
-/* array of colors mcols, and augmented by optional label text mtext. (x2 != NULL) */
+/* Vector uses x1, y1 to x2, y2 as a vector with a (optional) diagonal cross at x2, y2 */
+/* all in black with annotation ntext at the cross, */
+/* plus a (optiona) diagonal cross at x7, y7 in yellow. The color for x7, y7 can be */
+/* overidden by an array of colors mcols, plus optional label text mtext. (x2 != NULL) */
/* n = number of points/vectors. -ve for reversed X axis */
/* m = number of extra points (x2,y3 or x7,y7) */
+/* x8,y8 to x9,y9 are extra optional vectors with optional colors */
static int do_plot_imp(
+ int flags,
double xmin, double xmax, double ymin, double ymax, /* Bounding box */
double ratio, /* Aspect ratio of window, X/Y */
int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
@@ -809,6 +827,7 @@ static int do_plot_imp(
double *x8, double *y8, double *x9, double*y9, plot_col *ocols,
int o
) {
+ pd.flags = flags;
pd.dowait = 10 * dowait;
pd.ratio = ratio;
{
@@ -974,9 +993,6 @@ xtick(HDC hdc, plot_info *pdp, double x, char *lab)
{
int xx,yy;
RECT rct;
-// GrLine(10 + (int)((x - pdp->mnx) * scx + 0.5), sh - 10 - 5,
-// 10 + (int)((x - pdp->mnx) * scx + 0.5), sh - 10 + 5, 1);
-// GrTextXY(5 + (int)((x - pdp->mnx) * scx + 0.5), sh - 10 - 10, lab, 1, 0);
xx = 10 + (int)((x - pdp->mnx) * pdp->scx + 0.5);
yy = pdp->sh - 10;
@@ -995,9 +1011,6 @@ ytick(HDC hdc, plot_info *pdp, double y, char *lab)
{
int xx,yy;
RECT rct;
-// GrLine(5, 10 + (int)((y - pdp->mny) * pdp->scy + 0.5),
-// 15, 10 + (int)((y - pdp->mny) * pdp->scy + 0.5), 1);
-// GrTextXY(5, pdp->sh - 10 - (int)((y - pdp->mny) * pdp->scy + 0.5), lab, 1, 0);
xx = 5;
yy = pdp->sh - 10 - (int)((y - pdp->mny) * pdp->scy + 0.5);
@@ -1034,7 +1047,7 @@ loose_label(HDC hdc, plot_info *pdp, double min, double max, void (*pfunc)(HDC h
void
DoPlot(
HDC hdc,
-plot_info *pdp
+plot_info *p
) {
int i, j;
int lx,ly; /* Last x,y */
@@ -1046,18 +1059,18 @@ plot_info *pdp
SelectObject(hdc,pen);
/* Plot horizontal axis */
- if (pdp->revx)
- loose_label(hdc, pdp, pdp->mxx, pdp->mnx, xtick);
+ if (p->revx)
+ loose_label(hdc, p, p->mxx, p->mnx, xtick);
else
- loose_label(hdc, pdp, pdp->mnx, pdp->mxx, xtick);
+ loose_label(hdc, p, p->mnx, p->mxx, xtick);
/* Plot vertical axis */
- loose_label(hdc, pdp, pdp->mny, pdp->mxy, ytick);
+ loose_label(hdc, p, p->mny, p->mxy, ytick);
RestoreDC(hdc,-1);
DeleteObject(pen);
- if (pdp->graph) { /* Up to MXGPHS graphs + crosses */
+ if (p->graph) { /* Up to MXGPHS graphs + crosses */
int gcolors[MXGPHS][3] = {
{ 0, 0, 0}, /* Black */
{ 210, 30, 0}, /* Red */
@@ -1071,7 +1084,7 @@ plot_info *pdp
{ 220, 220, 220} /* White */
};
for (j = MXGPHS-1; j >= 0; j--) {
- double *yp = pdp->yy[j];
+ double *yp = p->yy[j];
if (yp == NULL)
continue;
@@ -1079,22 +1092,21 @@ plot_info *pdp
pen = CreatePen(PS_SOLID,ILTHICK,RGB(gcolors[j][0],gcolors[j][1],gcolors[j][2]));
SelectObject(hdc,pen);
- lx = (int)((pdp->x1[0] - pdp->mnx) * pdp->scx + 0.5);
- ly = (int)(( yp[0] - pdp->mny) * pdp->scy + 0.5);
+ lx = (int)((p->x1[0] - p->mnx) * p->scx + 0.5);
+ ly = (int)(( yp[0] - p->mny) * p->scy + 0.5);
- for (i = 0; i < pdp->n; i++) {
+ for (i = 0; i < p->n; i++) {
int cx,cy;
- cx = (int)((pdp->x1[i] - pdp->mnx) * pdp->scx + 0.5);
- cy = (int)(( yp[i] - pdp->mny) * pdp->scy + 0.5);
+ cx = (int)((p->x1[i] - p->mnx) * p->scx + 0.5);
+ cy = (int)(( yp[i] - p->mny) * p->scy + 0.5);
- MoveToEx(hdc, 10 + lx, pdp->sh - 10 - ly, NULL);
- LineTo(hdc, 10 + cx, pdp->sh - 10 - cy);
-#ifdef CROSSES
- MoveToEx(hdc, 10 + cx - 5, pdp->sh - 10 - cy - 5, NULL);
- LineTo(hdc, 10 + cx + 5, pdp->sh - 10 - cy + 5);
- GrLine(10 + cx + 5, pdp->sh - 10 - cy - 5);
- LineTo(hdc, 10 + cx - 5, pdp->sh - 10 - cy + 5);
-#endif
+ MoveToEx(hdc, 10 + lx, p->sh - 10 - ly, NULL);
+ LineTo(hdc, 10 + cx, p->sh - 10 - cy);
+ if (p->flags & PLOTF_GRAPHCROSSES) {
+ MoveToEx(hdc, 10 + cx - 5, p->sh - 10 - cy - 5, NULL);
+ LineTo(hdc, 10 + cx + 5, p->sh - 10 - cy + 5);
+ LineTo(hdc, 10 + cx - 5, p->sh - 10 - cy + 5);
+ }
lx = cx;
ly = cy;
}
@@ -1106,7 +1118,7 @@ plot_info *pdp
pen = CreatePen(PS_SOLID,ILTHICK,RGB(0,0,0));
SelectObject(hdc,pen);
- if (pdp->ntext != NULL) {
+ if (p->ntext != NULL) {
HFONT fon;
fon = CreateFont(12, 0, 0, 0, FW_LIGHT, FALSE, FALSE, FALSE, ANSI_CHARSET,
@@ -1121,41 +1133,43 @@ plot_info *pdp
}
}
- for (i = 0; i < pdp->n; i++) {
+ for (i = 0; i < p->n; i++) {
int cx,cy;
- lx = (int)((pdp->x1[i] - pdp->mnx) * pdp->scx + 0.5);
- ly = (int)((pdp->yy[0][i] - pdp->mny) * pdp->scy + 0.5);
+ lx = (int)((p->x1[i] - p->mnx) * p->scx + 0.5);
+ ly = (int)((p->yy[0][i] - p->mny) * p->scy + 0.5);
- cx = (int)((pdp->x2[i] - pdp->mnx) * pdp->scx + 0.5);
- cy = (int)((pdp->yy[1][i] - pdp->mny) * pdp->scy + 0.5);
+ cx = (int)((p->x2[i] - p->mnx) * p->scx + 0.5);
+ cy = (int)((p->yy[1][i] - p->mny) * p->scy + 0.5);
- MoveToEx(hdc, 10 + lx, pdp->sh - 10 - ly, NULL);
- LineTo(hdc, 10 + cx, pdp->sh - 10 - cy);
+ MoveToEx(hdc, 10 + lx, p->sh - 10 - ly, NULL);
+ LineTo(hdc, 10 + cx, p->sh - 10 - cy);
- MoveToEx(hdc, 10 + cx - 5, pdp->sh - 10 - cy - 5, NULL);
- LineTo(hdc, 10 + cx + 5, pdp->sh - 10 - cy + 5);
- MoveToEx(hdc, 10 + cx + 5, pdp->sh - 10 - cy - 5, NULL);
- LineTo(hdc, 10 + cx - 5, pdp->sh - 10 - cy + 5);
+ if (p->flags & PLOTF_VECCROSSES) {
+ MoveToEx(hdc, 10 + cx - 5, p->sh - 10 - cy - 5, NULL);
+ LineTo(hdc, 10 + cx + 5, p->sh - 10 - cy + 5);
+ MoveToEx(hdc, 10 + cx + 5, p->sh - 10 - cy - 5, NULL);
+ LineTo(hdc, 10 + cx - 5, p->sh - 10 - cy + 5);
+ }
- if (pdp->ntext != NULL) {
+ if (p->ntext != NULL) {
RECT rct;
rct.right =
rct.left = 10 + cx + 10;
rct.top =
- rct.bottom = pdp->sh - 10 - cy + 10;
- DrawText(hdc, pdp->ntext[i], -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
+ rct.bottom = p->sh - 10 - cy + 10;
+ DrawText(hdc, p->ntext[i], -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
}
}
DeleteObject(pen);
}
/* Extra points */
- if (pdp->x7 != NULL && pdp->y7 != NULL && pdp->m > 0 ) {
+ if (p->x7 != NULL && p->y7 != NULL && p->m > 0 ) {
pen = CreatePen(PS_SOLID,ILTHICK,RGB(210,150,0));
SelectObject(hdc,pen);
- if (pdp->mtext != NULL) {
+ if (p->mtext != NULL) {
HFONT fon;
@@ -1171,68 +1185,68 @@ plot_info *pdp
}
}
- for (i = 0; i < pdp->m; i++) {
- lx = (int)((pdp->x7[i] - pdp->mnx) * pdp->scx + 0.5);
- ly = (int)((pdp->y7[i] - pdp->mny) * pdp->scy + 0.5);
+ for (i = 0; i < p->m; i++) {
+ lx = (int)((p->x7[i] - p->mnx) * p->scx + 0.5);
+ ly = (int)((p->y7[i] - p->mny) * p->scy + 0.5);
- if (pdp->mcols != NULL) {
+ if (p->mcols != NULL) {
int rgb[3];
for (j = 0; j < 3; j++)
- rgb[j] = (int)(pdp->mcols[i].rgb[j] * 255.0 + 0.5);
+ rgb[j] = (int)(p->mcols[i].rgb[j] * 255.0 + 0.5);
DeleteObject(pen);
pen = CreatePen(PS_SOLID,ILTHICK,RGB(rgb[0],rgb[1],rgb[2]));
SelectObject(hdc,pen);
- if (pdp->mtext != NULL)
+ if (p->mtext != NULL)
SetTextColor(hdc, RGB(rgb[0],rgb[1],rgb[2]));
}
- MoveToEx(hdc, 10 + lx - 5, pdp->sh - 10 - ly, NULL);
- LineTo(hdc, 10 + lx + 5, pdp->sh - 10 - ly);
- MoveToEx(hdc, 10 + lx, pdp->sh - 10 - ly - 5, NULL);
- LineTo(hdc, 10 + lx, pdp->sh - 10 - ly + 5);
+ MoveToEx(hdc, 10 + lx - 5, p->sh - 10 - ly, NULL);
+ LineTo(hdc, 10 + lx + 5, p->sh - 10 - ly);
+ MoveToEx(hdc, 10 + lx, p->sh - 10 - ly - 5, NULL);
+ LineTo(hdc, 10 + lx, p->sh - 10 - ly + 5);
- if (pdp->mtext != NULL) {
+ if (p->mtext != NULL) {
RECT rct;
rct.right =
rct.left = 10 + lx + 10;
rct.top =
- rct.bottom = pdp->sh - 10 - ly - 10;
- DrawText(hdc, pdp->mtext[i], -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
+ rct.bottom = p->sh - 10 - ly - 10;
+ DrawText(hdc, p->mtext[i], -1, &rct, DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOCLIP);
}
}
DeleteObject(pen);
}
/* Extra vectors */
- if (pdp->x8 != NULL && pdp->y8 != NULL && pdp->x9 != NULL && pdp->y9 && pdp->o > 0 ) {
+ if (p->x8 != NULL && p->y8 != NULL && p->x9 != NULL && p->y9 && p->o > 0 ) {
pen = CreatePen(PS_SOLID,ILTHICK,RGB(150,255,255));
SelectObject(hdc,pen);
- for (i = 0; i < pdp->o; i++) {
+ for (i = 0; i < p->o; i++) {
int cx,cy;
- lx = (int)((pdp->x8[i] - pdp->mnx) * pdp->scx + 0.5);
- ly = (int)((pdp->y8[i] - pdp->mny) * pdp->scy + 0.5);
+ lx = (int)((p->x8[i] - p->mnx) * p->scx + 0.5);
+ ly = (int)((p->y8[i] - p->mny) * p->scy + 0.5);
- cx = (int)((pdp->x9[i] - pdp->mnx) * pdp->scx + 0.5);
- cy = (int)((pdp->y9[i] - pdp->mny) * pdp->scy + 0.5);
+ cx = (int)((p->x9[i] - p->mnx) * p->scx + 0.5);
+ cy = (int)((p->y9[i] - p->mny) * p->scy + 0.5);
- if (pdp->ocols != NULL) {
+ if (p->ocols != NULL) {
int rgb[3];
for (j = 0; j < 3; j++)
- rgb[j] = (int)(pdp->ocols[i].rgb[j] * 255.0 + 0.5);
+ rgb[j] = (int)(p->ocols[i].rgb[j] * 255.0 + 0.5);
DeleteObject(pen);
pen = CreatePen(PS_SOLID,ILTHICK,RGB(rgb[0],rgb[1],rgb[2]));
SelectObject(hdc,pen);
- if (pdp->mtext != NULL)
+ if (p->mtext != NULL)
SetTextColor(hdc, RGB(rgb[0],rgb[1],rgb[2]));
}
- MoveToEx(hdc, 10 + lx, pdp->sh - 10 - ly, NULL);
- LineTo(hdc, 10 + cx, pdp->sh - 10 - cy);
+ MoveToEx(hdc, 10 + lx, p->sh - 10 - ly, NULL);
+ LineTo(hdc, 10 + cx, p->sh - 10 - cy);
}
DeleteObject(pen);
}
@@ -1393,13 +1407,15 @@ static void create_my_win(cntx_t *cx) {
/* return 0 on success, -1 on error */
/* Hybrid Graph uses x1 : y1, y2, y3, y4, y5, y6 for up to 6 graph curves + */
/* optional diagonal crosses at x7, y7 in yellow (x2 == NULL). */
-/* Vector uses x1, y1 to x2, y2 as a vector with a diagonal cross at x2, y2 all in black, */
-/* with annotation ntext at the cross, */
-/* plus a diagonal cross at x7, y7 in yellow. The color for x7, y7 can be overidden by an */
-/* array of colors mcols, and augmented by optional label text mtext. (x2 != NULL) */
+/* Vector uses x1, y1 to x2, y2 as a vector with a (optional) diagonal cross at x2, y2 */
+/* all in black with annotation ntext at the cross, */
+/* plus a (optiona) diagonal cross at x7, y7 in yellow. The color for x7, y7 can be */
+/* overidden by an array of colors mcols, plus optional label text mtext. (x2 != NULL) */
/* n = number of points/vectors. -ve for reversed X axis */
/* m = number of extra points (x2,y3 or x7,y7) */
+/* x8,y8 to x9,y9 are extra optional vectors with optional colors */
static int do_plot_imp(
+ int flags,
double xmin, double xmax, double ymin, double ymax, /* Bounding box */
double ratio, /* Aspect ratio of window, X/Y */
int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
@@ -1416,6 +1432,7 @@ static int do_plot_imp(
int j;
double xr,yr;
+ pd.flags = flags;
pd.dowait = dowait;
pd.ratio = ratio;
@@ -1736,10 +1753,10 @@ static void DoPlot(NSRect *rect, plot_info *pdp) {
cy = (int)(( yp[i] - pdp->mny) * pdp->scy + 0.5);
ADrawLine(path, 20.0 + lx, 20.0 + ly, 20 + cx, 20.0 + cy);
-#ifdef CROSSES
- ADrawLine(path, 20.0 + cx - 5, 20.0 - cy - 5, 20.0 + cx + 5, 20.0 + cy + 5);
- ADrawLine(path, 20.0 + cx + 5, 20.0 - cy - 5, 20.0 + cx - 5, 20.0 + cy + 5);
-#endif
+ if (pdp->flags & PLOTF_GRAPHCROSSES) {
+ ADrawLine(path, 20.0 + cx - 5, 20.0 - cy - 5, 20.0 + cx + 5, 20.0 + cy + 5);
+ ADrawLine(path, 20.0 + cx + 5, 20.0 - cy - 5, 20.0 + cx - 5, 20.0 + cy + 5);
+ }
lx = cx;
ly = cy;
}
@@ -1767,8 +1784,10 @@ static void DoPlot(NSRect *rect, plot_info *pdp) {
ADrawLine(path, 20.0 + lx, 20.0 + ly, 20.0 + cx, 20.0 + cy);
- ADrawLine(path, 20.0 + cx - 5, 20.0 + cy - 5, 20.0 + cx + 5, 20.0 + cy + 5);
- ADrawLine(path, 20.0 + cx + 5, 20.0 + cy - 5, 20.0 + cx - 5, 20.0 + cy + 5);
+ if (pdp->flags & PLOTF_VECCROSSES) {
+ ADrawLine(path, 20.0 + cx - 5, 20.0 + cy - 5, 20.0 + cx + 5, 20.0 + cy + 5);
+ ADrawLine(path, 20.0 + cx + 5, 20.0 + cy - 5, 20.0 + cx - 5, 20.0 + cy + 5);
+ }
if (pdp->ntext != NULL)
ADrawText(tcol, 9.0, 20.0 + cx + 9, 20.0 + cy - 7, 0x1, pdp->ntext[i]);
@@ -1863,13 +1882,15 @@ void DoPlot(Display *mydisplay, Window mywindow, GC mygc, plot_info *pdp);
/* return 0 on success, -1 on error */
/* Hybrid Graph uses x1 : y1, y2, y3, y4, y5, y6 for up to 6 graph curves + */
/* optional diagonal crosses at x7, y7 in yellow (x2 == NULL). */
-/* Vector uses x1, y1 to x2, y2 as a vector with a diagonal cross at x2, y2 all in black, */
-/* with annotation ntext at the cross, */
-/* plus a diagonal cross at x7, y7 in yellow. The color for x7, y7 can be overidden by an */
-/* array of colors mcols, and augmented by optional label text mtext. (x2 != NULL) */
+/* Vector uses x1, y1 to x2, y2 as a vector with a (optional) diagonal cross at x2, y2 */
+/* all in black with annotation ntext at the cross, */
+/* plus a (optiona) diagonal cross at x7, y7 in yellow. The color for x7, y7 can be */
+/* overidden by an array of colors mcols, plus optional label text mtext. (x2 != NULL) */
/* n = number of points/vectors. -ve for reversed X axis */
/* m = number of extra points (x2,y3 or x7,y7) */
+/* x8,y8 to x9,y9 are extra optional vectors with optional colors */
static int do_plot_imp(
+ int flags,
double xmin, double xmax, double ymin, double ymax, /* Bounding box */
double ratio, /* Aspect ratio of window, X/Y */
int dowait, /* > 0 wait for user to hit space key, < 0 delat dowait seconds. */
@@ -1885,6 +1906,7 @@ static int do_plot_imp(
int j;
double xr,yr;
+ pd.flags = flags;
pd.dowait = dowait;
pd.ratio = ratio;
@@ -2174,11 +2196,10 @@ plot_info *pdp
cy = (int)(( yp[i] - pdp->mny) * pdp->scy + 0.5);
XDrawLine(mydisplay, mywindow, mygc, 10 + lx, pdp->sh - 10 - ly, 10 + cx, pdp->sh - 10 - cy);
-#ifdef CROSSES
-
- XDrawLine(mydisplay, mywindow, mygc, 10 + cx - 5, pdp->sh - 10 - cy - 5, 10 + cx + 5, pdp->sh - 10 - cy + 5);
- XDrawLine(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy - 5, 10 + cx - 5, pdp->sh - 10 - cy + 5);
-#endif
+ if (pdp->flags & PLOTF_GRAPHCROSSES) {
+ XDrawLine(mydisplay, mywindow, mygc, 10 + cx - 5, pdp->sh - 10 - cy - 5, 10 + cx + 5, pdp->sh - 10 - cy + 5);
+ XDrawLine(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy - 5, 10 + cx - 5, pdp->sh - 10 - cy + 5);
+ }
lx = cx;
ly = cy;
}
@@ -2200,10 +2221,14 @@ plot_info *pdp
cx = (int)((pdp->x2[i] - pdp->mnx) * pdp->scx + 0.5);
cy = (int)((pdp->yy[1][i] - pdp->mny) * pdp->scy + 0.5);
+ /* Vector */
XDrawLine(mydisplay, mywindow, mygc, 10 + lx, pdp->sh - 10 - ly, 10 + cx, pdp->sh - 10 - cy);
- XDrawLine(mydisplay, mywindow, mygc, 10 + cx - 5, pdp->sh - 10 - cy - 5, 10 + cx + 5, pdp->sh - 10 - cy + 5);
- XDrawLine(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy - 5, 10 + cx - 5, pdp->sh - 10 - cy + 5);
+ if (pdp->flags & PLOTF_VECCROSSES) {
+ /* Cross at end of vector */
+ XDrawLine(mydisplay, mywindow, mygc, 10 + cx - 5, pdp->sh - 10 - cy - 5, 10 + cx + 5, pdp->sh - 10 - cy + 5);
+ XDrawLine(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy - 5, 10 + cx - 5, pdp->sh - 10 - cy + 5);
+ }
if (pdp->ntext != NULL)
XDrawImageString(mydisplay, mywindow, mygc, 10 + cx + 5, pdp->sh - 10 - cy + 7,
diff --git a/profile/F1.sp b/profile/F1.sp
new file mode 100644
index 0000000..908cd72
--- /dev/null
+++ b/profile/F1.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F1 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.87 2.36 2.94 3.47 5.17 19.49 6.13 6.24 7.01 7.79 8.56 43.67 16.94 10.72 11.35 11.89 12.37 12.75 13.00 13.15 13.23 13.17 13.13 12.85 12.52 12.20 11.83 11.50 11.22 11.05 11.03 11.18 11.53 27.74 17.05 13.55 14.33 15.01 15.52 18.29 19.55 15.48 14.91 14.15 13.22 12.19 11.12 10.03 8.95 7.96 7.02 6.20 5.42 4.73 4.15 3.64 3.20 2.81 2.47 2.18 1.93 1.72 1.67 1.43 1.29 1.19 1.08 0.96 0.88 0.81 0.77 0.75 0.73 0.68 0.69 0.64 0.68 0.69 0.61 0.52 0.43
+END_DATA
diff --git a/profile/F5.sp b/profile/F5.sp
new file mode 100644
index 0000000..4959a50
--- /dev/null
+++ b/profile/F5.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F5 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.87 2.35 2.92 3.45 5.10 18.91 6.00 6.11 6.85 7.58 8.31 40.76 16.06 10.32 10.91 11.40 11.83 12.17 12.40 12.54 12.58 12.52 12.47 12.20 11.89 11.61 11.33 11.10 10.96 10.97 11.16 11.54 12.12 27.78 17.73 14.47 15.20 15.77 16.10 18.54 19.50 15.39 14.64 13.72 12.69 11.57 10.45 9.35 8.29 7.32 6.41 5.63 4.90 4.26 3.72 3.25 2.83 2.49 2.19 1.93 1.71 1.52 1.43 1.26 1.13 1.05 0.96 0.85 0.78 0.72 0.68 0.67 0.65 0.61 0.62 0.59 0.62 0.64 0.55 0.47 0.40
+END_DATA
diff --git a/profile/F8.sp b/profile/F8.sp
new file mode 100644
index 0000000..f1e7beb
--- /dev/null
+++ b/profile/F8.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F8 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.21 1.50 1.81 2.13 3.17 13.08 3.83 3.45 3.86 4.42 5.09 34.10 12.42 7.68 8.60 9.46 10.24 10.84 11.33 11.71 11.98 12.17 12.28 12.32 12.35 12.44 12.55 12.68 12.77 12.72 12.60 12.43 12.22 28.96 16.51 11.79 11.76 11.77 11.84 14.61 16.11 12.34 12.53 12.72 12.92 13.12 13.34 13.61 13.87 14.07 14.20 14.16 14.13 14.34 14.50 14.46 14.00 12.58 10.99 9.98 9.22 8.62 8.07 7.39 6.71 6.16 5.63 5.03 4.46 4.02 3.66 3.36 3.09 2.85 2.65 2.51 2.37 2.15 1.89 1.61 1.32
+END_DATA
diff --git a/profile/Jamfile b/profile/Jamfile
index 780f9a5..5c286b9 100644
--- a/profile/Jamfile
+++ b/profile/Jamfile
@@ -7,11 +7,11 @@ PREF_LINKFLAGS += $(LINKDEBUGFLAG) ;
#Products
Libraries = libprof ;
Executables = cb2ti3 kodak2ti3 txt2ti3 splitti3 mppcheck mppprof
- profcheck invprofcheck verify colprof printcal applycal ;
+ profcheck invprofcheck colverify colprof printcal applycal ;
Headers = prof.h ;
Samples = example.sp example121.sp 3dap5k.sp GTIPlus.sp Office.sp Trulux.sp TruluxPlus.sp
D50_0.0.sp D50_0.1.sp D50_0.3.sp D50_0.5.sp D50_0.7.sp D50_1.0.sp D50_1.2.sp
- D50_1.5.sp D50_1.7.sp D50_2.0.sp D50_2.5.sp D50_3.0.sp CIE_C.sp ;
+ D50_1.5.sp D50_1.7.sp D50_2.0.sp D50_2.5.sp D50_3.0.sp CIE_C.sp F1.sp F5.sp F8.sp ;
#Install
InstallBin $(DESTDIR)$(PREFIX)/bin : $(Executables) ;
@@ -63,7 +63,7 @@ Main mppcheck : mppcheck.c ;
LINKLIBS = ../plot/libvrml $(LINKLIBS) ;
# Verifyer
-Main verify : verify.c ;
+Main colverify : colverify.c ;
LINKLIBS = libprof ../gamut/libgammap $(LINKLIBS) $(TIFFLIB) $(JPEGLIB) ;
diff --git a/profile/afiles b/profile/afiles
index 986bf70..8b3b980 100644
--- a/profile/afiles
+++ b/profile/afiles
@@ -9,7 +9,7 @@ profout.c
colprof.c
profcheck.c
invprofcheck.c
-verify.c
+colverify.c
applycal.c
mppprof.c
mppcheck.c
@@ -25,6 +25,9 @@ Trulux.sp
TruluxPlus.sp
example.sp
example121.sp
+F1.sp
+F5.sp
+F8.sp
CIE_C.sp
D50_0.0.sp
D50_0.1.sp
diff --git a/profile/colprof.c b/profile/colprof.c
index 99e02cf..b80f13c 100644
--- a/profile/colprof.c
+++ b/profile/colprof.c
@@ -59,13 +59,15 @@
#define DEFAVGDEV 0.5 /* Default average deviation percentage */
/* This equates to a uniform added error of +/- 1% */
+#define DEMPH_DEFAULT 1.0 /* Default dark region emphasis == none */
+
/*
Flags used:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
upper . .. . ... .. .... .
- lower .... .. . .. ......... .
+ lower .... .. . .. .........
*/
@@ -94,7 +96,6 @@ void usage(char *diag, ...) {
// fprintf(stderr," -q fmsu Speed - Fast, Medium (def), Slow, Ultra Slow\n");
fprintf(stderr," -b [lmhun] Low quality B2A table - or specific B2A quality or none for input device\n");
// fprintf(stderr," -b [fmsun] B2A Speed - Fast, Medium, Slow, Ultra Slow, None, same as -q (def)\n");
- fprintf(stderr," -y Verify A2B profile\n");
fprintf(stderr," -ni Don't create input (Device) shaper curves\n");
fprintf(stderr," -np Don't create input (Device) grid position curves\n");
fprintf(stderr," -no Don't create output (PCS) shaper curves\n");
@@ -121,6 +122,7 @@ void usage(char *diag, ...) {
fprintf(stderr," -uc If input profile, clip cLUT values above WP\n");
fprintf(stderr," -U scale If input profile, scale media white point by scale\n");
fprintf(stderr," -R Restrict white <= 1.0, black and primaries to be +ve\n");
+ fprintf(stderr," -V demphasis Degree of dark region cLUT grid emphasis 1.0-4.0 (default %.2f = none)\n",DEMPH_DEFAULT);
fprintf(stderr," -f [illum] Use Fluorescent Whitening Agent compensation [opt. simulated inst. illum.:\n");
fprintf(stderr," M0, M1, M2, A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp]\n");
fprintf(stderr," -i illum Choose illuminant for computation of CIE XYZ from spectral data & FWA:\n");
@@ -172,7 +174,7 @@ int main(int argc, char *argv[]) {
int verb = 0;
int iquality = 1; /* A2B quality */
int oquality = -1; /* B2A quality same as A2B */
- int verify = 0;
+ int verify = 0; /* Not used anymore */
int noisluts = 0; /* No input shaper luts */
int noipluts = 0; /* No input position luts */
int nooluts = 0; /* No output shaper luts */
@@ -183,6 +185,7 @@ int main(int argc, char *argv[]) {
int autowpsc = 0; /* Auto scale the WP to prevent clipping above WP patch */
int clipovwp = 0; /* Clip cLUT values above WP */
int clipprims = 0; /* Clip white, black and primaries */
+ double demph = 0.0; /* Emphasise dark region grid resolution in cLUT */
double iwpscale = -1.0; /* Input white point scale factor */
int doinextrap = 1; /* Sythesize extra sample points for input device cLUT */
int doinb2a = 1; /* Create an input device B2A table */
@@ -238,7 +241,8 @@ int main(int argc, char *argv[]) {
ivc_p.Yb = -1.0;
ivc_p.Lv = -1.0;
ivc_p.Yf = -1.0;
- ivc_p.Fxyz[0] = -1.0; ivc_p.Fxyz[1] = -1.0; ivc_p.Fxyz[2] = -1.0;
+ ivc_p.Yg = -1.0;
+ ivc_p.Gxyz[0] = -1.0; ivc_p.Gxyz[1] = -1.0; ivc_p.Gxyz[2] = -1.0;
ovc_p.Ev = -1;
ovc_p.Wxyz[0] = -1.0; ovc_p.Wxyz[1] = -1.0; ovc_p.Wxyz[2] = -1.0;
@@ -246,7 +250,8 @@ int main(int argc, char *argv[]) {
ovc_p.Yb = -1.0;
ovc_p.Lv = -1.0;
ovc_p.Yf = -1.0;
- ovc_p.Fxyz[0] = -1.0; ovc_p.Fxyz[1] = -1.0; ovc_p.Fxyz[2] = -1.0;
+ ovc_p.Yg = -1.0;
+ ovc_p.Gxyz[0] = -1.0; ovc_p.Gxyz[1] = -1.0; ovc_p.Gxyz[2] = -1.0;
xicc_enum_gmapintent(&pgmi, icxPerceptualGMIntent, NULL);
xicc_enum_gmapintent(&sgmi, icxSaturationGMIntent, NULL);
@@ -276,7 +281,7 @@ int main(int argc, char *argv[]) {
if (argv[fa][1] == '?')
usage("Usage requested");
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
+ else if (argv[fa][1] == 'v')
verb = 1;
/* Manufacturer description string */
@@ -361,7 +366,7 @@ int main(int argc, char *argv[]) {
}
/* Quality */
- else if (argv[fa][1] == 'q' || argv[fa][1] == 'Q') {
+ else if (argv[fa][1] == 'q') {
fa = nfa;
// if (na == NULL) usage("Expect argument to quality flag -q");
if (na == NULL) usage("Expect argument to speed flag -q");
@@ -428,11 +433,8 @@ int main(int argc, char *argv[]) {
doinb2a = 0;
}
- else if (argv[fa][1] == 'y' || argv[fa][1] == 'Y')
- verify = 1;
-
/* Disable input or output luts */
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
+ else if (argv[fa][1] == 'n') {
fa = nfa;
if (na == NULL) { /* Backwards compatible */
nooluts = 1;
@@ -468,7 +470,7 @@ int main(int argc, char *argv[]) {
fa = nfa;
if (na == NULL) usage("Expected argument to input white point scale flag -U");
iwpscale = atof(na);
- if (iwpscale < 0.0 || iwpscale > 100.0)
+ if (iwpscale < 0.0 || iwpscale > 200.0)
usage("Argument '%s' to flag -U out of range",na);
}
/* Clip primaries */
@@ -476,8 +478,18 @@ int main(int argc, char *argv[]) {
clipprims = 1;
}
+ /* Degree of dark region emphasis */
+ else if (argv[fa][1] == 'V') {
+ if (na == NULL) usage(0,"Expected argument to dark emphasis flag -V");
+ demph = atof(na);
+ if (demph < 1.0 || demph > 3.0)
+ usage("Dark weighting argument %f to '-V' is out of range",demph);
+ fa = nfa;
+ }
+
/* Inking rule */
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
+ else if (argv[fa][1] == 'k'
+ || argv[fa][1] == 'K') {
fa = nfa;
if (na == NULL) usage("Expect argument to inking flag -k");
if (argv[fa][1] == 'k')
@@ -544,7 +556,7 @@ int main(int argc, char *argv[]) {
}
/* Algorithm type */
- else if (argv[fa][1] == 'a' || argv[fa][1] == 'A') {
+ else if (argv[fa][1] == 'a') {
fa = nfa;
if (na == NULL) usage("Expect argument to algorithm flag -a");
switch (na[0]) {
@@ -713,7 +725,8 @@ int main(int argc, char *argv[]) {
}
/* Percetual Source Gamut and Perceptual/Saturation Gamut Maping mode enable */
- else if (argv[fa][1] == 's' || argv[fa][1] == 'S') {
+ else if (argv[fa][1] == 's'
+ || argv[fa][1] == 'S') {
if (argv[fa][1] == 'S')
sepsat = 1;
if (na == NULL)
@@ -724,7 +737,7 @@ int main(int argc, char *argv[]) {
}
/* Source image gamut */
- else if (argv[fa][1] == 'g' || argv[fa][1] == 'G') {
+ else if (argv[fa][1] == 'g') {
if (na == NULL)
usage("Unrecognised argument to source image gamut flag -g",argv[fa][1]);
fa = nfa;
@@ -771,7 +784,8 @@ int main(int argc, char *argv[]) {
}
/* Viewing conditions */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'd') {
+ else if (argv[fa][1] == 'c'
+ || argv[fa][1] == 'd') {
icxViewCond *vc;
if (argv[fa][1] == 'c') {
@@ -781,7 +795,7 @@ int main(int argc, char *argv[]) {
}
fa = nfa;
- if (na == NULL) usage("Viewing conditions flag (-c) needs an argument");
+ if (na == NULL) usage("Viewing conditions flag (-%c) needs an argument",argv[fa][1]);
if (na[1] != ':') {
if (vc == &ivc_p) {
if ((ivc_e = xicc_enum_viewcond(NULL, NULL, -2, na, 1, NULL)) == -999)
@@ -792,7 +806,7 @@ int main(int argc, char *argv[]) {
}
} else if (na[0] == 's' || na[0] == 'S') {
if (na[1] != ':')
- usage("Viewing conditions (-cs) missing ':'");
+ usage("Viewing conditions (-%cs) missing ':'",argv[fa][1]);
if (na[2] == 'n' || na[2] == 'N') {
vc->Ev = vc_none; /* Automatic */
} else if (na[2] == 'a' || na[2] == 'A') {
@@ -804,7 +818,7 @@ int main(int argc, char *argv[]) {
} else if (na[2] == 'c' || na[2] == 'C') {
vc->Ev = vc_cut_sheet;
} else
- usage("Viewing condition (-c) unrecognised surround '%c'",na[2]);
+ usage("Viewing condition (-%c) unrecognised surround '%c'",argv[fa][1],na[2]);
} else if (na[0] == 'w' || na[0] == 'W') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
@@ -812,31 +826,35 @@ int main(int argc, char *argv[]) {
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
vc->Wxyz[0] = x; vc->Wxyz[1] = y;
} else
- usage("Viewing condition (-cw) unrecognised white point '%s'",na+1);
+ usage("Viewing condition (-%cw) unrecognised white point '%s'",argv[fa][1],na+1);
} else if (na[0] == 'a' || na[0] == 'A') {
if (na[1] != ':')
- usage("Viewing conditions (-ca) missing ':'");
+ usage("Viewing conditions (-%ca) missing ':'",argv[fa][1]);
vc->La = atof(na+2);
} else if (na[0] == 'b' || na[0] == 'B') {
if (na[1] != ':')
- usage("Viewing conditions (-cb) missing ':'");
+ usage("Viewing conditions (-%cb) missing ':'",argv[fa][1]);
vc->Yb = atof(na+2)/100.0;
} else if (na[0] == 'l' || na[0] == 'L') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]l) missing ':'");
+ usage("Viewing conditions (-%cl) missing ':'",argv[fa][1]);
vc->Lv = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ if (na[1] != ':')
+ usage("Viewing conditions (-%cf) missing ':'",argv[fa][1]);
+ vc->Yf = atof(na+2);
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc->Fxyz[0] = x; vc->Fxyz[1] = y; vc->Fxyz[2] = z;
+ vc->Gxyz[0] = x; vc->Gxyz[1] = y; vc->Gxyz[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc->Fxyz[0] = x; vc->Fxyz[1] = y;
+ vc->Gxyz[0] = x; vc->Gxyz[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
- vc->Yf = x/100.0;
+ vc->Yg = x/100.0;
} else
- usage("Viewing condition (-cf) unrecognised flare '%s'",na+1);
+ usage("Viewing condition (-%cg) unrecognised flare '%s'",argv[fa][1],na+1);
} else
- usage("Viewing condition (-c) unrecognised sub flag '%c'",na[0]);
+ usage("Viewing condition (-%c) unrecognised sub flag '%c'",argv[fa][1],na[0]);
}
/* Gammut mapping diagnostic plots */
@@ -929,6 +947,18 @@ int main(int argc, char *argv[]) {
error ("Requested spectral interpretation when data not available");
}
+ /* If not set in arguments, set default demph from .ti1 or default none */
+ if (demph == 0.0) {
+ if ((ti = icg->find_kword(icg, 0, "DARK_REGION_EMPHASIS")) >= 0) {
+ demph = atof(icg->t[0].kdata[ti]);
+ demph = pow(demph, 0.7); /* Reduce intensity */
+ if (verb)
+ printf("Dark emphasis factor %f from targen\n",demph);
+ } else {
+ demph = DEMPH_DEFAULT;
+ }
+ }
+
/* read the device class, and call function to create profile. */
if ((ti = icg->find_kword(icg, 0, "DEVICE_CLASS")) < 0)
error ("Input file doesn't contain keyword DEVICE_CLASS");
@@ -1045,9 +1075,9 @@ int main(int argc, char *argv[]) {
make_output_icc(ptype, 0, iccver, verb, iquality, oquality,
noisluts, noipluts, nooluts, nocied, noptop, nostos,
- gamdiag, verify, clipprims, &ink, inname, outname, icg,
+ gamdiag, verify, clipprims, iwpscale, &ink, inname, outname, icg,
spec, tillum, &cust_tillum, illum, &cust_illum, observ, fwacomp,
- smooth, avgdev,
+ smooth, avgdev, 1.0,
ipname[0] != '\000' ? ipname : NULL,
sgname[0] != '\000' ? sgname : NULL,
absnames,
@@ -1083,9 +1113,9 @@ int main(int argc, char *argv[]) {
/* If a source gamut is provided for a Display, then a V2.4.0 profile will be created */
make_output_icc(ptype, mtxtoo, iccver, verb, iquality, oquality,
noisluts, noipluts, nooluts, nocied, noptop, nostos,
- gamdiag, verify, clipprims, NULL, inname, outname, icg,
+ gamdiag, verify, clipprims, iwpscale, NULL, inname, outname, icg,
spec, icxIT_none, NULL, illum, &cust_illum, observ, 0,
- smooth, avgdev,
+ smooth, avgdev, demph,
ipname[0] != '\000' ? ipname : NULL,
sgname[0] != '\000' ? sgname : NULL,
absnames,
diff --git a/profile/verify.c b/profile/colverify.c
index 849d7fc..ba09366 100644
--- a/profile/verify.c
+++ b/profile/colverify.c
@@ -46,9 +46,10 @@ usage(void) {
fprintf(stderr,"Verify CIE values, Version %s\n",ARGYLL_VERSION_STR);
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
fprintf(stderr,"usage: verify [-options] target.ti3 measured.ti3\n");
- fprintf(stderr," -v Verbose - print each patch value\n");
- fprintf(stderr," -n Normalise each files reading to white Y\n");
- fprintf(stderr," -N Normalise each files reading to white XYZ\n");
+ fprintf(stderr," -v [n] Verbose mode, n >= 2 print each value\n");
+ fprintf(stderr," -n Normalise each files reading to its white Y\n");
+ fprintf(stderr," -N Normalise each files reading to its white XYZ\n");
+ fprintf(stderr," -m Normalise each files reading to its white X+Y+Z\n");
fprintf(stderr," -D Use D50 100.0 as L*a*b* white reference\n");
fprintf(stderr," -c Show CIE94 delta E values\n");
fprintf(stderr," -k Show CIEDE2000 delta E values\n");
@@ -62,6 +63,7 @@ usage(void) {
fprintf(stderr," A, C, D50 (def.), D50M2, D65, F5, F8, F10 or file.sp\n");
fprintf(stderr," -o observ Choose CIE Observer for spectral data:\n");
fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2\n");
+ fprintf(stderr," -L profile.%s Skip any first file out of profile gamut patches\n",ICC_FILE_EXT_ND);
fprintf(stderr," -X file.ccmx Apply Colorimeter Correction Matrix to second file\n");
fprintf(stderr," target.ti3 Target (reference) PCS or spectral values.\n");
fprintf(stderr," measured.ti3 Measured (actual) PCS or spectral values\n");
@@ -71,16 +73,22 @@ usage(void) {
/* Patch value type */
typedef struct {
char sid[50]; /* sample id */
+ char loc[100]; /* sample location (empty if none) */
+ int og; /* Out of gamut flag */
+ double xyz[3]; /* XYZ value */
double v[3]; /* Lab value */
double de; /* Delta E */
+ double ixde[3]; /* XYZ Component DE */
+ double ide[3]; /* Lab Component DE */
} pval;
int main(int argc, char *argv[])
{
- int fa,nfa; /* current argument we're looking at */
- int verb = 0;
- int norm = 0; /* 1 = norm to Y, 2 = norm to XYZ */
- int usestdd50 = 0; /* Use standard D50 instead of scaled D50 as Lab reference */
+ int fa,nfa,mfa; /* current argument we're looking at */
+ int verb = 0; /* Verbose level */
+ int norm = 0; /* 1 = norm to White Y, 2 = norm to White XYZ */
+ /* 3 = norm to White X+Y+Z */
+ int usestdd50 = 0; /* Use standard D50 instead of avg white as reference */
int cie94 = 0;
int cie2k = 0;
int dovrml = 0;
@@ -88,12 +96,20 @@ int main(int argc, char *argv[])
int dosort = 0;
char ccmxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
ccmx *cmx = NULL; /* Colorimeter Correction Matrix */
+ char gprofname[MAXNAMEL+1] = "\000"; /* Gamut limit profile name */
+ icmFile *fp = NULL;
+ icc *icco = NULL;
+ xicc *xicco = NULL;
+ icxLuBase *luo = NULL;
struct {
char name[MAXNAMEL+1]; /* Patch filename */
int isdisp; /* nz if display */
int isdnormed; /* Has display data been normalised to 100 ? */
int npat; /* Number of patches */
+ int nig; /* Number of patches in gamut */
+ double w[3]; /* XYZ of "white" */
+ double nw[3]; /* Normalised XYZ of "white" */
pval *pat; /* patch values */
} cg[2]; /* Target and current patch file information */
@@ -123,6 +139,7 @@ int main(int argc, char *argv[])
usage();
/* Process the arguments */
+ mfa = 2; /* Minimum final arguments */
for(fa = 1;fa < argc;fa++) {
nfa = fa; /* skip to nfa if next argument is used */
@@ -132,7 +149,7 @@ int main(int argc, char *argv[])
if (argv[fa][2] != '\000')
na = &argv[fa][2]; /* next is directly after flag */
else {
- if ((fa+1) < argc) {
+ if ((fa+1+mfa) < argc) {
if (argv[fa+1][0] != '-') {
nfa = fa + 1;
na = argv[nfa]; /* next is seperate non-flag argument */
@@ -143,16 +160,28 @@ int main(int argc, char *argv[])
if (argv[fa][1] == '?')
usage();
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
+ /* Verbose */
+ else if (argv[fa][1] == 'v') {
verb = 1;
+ if (na != NULL && na[0] >= '0' && na[0] <= '9') {
+ verb = atoi(na);
+ fa = nfa;
+ }
+ }
+
/* normalize */
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
+ else if (argv[fa][1] == 'n'
+ || argv[fa][1] == 'N') {
norm = 1;
if (argv[fa][1] == 'N')
norm = 2;
}
+ else if (argv[fa][1] == 'm') {
+ norm = 3;
+ }
+
else if (argv[fa][1] == 'D')
usestdd50 = 1;
@@ -167,18 +196,18 @@ int main(int argc, char *argv[])
doaxes = 1;
/* CIE94 delta E */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
+ else if (argv[fa][1] == 'c') {
cie94 = 1;
cie2k = 0;
}
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
+ else if (argv[fa][1] == 'k') {
cie94 = 0;
cie2k = 1;
}
/* Sort */
- else if (argv[fa][1] == 's' || argv[fa][1] == 'S')
+ else if (argv[fa][1] == 's')
dosort = 1;
/* FWA compensation */
@@ -224,7 +253,7 @@ int main(int argc, char *argv[])
}
/* Spectral to CIE Illuminant type */
- else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
+ else if (argv[fa][1] == 'i') {
fa = nfa;
if (na == NULL) usage();
if (strcmp(na, "A") == 0) {
@@ -260,7 +289,7 @@ int main(int argc, char *argv[])
}
/* Spectral Observer type */
- else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
+ else if (argv[fa][1] == 'o') {
fa = nfa;
if (na == NULL) usage();
if (strcmp(na, "1931_2") == 0) { /* Classic 2 degree */
@@ -282,6 +311,13 @@ int main(int argc, char *argv[])
usage();
}
+ /* Gamut limit profile for first file */
+ else if (argv[fa][1] == 'L') {
+ fa = nfa;
+ if (na == NULL) usage();
+ strncpy(gprofname,na,MAXNAMEL-1); gprofname[MAXNAMEL-1] = '\000';
+ }
+
/* Colorimeter Correction Matrix for second file */
else if (argv[fa][1] == 'X') {
fa = nfa;
@@ -313,6 +349,35 @@ int main(int argc, char *argv[])
if (fwacomp && spec == 0)
error ("FWA compensation only works when viewer and/or illuminant selected");
+ /* Gamut limit profile */
+ if (gprofname[0] != '\000') {
+ int rv;
+
+ if ((fp = new_icmFileStd_name(gprofname,"r")) == NULL)
+ error ("Can't open file '%s'",gprofname);
+
+ if ((icco = new_icc()) == NULL)
+ error ("Creation of ICC object failed");
+
+ if ((rv = icco->read(icco,fp,0)) != 0)
+ error("Reading profile '%s' failed failed with error %d:'%s'\n",
+ gprofname, icco->errc, icco->err);
+
+ if (icco->header->deviceClass != icSigInputClass
+ && icco->header->deviceClass != icSigDisplayClass
+ && icco->header->deviceClass != icSigOutputClass)
+ error("Profile '%s' must be a device profile to filter by gamut",gprofname);
+
+ /* Wrap with an expanded icc */
+ if ((xicco = new_xicc(icco)) == NULL)
+ error ("Creation of xicc failed");
+
+ /* Get a expanded color conversion object */
+ if ((luo = xicco->get_luobj(xicco, ICX_CLIP_NEAREST | ICX_FAST_SETUP,
+ icmFwd, icRelativeColorimetric, icSigXYZData, icmLuOrdNorm, NULL, NULL)) == NULL)
+ error ("%d, %s",xicco->errc, xicco->err);
+ }
+
/* Colorimeter Correction Matrix */
if (ccmxname[0] != '\000') {
if ((cmx = new_ccmx()) == NULL)
@@ -322,12 +387,14 @@ int main(int argc, char *argv[])
ccmxname, cmx->errc, cmx->err);
}
+
/* Open up each file in turn, target then measured, */
/* and read in the CIE values. */
for (n = 0; n < 2; n++) {
cgats *cgf = NULL; /* cgats file data */
int isLab = 0; /* 0 if file CIE is XYZ, 1 if is Lab */
int sidx; /* Sample ID index */
+ int sldx = -1; /* Sample location index, < 0 if invalid */
int xix, yix, zix;
/* Open CIE target values */
@@ -361,29 +428,41 @@ int main(int argc, char *argv[])
if (!spec && cgf->find_field(cgf, 0, "LAB_L") >= 0)
isLab = 1;
- cg[n].npat = cgf->t[0].nsets; /* Number of patches */
+ cg[n].nig = cg[n].npat = cgf->t[0].nsets; /* Number of patches */
/* Figure out what sort of device it is */
{
int ti;
cg[n].isdisp = 0;
+ cg[n].isdnormed = 0;
+ cg[n].w[0] = cg[n].w[1] = cg[n].w[2] = 0.0;
if ((ti = cgf->find_kword(cgf, 0, "DEVICE_CLASS")) < 0)
error ("Input file '%s' doesn't contain keyword DEVICE_CLASS",cg[n].name);
if (strcmp(cgf->t[0].kdata[ti],"DISPLAY") == 0) {
cg[n].isdisp = 1;
+ cg[n].isdnormed = 1; /* Assume display type is normalised to 100 */
illum = icxIT_none; /* Displays are assumed to be self luminous */
/* ?? What if two files are different ?? */
}
- /* See if the CIE data has been normalised to Y = 100 */
- if ((ti = cgf->find_kword(cgf, 0, "NORMALIZED_TO_Y_100")) < 0
- || strcmp(cgf->t[0].kdata[ti],"NO") == 0) {
- cg[n].isdnormed = 0;
- } else {
- cg[n].isdnormed = 1;
+ if (cg[n].isdisp) {
+
+ if ((ti = cgf->find_kword(cgf, 0, "LUMINANCE_XYZ_CDM2")) >= 0) {
+ if (sscanf(cgf->t[0].kdata[ti], " %lf %lf %lf ",&cg[n].w[0], &cg[n].w[1], &cg[n].w[2]) != 3)
+ cg[n].w[0] = cg[n].w[1] = cg[n].w[2] = 0.0;
+ }
+
+ /* See if there is an explicit tag indicating data has been normalised to Y = 100 */
+ if ((ti = cgf->find_kword(cgf, 0, "NORMALIZED_TO_Y_100")) >= 0) {
+ if (strcmp(cgf->t[0].kdata[ti],"NO") == 0) {
+ cg[n].isdnormed = 0;
+ } else {
+ cg[n].isdnormed = 1;
+ }
+ }
}
}
@@ -410,6 +489,10 @@ int main(int argc, char *argv[])
&& cgf->t[0].ftype[sidx] != cs_t)
error("Sample ID/Name field isn't a quoted or non quoted character string");
+ if ((sldx = cgf->find_field(cgf, 0, "SAMPLE_LOC")) < 0
+ || cgf->t[0].ftype[sldx] != cs_t)
+ sldx = -1;
+
if (spec == 0) { /* Using instrument tristimulous value */
if (isLab) { /* Expect Lab */
@@ -443,24 +526,39 @@ int main(int argc, char *argv[])
for (i = 0; i < cg[n].npat; i++) {
strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
- cg[n].pat[i].v[0] = *((double *)cgf->t[0].fdata[i][xix]);
- cg[n].pat[i].v[1] = *((double *)cgf->t[0].fdata[i][yix]);
- cg[n].pat[i].v[2] = *((double *)cgf->t[0].fdata[i][zix]);
-
- if (!isLab) { /* If XYZ */
-
- /* If normalised to 100, scale back to 1.0 */
- if (!cg[n].isdisp || !cg[n].isdnormed) {
- cg[n].pat[i].v[0] /= 100.0; /* scale back to 1.0 */
- cg[n].pat[i].v[1] /= 100.0;
- cg[n].pat[i].v[2] /= 100.0;
+ if (sldx >= 0)
+ strcpy(cg[n].pat[i].loc, (char *)cgf->t[0].fdata[i][sldx]);
+ else
+ cg[n].pat[i].loc[0] = '\000';
+ cg[n].pat[i].og = 0;
+ cg[n].pat[i].xyz[0] = *((double *)cgf->t[0].fdata[i][xix]);
+ cg[n].pat[i].xyz[1] = *((double *)cgf->t[0].fdata[i][yix]);
+ cg[n].pat[i].xyz[2] = *((double *)cgf->t[0].fdata[i][zix]);
+
+ if (isLab) { /* Convert to XYZ */
+ icmLab2XYZ(&icmD50, cg[n].pat[i].xyz, cg[n].pat[i].xyz);
+ }
+//printf("~1 file %d patch %d = XYZ %f %f %f\n", n,i,cg[n].pat[i].xyz[0],cg[n].pat[i].xyz[1],cg[n].pat[i].xyz[2]);
+
+ /* restore normalised display values to absolute */
+ if (cg[n].isdnormed) {
+ if (cg[n].w[1] > 0.0) {
+ cg[n].pat[i].xyz[0] *= cg[n].w[1]/100.0;
+ cg[n].pat[i].xyz[1] *= cg[n].w[1]/100.0;
+ cg[n].pat[i].xyz[2] *= cg[n].w[1]/100.0;
}
- } else { /* If Lab */
- icmLab2XYZ(&icmD50, cg[n].pat[i].v, cg[n].pat[i].v);
+
+ } else if (!cg[n].isdisp) {
+ /* If reflective or transmissive that are 0..100%, */
+ /* scale back to 0.. 1 */
+ cg[n].pat[i].xyz[0] /= 100.0; /* scale back to XYZ 1.0 */
+ cg[n].pat[i].xyz[1] /= 100.0;
+ cg[n].pat[i].xyz[2] /= 100.0;
}
+
/* Apply ccmx */
if (n == 1 && cmx != NULL) {
- cmx->xform(cmx, cg[n].pat[i].v, cg[n].pat[i].v);
+ cmx->xform(cmx, cg[n].pat[i].xyz, cg[n].pat[i].xyz);
}
}
@@ -563,6 +661,11 @@ int main(int argc, char *argv[])
for (i = 0; i < cg[0].npat; i++) {
strcpy(cg[n].pat[i].sid, (char *)cgf->t[0].fdata[i][sidx]);
+ if (sldx >= 0)
+ strcpy(cg[n].pat[i].loc, (char *)cgf->t[0].fdata[i][sldx]);
+ else
+ cg[n].pat[i].loc[0] = '\000';
+ cg[n].pat[i].og = 0;
/* Read the spectral values for this patch */
for (j = 0; j < sp.spec_n; j++) {
@@ -570,11 +673,21 @@ int main(int argc, char *argv[])
}
/* Convert it to XYZ space */
- sp2cie->convert(sp2cie, cg[n].pat[i].v, &sp);
+ sp2cie->convert(sp2cie, cg[n].pat[i].xyz, &sp);
+
+ /* restore normalised display values to absolute */
+ if (cg[n].isdnormed) {
+ if (cg[n].w[1] > 0.0) {
+ cg[n].pat[i].xyz[0] *= cg[n].w[1];
+ cg[n].pat[i].xyz[1] *= cg[n].w[1];
+ cg[n].pat[i].xyz[2] *= cg[n].w[1];
+ }
- /* Applu ccmx */
+ }
+
+ /* Apply ccmx */
if (n == 1 && cmx != NULL) {
- cmx->xform(cmx, cg[n].pat[i].v, cg[n].pat[i].v);
+ cmx->xform(cmx, cg[n].pat[i].xyz, cg[n].pat[i].xyz);
}
}
@@ -583,31 +696,68 @@ int main(int argc, char *argv[])
} /* End of reading in CGATs file */
- /* Normalise this file to white = 1.0 or D50 */
+ /* Locate the patch with maximum Y, a possible white patch */
if (norm) {
- double bxyz[3] = { 0.0, -100.0, 0.0 };
+ int ii;
- /* Locate patch with biggest Y */
- for (i = 0; i < cg[n].npat; i++) {
- double xyz[3];
- icmLab2XYZ(&icmD50, xyz, cg[n].pat[i].v);
- if (cg[n].pat[i].v[1] > bxyz[1]) {
- icmCpy3(bxyz, cg[n].pat[i].v);
+ if (cg[n].w[1] == 0.0) { /* No white patch */
+
+ /* Locate patch with biggest Y, assume it is white... */
+ for (i = 0; i < cg[n].npat; i++) {
+ if (cg[n].pat[i].xyz[1] > cg[n].w[1]) {
+ icmCpy3(cg[n].w, cg[n].pat[i].xyz);
+ ii = i;
+ }
}
+ if (verb) printf("File %d Chose patch %d as white, xyz %f %f %f\n",
+ n, ii+1,cg[n].w[0],cg[n].w[1],cg[n].w[2]);
+ } else {
+ if (verb) printf("File %d White is from display luminance ref. xyz %f %f %f\n",
+ n, cg[n].w[0],cg[n].w[1],cg[n].w[2]);
+ }
+ icmCpy3(cg[n].nw, cg[n].w);
+ }
+
+
+ /* Normalise this file to white = 1.0 or D50 */
+ if (norm) {
+ int ii;
+
+ double chmat[3][3]; /* Chromatic adapation matrix */
+
+ if (norm == 2) { /* Norm to white XYZ */
+ icmXYZNumber s_wp;
+ icmAry2XYZ(s_wp, cg[n].w);
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, s_wp, chmat);
}
- /* Then normalize all the values */
for (i = 0; i < cg[n].npat; i++) {
if (norm == 1) {
- cg[n].pat[i].v[0] /= bxyz[1];
- cg[n].pat[i].v[1] /= bxyz[1];
- cg[n].pat[i].v[2] /= bxyz[1];
+ cg[n].pat[i].xyz[0] *= 100.0 / cg[n].w[1];
+ cg[n].pat[i].xyz[1] *= 100.0 / cg[n].w[1];
+ cg[n].pat[i].xyz[2] *= 100.0 / cg[n].w[1];
+ } else if (norm == 2) {
+ icmMulBy3x3(cg[n].pat[i].xyz, chmat, cg[n].pat[i].xyz);
} else {
- cg[n].pat[i].v[0] *= icmD50.X/bxyz[0];
- cg[n].pat[i].v[1] *= icmD50.Y/bxyz[1];
- cg[n].pat[i].v[2] *= icmD50.Z/bxyz[2];
+ cg[n].pat[i].xyz[0] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].pat[i].xyz[1] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].pat[i].xyz[2] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
}
+//printf("~1 file %d patch %d = norm XYZ %f %f %f\n", n,i,cg[n].pat[i].xyz[0],cg[n].pat[i].xyz[1],cg[n].pat[i].xyz[2]);
}
+ /* Compute normalised white too */
+ if (norm == 1) {
+ cg[n].nw[0] *= 100.0 / cg[n].w[1];
+ cg[n].nw[1] *= 100.0 / cg[n].w[1];
+ cg[n].nw[2] *= 100.0 / cg[n].w[1];
+ } else if (norm == 2) {
+ icmMulBy3x3(cg[n].nw, chmat, cg[n].w);
+ } else {
+ cg[n].nw[0] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].nw[1] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ cg[n].nw[2] *= 100.0 / (cg[n].w[0] + cg[n].w[1] + cg[n].w[2]);
+ }
+//printf("~1 file %d norm white XYZ %f %f %f\n", n,cg[n].nw[0], cg[n].nw[1], cg[n].nw[2]);
}
cgf->del(cgf); /* Clean up */
}
@@ -634,19 +784,46 @@ int main(int argc, char *argv[])
}
}
- /* Adjust the reference white Y to be larger than the largest Y of the two files */
- if (!usestdd50) {
- double maxy = -1e6;
-
- for (n = 0; n < 2; n++) {
- for (i = 0; i < cg[n].npat; i++) {
- if (cg[n].pat[i].v[1] > maxy)
- maxy = cg[n].pat[i].v[1];
+ /* Figure out which patches to skip because they are out of gamut */
+ if (luo != NULL) {
+ double chmat[3][3]; /* Chromatic adapation matrix */
+ double out[MAX_CHAN], in[3], check[3];
+ icmXYZNumber s_wp;
+ int rv;
+
+ /* Convert sample PCS to relative */
+ icmAry2XYZ(s_wp, cg[0].nw);
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, s_wp, chmat);
+
+ for (i = 0; i < cg[0].npat; i++) {
+ icmMulBy3x3(in, chmat, cg[0].pat[i].xyz);
+//printf("~1 %d: xyz %f %f %f, rel %f %f %f\n", i+1, cg[0].pat[i].xyz[0], cg[0].pat[i].xyz[1], cg[0].pat[i].xyz[2], in[0], in[1], in[2]);
+
+ if ((rv = luo->inv_lookup(luo, out, in)) > 0 || 1) {
+ double de;
+
+ luo->lookup(luo, check, out);
+ de = icmXYZLabDE(&icmD50,check, in);
+//printf("~1 %d: rv %d, de %f, check XYZ %f %f %f\n",i+1,rv, de, check[0],check[1],check[2]);
+
+ if (de >= 0.01) {
+ cg[0].pat[i].og = 1;
+//printf("~1 Patch %d is out of gamut by DE %f RGB %f %f %f\n",i+1,de,out[0],out[1],out[2]);
+ if (verb >= 3)
+ printf("Patch %d is out of gamut by DE %f\n",i+1,de);
+ cg[0].nig--;
+ }
}
}
- labw.X *= maxy/icmD50.Y; /* Scale white uniformly */
- labw.Y *= maxy/icmD50.Y; /* Scale white uniformly */
- labw.Z *= maxy/icmD50.Y;
+ if (verb)
+ fprintf(verbo,"No of test patches in gamut = %d/%d\n",cg[0].npat - cg[0].nig,cg[0].npat);
+ }
+
+ /* Adjust the Lab reference white to be the mean of the white of the two files */
+ if (norm != 0 && !usestdd50) {
+ labw.X = 0.5 * (cg[0].nw[0] + cg[1].nw[0]);
+ labw.Y = 0.5 * (cg[0].nw[1] + cg[1].nw[1]);
+ labw.Z = 0.5 * (cg[0].nw[2] + cg[1].nw[2]);
if (verb)
printf("L*a*b* white reference = XYZ %f %f %f\n",labw.X,labw.Y,labw.Z);
@@ -655,18 +832,30 @@ int main(int argc, char *argv[])
/* Convert XYZ to Lab */
for (n = 0; n < 2; n++) {
for (i = 0; i < cg[n].npat; i++) {
- icmXYZ2Lab(&labw, cg[n].pat[i].v, cg[n].pat[i].v);
+ icmXYZ2Lab(&labw, cg[n].pat[i].v, cg[n].pat[i].xyz);
}
}
/* Compute the delta E's */
for (i = 0; i < cg[0].npat; i++) {
+
+ if (cg[0].pat[i].og) /* Skip out of gamut patches */
+ continue;
+
+ cg[0].pat[i].ixde[0] = fabs(cg[0].pat[i].xyz[0] - cg[1].pat[match[i]].xyz[0]);
+ cg[0].pat[i].ixde[1] = fabs(cg[0].pat[i].xyz[1] - cg[1].pat[match[i]].xyz[1]);
+ cg[0].pat[i].ixde[2] = fabs(cg[0].pat[i].xyz[2] - cg[1].pat[match[i]].xyz[2]);
+
if (cie2k)
cg[0].pat[i].de = icmCIE2K(cg[0].pat[i].v, cg[1].pat[match[i]].v);
else if (cie94)
cg[0].pat[i].de = icmCIE94(cg[0].pat[i].v, cg[1].pat[match[i]].v);
else
cg[0].pat[i].de = icmLabDE(cg[0].pat[i].v, cg[1].pat[match[i]].v);
+
+ cg[0].pat[i].ide[0] = fabs(cg[0].pat[i].v[0] - cg[1].pat[match[i]].v[0]);
+ cg[0].pat[i].ide[1] = fabs(cg[0].pat[i].v[1] - cg[1].pat[match[i]].v[1]);
+ cg[0].pat[i].ide[2] = fabs(cg[0].pat[i].v[2] - cg[1].pat[match[i]].v[2]);
}
/* Create sorted list, from worst to best. */
@@ -688,6 +877,8 @@ int main(int argc, char *argv[])
int n10;
double merr10 = 0.0, aerr10 = 0.0;
double rad;
+ double aierr[3] = { 0.0, 0.0, 0.0 };
+ double aixerr[3] = { 0.0, 0.0, 0.0 };
if (dovrml) {
wrl = new_vrml(out_name, doaxes, 0);
@@ -700,6 +891,10 @@ int main(int argc, char *argv[])
/* Do overall results */
for (i = 0; i < cg[0].npat; i++) {
double de;
+
+ if (cg[0].pat[i].og) /* Skip out of gamut patches */
+ continue;
+
if (dosort)
j = sort[i];
else
@@ -708,12 +903,29 @@ int main(int argc, char *argv[])
de = cg[0].pat[j].de;
aerr += de;
- if (verb) {
- printf("%s: %f %f %f <=> %f %f %f de %f\n",
+ aierr[0] += cg[0].pat[j].ide[0];
+ aierr[1] += cg[0].pat[j].ide[1];
+ aierr[2] += cg[0].pat[j].ide[2];
+
+ aixerr[0] += cg[0].pat[j].ixde[0];
+ aixerr[1] += cg[0].pat[j].ixde[1];
+ aixerr[2] += cg[0].pat[j].ixde[2];
+
+ if (verb >= 2) {
+
+ printf("%s%s%s: %f %f %f <=> %f %f %f de %f\n",
cg[0].pat[j].sid,
+ cg[0].pat[j].loc[0] != '\000' ? " " : "",
+ cg[0].pat[j].loc,
cg[0].pat[j].v[0], cg[0].pat[j].v[1], cg[0].pat[j].v[2],
cg[1].pat[match[j]].v[0], cg[1].pat[match[j]].v[1], cg[1].pat[match[j]].v[2],
de);
+
+#ifdef NEVER /* Print XYZ as well */
+ printf(" %f %f %f <=> %f %f %f\n",
+ cg[0].pat[j].xyz[0], cg[0].pat[j].xyz[1], cg[0].pat[j].xyz[2],
+ cg[1].pat[match[j]].xyz[0], cg[1].pat[match[j]].xyz[1], cg[1].pat[match[j]].xyz[2]);
+#endif
}
if (de > merr)
@@ -731,8 +943,16 @@ int main(int argc, char *argv[])
}
}
- if (cg[0].npat > 0)
- aerr /= (double)cg[0].npat;
+ if (cg[0].nig > 0) {
+ aerr /= (double)cg[0].nig;
+ aierr[0] /= (double)cg[0].nig;
+ aierr[1] /= (double)cg[0].nig;
+ aierr[2] /= (double)cg[0].nig;
+
+ aixerr[0] /= (double)cg[0].nig;
+ aixerr[1] /= (double)cg[0].nig;
+ aixerr[2] /= (double)cg[0].nig;
+ }
if (dovrml) {
wrl->make_lines(wrl, 0, 2);
@@ -741,23 +961,33 @@ int main(int argc, char *argv[])
}
/* Do best 90% */
- n90 = (int)(cg[0].npat * 9.0/10.0 + 0.5);
- for (i = (cg[0].npat-n90); i < cg[0].npat; i++) {
+ n90 = (int)(cg[0].nig * 9.0/10.0 + 0.5);
+ for (i = j = 0; i < cg[0].npat; i++) {
double de = cg[0].pat[sort[i]].de;
- aerr90 += de;
- if (de > merr90)
- merr90 = de;
+ if (cg[0].pat[i].og) /* Skip out of gamut */
+ continue;
+ if (j >= (cg[0].nig-n90)) { /* If in top 90% of in gamut patches */
+ aerr90 += de;
+ if (de > merr90)
+ merr90 = de;
+ }
+ j++; /* Index of within gamut patches */
}
if (n90 > 0)
aerr90 /= (double)n90;
/* Do worst 10% */
- n10 = (int)(cg[0].npat * 1.0/10.0 + 0.5);
- for (i = 0; i < n10; i++) {
+ n10 = (int)(cg[0].nig * 1.0/10.0 + 0.5);
+ for (i = j = 0; i < cg[0].npat; i++) {
double de = cg[0].pat[sort[i]].de;
- aerr10 += de;
- if (de > merr10)
- merr10 = de;
+ if (cg[0].pat[i].og) /* Skip out of gamut */
+ continue;
+ if (j <= n10) { /* If in worst 10% of in gamut patches */
+ aerr10 += de;
+ if (de > merr10)
+ merr10 = de;
+ }
+ j++;
}
if (n10 > 0)
aerr10 /= (double)n10;
@@ -770,6 +1000,8 @@ int main(int argc, char *argv[])
printf(" Total errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr, aerr);
printf(" Worst 10%% errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr10, aerr10);
printf(" Best 90%% errors%s: peak = %f, avg = %f\n", cie2k ? " (CIEDE2000)" : cie94 ? " (CIE94)" : "", merr90, aerr90);
+ printf(" avg err X %f, Y %f, Z %f\n", aixerr[0], aixerr[1], aixerr[2]);
+ printf(" avg err L* %f, a* %f, b* %f\n", aierr[0], aierr[1], aierr[2]);
free(sort);
free(match);
@@ -777,6 +1009,15 @@ int main(int argc, char *argv[])
free(cg[1].pat);
}
+ if (luo != NULL)
+ luo->del(luo);
+ if (xicco != NULL)
+ xicco->del(xicco); /* Expansion wrapper */
+ if (icco != NULL)
+ icco->del(icco); /* Icc */
+ if (fp != NULL)
+ fp->del(fp);
+
return 0;
}
diff --git a/profile/prof.h b/profile/prof.h
index 074bb73..6013d99 100644
--- a/profile/prof.h
+++ b/profile/prof.h
@@ -49,6 +49,7 @@ void make_output_icc(
int gamdiag, /* Make gamut mapping diagnostic wrl plots */
int verify, /* nz to print verification */
int clipprims, /* Clip white, black and primaries */
+ double wpscale, /* >= 0.0 for media white point scale factor */
icxInk *ink, /* Ink limit/black generation setup */
char *in_name, /* input .ti3 file name */
char *file_name, /* output icc name */
@@ -62,6 +63,7 @@ void make_output_icc(
int fwacomp, /* FWA compensation requested */
double smooth, /* RSPL smoothing factor, -ve if raw */
double avgdev, /* reading Average Deviation as a proportion of the input range */
+ double demph, /* Emphasise dark region grid resolution in cLUT */
char *ipname, /* input icc profile - enables gamut map, NULL if none */
char *sgname, /* source image gamut - NULL if none */
char *absname[3], /* abstract profile name for each table */
diff --git a/profile/profcheck.c b/profile/profcheck.c
index ca9b0b2..1895713 100644
--- a/profile/profcheck.c
+++ b/profile/profcheck.c
@@ -507,7 +507,7 @@ int main(int argc, char *argv[])
/* Read in the CGATs fields */
{
int sidx; /* Sample ID index */
- int sloc; /* Sample location indexi (if any) */
+ int sloc; /* Sample location index (if any) */
int ti, ci, mi, yi, ki;
int Xi, Yi, Zi;
diff --git a/profile/profin.c b/profile/profin.c
index 2f74ec2..c703c42 100644
--- a/profile/profin.c
+++ b/profile/profin.c
@@ -825,6 +825,8 @@ make_input_icc(
flags |= ICX_SET_BLACK; /* Compute & use black */
flags |= ICX_SET_WHITE; /* Compute & use white */
+
+ /* ICX_SET_WHITE_C isn't applicable to matrix profiles */
if (autowpsc)
flags |= ICX_SET_WHITE_US; /* Compute & use white without scaling to L */
@@ -836,7 +838,7 @@ make_input_icc(
wr_xicc, icmFwd, icmDefaultIntent,
icmLuOrdNorm,
flags, /* Flags */
- npat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev,
+ npat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev, 1.0,
NULL, NULL, NULL, iquality)) == NULL)
error("%d, %s",wr_xicc->errc, wr_xicc->err);
@@ -1121,7 +1123,7 @@ make_input_icc(
ICX_2PASSSMTH |
#endif
flags, /* Flags */
- npat + nxpat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev,
+ npat + nxpat, npat, tpat, NULL, 0.0, wpscale, smooth, avgdev, 1.0,
NULL, NULL, NULL, iquality)) == NULL)
error ("%d, %s",wr_xicc->errc, wr_xicc->err);
@@ -1207,7 +1209,8 @@ make_input_icc(
NULL, NULL, /* Use default Lab' range */
in_b2a_clut, /* Lab' -> Device' transfer function */
NULL, NULL, /* Use default Device' range */
- in_b2a_output) != 0) /* Output transfer function, Device'->Device */
+ in_b2a_output, /* Output transfer function, Device'->Device */
+ NULL, NULL) != 0) /* Use default APXLS range */
error("Setting 16 bit PCS->Device Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
if (cx.verb) {
printf("\n");
diff --git a/profile/profout.c b/profile/profout.c
index d89ae4e..8c6fa0d 100644
--- a/profile/profout.c
+++ b/profile/profout.c
@@ -65,6 +65,7 @@
#undef IMP_MONO /* [Undef] Turn on development code */
+#define EMPH_DISP_BLACKPOINT /* [Define] Increase weight near diplay black point */
#define NO_B2A_PCS_CURVES /* [Define] PCS curves seem to make B2A less accurate. Why ? */
#define USE_CAM_CLIP_OPT /* [Define] Clip out of gamut in CAM space rather than PCS */
#define USE_LEASTSQUARES_APROX /* [Define] Use least squares fitting approximation in B2A */
@@ -73,7 +74,7 @@
#undef DISABLE_GAMUT_TAG /* [Undef] To disable gamut tag */
#undef WARN_CLUT_CLIPPING /* [Undef] Print warning if setting clut clips */
#undef COMPARE_INV_CLUT /* [Undef] Compare result of inv_clut with clut to diag inv probs */
-#define FILTER_B2ACLIP /* [Define] Filter clip area of B2A */
+#undef FILTER_B2ACLIP /* [Undef] Filter clip area of B2A (Causes reversal problems) */
#define FILTER_THR_DE 3.0 /* [5.0] Filtering threshold DE */
#define FILTER_MAX_DE 5.0 /* [10.0] Filtering DE to gamut surface at whit MAX_RAD starts */
#define FILTER_MAX_RAD 0.1 /* [0.1] Filtering maximum radius in grid */
@@ -185,7 +186,7 @@ typedef struct {
double swxyz[3]; /* Source white point in XYZ */
gamut *gam; /* Output gamut object for setting gamut Lut */
- int wantLab; /* 0 if want is XYZ PCS, 1 want is Lab PCS */
+ int wantLab; /* 0 if is XYZ PCS, 1 if is Lab PCS */
} out_b2a_callback;
/* Utility to handle abstract profile application to PCS. */
@@ -642,6 +643,7 @@ make_output_icc(
int gamdiag, /* Make gamut mapping diagnostic wrl plots */
int verify, /* nz to print verification */
int clipprims, /* Clip white, black and primaries */
+ double wpscale, /* >= 0.0 for media white point scale factor */
icxInk *oink, /* Ink limit/black generation setup (NULL if n/a) */
char *in_name, /* input .ti3 file name */
char *file_name, /* output icc name */
@@ -655,6 +657,7 @@ make_output_icc(
int fwacomp, /* FWA compensation requested */
double smooth, /* RSPL smoothing factor, -ve if raw */
double avgdev, /* reading Average Deviation as a proportion of the input range */
+ double demph, /* Emphasise dark region grid resolution in cLUT */
char *ipname, /* input icc profile - enables gamut map, NULL if none */
char *sgname, /* source image gamut - NULL if none */
char *absname[3], /* abstract profile name for each table */
@@ -737,7 +740,7 @@ make_output_icc(
int ti;
if ((ti = icg->find_kword(icg, 0, "LUMINANCE_XYZ_CDM2")) >= 0) {
- if (sscanf(icg->t[0].kdata[ti], " %*lf %lf %*lf ",&dispLuminance) != 1)
+ if (sscanf(icg->t[0].kdata[ti], " %*f %lf %*f ",&dispLuminance) != 1)
dispLuminance = 0.0;
}
@@ -1215,6 +1218,17 @@ make_output_icc(
cc = 0.0;
else if (cc > 1.0)
cc = 1.0;
+
+ if (cal->tvenc) {
+ cc = (cc * (235.0-16.0) + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit shifting */
+ /* rather than scaling, so we need to scale the fp value to account for this. */
+ /* We assume the precision is the vcgt table size = 16 */
+ /* ~~99 ideally we should tag the fact that this is video encoded, so that */
+ /* the vcgt loaded can adjust for a different bit precision ~~~~ */
+ cc = (cc * 255 * (1 << (16 - 8)))/((1 << 16) - 1.0);
+ }
((unsigned short*)wo->u.table.data)[ncal * j + i] = (int)(cc * 65535.0 + 0.5);
}
}
@@ -1389,12 +1403,12 @@ make_output_icc(
wog->allocate((icmBase *)wog);
wob->allocate((icmBase *)wob);
- wor->data[0].X = 1.0; wor->data[0].Y = 0.0; wor->data[0].Z = 0.0;
- wog->data[0].X = 0.0; wog->data[0].Y = 1.0; wog->data[0].Z = 0.0;
- wob->data[0].X = 0.0; wob->data[0].Y = 0.0; wob->data[0].Z = 1.0;
+// wor->data[0].X = 1.0; wor->data[0].Y = 0.0; wor->data[0].Z = 0.0;
+// wog->data[0].X = 0.0; wog->data[0].Y = 1.0; wog->data[0].Z = 0.0;
+// wob->data[0].X = 0.0; wob->data[0].Y = 0.0; wob->data[0].Z = 1.0;
/* Setup deliberately wrong dummy values (channels rotated). */
- /* icxMatrix may override override these later */
+ /* icxMatrix may override these later */
wor->data[0].X = 0.143066; wor->data[0].Y = 0.060608; wor->data[0].Z = 0.714096;
wog->data[0].X = 0.436066; wog->data[0].Y = 0.222488; wog->data[0].Z = 0.013916;
wob->data[0].X = 0.385147; wob->data[0].Y = 0.716873; wob->data[0].Z = 0.097076;
@@ -1834,6 +1848,8 @@ make_output_icc(
}
+ isLab = wantLab; /* We now have what we want */
+
/* Normalize display values to Y = 1.0 if needed */
/* (re-norm spec derived, since observer may be different) */
if (isdisp && (isdnormed == 0 || spec != 0)) {
@@ -1878,6 +1894,51 @@ make_output_icc(
}
} /* End of reading in CGATs file */
+
+#ifdef EMPH_DISP_BLACKPOINT
+ /* Add extra weighting to sample points near black for additive display. */
+ /* Not sure what the justification is, apart from making the black */
+ /* point more accurately modelled. Does this reflect an underlying */
+ /* problem with rspl in perceptual space ? Or is it a reflection */
+ /* of the possible "scaled" viewing mode of additive display */
+ /* usage ? What about print and scan ?? */
+ if (isdisp && (imask == ICX_W || imask == ICX_RGB)) {
+ double minL = 1e6;;
+
+ /* Locate the lowest L* value */
+ for (i = 0; i < npat; i++) {
+ if (wantLab) {
+ if (tpat[i].v[0] < minL)
+ minL = tpat[i].v[0];
+ } else {
+ double lab[2];
+ icmXYZ2Lab(&icmD50, lab, tpat[i].v);
+ if (lab[0] < minL)
+ minL = lab[0];
+ }
+ }
+
+ /* Compute weighting factor */
+ /* (Hard to guess what numbers to put in here.. */
+ for (i = 0; i < npat; i++) {
+ double lab[3], L;
+ if (wantLab) {
+ L = tpat[i].v[0];
+ } else {
+ icmXYZ2Lab(&icmD50, lab, tpat[i].v);
+ L = lab[0];
+ }
+ L -= minL;
+ L /= 20.0; /* Just weight over 20 L* range */
+ if (L > 1.0)
+ continue;
+ L = 1.0 + 19.0 * pow(1.0 - L, 3.0);
+ tpat[i].w *= L;
+//printf("~1 pat %d %f %f %f weight %f\n", i,tpat[i].p[0], tpat[i].p[1], tpat[i].p[2], tpat[i].w);
+ }
+ }
+#endif /* EMPH_DISP_BLACKPOINT */
+
if (isLut) {
xicc *wr_xicc; /* extention object */
icxLuBase *AtoB; /* AtoB ixcLu */
@@ -1920,7 +1981,7 @@ make_output_icc(
ICX_2PASSSMTH |
#endif
flags,
- npat, npat, tpat, NULL, dispLuminance, -1.0, smooth, avgdev,
+ npat, npat, tpat, NULL, dispLuminance, wpscale, smooth, avgdev, demph,
NULL, oink, cal, iquality)) == NULL)
error("%d, %s",wr_xicc->errc, wr_xicc->err);
@@ -2016,18 +2077,20 @@ make_output_icc(
vc->Lv = v->Lv;
if (v->Yf >= 0.0)
vc->Yf = v->Yf;
- if (v->Fxyz[0] >= 0.0 && v->Fxyz[1] > 0.0 && v->Fxyz[2] >= 0.0) {
+ if (v->Yg >= 0.0)
+ vc->Yg = v->Yg;
+ if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] > 0.0 && v->Gxyz[2] >= 0.0) {
/* Normalise XYZ to current media white */
- vc->Fxyz[0] = v->Fxyz[0]/v->Fxyz[1] * vc->Fxyz[1];
- vc->Fxyz[2] = v->Fxyz[2]/v->Fxyz[1] * vc->Fxyz[1];
+ vc->Gxyz[0] = v->Gxyz[0]/v->Gxyz[1] * vc->Gxyz[1];
+ vc->Gxyz[2] = v->Gxyz[2]/v->Gxyz[1] * vc->Gxyz[1];
}
- if (v->Fxyz[0] >= 0.0 && v->Fxyz[1] >= 0.0 && v->Fxyz[2] < 0.0) {
+ if (v->Gxyz[0] >= 0.0 && v->Gxyz[1] >= 0.0 && v->Gxyz[2] < 0.0) {
/* Convert Yxy to XYZ */
- double x = v->Fxyz[0];
- double y = v->Fxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ double x = v->Gxyz[0];
+ double y = v->Gxyz[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc->Fxyz[0] = x/y * vc->Fxyz[1];
- vc->Fxyz[2] = z/y * vc->Fxyz[1];
+ vc->Gxyz[0] = x/y * vc->Gxyz[1];
+ vc->Gxyz[2] = z/y * vc->Gxyz[1];
}
}
@@ -2182,31 +2245,40 @@ make_output_icc(
/* cx.ix and cx.ox for each intent, but that would be expensive!. */
if (sepsat && (pgmi->usecas & 0xff) != (sgmi->usecas & 0xff))
error("Can't handle percept and sat table intents with different CAM spaces");
- /* Default perceptual input gamut mapping space is absolute perceptual */
- intentp = noptop ? icAbsoluteColorimetric : icmAbsolutePerceptual;
- /* But override this for apperance space gamut mapping */
- if ((pgmi->usecas & 0xff) != 0x0) {
+ /* If apperance space perceptual table gamut mapping */
+ if ((pgmi->usecas & 0xff) >= 0x2) {
intentp = noptop ? icxAppearance : icxPerceptualAppearance;
+ } else {
+ if ((pgmi->usecas & 0xff) == 0x0)
+ intentp = noptop ? icRelativeColorimetric : icPerceptual;
+ else /* pgmi->usecas & 0xff == 0x1 */
+ intentp = noptop ? icAbsoluteColorimetric : icmAbsolutePerceptual;
}
+
if (sepsat) {
- /* Default saturation gamut mapping space is absolute saturation */
- intents = nostos ? icAbsoluteColorimetric : icmAbsoluteSaturation;
- /* But override this for apperance space gamut mapping */
- if ((sgmi->usecas & 0xff) != 0x0) {
+ /* If apperance space saturation table gamut mapping */
+ if ((sgmi->usecas & 0xff) >= 0x2) {
intents = nostos ? icxAppearance : icxSaturationAppearance;
+ } else {
+ if ((sgmi->usecas & 0xff) == 0x0)
+ intents = nostos ? icRelativeColorimetric : icSaturation;
+ else
+ intents = nostos ? icAbsoluteColorimetric : icmAbsoluteSaturation;
}
}
- /* Default output gamut mapping space is absolute colorimetric */
- intento = icAbsoluteColorimetric;
- /* But override this for apperance space gamut mapping */
- if ((pgmi->usecas & 0xff) != 0x0) {
+ if ((pgmi->usecas & 0xff) >= 0x2) {
intento = icxAppearance;
+ } else {
+ if ((pgmi->usecas & 0xff) == 0x0)
+ intento = icRelativeColorimetric;
+ else /* pgmi->usecas & 0xff == 0x1 */
+ intento = icAbsoluteColorimetric;
}
- if ((pgmi->usecas & 0xff) == 0x2) {
+ if ((pgmi->usecas & 0xff) == 0x3) { /* Abs. appearance */
double mxw;
intentp = intents = intento = icxAbsAppearance;
@@ -2274,7 +2346,7 @@ make_output_icc(
if (sgname != NULL) { /* Optional source gamut - ie. from an images */
int isJab = 0;
- if ((pgmi->usecas & 0xff) != 0)
+ if ((pgmi->usecas & 0xff) >= 0x2)
isJab = 1;
if (verb)
@@ -2628,14 +2700,16 @@ make_output_icc(
ICM_CLUT_SET_FILTER |
#endif
0,
- &cx, /* Context */
- cx.pcsspace, /* Input color space */
- devspace, /* Output color space */
- out_b2a_input, /* Input transform PCS->PCS' */
- NULL, NULL, /* Use default PCS range */
- out_b2a_clut, /* Lab' -> Device' transfer function */
- NULL, NULL, /* Use default Device' range */
- out_b2a_output) != 0) /* Output transfer function, Device'->Device */
+ &cx, /* Context */
+ cx.pcsspace, /* Input color space */
+ devspace, /* Output color space */
+ out_b2a_input, /* Input transform PCS->PCS' */
+ NULL, NULL, /* Use default PCS range */
+ out_b2a_clut, /* Lab' -> Device' transfer function */
+ NULL, NULL, /* Use default Device' range */
+ out_b2a_output, /* Output transfer function, Device'->Device */
+ NULL, NULL /* Use default APXLS range */
+ ) != 0)
error("Setting 16 bit PCS->Device Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
if (cx.verb) {
printf("\n");
@@ -2769,7 +2843,9 @@ make_output_icc(
NULL, NULL, /* Use default Lab' range */
PCSp_bdist, /* Lab' -> Boundary distance */
NULL, NULL, /* Use default Device' range */
- gamut_output) != 0) /* Boundary distance to out of gamut value */
+ gamut_output, /* Boundary distance to out of gamut value */
+ NULL, NULL
+ ) != 0)
error("Setting 16 bit PCS->Device Gamut Lut failed: %d, %s",wr_icco->errc,wr_icco->err);
#endif /* !DEBUG_ONE */
if (cx.verb) {
@@ -2823,7 +2899,7 @@ make_output_icc(
wr_xicc, icmFwd, isdisp ? icmDefaultIntent : icRelativeColorimetric,
icmLuOrdRev,
flags, /* Compute white & black */
- npat, npat, tpat, NULL, dispLuminance, -1.0, smooth, avgdev,
+ npat, npat, tpat, NULL, dispLuminance, wpscale, smooth, avgdev, demph,
NULL, oink, cal, iquality)) == NULL)
error("%d, %s",wr_xicc->errc, wr_xicc->err);
diff --git a/profile/txt2ti3.c b/profile/txt2ti3.c
index 9b425f3..62807f3 100644
--- a/profile/txt2ti3.c
+++ b/profile/txt2ti3.c
@@ -28,7 +28,7 @@
*/
-#undef DEBUG
+#define DEBUG
#include <stdio.h>
#include <stdlib.h>
@@ -50,7 +50,7 @@ usage(char *mes) {
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
if (mes != NULL)
fprintf(stderr,"error: %s\n",mes);
- fprintf(stderr,"usage: txt2ti3 [-v] [-l limit] [devfile] infile [specfile] outfile\n");
+ fprintf(stderr,"usage: txt2ti3 [-v] [-l limit] [devfile] infile [specfile] outbase\n");
/* fprintf(stderr," -v Verbose mode\n"); */
fprintf(stderr," -2 Create dummy .ti2 file as well\n");
fprintf(stderr," -l limit set ink limit, 0 - 400%% (default max in file)\n");
@@ -200,7 +200,7 @@ int main(int argc, char *argv[])
cmy->add_other(cmy, "ECI2002"); /* Gretag/Logo Target file */
cmy->add_other(cmy, ""); /* Wildcard */
if (cmy->read_name(cmy, devname))
- error ("Read: Can't read dev file '%s'. Unknown format or corrupted file ?",devname);
+ error ("Read: Can't read dev file '%s'. Unknown format or corrupted file ? (%s)",devname,cmy->err);
if (cmy->ntables != 1)
warning("Input file '%s' doesn't contain exactly one table",devname);
diff --git a/ref/ClayRGB1998.icm b/ref/ClayRGB1998.icm
index 1eedf09..1c3a02e 100644
--- a/ref/ClayRGB1998.icm
+++ b/ref/ClayRGB1998.icm
Binary files differ
diff --git a/ref/ColorCheckerDC.ti2 b/ref/ColorCheckerDC.ti2
new file mode 100644
index 0000000..f87284c
--- /dev/null
+++ b/ref/ColorCheckerDC.ti2
@@ -0,0 +1,264 @@
+CTI2
+
+DESCRIPTOR "Argyll Calibration Target chart information 2"
+ORIGINATOR "Argyll printtarg"
+CREATED "Tue Nov 19 14:16:26 2013"
+KEYWORD "TARGET_INSTRUMENT"
+TARGET_INSTRUMENT "GretagMacbeth SpectroScan"
+APPROX_WHITE_POINT "95.106486 100.000000 108.844025"
+COLOR_REP "RGB"
+CHART_ID 26
+STEPS_IN_PASS 12
+PASSES_IN_STRIPS2 20
+STRIP_INDEX_PATTERN "A-Z, A-Z"
+PATCH_INDEX_PATTERN "@-9,0-9;01-99"
+INDEX_ORDER "STRIP_THEN_PATCH"
+
+NUMBER_OF_FIELDS 8
+BEGIN_DATA_FORMAT
+SAMPLE_ID SAMPLE_LOC RGB_R RGB_G RGB_B XYZ_X XYZ_Y XYZ_Z
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 240
+BEGIN_DATA
+1 "A01" 95.27 94.34 100 74.79 77.56 64.46
+2 "A02" 10.1 12.72 15.23 3.08 3.19 2.77
+3 "A03" 50.01 49.47 53.83 18.98 19.71 16.53
+4 "A04" 95.19 94.25 100 74.57 77.34 64.38
+5 "A05" 10.25 12.82 15.3 3.1 3.21 2.78
+6 "A06" 49.76 49.32 53.63 18.88 19.62 16.44
+7 "A07" 95.23 94.31 100 74.65 77.43 64.37
+8 "A08" 9.95 12.59 14.99 3.05 3.16 2.74
+9 "A09" 49.73 49.25 53.58 18.86 19.59 16.42
+10 "A10" 95.1 94.22 99.98 74.33 77.13 64.18
+11 "A11" 9.95 12.59 14.99 3.05 3.16 2.74
+12 "A12" 49.93 49.4 53.72 18.94 19.67 16.48
+13 "B01" 50.01 49.47 53.83 18.98 19.71 16.53
+14 "B02" 46.36 12.46 22.34 9.28 6.32 3.27
+15 "B03" 32.74 22.03 19.37 7.34 6.63 3.64
+16 "B04" 56.14 48.21 40.46 19.71 19.69 11.13
+17 "B05" 35.71 36.78 28.68 10.69 11.58 6.54
+18 "B06" 19.44 26.18 17.23 5.55 6.26 3.53
+19 "B07" 9.63 29.83 19.36 4.69 6.4 3.88
+20 "B08" 5.03 29.78 29.99 4.45 6.24 5.6
+21 "B09" 11.74 26.06 33.69 5.26 6.13 6.71
+22 "B10" 7.48 17.09 38.75 4.16 4.4 7.55
+23 "B11" 31.81 19.87 28.2 7.13 6.18 5.2
+24 "B12" 95.28 94.35 100 74.68 77.45 64.31
+25 "C01" 9.86 12.49 14.83 3.03 3.14 2.72
+26 "C02" 78.87 8.12 37.96 22.27 12.45 5.91
+27 "C03" 50.95 30.12 24.15 13.73 11.57 5.26
+28 "C04" 44.44 34.21 17.16 12.35 11.83 4.46
+29 "C05" 46.22 52.19 26.89 16.62 19.15 7.75
+30 "C06" 23 40.19 25.32 8.81 11.49 5.72
+31 "C07" 9.34 43.53 27.72 7.38 11.51 5.94
+32 "C08" 9.06 40.65 41.35 7.96 11.09 9.57
+33 "C09" 8.24 25.27 43.76 5.61 6.35 9.68
+34 "C10" 4.46 23.9 51.18 5.49 6.22 12.37
+35 "C11" 39.09 18.2 33.1 8.5 6.58 6.19
+36 "C12" 9.9 12.54 14.91 3.04 3.15 2.73
+37 "D01" 95.25 94.34 100 74.7 77.48 64.38
+38 "D02" 83.18 3.28 29.2 23.6 12.43 3.41
+39 "D03" 58.04 28.35 19.08 15.71 12.25 4.16
+40 "D04" 60.64 50.58 1.68 19.85 19.78 4.3
+41 "D05" 44.66 55.44 3.99 15.7 19.2 4.89
+42 "D06" 50.68 71.99 20.2 22.07 30.17 8.05
+43 "D07" 1.82 46.45 32.24 6.22 11.44 6.34
+44 "D08" 2.68 60.96 59.88 11.56 19.31 16.65
+45 "D09" 6.74 22.7 51.61 5.69 6.13 12.53
+46 "D10" 5.74 20.48 57.17 5.6 5.88 14.72
+47 "D11" 43.58 14.07 38.16 9.13 6.35 7.28
+48 "D12" 49.85 49.34 53.67 18.91 19.64 16.46
+49 "E01" 49.93 49.45 53.76 18.95 19.69 16.5
+50 "E02" 98.18 12.49 38.48 35.41 20.25 6.45
+51 "E03" 83.15 34.43 11.22 28.25 20.38 3.83
+52 "E04" 62.85 47.43 3.48 20.73 19.59 4.47
+53 "E05" 49.17 54.51 0.58 16.4 19.03 4.34
+54 "E06" 67.94 82.3 53.02 34.81 43.02 17.75
+55 "E07" 7.82 61.12 45.54 11.78 19.58 11.32
+56 "E08" 0.06 48.5 61.14 6.88 11.75 14.39
+57 "E09" 0.19 40.75 67.67 7.88 11.31 19.64
+58 "E10" 3.32 36.11 77.29 9.22 11.09 27.08
+59 "E11" 65.18 18.84 54.73 17.84 11.47 13.98
+60 "E12" 95.25 94.3 100 74.56 77.32 64.24
+61 "F01" 9.9 12.54 14.91 3.04 3.15 2.73
+62 "F02" 99.74 26.47 46.59 48.3 30.25 11.41
+63 "F03" 62.95 20.45 23.38 16.14 10.93 3.9
+64 "F04" 76.63 60.56 22.07 31.33 29.91 8.52
+65 "F05" 36.63 55.19 18.02 14.11 18.71 6.4
+66 "F06" 78.75 80.96 20.26 38.16 43.99 9.51
+67 "F07" 7.01 62.38 35.44 10.52 19.33 8.14
+68 "F08" 1.48 41.62 59.96 7.96 11.49 16.13
+69 "F09" 4.66 38.88 62.1 8.63 11.3 17.86
+70 "F10" 8.56 33.53 76.84 10.41 11.24 27.64
+71 "F11" 76.83 8.82 46.69 21.49 12.15 9.52
+72 "F12" 9.9 12.54 14.91 3.04 3.15 2.73
+73 "G01" 95.27 94.34 100 74.73 77.5 64.38
+74 "G02" 98.55 34.63 57.21 44.51 29.8 15.52
+75 "G03" 71.71 37.83 33.38 24.34 19.34 8.11
+76 "G04" 74.92 38.56 10.79 25.26 19.88 4.38
+77 "G05" 36.15 59.64 1.53 13.65 19.52 4.62
+78 "G06" 79.26 82.87 1.12 36.49 43.18 5.73
+79 "G07" 31.42 73.13 50.51 19.42 29.58 14.51
+80 "G08" 5.45 70.76 91.77 19.86 28.9 37.67
+81 "G09" 9.76 53.95 72.09 14.15 18.75 25.13
+82 "G10" 12.93 35.04 69.77 10.69 11.62 23.13
+83 "G11" 91.13 23.55 63.45 31.57 19.76 17.91
+84 "G12" 49.85 49.34 53.67 18.91 19.64 16.46
+85 "H01" 50.01 49.47 53.83 18.98 19.71 16.53
+86 "H02" 94.23 19.84 47.13 33.5 20.33 9.91
+87 "H03" 84.08 49.98 45.1 34.67 28.65 13.17
+88 "H04" 63.04 25.22 10.51 16.86 12.12 2.75
+89 "H05" 49.17 72.98 8.29 21.16 30.06 6.66
+90 "H06" 90.01 92 51.94 52.08 58.65 19.39
+91 "H07" 51.68 69.17 35.96 22.63 29.16 10.83
+92 "H08" 22.67 69.1 84.54 21.74 29.15 34.08
+93 "H09" 2.08 53.56 85.09 13.59 18.65 33.2
+94 "H10" 18.2 48.01 90.52 17.32 18.86 39.16
+95 "H11" 84.22 29.36 61.76 29.3 19.82 17.88
+96 "H12" 95.28 94.34 100 74.65 77.41 64.27
+97 "I01" 9.95 12.59 14.99 3.05 3.16 2.74
+98 "I02" 63.39 42.06 52.1 22.03 19.1 15.09
+99 "I03" 76.57 55.72 50.91 31.97 28.79 15.9
+100 "I04" 98.78 37.3 25.86 42.69 29.41 6.24
+101 "I05" 97.3 98.04 99.89 82.21 85.41 69.86
+102 "I06" 65.58 65.98 70.9 30.96 32.15 26.58
+103 "I07" 44.74 45.12 49.16 16.49 17.18 14.34
+104 "I08" 24.98 26.86 30.43 7.03 7.28 6.15
+105 "I09" 39.67 65.7 88.49 24.91 29.34 38.48
+106 "I10" 52.39 60.56 94.9 29.04 29.31 45.2
+107 "I11" 95.98 42.83 73.82 41.09 29.82 26.18
+108 "I12" 9.92 12.58 15.07 3.05 3.16 2.75
+109 "J01" 95.23 94.32 100 74.72 77.5 64.44
+110 "J02" 77.57 32.64 54.49 26.91 19.35 14.94
+111 "J03" 83.29 53.78 37.02 34.54 29.66 11.16
+112 "J04" 100 52.92 30.05 58.1 42.93 8.71
+113 "J05" 92.1 89.96 96.97 64.14 66.75 54.99
+114 "J06" 98.88 99.51 99.69 87.06 90.39 72.76
+115 "J07" 98.8 99.45 99.69 86.82 90.15 72.56
+116 "J08" 15.3 18.64 21.56 4.28 4.47 3.84
+117 "J09" 35.08 63.84 96.62 24.87 28.59 45.17
+118 "J10" 65.98 70.7 100 41.47 42.2 57.7
+119 "J11" 99.15 59.59 84.68 53.38 42.55 36.49
+120 "J12" 49.87 49.36 53.7 18.92 19.65 16.47
+121 "K01" 49.99 49.46 53.81 18.97 19.7 16.52
+122 "K02" 86.58 49.77 60.7 36.7 29.69 19.45
+123 "K03" 88.67 51.5 28.75 36.83 30.22 8.83
+124 "K04" 98.88 62.08 32.27 53.42 43.05 10.13
+125 "K05" 85.31 83.06 90.88 51.78 53.86 44.86
+126 "K06" 98.81 99.46 99.68 86.85 90.18 72.55
+127 "K07" 98.82 99.48 99.69 86.91 90.25 72.64
+128 "K08" 12.06 14.95 17.22 3.45 3.59 3.07
+129 "K09" 6.92 67.52 99.04 21.49 28.73 46.46
+130 "K10" 50.08 42.95 86.74 21.85 19.42 36.39
+131 "K11" 75.42 56.11 68.02 32.48 29.05 24.22
+132 "K12" 95.27 94.32 100 74.63 77.39 64.28
+133 "L01" 9.84 12.49 14.92 3.03 3.14 2.73
+134 "L02" 98.98 57.11 74.4 53.85 42.1 29.27
+135 "L03" 99.89 50.46 60.72 58.21 42.93 21.15
+136 "L04" 99.29 46.21 3.17 40.96 30.79 3.87
+137 "L05" 75.24 75.43 81.94 40.79 42.45 35.04
+138 "L06" 57.21 57.01 61.15 23.51 24.47 20.31
+139 "L07" 34.32 36.31 40.46 11.1 11.62 9.8
+140 "L08" 9.82 12.45 14.75 3.02 3.13 2.71
+141 "L09" 33.27 77.33 99.89 31.86 41.84 53.57
+142 "L10" 33.9 16.63 45.96 7.9 6.16 10.17
+143 "L11" 98.43 80.02 96.18 62.34 57.68 47.93
+144 "L12" 9.86 12.49 14.83 3.03 3.14 2.72
+145 "M01" 95.25 94.34 100 74.74 77.52 64.43
+146 "M02" 99.99 73.82 90.19 68.21 58.76 45.3
+147 "M03" 99.19 58.74 71.9 54.32 42.79 26.91
+148 "M04" 99.98 75.49 34.17 68.17 58.65 13.41
+149 "M05" 99.35 99.63 30.25 76.51 80.88 14.08
+150 "M06" 25.3 54.85 59.81 15.06 19.36 18.82
+151 "M07" 12.74 75.9 44.48 16.03 29.31 11.79
+152 "M08" 79 86.77 95.63 52.05 57.11 51.73
+153 "M09" 42.83 80.8 96.51 32.54 42.52 46.33
+154 "M10" 29 19.89 40.72 7.2 6.19 8.57
+155 "M11" 97.05 93.04 100 78.01 78.48 67.07
+156 "M12" 49.89 49.41 53.72 18.93 19.67 16.48
+157 "N01" 50 49.45 53.79 18.97 19.7 16.51
+158 "N02" 99.34 79.72 88.26 65.97 60.13 42.01
+159 "N03" 96.25 63.6 74.67 50.5 42.33 28.58
+160 "N04" 99.27 81.88 42.08 63.78 59.07 15.95
+161 "N05" 99.65 82.63 11.45 62.58 58.72 7.2
+162 "N06" 26.24 70.63 78.27 21.33 29.57 29.73
+163 "N07" 9.82 75.76 59.79 17.06 29.9 17.13
+164 "N08" 76.26 84.42 99.75 54.05 58.63 61.58
+165 "N09" 68.69 87.9 99.27 49.41 57.82 58.22
+166 "N10" 58.46 25.45 64.62 16.9 12.02 19.29
+167 "N11" 97.22 42 83.28 41.76 29.82 32.52
+168 "N12" 95.29 94.35 100 74.67 77.43 64.28
+169 "O01" 9.82 12.45 14.75 3.02 3.13 2.71
+170 "O02" 91.01 68.56 77.87 47.1 42.51 31.08
+171 "O03" 97.63 62.78 50 51.87 42.51 15.81
+172 "O04" 98.83 97.18 92.89 77.2 77.91 50.55
+173 "O05" 98.9 73.19 0 45.99 42.6 4.49
+174 "O06" 40.94 68.1 75.26 23.64 29.5 29.06
+175 "O07" 41.16 87.88 60.49 26.97 42.73 19.28
+176 "O08" 59.59 63.21 73.49 27.97 29.35 28.33
+177 "O09" 75.74 88.91 93.15 50.32 57.45 48.38
+178 "O10" 63.01 42.18 68.33 23.06 19.58 23.21
+179 "O11" 69.87 57.18 83.37 32.18 29.25 34.95
+180 "O12" 9.77 12.4 14.67 3.01 3.12 2.7
+181 "P01" 95.25 94.32 100 74.64 77.41 64.32
+182 "P02" 84.46 72.89 80.48 44.39 42.98 33.4
+183 "P03" 100 72.99 59.81 71.49 59.42 23.1
+184 "P04" 100 97.78 79.43 79.86 78.26 38.44
+185 "P05" 80.84 60.67 1.37 31.59 29.6 5.37
+186 "P06" 25.93 70.68 69.27 20.07 28.76 23.92
+187 "P07" 50.83 83.03 73.17 31.22 42.07 27.31
+188 "P08" 37.02 50.17 67.49 17.15 18.99 23.19
+189 "P09" 65.74 78.01 85.01 37.97 42.95 38.15
+190 "P10" 54.49 46.66 57.66 19.91 19.24 17.99
+191 "P11" 79.86 72.98 93.2 44.36 43.41 45.48
+192 "P12" 49.95 49.42 53.74 18.95 19.68 16.49
+193 "Q01" 49.97 49.44 53.79 18.96 19.69 16.51
+194 "Q02" 95.79 84.32 88.88 59.99 58.87 41.85
+195 "Q03" 99.99 75.47 73.09 67.98 58.85 30.96
+196 "Q04" 100 95.41 90.21 82.15 79.03 48.34
+197 "Q05" 84.41 57.2 5.84 33.18 29.48 5.74
+198 "Q06" 9.17 72.73 77.86 18.92 29.39 27.97
+199 "Q07" 62.99 96.48 86.58 44.1 58.65 39.14
+200 "Q08" 71.85 77.1 70.94 37.51 41.38 26.69
+201 "Q09" 81.83 75.79 50.62 40.27 42.04 17.38
+202 "Q10" 53.2 64.94 64.37 24.86 28.48 22.3
+203 "Q11" 23.22 38.44 40.32 9.43 11.28 9.5
+204 "Q12" 95.28 94.33 100 74.61 77.37 64.24
+205 "R01" 9.95 12.59 14.99 3.05 3.16 2.74
+206 "R02" 71.47 61.11 61.93 31.16 30.09 20.86
+207 "R03" 93.36 84.53 83.13 56.92 56.98 36.53
+208 "R04" 99.7 95.07 97.1 79.37 78.57 56.95
+209 "R05" 89.21 74.18 15.19 42.68 42.54 8.26
+210 "R06" 35.67 84.82 81.93 28.15 41.91 31.53
+211 "R07" 77.72 93.12 78.3 48.61 58.02 33.46
+212 "R08" 62.64 63.77 53.68 26.81 28.91 16.95
+213 "R09" 81.95 77.86 34 39.83 43.08 12.47
+214 "R10" 41.4 34.94 25.31 11.8 11.72 5.87
+215 "R11" 40.7 52.5 53.8 17.1 19.71 16.41
+216 "R12" 9.82 12.45 14.75 3.02 3.13 2.71
+217 "S01" 95.25 94.32 100 74.66 77.43 64.34
+218 "S02" 78.68 76.08 69.89 40.67 42.42 26.09
+219 "S03" 94.62 94.65 86.45 65.09 68.67 41.71
+220 "S04" 0 10.44 63.73 3.01 3.34 15.4
+221 "S05" 0 57.08 10.66 3.26 11.22 2.89
+222 "S06" 82.88 0 10.83 17.7 8.11 0.42
+223 "S07" 99.49 100 99.75 89.01 92.27 74.63
+224 "S08" 0.01 0 0.02 0.28 0.29 0.24
+225 "S09" 99.68 99.73 0.01 72.92 74.82 4.56
+226 "S10" 81.93 0 35.68 17.03 7.57 3.05
+227 "S11" 0 45.14 76.9 6.56 11.29 24.29
+228 "S12" 49.85 49.34 53.67 18.91 19.64 16.46
+229 "T01" 49.85 49.34 53.67 18.91 19.64 16.46
+230 "T02" 9.97 12.59 14.91 3.05 3.16 2.73
+231 "T03" 95.15 94.21 99.99 74.38 77.15 64.2
+232 "T04" 49.92 49.43 53.72 18.94 19.68 16.48
+233 "T05" 10.35 13.04 15.35 3.12 3.24 2.79
+234 "T06" 95.13 94.16 99.93 74.2 76.97 63.98
+235 "T07" 49.74 49.3 53.61 18.87 19.61 16.43
+236 "T08" 9.84 12.67 14.89 3.04 3.16 2.73
+237 "T09" 95.22 94.29 99.96 74.41 77.19 64.05
+238 "T10" 49.82 49.33 53.67 18.9 19.63 16.46
+239 "T11" 10.16 12.77 15.31 3.09 3.2 2.78
+240 "T12" 95.28 94.32 100 74.57 77.32 64.19
+END_DATA
diff --git a/ref/EBU3213_PAL.icm b/ref/EBU3213_PAL.icm
new file mode 100644
index 0000000..54cfed7
--- /dev/null
+++ b/ref/EBU3213_PAL.icm
Binary files differ
diff --git a/ref/F1.sp b/ref/F1.sp
new file mode 100644
index 0000000..908cd72
--- /dev/null
+++ b/ref/F1.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F1 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.87 2.36 2.94 3.47 5.17 19.49 6.13 6.24 7.01 7.79 8.56 43.67 16.94 10.72 11.35 11.89 12.37 12.75 13.00 13.15 13.23 13.17 13.13 12.85 12.52 12.20 11.83 11.50 11.22 11.05 11.03 11.18 11.53 27.74 17.05 13.55 14.33 15.01 15.52 18.29 19.55 15.48 14.91 14.15 13.22 12.19 11.12 10.03 8.95 7.96 7.02 6.20 5.42 4.73 4.15 3.64 3.20 2.81 2.47 2.18 1.93 1.72 1.67 1.43 1.29 1.19 1.08 0.96 0.88 0.81 0.77 0.75 0.73 0.68 0.69 0.64 0.68 0.69 0.61 0.52 0.43
+END_DATA
diff --git a/ref/F5.sp b/ref/F5.sp
new file mode 100644
index 0000000..4959a50
--- /dev/null
+++ b/ref/F5.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F5 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.87 2.35 2.92 3.45 5.10 18.91 6.00 6.11 6.85 7.58 8.31 40.76 16.06 10.32 10.91 11.40 11.83 12.17 12.40 12.54 12.58 12.52 12.47 12.20 11.89 11.61 11.33 11.10 10.96 10.97 11.16 11.54 12.12 27.78 17.73 14.47 15.20 15.77 16.10 18.54 19.50 15.39 14.64 13.72 12.69 11.57 10.45 9.35 8.29 7.32 6.41 5.63 4.90 4.26 3.72 3.25 2.83 2.49 2.19 1.93 1.71 1.52 1.43 1.26 1.13 1.05 0.96 0.85 0.78 0.72 0.68 0.67 0.65 0.61 0.62 0.59 0.62 0.64 0.55 0.47 0.40
+END_DATA
diff --git a/ref/F8.sp b/ref/F8.sp
new file mode 100644
index 0000000..f1e7beb
--- /dev/null
+++ b/ref/F8.sp
@@ -0,0 +1,106 @@
+SPECT
+
+DESCRIPTOR "Argyll F8 illimunant spectral power"
+
+ORIGINATOR "Argyll CMS"
+
+CREATED "Fri Jul 06 17:49:57 2001"
+KEYWORD "SPECTRAL_BANDS"
+SPECTRAL_BANDS "81"
+KEYWORD "SPECTRAL_START_NM"
+SPECTRAL_START_NM "380.000000"
+KEYWORD "SPECTRAL_END_NM"
+SPECTRAL_END_NM "780.000000"
+KEYWORD "SPECTRAL_NORM"
+SPECTRAL_NORM "30.00"
+
+KEYWORD "SPEC_380"
+KEYWORD "SPEC_385"
+KEYWORD "SPEC_390"
+KEYWORD "SPEC_395"
+KEYWORD "SPEC_400"
+KEYWORD "SPEC_405"
+KEYWORD "SPEC_410"
+KEYWORD "SPEC_415"
+KEYWORD "SPEC_420"
+KEYWORD "SPEC_425"
+KEYWORD "SPEC_430"
+KEYWORD "SPEC_435"
+KEYWORD "SPEC_440"
+KEYWORD "SPEC_445"
+KEYWORD "SPEC_450"
+KEYWORD "SPEC_455"
+KEYWORD "SPEC_460"
+KEYWORD "SPEC_465"
+KEYWORD "SPEC_470"
+KEYWORD "SPEC_475"
+KEYWORD "SPEC_480"
+KEYWORD "SPEC_485"
+KEYWORD "SPEC_490"
+KEYWORD "SPEC_495"
+KEYWORD "SPEC_500"
+KEYWORD "SPEC_505"
+KEYWORD "SPEC_510"
+KEYWORD "SPEC_515"
+KEYWORD "SPEC_520"
+KEYWORD "SPEC_525"
+KEYWORD "SPEC_530"
+KEYWORD "SPEC_535"
+KEYWORD "SPEC_540"
+KEYWORD "SPEC_545"
+KEYWORD "SPEC_550"
+KEYWORD "SPEC_555"
+KEYWORD "SPEC_560"
+KEYWORD "SPEC_565"
+KEYWORD "SPEC_570"
+KEYWORD "SPEC_575"
+KEYWORD "SPEC_580"
+KEYWORD "SPEC_585"
+KEYWORD "SPEC_590"
+KEYWORD "SPEC_595"
+KEYWORD "SPEC_600"
+KEYWORD "SPEC_605"
+KEYWORD "SPEC_610"
+KEYWORD "SPEC_615"
+KEYWORD "SPEC_620"
+KEYWORD "SPEC_625"
+KEYWORD "SPEC_630"
+KEYWORD "SPEC_635"
+KEYWORD "SPEC_640"
+KEYWORD "SPEC_645"
+KEYWORD "SPEC_650"
+KEYWORD "SPEC_655"
+KEYWORD "SPEC_660"
+KEYWORD "SPEC_665"
+KEYWORD "SPEC_670"
+KEYWORD "SPEC_675"
+KEYWORD "SPEC_680"
+KEYWORD "SPEC_685"
+KEYWORD "SPEC_690"
+KEYWORD "SPEC_695"
+KEYWORD "SPEC_700"
+KEYWORD "SPEC_705"
+KEYWORD "SPEC_710"
+KEYWORD "SPEC_715"
+KEYWORD "SPEC_720"
+KEYWORD "SPEC_725"
+KEYWORD "SPEC_730"
+KEYWORD "SPEC_735"
+KEYWORD "SPEC_740"
+KEYWORD "SPEC_745"
+KEYWORD "SPEC_750"
+KEYWORD "SPEC_755"
+KEYWORD "SPEC_760"
+KEYWORD "SPEC_765"
+KEYWORD "SPEC_770"
+KEYWORD "SPEC_775"
+KEYWORD "SPEC_780"
+NUMBER_OF_FIELDS 81
+BEGIN_DATA_FORMAT
+SPEC_380 SPEC_385 SPEC_390 SPEC_395 SPEC_400 SPEC_405 SPEC_410 SPEC_415 SPEC_420 SPEC_425 SPEC_430 SPEC_435 SPEC_440 SPEC_445 SPEC_450 SPEC_455 SPEC_460 SPEC_465 SPEC_470 SPEC_475 SPEC_480 SPEC_485 SPEC_490 SPEC_495 SPEC_500 SPEC_505 SPEC_510 SPEC_515 SPEC_520 SPEC_525 SPEC_530 SPEC_535 SPEC_540 SPEC_545 SPEC_550 SPEC_555 SPEC_560 SPEC_565 SPEC_570 SPEC_575 SPEC_580 SPEC_585 SPEC_590 SPEC_595 SPEC_600 SPEC_605 SPEC_610 SPEC_615 SPEC_620 SPEC_625 SPEC_630 SPEC_635 SPEC_640 SPEC_645 SPEC_650 SPEC_655 SPEC_660 SPEC_665 SPEC_670 SPEC_675 SPEC_680 SPEC_685 SPEC_690 SPEC_695 SPEC_700 SPEC_705 SPEC_710 SPEC_715 SPEC_720 SPEC_725 SPEC_730 SPEC_735 SPEC_740 SPEC_745 SPEC_750 SPEC_755 SPEC_760 SPEC_765 SPEC_770 SPEC_775 SPEC_780
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 1
+BEGIN_DATA
+1.21 1.50 1.81 2.13 3.17 13.08 3.83 3.45 3.86 4.42 5.09 34.10 12.42 7.68 8.60 9.46 10.24 10.84 11.33 11.71 11.98 12.17 12.28 12.32 12.35 12.44 12.55 12.68 12.77 12.72 12.60 12.43 12.22 28.96 16.51 11.79 11.76 11.77 11.84 14.61 16.11 12.34 12.53 12.72 12.92 13.12 13.34 13.61 13.87 14.07 14.20 14.16 14.13 14.34 14.50 14.46 14.00 12.58 10.99 9.98 9.22 8.62 8.07 7.39 6.71 6.16 5.63 5.03 4.46 4.02 3.66 3.36 3.09 2.85 2.65 2.51 2.37 2.15 1.89 1.61 1.32
+END_DATA
diff --git a/ref/ProPhoto.icm b/ref/ProPhoto.icm
new file mode 100644
index 0000000..3ed16cb
--- /dev/null
+++ b/ref/ProPhoto.icm
Binary files differ
diff --git a/ref/ProPhotoLin.icm b/ref/ProPhotoLin.icm
new file mode 100644
index 0000000..579b903
--- /dev/null
+++ b/ref/ProPhotoLin.icm
Binary files differ
diff --git a/ref/ReadMe.txt b/ref/ReadMe.txt
index ab03ad5..10dc457 100644
--- a/ref/ReadMe.txt
+++ b/ref/ReadMe.txt
@@ -8,6 +8,10 @@ The following files are in the public domain:
ClayRGB1998.icm
lab2lab.icm
+ Rec709.icm Standard Rec 709 High Def. Video space
+ EBU3213_PAL.icm PAL TV Standard Def. type colorspace with Rec 709 transfer curve
+ SMPTE_RP145_NTSC.icm NTSC TV Standard Def. type colorspace with Rec 709 transfer curve
+
The following files are licensed acording to the
GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
see the License.txt file for licensing details.
diff --git a/ref/Rec2020.icm b/ref/Rec2020.icm
new file mode 100644
index 0000000..09d5ccf
--- /dev/null
+++ b/ref/Rec2020.icm
Binary files differ
diff --git a/ref/Rec709.icm b/ref/Rec709.icm
new file mode 100644
index 0000000..46140bd
--- /dev/null
+++ b/ref/Rec709.icm
Binary files differ
diff --git a/ref/SMPTE431_P3.icm b/ref/SMPTE431_P3.icm
new file mode 100644
index 0000000..f3861be
--- /dev/null
+++ b/ref/SMPTE431_P3.icm
Binary files differ
diff --git a/ref/SMPTE_RP145_NTSC.icm b/ref/SMPTE_RP145_NTSC.icm
new file mode 100644
index 0000000..a6ce7f1
--- /dev/null
+++ b/ref/SMPTE_RP145_NTSC.icm
Binary files differ
diff --git a/ref/afiles b/ref/afiles
index 17bdef2..f5d9028 100644
--- a/ref/afiles
+++ b/ref/afiles
@@ -3,6 +3,13 @@ ReadMe.txt
License.txt
sRGB.icm
ClayRGB1998.icm
+ProPhoto.icm
+ProPhotoLin.icm
+EBU3213_PAL.icm
+SMPTE_RP145_NTSC.icm
+Rec709.icm
+Rec2020.icm
+SMPTE431_P3.icm
lab2lab.icm
ccxx.ti1
CMP_DT_003.cht
@@ -13,6 +20,7 @@ ColorChecker.cht
ColorChecker.cie
ColorChecker.ti2
ColorCheckerDC.cht
+ColorCheckerDC.ti2
ColorCheckerSG.cht
ColorCheckerPassport.cht
ColorCheckerPassport.cie
@@ -36,6 +44,9 @@ it8.cht
linear.cal
strange.cal
3dap5k.sp
+F1.sp
+F5.sp
+F8.sp
CIE_C.sp
D50_0.0.sp
D50_0.1.sp
diff --git a/ref/lab2lab.icm b/ref/lab2lab.icm
index fe518e6..0b8a4b3 100644
--- a/ref/lab2lab.icm
+++ b/ref/lab2lab.icm
Binary files differ
diff --git a/ref/linear.cal b/ref/linear.cal
index 30da145..6001c2d 100644
--- a/ref/linear.cal
+++ b/ref/linear.cal
@@ -2,7 +2,7 @@ CAL
DESCRIPTOR "Argyll Device Calibration Curves"
ORIGINATOR "Argyll synthcal"
-CREATED "Sat Mar 09 18:33:22 2013"
+CREATED "Tue Nov 12 17:20:57 2013"
KEYWORD "DEVICE_CLASS"
DEVICE_CLASS "DISPLAY"
KEYWORD "COLOR_REP"
@@ -16,260 +16,260 @@ END_DATA_FORMAT
NUMBER_OF_SETS 256
BEGIN_DATA
-0.0000 0.0000 0.0000 0.0000
-3.9216e-003 3.9216e-003 3.9216e-003 3.9216e-003
-7.8431e-003 7.8431e-003 7.8431e-003 7.8431e-003
-0.011765 0.011765 0.011765 0.011765
-0.015686 0.015686 0.015686 0.015686
-0.019608 0.019608 0.019608 0.019608
-0.023529 0.023529 0.023529 0.023529
-0.027451 0.027451 0.027451 0.027451
-0.031373 0.031373 0.031373 0.031373
-0.035294 0.035294 0.035294 0.035294
-0.039216 0.039216 0.039216 0.039216
-0.043137 0.043137 0.043137 0.043137
-0.047059 0.047059 0.047059 0.047059
-0.050980 0.050980 0.050980 0.050980
-0.054902 0.054902 0.054902 0.054902
-0.058824 0.058824 0.058824 0.058824
-0.062745 0.062745 0.062745 0.062745
-0.066667 0.066667 0.066667 0.066667
-0.070588 0.070588 0.070588 0.070588
-0.074510 0.074510 0.074510 0.074510
-0.078431 0.078431 0.078431 0.078431
-0.082353 0.082353 0.082353 0.082353
-0.086275 0.086275 0.086275 0.086275
-0.090196 0.090196 0.090196 0.090196
-0.094118 0.094118 0.094118 0.094118
-0.098039 0.098039 0.098039 0.098039
-0.10196 0.10196 0.10196 0.10196
-0.10588 0.10588 0.10588 0.10588
-0.10980 0.10980 0.10980 0.10980
-0.11373 0.11373 0.11373 0.11373
-0.11765 0.11765 0.11765 0.11765
-0.12157 0.12157 0.12157 0.12157
-0.12549 0.12549 0.12549 0.12549
-0.12941 0.12941 0.12941 0.12941
-0.13333 0.13333 0.13333 0.13333
-0.13725 0.13725 0.13725 0.13725
-0.14118 0.14118 0.14118 0.14118
-0.14510 0.14510 0.14510 0.14510
-0.14902 0.14902 0.14902 0.14902
-0.15294 0.15294 0.15294 0.15294
-0.15686 0.15686 0.15686 0.15686
-0.16078 0.16078 0.16078 0.16078
-0.16471 0.16471 0.16471 0.16471
-0.16863 0.16863 0.16863 0.16863
-0.17255 0.17255 0.17255 0.17255
-0.17647 0.17647 0.17647 0.17647
-0.18039 0.18039 0.18039 0.18039
-0.18431 0.18431 0.18431 0.18431
-0.18824 0.18824 0.18824 0.18824
-0.19216 0.19216 0.19216 0.19216
-0.19608 0.19608 0.19608 0.19608
-0.20000 0.20000 0.20000 0.20000
-0.20392 0.20392 0.20392 0.20392
-0.20784 0.20784 0.20784 0.20784
-0.21176 0.21176 0.21176 0.21176
-0.21569 0.21569 0.21569 0.21569
-0.21961 0.21961 0.21961 0.21961
-0.22353 0.22353 0.22353 0.22353
-0.22745 0.22745 0.22745 0.22745
-0.23137 0.23137 0.23137 0.23137
-0.23529 0.23529 0.23529 0.23529
-0.23922 0.23922 0.23922 0.23922
-0.24314 0.24314 0.24314 0.24314
-0.24706 0.24706 0.24706 0.24706
-0.25098 0.25098 0.25098 0.25098
-0.25490 0.25490 0.25490 0.25490
-0.25882 0.25882 0.25882 0.25882
-0.26275 0.26275 0.26275 0.26275
-0.26667 0.26667 0.26667 0.26667
-0.27059 0.27059 0.27059 0.27059
-0.27451 0.27451 0.27451 0.27451
-0.27843 0.27843 0.27843 0.27843
-0.28235 0.28235 0.28235 0.28235
-0.28627 0.28627 0.28627 0.28627
-0.29020 0.29020 0.29020 0.29020
-0.29412 0.29412 0.29412 0.29412
-0.29804 0.29804 0.29804 0.29804
-0.30196 0.30196 0.30196 0.30196
-0.30588 0.30588 0.30588 0.30588
-0.30980 0.30980 0.30980 0.30980
-0.31373 0.31373 0.31373 0.31373
-0.31765 0.31765 0.31765 0.31765
-0.32157 0.32157 0.32157 0.32157
-0.32549 0.32549 0.32549 0.32549
-0.32941 0.32941 0.32941 0.32941
-0.33333 0.33333 0.33333 0.33333
-0.33725 0.33725 0.33725 0.33725
-0.34118 0.34118 0.34118 0.34118
-0.34510 0.34510 0.34510 0.34510
-0.34902 0.34902 0.34902 0.34902
-0.35294 0.35294 0.35294 0.35294
-0.35686 0.35686 0.35686 0.35686
-0.36078 0.36078 0.36078 0.36078
-0.36471 0.36471 0.36471 0.36471
-0.36863 0.36863 0.36863 0.36863
-0.37255 0.37255 0.37255 0.37255
-0.37647 0.37647 0.37647 0.37647
-0.38039 0.38039 0.38039 0.38039
-0.38431 0.38431 0.38431 0.38431
-0.38824 0.38824 0.38824 0.38824
-0.39216 0.39216 0.39216 0.39216
-0.39608 0.39608 0.39608 0.39608
-0.40000 0.40000 0.40000 0.40000
-0.40392 0.40392 0.40392 0.40392
-0.40784 0.40784 0.40784 0.40784
-0.41176 0.41176 0.41176 0.41176
-0.41569 0.41569 0.41569 0.41569
-0.41961 0.41961 0.41961 0.41961
-0.42353 0.42353 0.42353 0.42353
-0.42745 0.42745 0.42745 0.42745
-0.43137 0.43137 0.43137 0.43137
-0.43529 0.43529 0.43529 0.43529
-0.43922 0.43922 0.43922 0.43922
-0.44314 0.44314 0.44314 0.44314
-0.44706 0.44706 0.44706 0.44706
-0.45098 0.45098 0.45098 0.45098
-0.45490 0.45490 0.45490 0.45490
-0.45882 0.45882 0.45882 0.45882
-0.46275 0.46275 0.46275 0.46275
-0.46667 0.46667 0.46667 0.46667
-0.47059 0.47059 0.47059 0.47059
-0.47451 0.47451 0.47451 0.47451
-0.47843 0.47843 0.47843 0.47843
-0.48235 0.48235 0.48235 0.48235
-0.48627 0.48627 0.48627 0.48627
-0.49020 0.49020 0.49020 0.49020
-0.49412 0.49412 0.49412 0.49412
-0.49804 0.49804 0.49804 0.49804
-0.50196 0.50196 0.50196 0.50196
-0.50588 0.50588 0.50588 0.50588
-0.50980 0.50980 0.50980 0.50980
-0.51373 0.51373 0.51373 0.51373
-0.51765 0.51765 0.51765 0.51765
-0.52157 0.52157 0.52157 0.52157
-0.52549 0.52549 0.52549 0.52549
-0.52941 0.52941 0.52941 0.52941
-0.53333 0.53333 0.53333 0.53333
-0.53725 0.53725 0.53725 0.53725
-0.54118 0.54118 0.54118 0.54118
-0.54510 0.54510 0.54510 0.54510
-0.54902 0.54902 0.54902 0.54902
-0.55294 0.55294 0.55294 0.55294
-0.55686 0.55686 0.55686 0.55686
-0.56078 0.56078 0.56078 0.56078
-0.56471 0.56471 0.56471 0.56471
-0.56863 0.56863 0.56863 0.56863
-0.57255 0.57255 0.57255 0.57255
-0.57647 0.57647 0.57647 0.57647
-0.58039 0.58039 0.58039 0.58039
-0.58431 0.58431 0.58431 0.58431
-0.58824 0.58824 0.58824 0.58824
-0.59216 0.59216 0.59216 0.59216
-0.59608 0.59608 0.59608 0.59608
-0.60000 0.60000 0.60000 0.60000
-0.60392 0.60392 0.60392 0.60392
-0.60784 0.60784 0.60784 0.60784
-0.61176 0.61176 0.61176 0.61176
-0.61569 0.61569 0.61569 0.61569
-0.61961 0.61961 0.61961 0.61961
-0.62353 0.62353 0.62353 0.62353
-0.62745 0.62745 0.62745 0.62745
-0.63137 0.63137 0.63137 0.63137
-0.63529 0.63529 0.63529 0.63529
-0.63922 0.63922 0.63922 0.63922
-0.64314 0.64314 0.64314 0.64314
-0.64706 0.64706 0.64706 0.64706
-0.65098 0.65098 0.65098 0.65098
-0.65490 0.65490 0.65490 0.65490
-0.65882 0.65882 0.65882 0.65882
-0.66275 0.66275 0.66275 0.66275
-0.66667 0.66667 0.66667 0.66667
-0.67059 0.67059 0.67059 0.67059
-0.67451 0.67451 0.67451 0.67451
-0.67843 0.67843 0.67843 0.67843
-0.68235 0.68235 0.68235 0.68235
-0.68627 0.68627 0.68627 0.68627
-0.69020 0.69020 0.69020 0.69020
-0.69412 0.69412 0.69412 0.69412
-0.69804 0.69804 0.69804 0.69804
-0.70196 0.70196 0.70196 0.70196
-0.70588 0.70588 0.70588 0.70588
-0.70980 0.70980 0.70980 0.70980
-0.71373 0.71373 0.71373 0.71373
-0.71765 0.71765 0.71765 0.71765
-0.72157 0.72157 0.72157 0.72157
-0.72549 0.72549 0.72549 0.72549
-0.72941 0.72941 0.72941 0.72941
-0.73333 0.73333 0.73333 0.73333
-0.73725 0.73725 0.73725 0.73725
-0.74118 0.74118 0.74118 0.74118
-0.74510 0.74510 0.74510 0.74510
-0.74902 0.74902 0.74902 0.74902
-0.75294 0.75294 0.75294 0.75294
-0.75686 0.75686 0.75686 0.75686
-0.76078 0.76078 0.76078 0.76078
-0.76471 0.76471 0.76471 0.76471
-0.76863 0.76863 0.76863 0.76863
-0.77255 0.77255 0.77255 0.77255
-0.77647 0.77647 0.77647 0.77647
-0.78039 0.78039 0.78039 0.78039
-0.78431 0.78431 0.78431 0.78431
-0.78824 0.78824 0.78824 0.78824
-0.79216 0.79216 0.79216 0.79216
-0.79608 0.79608 0.79608 0.79608
-0.80000 0.80000 0.80000 0.80000
-0.80392 0.80392 0.80392 0.80392
-0.80784 0.80784 0.80784 0.80784
-0.81176 0.81176 0.81176 0.81176
-0.81569 0.81569 0.81569 0.81569
-0.81961 0.81961 0.81961 0.81961
-0.82353 0.82353 0.82353 0.82353
-0.82745 0.82745 0.82745 0.82745
-0.83137 0.83137 0.83137 0.83137
-0.83529 0.83529 0.83529 0.83529
-0.83922 0.83922 0.83922 0.83922
-0.84314 0.84314 0.84314 0.84314
-0.84706 0.84706 0.84706 0.84706
-0.85098 0.85098 0.85098 0.85098
-0.85490 0.85490 0.85490 0.85490
-0.85882 0.85882 0.85882 0.85882
-0.86275 0.86275 0.86275 0.86275
-0.86667 0.86667 0.86667 0.86667
-0.87059 0.87059 0.87059 0.87059
-0.87451 0.87451 0.87451 0.87451
-0.87843 0.87843 0.87843 0.87843
-0.88235 0.88235 0.88235 0.88235
-0.88627 0.88627 0.88627 0.88627
-0.89020 0.89020 0.89020 0.89020
-0.89412 0.89412 0.89412 0.89412
-0.89804 0.89804 0.89804 0.89804
-0.90196 0.90196 0.90196 0.90196
-0.90588 0.90588 0.90588 0.90588
-0.90980 0.90980 0.90980 0.90980
-0.91373 0.91373 0.91373 0.91373
-0.91765 0.91765 0.91765 0.91765
-0.92157 0.92157 0.92157 0.92157
-0.92549 0.92549 0.92549 0.92549
-0.92941 0.92941 0.92941 0.92941
-0.93333 0.93333 0.93333 0.93333
-0.93725 0.93725 0.93725 0.93725
-0.94118 0.94118 0.94118 0.94118
-0.94510 0.94510 0.94510 0.94510
-0.94902 0.94902 0.94902 0.94902
-0.95294 0.95294 0.95294 0.95294
-0.95686 0.95686 0.95686 0.95686
-0.96078 0.96078 0.96078 0.96078
-0.96471 0.96471 0.96471 0.96471
-0.96863 0.96863 0.96863 0.96863
-0.97255 0.97255 0.97255 0.97255
-0.97647 0.97647 0.97647 0.97647
-0.98039 0.98039 0.98039 0.98039
-0.98431 0.98431 0.98431 0.98431
-0.98824 0.98824 0.98824 0.98824
-0.99216 0.99216 0.99216 0.99216
-0.99608 0.99608 0.99608 0.99608
-1.0000 1.0000 1.0000 1.0000
+0.00000 0.00000 0.00000 0.00000
+3.92157e-003 3.92157e-003 3.92157e-003 3.92157e-003
+7.84314e-003 7.84314e-003 7.84314e-003 7.84314e-003
+0.0117647 0.0117647 0.0117647 0.0117647
+0.0156863 0.0156863 0.0156863 0.0156863
+0.0196078 0.0196078 0.0196078 0.0196078
+0.0235294 0.0235294 0.0235294 0.0235294
+0.0274510 0.0274510 0.0274510 0.0274510
+0.0313725 0.0313725 0.0313725 0.0313725
+0.0352941 0.0352941 0.0352941 0.0352941
+0.0392157 0.0392157 0.0392157 0.0392157
+0.0431373 0.0431373 0.0431373 0.0431373
+0.0470588 0.0470588 0.0470588 0.0470588
+0.0509804 0.0509804 0.0509804 0.0509804
+0.0549020 0.0549020 0.0549020 0.0549020
+0.0588235 0.0588235 0.0588235 0.0588235
+0.0627451 0.0627451 0.0627451 0.0627451
+0.0666667 0.0666667 0.0666667 0.0666667
+0.0705882 0.0705882 0.0705882 0.0705882
+0.0745098 0.0745098 0.0745098 0.0745098
+0.0784314 0.0784314 0.0784314 0.0784314
+0.0823529 0.0823529 0.0823529 0.0823529
+0.0862745 0.0862745 0.0862745 0.0862745
+0.0901961 0.0901961 0.0901961 0.0901961
+0.0941176 0.0941176 0.0941176 0.0941176
+0.0980392 0.0980392 0.0980392 0.0980392
+0.101961 0.101961 0.101961 0.101961
+0.105882 0.105882 0.105882 0.105882
+0.109804 0.109804 0.109804 0.109804
+0.113725 0.113725 0.113725 0.113725
+0.117647 0.117647 0.117647 0.117647
+0.121569 0.121569 0.121569 0.121569
+0.125490 0.125490 0.125490 0.125490
+0.129412 0.129412 0.129412 0.129412
+0.133333 0.133333 0.133333 0.133333
+0.137255 0.137255 0.137255 0.137255
+0.141176 0.141176 0.141176 0.141176
+0.145098 0.145098 0.145098 0.145098
+0.149020 0.149020 0.149020 0.149020
+0.152941 0.152941 0.152941 0.152941
+0.156863 0.156863 0.156863 0.156863
+0.160784 0.160784 0.160784 0.160784
+0.164706 0.164706 0.164706 0.164706
+0.168627 0.168627 0.168627 0.168627
+0.172549 0.172549 0.172549 0.172549
+0.176471 0.176471 0.176471 0.176471
+0.180392 0.180392 0.180392 0.180392
+0.184314 0.184314 0.184314 0.184314
+0.188235 0.188235 0.188235 0.188235
+0.192157 0.192157 0.192157 0.192157
+0.196078 0.196078 0.196078 0.196078
+0.200000 0.200000 0.200000 0.200000
+0.203922 0.203922 0.203922 0.203922
+0.207843 0.207843 0.207843 0.207843
+0.211765 0.211765 0.211765 0.211765
+0.215686 0.215686 0.215686 0.215686
+0.219608 0.219608 0.219608 0.219608
+0.223529 0.223529 0.223529 0.223529
+0.227451 0.227451 0.227451 0.227451
+0.231373 0.231373 0.231373 0.231373
+0.235294 0.235294 0.235294 0.235294
+0.239216 0.239216 0.239216 0.239216
+0.243137 0.243137 0.243137 0.243137
+0.247059 0.247059 0.247059 0.247059
+0.250980 0.250980 0.250980 0.250980
+0.254902 0.254902 0.254902 0.254902
+0.258824 0.258824 0.258824 0.258824
+0.262745 0.262745 0.262745 0.262745
+0.266667 0.266667 0.266667 0.266667
+0.270588 0.270588 0.270588 0.270588
+0.274510 0.274510 0.274510 0.274510
+0.278431 0.278431 0.278431 0.278431
+0.282353 0.282353 0.282353 0.282353
+0.286275 0.286275 0.286275 0.286275
+0.290196 0.290196 0.290196 0.290196
+0.294118 0.294118 0.294118 0.294118
+0.298039 0.298039 0.298039 0.298039
+0.301961 0.301961 0.301961 0.301961
+0.305882 0.305882 0.305882 0.305882
+0.309804 0.309804 0.309804 0.309804
+0.313725 0.313725 0.313725 0.313725
+0.317647 0.317647 0.317647 0.317647
+0.321569 0.321569 0.321569 0.321569
+0.325490 0.325490 0.325490 0.325490
+0.329412 0.329412 0.329412 0.329412
+0.333333 0.333333 0.333333 0.333333
+0.337255 0.337255 0.337255 0.337255
+0.341176 0.341176 0.341176 0.341176
+0.345098 0.345098 0.345098 0.345098
+0.349020 0.349020 0.349020 0.349020
+0.352941 0.352941 0.352941 0.352941
+0.356863 0.356863 0.356863 0.356863
+0.360784 0.360784 0.360784 0.360784
+0.364706 0.364706 0.364706 0.364706
+0.368627 0.368627 0.368627 0.368627
+0.372549 0.372549 0.372549 0.372549
+0.376471 0.376471 0.376471 0.376471
+0.380392 0.380392 0.380392 0.380392
+0.384314 0.384314 0.384314 0.384314
+0.388235 0.388235 0.388235 0.388235
+0.392157 0.392157 0.392157 0.392157
+0.396078 0.396078 0.396078 0.396078
+0.400000 0.400000 0.400000 0.400000
+0.403922 0.403922 0.403922 0.403922
+0.407843 0.407843 0.407843 0.407843
+0.411765 0.411765 0.411765 0.411765
+0.415686 0.415686 0.415686 0.415686
+0.419608 0.419608 0.419608 0.419608
+0.423529 0.423529 0.423529 0.423529
+0.427451 0.427451 0.427451 0.427451
+0.431373 0.431373 0.431373 0.431373
+0.435294 0.435294 0.435294 0.435294
+0.439216 0.439216 0.439216 0.439216
+0.443137 0.443137 0.443137 0.443137
+0.447059 0.447059 0.447059 0.447059
+0.450980 0.450980 0.450980 0.450980
+0.454902 0.454902 0.454902 0.454902
+0.458824 0.458824 0.458824 0.458824
+0.462745 0.462745 0.462745 0.462745
+0.466667 0.466667 0.466667 0.466667
+0.470588 0.470588 0.470588 0.470588
+0.474510 0.474510 0.474510 0.474510
+0.478431 0.478431 0.478431 0.478431
+0.482353 0.482353 0.482353 0.482353
+0.486275 0.486275 0.486275 0.486275
+0.490196 0.490196 0.490196 0.490196
+0.494118 0.494118 0.494118 0.494118
+0.498039 0.498039 0.498039 0.498039
+0.501961 0.501961 0.501961 0.501961
+0.505882 0.505882 0.505882 0.505882
+0.509804 0.509804 0.509804 0.509804
+0.513725 0.513725 0.513725 0.513725
+0.517647 0.517647 0.517647 0.517647
+0.521569 0.521569 0.521569 0.521569
+0.525490 0.525490 0.525490 0.525490
+0.529412 0.529412 0.529412 0.529412
+0.533333 0.533333 0.533333 0.533333
+0.537255 0.537255 0.537255 0.537255
+0.541176 0.541176 0.541176 0.541176
+0.545098 0.545098 0.545098 0.545098
+0.549020 0.549020 0.549020 0.549020
+0.552941 0.552941 0.552941 0.552941
+0.556863 0.556863 0.556863 0.556863
+0.560784 0.560784 0.560784 0.560784
+0.564706 0.564706 0.564706 0.564706
+0.568627 0.568627 0.568627 0.568627
+0.572549 0.572549 0.572549 0.572549
+0.576471 0.576471 0.576471 0.576471
+0.580392 0.580392 0.580392 0.580392
+0.584314 0.584314 0.584314 0.584314
+0.588235 0.588235 0.588235 0.588235
+0.592157 0.592157 0.592157 0.592157
+0.596078 0.596078 0.596078 0.596078
+0.600000 0.600000 0.600000 0.600000
+0.603922 0.603922 0.603922 0.603922
+0.607843 0.607843 0.607843 0.607843
+0.611765 0.611765 0.611765 0.611765
+0.615686 0.615686 0.615686 0.615686
+0.619608 0.619608 0.619608 0.619608
+0.623529 0.623529 0.623529 0.623529
+0.627451 0.627451 0.627451 0.627451
+0.631373 0.631373 0.631373 0.631373
+0.635294 0.635294 0.635294 0.635294
+0.639216 0.639216 0.639216 0.639216
+0.643137 0.643137 0.643137 0.643137
+0.647059 0.647059 0.647059 0.647059
+0.650980 0.650980 0.650980 0.650980
+0.654902 0.654902 0.654902 0.654902
+0.658824 0.658824 0.658824 0.658824
+0.662745 0.662745 0.662745 0.662745
+0.666667 0.666667 0.666667 0.666667
+0.670588 0.670588 0.670588 0.670588
+0.674510 0.674510 0.674510 0.674510
+0.678431 0.678431 0.678431 0.678431
+0.682353 0.682353 0.682353 0.682353
+0.686275 0.686275 0.686275 0.686275
+0.690196 0.690196 0.690196 0.690196
+0.694118 0.694118 0.694118 0.694118
+0.698039 0.698039 0.698039 0.698039
+0.701961 0.701961 0.701961 0.701961
+0.705882 0.705882 0.705882 0.705882
+0.709804 0.709804 0.709804 0.709804
+0.713725 0.713725 0.713725 0.713725
+0.717647 0.717647 0.717647 0.717647
+0.721569 0.721569 0.721569 0.721569
+0.725490 0.725490 0.725490 0.725490
+0.729412 0.729412 0.729412 0.729412
+0.733333 0.733333 0.733333 0.733333
+0.737255 0.737255 0.737255 0.737255
+0.741176 0.741176 0.741176 0.741176
+0.745098 0.745098 0.745098 0.745098
+0.749020 0.749020 0.749020 0.749020
+0.752941 0.752941 0.752941 0.752941
+0.756863 0.756863 0.756863 0.756863
+0.760784 0.760784 0.760784 0.760784
+0.764706 0.764706 0.764706 0.764706
+0.768627 0.768627 0.768627 0.768627
+0.772549 0.772549 0.772549 0.772549
+0.776471 0.776471 0.776471 0.776471
+0.780392 0.780392 0.780392 0.780392
+0.784314 0.784314 0.784314 0.784314
+0.788235 0.788235 0.788235 0.788235
+0.792157 0.792157 0.792157 0.792157
+0.796078 0.796078 0.796078 0.796078
+0.800000 0.800000 0.800000 0.800000
+0.803922 0.803922 0.803922 0.803922
+0.807843 0.807843 0.807843 0.807843
+0.811765 0.811765 0.811765 0.811765
+0.815686 0.815686 0.815686 0.815686
+0.819608 0.819608 0.819608 0.819608
+0.823529 0.823529 0.823529 0.823529
+0.827451 0.827451 0.827451 0.827451
+0.831373 0.831373 0.831373 0.831373
+0.835294 0.835294 0.835294 0.835294
+0.839216 0.839216 0.839216 0.839216
+0.843137 0.843137 0.843137 0.843137
+0.847059 0.847059 0.847059 0.847059
+0.850980 0.850980 0.850980 0.850980
+0.854902 0.854902 0.854902 0.854902
+0.858824 0.858824 0.858824 0.858824
+0.862745 0.862745 0.862745 0.862745
+0.866667 0.866667 0.866667 0.866667
+0.870588 0.870588 0.870588 0.870588
+0.874510 0.874510 0.874510 0.874510
+0.878431 0.878431 0.878431 0.878431
+0.882353 0.882353 0.882353 0.882353
+0.886275 0.886275 0.886275 0.886275
+0.890196 0.890196 0.890196 0.890196
+0.894118 0.894118 0.894118 0.894118
+0.898039 0.898039 0.898039 0.898039
+0.901961 0.901961 0.901961 0.901961
+0.905882 0.905882 0.905882 0.905882
+0.909804 0.909804 0.909804 0.909804
+0.913725 0.913725 0.913725 0.913725
+0.917647 0.917647 0.917647 0.917647
+0.921569 0.921569 0.921569 0.921569
+0.925490 0.925490 0.925490 0.925490
+0.929412 0.929412 0.929412 0.929412
+0.933333 0.933333 0.933333 0.933333
+0.937255 0.937255 0.937255 0.937255
+0.941176 0.941176 0.941176 0.941176
+0.945098 0.945098 0.945098 0.945098
+0.949020 0.949020 0.949020 0.949020
+0.952941 0.952941 0.952941 0.952941
+0.956863 0.956863 0.956863 0.956863
+0.960784 0.960784 0.960784 0.960784
+0.964706 0.964706 0.964706 0.964706
+0.968627 0.968627 0.968627 0.968627
+0.972549 0.972549 0.972549 0.972549
+0.976471 0.976471 0.976471 0.976471
+0.980392 0.980392 0.980392 0.980392
+0.984314 0.984314 0.984314 0.984314
+0.988235 0.988235 0.988235 0.988235
+0.992157 0.992157 0.992157 0.992157
+0.996078 0.996078 0.996078 0.996078
+1.00000 1.00000 1.00000 1.00000
END_DATA
diff --git a/ref/sRGB.icm b/ref/sRGB.icm
index db0355f..5491330 100644
--- a/ref/sRGB.icm
+++ b/ref/sRGB.icm
Binary files differ
diff --git a/ref/strange.cal b/ref/strange.cal
index 23c1e87..2a81602 100644
--- a/ref/strange.cal
+++ b/ref/strange.cal
@@ -2,7 +2,7 @@ CAL
DESCRIPTOR "Argyll Device Calibration Curves"
ORIGINATOR "Argyll synthcal"
-CREATED "Sat Mar 09 18:33:22 2013"
+CREATED "Tue Nov 12 17:20:57 2013"
KEYWORD "DEVICE_CLASS"
DEVICE_CLASS "DISPLAY"
KEYWORD "COLOR_REP"
@@ -16,260 +16,260 @@ END_DATA_FORMAT
NUMBER_OF_SETS 256
BEGIN_DATA
-0.0000 0.0000 0.0000 0.0000
-3.9216e-003 5.6752e-005 0.011879 0.018606
-7.8431e-003 1.8439e-004 0.020682 0.030226
-0.011765 3.6735e-004 0.028607 0.040147
-0.015686 5.9908e-004 0.036009 0.049103
-0.019608 8.7544e-004 0.043047 0.057404
-0.023529 1.1935e-003 0.049807 0.065218
-0.027451 1.5511e-003 0.056344 0.072650
-0.031373 1.9464e-003 0.062696 0.079768
-0.035294 2.3779e-003 0.068891 0.086623
-0.039216 2.8443e-003 0.074949 0.093253
-0.043137 3.3446e-003 0.080888 0.099687
-0.047059 3.8778e-003 0.086719 0.10595
-0.050980 4.4431e-003 0.092453 0.11205
-0.054902 5.0396e-003 0.098100 0.11802
-0.058824 5.6668e-003 0.10367 0.12386
-0.062745 6.3239e-003 0.10916 0.12958
-0.066667 7.0104e-003 0.11458 0.13520
-0.070588 7.7258e-003 0.11995 0.14072
-0.074510 8.4696e-003 0.12525 0.14615
-0.078431 9.2413e-003 0.13049 0.15149
-0.082353 0.010040 0.13569 0.15675
-0.086275 0.010867 0.14083 0.16194
-0.090196 0.011720 0.14593 0.16706
-0.094118 0.012599 0.15099 0.17211
-0.098039 0.013504 0.15600 0.17710
-0.10196 0.014436 0.16097 0.18203
-0.10588 0.015392 0.16590 0.18690
-0.10980 0.016374 0.17080 0.19172
-0.11373 0.017380 0.17567 0.19649
-0.11765 0.018411 0.18049 0.20121
-0.12157 0.019467 0.18529 0.20588
-0.12549 0.020546 0.19006 0.21051
-0.12941 0.021650 0.19480 0.21509
-0.13333 0.022777 0.19950 0.21963
-0.13725 0.023927 0.20418 0.22414
-0.14118 0.025101 0.20884 0.22860
-0.14510 0.026298 0.21347 0.23303
-0.14902 0.027518 0.21807 0.23742
-0.15294 0.028760 0.22265 0.24177
-0.15686 0.030025 0.22720 0.24610
-0.16078 0.031312 0.23174 0.25039
-0.16471 0.032621 0.23625 0.25465
-0.16863 0.033953 0.24074 0.25888
-0.17255 0.035306 0.24521 0.26308
-0.17647 0.036681 0.24965 0.26725
-0.18039 0.038077 0.25408 0.27139
-0.18431 0.039495 0.25849 0.27551
-0.18824 0.040935 0.26288 0.27960
-0.19216 0.042395 0.26725 0.28366
-0.19608 0.043876 0.27161 0.28770
-0.20000 0.045378 0.27595 0.29172
-0.20392 0.046901 0.28027 0.29571
-0.20784 0.048445 0.28457 0.29968
-0.21176 0.050009 0.28886 0.30363
-0.21569 0.051594 0.29313 0.30755
-0.21961 0.053198 0.29738 0.31146
-0.22353 0.054824 0.30163 0.31534
-0.22745 0.056469 0.30585 0.31920
-0.23137 0.058134 0.31006 0.32304
-0.23529 0.059819 0.31426 0.32687
-0.23922 0.061523 0.31844 0.33067
-0.24314 0.063248 0.32261 0.33446
-0.24706 0.064992 0.32677 0.33822
-0.25098 0.066755 0.33091 0.34197
-0.25490 0.068538 0.33504 0.34570
-0.25882 0.070340 0.33916 0.34942
-0.26275 0.072162 0.34326 0.35312
-0.26667 0.074002 0.34736 0.35680
-0.27059 0.075862 0.35144 0.36046
-0.27451 0.077740 0.35551 0.36411
-0.27843 0.079638 0.35956 0.36774
-0.28235 0.081554 0.36361 0.37136
-0.28627 0.083489 0.36764 0.37496
-0.29020 0.085442 0.37167 0.37855
-0.29412 0.087415 0.37568 0.38213
-0.29804 0.089405 0.37968 0.38569
-0.30196 0.091414 0.38367 0.38923
-0.30588 0.093442 0.38765 0.39276
-0.30980 0.095487 0.39162 0.39628
-0.31373 0.097551 0.39559 0.39979
-0.31765 0.099633 0.39954 0.40328
-0.32157 0.10173 0.40348 0.40676
-0.32549 0.10385 0.40741 0.41022
-0.32941 0.10599 0.41133 0.41368
-0.33333 0.10814 0.41524 0.41712
-0.33725 0.11031 0.41915 0.42055
-0.34118 0.11250 0.42304 0.42396
-0.34510 0.11471 0.42693 0.42737
-0.34902 0.11693 0.43080 0.43076
-0.35294 0.11918 0.43467 0.43414
-0.35686 0.12144 0.43853 0.43752
-0.36078 0.12371 0.44238 0.44088
-0.36471 0.12601 0.44623 0.44422
-0.36863 0.12832 0.45006 0.44756
-0.37255 0.13065 0.45389 0.45089
-0.37647 0.13300 0.45770 0.45421
-0.38039 0.13536 0.46151 0.45751
-0.38431 0.13774 0.46532 0.46081
-0.38824 0.14014 0.46911 0.46410
-0.39216 0.14255 0.47290 0.46737
-0.39608 0.14499 0.47668 0.47064
-0.40000 0.14743 0.48045 0.47390
-0.40392 0.14990 0.48421 0.47715
-0.40784 0.15238 0.48797 0.48038
-0.41176 0.15488 0.49172 0.48361
-0.41569 0.15740 0.49546 0.48683
-0.41961 0.15993 0.49920 0.49004
-0.42353 0.16248 0.50293 0.49324
-0.42745 0.16505 0.50665 0.49644
-0.43137 0.16763 0.51037 0.49962
-0.43529 0.17023 0.51407 0.50279
-0.43922 0.17284 0.51778 0.50596
-0.44314 0.17547 0.52147 0.50912
-0.44706 0.17812 0.52516 0.51227
-0.45098 0.18079 0.52884 0.51541
-0.45490 0.18347 0.53252 0.51854
-0.45882 0.18616 0.53619 0.52167
-0.46275 0.18888 0.53985 0.52479
-0.46667 0.19161 0.54351 0.52789
-0.47059 0.19435 0.54716 0.53100
-0.47451 0.19711 0.55080 0.53409
-0.47843 0.19989 0.55444 0.53718
-0.48235 0.20268 0.55807 0.54025
-0.48627 0.20549 0.56170 0.54332
-0.49020 0.20832 0.56532 0.54639
-0.49412 0.21116 0.56894 0.54944
-0.49804 0.21402 0.57255 0.55249
-0.50196 0.21689 0.57615 0.55553
-0.50588 0.21978 0.57975 0.55857
-0.50980 0.22268 0.58334 0.56160
-0.51373 0.22560 0.58693 0.56462
-0.51765 0.22854 0.59051 0.56763
-0.52157 0.23149 0.59409 0.57064
-0.52549 0.23445 0.59766 0.57364
-0.52941 0.23744 0.60122 0.57663
-0.53333 0.24043 0.60478 0.57962
-0.53725 0.24345 0.60834 0.58260
-0.54118 0.24648 0.61189 0.58557
-0.54510 0.24952 0.61543 0.58854
-0.54902 0.25258 0.61897 0.59150
-0.55294 0.25565 0.62251 0.59445
-0.55686 0.25874 0.62603 0.59740
-0.56078 0.26185 0.62956 0.60034
-0.56471 0.26497 0.63308 0.60328
-0.56863 0.26811 0.63659 0.60621
-0.57255 0.27126 0.64010 0.60913
-0.57647 0.27442 0.64361 0.61205
-0.58039 0.27760 0.64711 0.61496
-0.58431 0.28080 0.65060 0.61787
-0.58824 0.28401 0.65410 0.62077
-0.59216 0.28724 0.65758 0.62366
-0.59608 0.29048 0.66106 0.62655
-0.60000 0.29373 0.66454 0.62943
-0.60392 0.29701 0.66801 0.63231
-0.60784 0.30029 0.67148 0.63518
-0.61176 0.30359 0.67494 0.63805
-0.61569 0.30691 0.67840 0.64091
-0.61961 0.31024 0.68186 0.64376
-0.62353 0.31358 0.68531 0.64661
-0.62745 0.31694 0.68875 0.64945
-0.63137 0.32032 0.69220 0.65229
-0.63529 0.32371 0.69563 0.65513
-0.63922 0.32711 0.69907 0.65795
-0.64314 0.33053 0.70249 0.66078
-0.64706 0.33397 0.70592 0.66360
-0.65098 0.33741 0.70934 0.66641
-0.65490 0.34088 0.71276 0.66922
-0.65882 0.34435 0.71617 0.67202
-0.66275 0.34785 0.71958 0.67482
-0.66667 0.35135 0.72298 0.67761
-0.67059 0.35487 0.72638 0.68040
-0.67451 0.35841 0.72978 0.68318
-0.67843 0.36196 0.73317 0.68596
-0.68235 0.36552 0.73656 0.68873
-0.68627 0.36910 0.73994 0.69150
-0.69020 0.37269 0.74332 0.69426
-0.69412 0.37630 0.74670 0.69702
-0.69804 0.37992 0.75007 0.69977
-0.70196 0.38356 0.75344 0.70252
-0.70588 0.38721 0.75681 0.70527
-0.70980 0.39087 0.76017 0.70801
-0.71373 0.39455 0.76353 0.71075
-0.71765 0.39824 0.76688 0.71348
-0.72157 0.40195 0.77023 0.71620
-0.72549 0.40567 0.77358 0.71893
-0.72941 0.40940 0.77692 0.72164
-0.73333 0.41315 0.78026 0.72436
-0.73725 0.41692 0.78360 0.72707
-0.74118 0.42069 0.78693 0.72977
-0.74510 0.42448 0.79026 0.73247
-0.74902 0.42829 0.79359 0.73517
-0.75294 0.43211 0.79691 0.73786
-0.75686 0.43594 0.80023 0.74055
-0.76078 0.43979 0.80354 0.74323
-0.76471 0.44365 0.80686 0.74591
-0.76863 0.44752 0.81016 0.74859
-0.77255 0.45141 0.81347 0.75126
-0.77647 0.45531 0.81677 0.75393
-0.78039 0.45923 0.82007 0.75659
-0.78431 0.46316 0.82336 0.75925
-0.78824 0.46710 0.82666 0.76191
-0.79216 0.47106 0.82994 0.76456
-0.79608 0.47503 0.83323 0.76721
-0.80000 0.47902 0.83651 0.76985
-0.80392 0.48302 0.83979 0.77249
-0.80784 0.48703 0.84307 0.77512
-0.81176 0.49105 0.84634 0.77776
-0.81569 0.49509 0.84961 0.78038
-0.81961 0.49915 0.85287 0.78301
-0.82353 0.50321 0.85614 0.78563
-0.82745 0.50729 0.85940 0.78825
-0.83137 0.51139 0.86265 0.79086
-0.83529 0.51550 0.86591 0.79347
-0.83922 0.51962 0.86916 0.79608
-0.84314 0.52375 0.87241 0.79868
-0.84706 0.52790 0.87565 0.80128
-0.85098 0.53206 0.87889 0.80387
-0.85490 0.53624 0.88213 0.80646
-0.85882 0.54042 0.88537 0.80905
-0.86275 0.54463 0.88860 0.81163
-0.86667 0.54884 0.89183 0.81421
-0.87059 0.55307 0.89506 0.81679
-0.87451 0.55731 0.89828 0.81937
-0.87843 0.56157 0.90150 0.82194
-0.88235 0.56584 0.90472 0.82450
-0.88627 0.57012 0.90793 0.82707
-0.89020 0.57441 0.91115 0.82963
-0.89412 0.57872 0.91436 0.83218
-0.89804 0.58304 0.91756 0.83474
-0.90196 0.58738 0.92077 0.83729
-0.90588 0.59173 0.92397 0.83983
-0.90980 0.59609 0.92717 0.84238
-0.91373 0.60046 0.93036 0.84492
-0.91765 0.60485 0.93356 0.84745
-0.92157 0.60925 0.93675 0.84999
-0.92549 0.61366 0.93993 0.85252
-0.92941 0.61809 0.94312 0.85504
-0.93333 0.62253 0.94630 0.85757
-0.93725 0.62698 0.94948 0.86009
-0.94118 0.63145 0.95266 0.86261
-0.94510 0.63593 0.95583 0.86512
-0.94902 0.64042 0.95900 0.86763
-0.95294 0.64493 0.96217 0.87014
-0.95686 0.64945 0.96534 0.87264
-0.96078 0.65398 0.96850 0.87515
-0.96471 0.65852 0.97166 0.87765
-0.96863 0.66308 0.97482 0.88014
-0.97255 0.66765 0.97798 0.88263
-0.97647 0.67223 0.98113 0.88512
-0.98039 0.67683 0.98428 0.88761
-0.98431 0.68144 0.98743 0.89009
-0.98824 0.68606 0.99058 0.89258
-0.99216 0.69069 0.99372 0.89505
-0.99608 0.69534 0.99686 0.89753
-1.0000 0.70000 1.0000 0.90000
+0.00000 0.00000 0.00000 0.00000
+3.92157e-003 5.67518e-005 0.0118787 0.0186065
+7.84314e-003 1.84387e-004 0.0206820 0.0302263
+0.0117647 3.67355e-004 0.0286065 0.0401466
+0.0156863 5.99076e-004 0.0360094 0.0491028
+0.0196078 8.75445e-004 0.0430471 0.0574042
+0.0235294 1.19354e-003 0.0498068 0.0652184
+0.0274510 1.55112e-003 0.0563438 0.0726496
+0.0313725 1.94640e-003 0.0626960 0.0797678
+0.0352941 2.37789e-003 0.0688909 0.0866232
+0.0392157 2.84433e-003 0.0749493 0.0932533
+0.0431373 3.34462e-003 0.0808876 0.0996872
+0.0470588 3.87782e-003 0.0867187 0.105948
+0.0509804 4.44307e-003 0.0924533 0.112053
+0.0549020 5.03962e-003 0.0981003 0.118020
+0.0588235 5.66676e-003 0.103667 0.123859
+0.0627451 6.32388e-003 0.109160 0.129583
+0.0666667 7.01040e-003 0.114585 0.135201
+0.0705882 7.72579e-003 0.119946 0.140720
+0.0745098 8.46956e-003 0.125248 0.146148
+0.0784314 9.24125e-003 0.130494 0.151490
+0.0823529 0.0100404 0.135689 0.156754
+0.0862745 0.0108667 0.140834 0.161942
+0.0901961 0.0117197 0.145932 0.167061
+0.0941176 0.0125991 0.150986 0.172112
+0.0980392 0.0135045 0.155998 0.177102
+0.101961 0.0144356 0.160971 0.182031
+0.105882 0.0153921 0.165905 0.186904
+0.109804 0.0163738 0.170803 0.191723
+0.113725 0.0173803 0.175665 0.196491
+0.117647 0.0184114 0.180495 0.201210
+0.121569 0.0194668 0.185292 0.205882
+0.125490 0.0205464 0.190059 0.210508
+0.129412 0.0216498 0.194796 0.215092
+0.133333 0.0227769 0.199504 0.219634
+0.137255 0.0239274 0.204184 0.224136
+0.141176 0.0251012 0.208838 0.228600
+0.145098 0.0262980 0.213466 0.233027
+0.149020 0.0275177 0.218069 0.237418
+0.152941 0.0287600 0.222648 0.241774
+0.156863 0.0300249 0.227204 0.246097
+0.160784 0.0313121 0.231737 0.250388
+0.164706 0.0326215 0.236248 0.254647
+0.168627 0.0339528 0.240737 0.258876
+0.172549 0.0353061 0.245205 0.263076
+0.176471 0.0366810 0.249654 0.267247
+0.180392 0.0380775 0.254082 0.271391
+0.184314 0.0394954 0.258491 0.275507
+0.188235 0.0409345 0.262882 0.279597
+0.192157 0.0423948 0.267254 0.283662
+0.196078 0.0438762 0.271609 0.287702
+0.200000 0.0453784 0.275946 0.291718
+0.203922 0.0469014 0.280266 0.295710
+0.207843 0.0484450 0.284570 0.299680
+0.211765 0.0500091 0.288857 0.303627
+0.215686 0.0515937 0.293128 0.307552
+0.219608 0.0531985 0.297384 0.311455
+0.223529 0.0548235 0.301625 0.315338
+0.227451 0.0564686 0.305851 0.319201
+0.231373 0.0581337 0.310063 0.323043
+0.235294 0.0598187 0.314260 0.326866
+0.239216 0.0615234 0.318443 0.330670
+0.243137 0.0632478 0.322613 0.334456
+0.247059 0.0649918 0.326769 0.338223
+0.250980 0.0667553 0.330911 0.341972
+0.254902 0.0685382 0.335041 0.345703
+0.258824 0.0703403 0.339159 0.349418
+0.262745 0.0721617 0.343264 0.353115
+0.266667 0.0740022 0.347356 0.356797
+0.270588 0.0758618 0.351437 0.360461
+0.274510 0.0777403 0.355505 0.364110
+0.278431 0.0796377 0.359563 0.367744
+0.282353 0.0815539 0.363608 0.371362
+0.286275 0.0834889 0.367643 0.374965
+0.290196 0.0854424 0.371666 0.378553
+0.294118 0.0874146 0.375679 0.382127
+0.298039 0.0894052 0.379681 0.385686
+0.301961 0.0914143 0.383672 0.389231
+0.305882 0.0934417 0.387653 0.392763
+0.309804 0.0954873 0.391624 0.396281
+0.313725 0.0975512 0.395585 0.399786
+0.317647 0.0996332 0.399536 0.403277
+0.321569 0.101733 0.403477 0.406756
+0.325490 0.103851 0.407409 0.410222
+0.329412 0.105987 0.411331 0.413676
+0.333333 0.108141 0.415244 0.417117
+0.337255 0.110313 0.419147 0.420546
+0.341176 0.112503 0.423042 0.423963
+0.345098 0.114710 0.426927 0.427368
+0.349020 0.116935 0.430804 0.430762
+0.352941 0.119177 0.434672 0.434144
+0.356863 0.121437 0.438532 0.437515
+0.360784 0.123714 0.442383 0.440875
+0.364706 0.126009 0.446225 0.444224
+0.368627 0.128321 0.450060 0.447563
+0.372549 0.130650 0.453886 0.450890
+0.376471 0.132997 0.457704 0.454207
+0.380392 0.135360 0.461514 0.457514
+0.384314 0.137741 0.465317 0.460811
+0.388235 0.140139 0.469111 0.464097
+0.392157 0.142554 0.472898 0.467374
+0.396078 0.144986 0.476678 0.470641
+0.400000 0.147435 0.480450 0.473898
+0.403922 0.149900 0.484214 0.477145
+0.407843 0.152383 0.487972 0.480383
+0.411765 0.154882 0.491722 0.483612
+0.415686 0.157398 0.495465 0.486831
+0.419608 0.159931 0.499200 0.490042
+0.423529 0.162480 0.502929 0.493243
+0.427451 0.165046 0.506651 0.496436
+0.431373 0.167628 0.510366 0.499619
+0.435294 0.170227 0.514075 0.502794
+0.439216 0.172842 0.517776 0.505961
+0.443137 0.175474 0.521472 0.509119
+0.447059 0.178122 0.525160 0.512269
+0.450980 0.180787 0.528842 0.515410
+0.454902 0.183467 0.532518 0.518543
+0.458824 0.186164 0.536187 0.521668
+0.462745 0.188877 0.539850 0.524785
+0.466667 0.191606 0.543507 0.527895
+0.470588 0.194351 0.547158 0.530996
+0.474510 0.197113 0.550803 0.534090
+0.478431 0.199890 0.554441 0.537176
+0.482353 0.202684 0.558074 0.540254
+0.486275 0.205493 0.561701 0.543325
+0.490196 0.208318 0.565322 0.546388
+0.494118 0.211159 0.568937 0.549444
+0.498039 0.214016 0.572547 0.552493
+0.501961 0.216889 0.576150 0.555535
+0.505882 0.219777 0.579748 0.558569
+0.509804 0.222681 0.583341 0.561597
+0.513725 0.225601 0.586928 0.564617
+0.517647 0.228536 0.590510 0.567631
+0.521569 0.231487 0.594086 0.570638
+0.525490 0.234454 0.597657 0.573638
+0.529412 0.237436 0.601222 0.576631
+0.533333 0.240434 0.604782 0.579618
+0.537255 0.243447 0.608337 0.582598
+0.541176 0.246476 0.611887 0.585571
+0.545098 0.249520 0.615431 0.588538
+0.549020 0.252579 0.618971 0.591499
+0.552941 0.255654 0.622505 0.594453
+0.556863 0.258744 0.626035 0.597401
+0.560784 0.261849 0.629559 0.600343
+0.564706 0.264970 0.633079 0.603279
+0.568627 0.268105 0.636594 0.606208
+0.572549 0.271256 0.640103 0.609132
+0.576471 0.274422 0.643608 0.612049
+0.580392 0.277603 0.647109 0.614961
+0.584314 0.280800 0.650604 0.617867
+0.588235 0.284011 0.654095 0.620766
+0.592157 0.287237 0.657581 0.623661
+0.596078 0.290478 0.661063 0.626549
+0.600000 0.293735 0.664540 0.629431
+0.603922 0.297006 0.668012 0.632308
+0.607843 0.300292 0.671480 0.635180
+0.611765 0.303593 0.674944 0.638045
+0.615686 0.306909 0.678403 0.640906
+0.619608 0.310239 0.681857 0.643761
+0.623529 0.313585 0.685308 0.646610
+0.627451 0.316945 0.688754 0.649454
+0.631373 0.320320 0.692195 0.652293
+0.635294 0.323709 0.695633 0.655126
+0.639216 0.327114 0.699066 0.657954
+0.643137 0.330533 0.702495 0.660777
+0.647059 0.333966 0.705919 0.663595
+0.650980 0.337414 0.709340 0.666408
+0.654902 0.340877 0.712756 0.669215
+0.658824 0.344354 0.716169 0.672018
+0.662745 0.347846 0.719577 0.674816
+0.666667 0.351352 0.722981 0.677608
+0.670588 0.354873 0.726381 0.680396
+0.674510 0.358408 0.729778 0.683179
+0.678431 0.361958 0.733170 0.685957
+0.682353 0.365522 0.736559 0.688730
+0.686275 0.369100 0.739943 0.691498
+0.690196 0.372693 0.743324 0.694262
+0.694118 0.376300 0.746701 0.697021
+0.698039 0.379921 0.750074 0.699775
+0.701961 0.383557 0.753443 0.702525
+0.705882 0.387207 0.756808 0.705270
+0.709804 0.390871 0.760170 0.708010
+0.713725 0.394549 0.763528 0.710746
+0.717647 0.398242 0.766882 0.713477
+0.721569 0.401948 0.770233 0.716204
+0.725490 0.405669 0.773580 0.718927
+0.729412 0.409404 0.776923 0.721645
+0.733333 0.413153 0.780263 0.724358
+0.737255 0.416916 0.783599 0.727068
+0.741176 0.420693 0.786932 0.729773
+0.745098 0.424484 0.790261 0.732473
+0.749020 0.428289 0.793587 0.735170
+0.752941 0.432108 0.796909 0.737862
+0.756863 0.435940 0.800228 0.740550
+0.760784 0.439787 0.803543 0.743234
+0.764706 0.443648 0.806855 0.745914
+0.768627 0.447523 0.810164 0.748589
+0.772549 0.451411 0.813469 0.751261
+0.776471 0.455314 0.816770 0.753928
+0.780392 0.459230 0.820069 0.756592
+0.784314 0.463160 0.823364 0.759251
+0.788235 0.467103 0.826656 0.761906
+0.792157 0.471061 0.829944 0.764558
+0.796078 0.475032 0.833230 0.767205
+0.800000 0.479017 0.836512 0.769849
+0.803922 0.483016 0.839790 0.772489
+0.807843 0.487028 0.843066 0.775124
+0.811765 0.491054 0.846339 0.777756
+0.815686 0.495094 0.849608 0.780385
+0.819608 0.499147 0.852874 0.783009
+0.823529 0.503214 0.856137 0.785630
+0.827451 0.507294 0.859397 0.788247
+0.831373 0.511388 0.862654 0.790860
+0.835294 0.515496 0.865908 0.793469
+0.839216 0.519617 0.869158 0.796075
+0.843137 0.523751 0.872406 0.798677
+0.847059 0.527899 0.875651 0.801276
+0.850980 0.532061 0.878892 0.803871
+0.854902 0.536236 0.882131 0.806462
+0.858824 0.540424 0.885367 0.809050
+0.862745 0.544626 0.888599 0.811634
+0.866667 0.548841 0.891829 0.814215
+0.870588 0.553070 0.895056 0.816792
+0.874510 0.557311 0.898280 0.819366
+0.878431 0.561567 0.901501 0.821936
+0.882353 0.565835 0.904719 0.824503
+0.886275 0.570117 0.907935 0.827066
+0.890196 0.574412 0.911147 0.829626
+0.894118 0.578721 0.914357 0.832183
+0.898039 0.583042 0.917564 0.834736
+0.901961 0.587377 0.920768 0.837286
+0.905882 0.591725 0.923969 0.839833
+0.909804 0.596087 0.927168 0.842376
+0.913725 0.600461 0.930363 0.844916
+0.917647 0.604849 0.933556 0.847453
+0.921569 0.609249 0.936747 0.849986
+0.925490 0.613663 0.939934 0.852516
+0.929412 0.618090 0.943119 0.855044
+0.933333 0.622530 0.946301 0.857567
+0.937255 0.626984 0.949481 0.860088
+0.941176 0.631450 0.952658 0.862606
+0.945098 0.635929 0.955832 0.865120
+0.949020 0.640421 0.959003 0.867631
+0.952941 0.644927 0.962172 0.870139
+0.956863 0.649445 0.965339 0.872644
+0.960784 0.653976 0.968502 0.875146
+0.964706 0.658521 0.971664 0.877645
+0.968627 0.663078 0.974822 0.880141
+0.972549 0.667648 0.977978 0.882634
+0.976471 0.672231 0.981132 0.885124
+0.980392 0.676827 0.984283 0.887610
+0.984314 0.681436 0.987431 0.890094
+0.988235 0.686058 0.990577 0.892575
+0.992157 0.690692 0.993721 0.895053
+0.996078 0.695340 0.996862 0.897528
+1.00000 0.700000 1.00000 0.900000
END_DATA
diff --git a/rspl/Jamfile b/rspl/Jamfile
index a3f2e8c..dbca6d5 100644
--- a/rspl/Jamfile
+++ b/rspl/Jamfile
@@ -3,8 +3,8 @@
# Optimization and Debug flags
-PREF_CCFLAGS += $(CCOPTFLAG) ; # Turn optimisation on
-#PREF_CCFLAGS += $(CCDEBUGFLAG) ; # Debugging flags
+#PREF_CCFLAGS += $(CCOPTFLAG) ; # Turn optimisation on
+PREF_CCFLAGS += $(CCDEBUGFLAG) ; # Debugging flags
#PREF_CCFLAGS += $(CCPROFFLAG) ; # Profile flags
#PREF_LINKFLAGS += $(LINKPROFFLAG) ; # Profile flags
#PREF_CCFLAGS += $(CCHEAPDEBUG) ; # Heap Debugging flags
@@ -27,9 +27,9 @@ HDRS = ../h ../numlib ../plot $(TIFFINC) ;
LINKLIBS = librspl ../numlib/libnum ../plot/libplot ../plot/libvrml ../icc/libicc $(TIFFLIB) $(JPEGLIB) ;
# Test programs
-MainsFromSources revbench.c c1.c c1df.c t2d.c t2ddf.c t3d.c t3ddf.c tnd.c trnd.c ;
+MainsFromSources revbench.c c1.c cw1.c cw3.c c1df.c t2d.c t2ddf.c t3d.c t3ddf.c tnd.c trnd.c ;
-BUILD_TESTS = true ;
+BUILD_TESTS = false ;
if $(BUILD_TESTS) {
diff --git a/rspl/afiles b/rspl/afiles
index af20c44..7d9c29f 100644
--- a/rspl/afiles
+++ b/rspl/afiles
@@ -16,6 +16,8 @@ gam.h
gam.c
revbench.c
c1.c
+cw1.c
+cw3.c
c1df.c
spline.c
t2d.c
diff --git a/rspl/c1.c b/rspl/c1.c
index 8172cef..2717920 100644
--- a/rspl/c1.c
+++ b/rspl/c1.c
@@ -19,7 +19,7 @@
#undef DIAG
#undef DIAG2
#undef GLOB_CHECK
-#undef RES2 /* Do multiple test at various resolutions */
+#define RES2 /* Do multiple test at various resolutions */
#define AVGDEV 0.0 /* Average deviation of function data */
#include <stdio.h>
@@ -285,7 +285,6 @@ int main(int argc, char *argv[]) {
rss->fit_rspl(rss,
0 | (twopass ? RSPL_2PASSSMTH : 0)
| (extra ? RSPL_EXTRAFIT2 : 0) ,
- 0,
test_points, /* Test points */
pnts, /* Number of test points */
low, high, gres, /* Low, high, resolution of grid */
diff --git a/rspl/cw1.c b/rspl/cw1.c
new file mode 100644
index 0000000..75a4f55
--- /dev/null
+++ b/rspl/cw1.c
@@ -0,0 +1,308 @@
+
+/************************************************/
+/* Investigate various curve approximations */
+/************************************************/
+
+/* Discrete regularized spline versions */
+/* Test variable grid spacing in 1D
+
+/* Author: Graeme Gill
+ * Date: 4/10/95
+ * Date: 5/4/96
+ *
+ * Copyright 1995, 2013 Graeme W. Gill
+ *
+ * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
+ * see the License.txt file for licencing details.
+ */
+
+#undef DIAG
+#undef DIAG2
+#undef GLOB_CHECK
+#define AVGDEV 0.0 /* Average deviation of function data */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <math.h>
+#include "copyright.h"
+#include "aconfig.h"
+#include "numlib.h"
+#include "plot.h"
+#include "rspl.h"
+
+double lin();
+void usage(void);
+
+#define TRIALS 1 /* Number of random trials */
+#define XRES 100 /* Plotting res */
+
+
+#define PNTS1 10
+#define GRES1 100
+
+/* Function that we're approximating */
+static double func(double val) {
+ double out;
+ int sgn = 0;
+
+ if (val < 0.0) {
+ sgn = 1;
+ val = -val;
+ }
+
+ out = pow(val, 2.5);
+
+ if (sgn)
+ out = -out;
+
+ return out;
+}
+
+/* Grid spacing power */
+#define GRIDPOW 1.5
+
+/* Scattered data sample spacing power */
+#define SAMPPOW 1.3
+
+
+co test_points[PNTS1];
+
+double ipos[GRES1];
+double *iposes[1] = { ipos };
+
+double powlike(double vv, double pp);
+
+void usage(void) {
+ fprintf(stderr,"Test 1D rspl interpolation variable grid spacing\n");
+ fprintf(stderr,"Author: Graeme W. Gill\n");
+ fprintf(stderr,"usage: c1 [options]\n");
+ fprintf(stderr," -s smooth Use given smoothness (default 1.0)\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[]) {
+ int fa,nfa; /* argument we're looking at */
+ int i,j, n;
+ double x;
+ double xx1[XRES];
+ double yy1[6][XRES];
+ double xx2[XRES];
+ double yy2[6][XRES];
+ rspl *rss; /* incremental solution version */
+ datai low,high;
+ int gres[MXDI];
+ double smooth = 1.0;
+ double avgdev[MXDO];
+
+ low[0] = 0.0;
+ high[0] = 1.0;
+ avgdev[0] = AVGDEV;
+
+ error_program = "c1";
+ check_if_not_interactive();
+
+ /* 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 */
+ }
+ }
+ }
+
+ if (argv[fa][1] == '?')
+ usage();
+
+ /* smoothness */
+ else if (argv[fa][1] == 's' || argv[fa][1] == 'S') {
+ fa = nfa;
+ if (na == NULL) usage();
+ smooth = atof(na);
+ }
+ else
+ usage();
+ } else
+ break;
+ }
+
+ /* Only one trial */
+ for (n = 0; n < TRIALS; n++) {
+ double lrand = 0.0; /* Amount of level randomness */
+ int pnts;
+ int fres;
+
+ pnts = PNTS1;
+ fres = GRES1;
+ gres[0] = fres;
+
+ /* Create the object */
+ rss = new_rspl(RSPL_NOFLAGS,
+ 1, /* di */
+ 1); /* fdi */
+
+ /* For each grid spacing test */
+ for (j = 0; j < 2; j++) {
+
+ for (i = 0; i < pnts; i++) {
+ double val, out;
+
+ val = i/(pnts - 1.0);
+
+ if (j == 0) { /* Linear */
+// out = func(val + d_rand(-0.001, 0.001));
+ out = func(val);
+ test_points[i].p[0] = val;
+ test_points[i].v[0] = out;
+
+ } else { /* power 2.0 grid spacing */
+ val = pow(val, SAMPPOW); /* sample point spacing */
+
+// out = func(val + d_rand(-0.001, 0.001));
+ out = func(val);
+ val = powlike(val, 1.0/GRIDPOW); /* To grid spacing */
+ test_points[i].p[0] = val;
+ test_points[i].v[0] = out;
+ }
+ }
+
+ /* Set grid position info */
+ for (i = 0; i < gres[0]; i++) {
+ double val, out;
+
+ val = i/(gres[0] - 1.0);
+ if (j == 1)
+ val = powlike(val, 1.0/GRIDPOW); /* To grid spacing */
+ ipos[i] = val;
+ }
+
+ rss->fit_rspl(rss,
+ 0,
+ test_points, /* Test points */
+ pnts, /* Number of test points */
+ low, high, gres, /* Low, high, resolution of grid */
+ NULL, NULL, /* Default data scale */
+ smooth, /* Smoothing */
+ avgdev, /* Average deviation */
+ j == 0 ? NULL : iposes); /* iwidth */
+
+ /* Show the result full scale */
+ for (i = 0; i < XRES; i++) {
+ co tp; /* Test point */
+ x = i/(double)(XRES-1);
+ xx1[i] = x;
+ yy1[0][i] = func(x);
+ tp.p[0] = x;
+ if (j == 1)
+ tp.p[0] = powlike(tp.p[0], 1.0/GRIDPOW); /* Grid spacing input */
+ rss->interp(rss, &tp);
+ yy1[1+j][i] = tp.v[0];
+ if (yy1[1+j][i] < -0.2)
+ yy1[1+j][i] = -0.2;
+ else if (yy1[1+j][i] > 1.2)
+ yy1[1+j][i] = 1.2;
+ }
+
+ /* Show the result magnified */
+ for (i = 0; i < XRES; i++) {
+ co tp; /* Test point */
+ x = i/(double)(XRES-1);
+ x *= 0.1;
+ xx2[i] = x;
+ yy2[0][i] = func(x);
+ tp.p[0] = x;
+ if (j == 1)
+ tp.p[0] = powlike(tp.p[0], 1.0/GRIDPOW); /* Grid spacing input */
+ rss->interp(rss, &tp);
+ yy2[1+j][i] = tp.v[0];
+ if (yy2[1+j][i] < -0.2)
+ yy2[1+j][i] = -0.2;
+ else if (yy2[1+j][i] > 1.2)
+ yy2[1+j][i] = 1.2;
+ }
+ }
+
+ printf("Full scale: Black = lin, Red = even, Green = pow2\n");
+ do_plot6(xx1,yy1[0],yy1[1],yy1[2],NULL,NULL,NULL,XRES);
+
+ printf("Magnified: Black = lin, Red = even, Green = pow2\n");
+ do_plot6(xx2,yy2[0],yy2[1],yy2[2],NULL,NULL,NULL,XRES);
+ }
+ return 0;
+}
+
+
+/* A power-like function, based on Graphics Gems adjustment curve. */
+/* Avoids "toe" problem of pure power. */
+/* Adjusted so that "power" 2 and 0.5 agree with real power at 0.5 */
+
+double powlike(double vv, double pp) {
+ double tt, g;
+
+ if (pp >= 1.0) {
+ g = 2.0 * (pp - 1.0);
+ vv = vv/(g - g * vv + 1.0);
+ } else {
+ g = 2.0 - 2.0/pp;
+ vv = (vv - g * vv)/(1.0 - g * vv);
+ }
+
+ return vv;
+}
+
+
+/******************************************************************/
+/* Error/debug output routines */
+/******************************************************************/
+
+/* Next u function done with optimization */
+
+/* Structure to hold data for optimization function */
+struct _edatas {
+ rspl *rss;
+ int j;
+ }; typedef struct _edatas edatas;
+
+#ifdef GLOB_CHECK
+/* Overall Global optimization method */
+/* Definition of the optimization function handed to powell() */
+double efunc2(void *edata, double p[])
+ {
+ int j;
+ double rv;
+ rspl *rss = (rspl *)edata;
+ for (j = 0; j < rss->nig; j++) /* Ugg */
+ rss->u[j].v = p[j];
+ rv = rss->efactor(rss);
+#ifdef DIAG2
+ /* printf("%c%e",cr_char,rv); */
+ printf("%e\n",rv);
+#endif
+ return rv;
+ }
+
+solveu(rss)
+rspl *rss;
+ {
+ int j;
+ double *cp;
+ double *s;
+
+ cp = dvector(0,rss->nig);
+ s = dvector(0,rss->nig);
+ for (j = 0; j < rss->nig; j++) /* Ugg */
+ {
+ cp[j] = rss->u[j].v;
+ s[j] = 0.1;
+ }
+ powell(rss->nig,cp,s,1e-7,1000,efunc2,(void *)rss);
+ }
+#endif /* GLOB_CHECK */
diff --git a/rspl/cw3.c b/rspl/cw3.c
new file mode 100644
index 0000000..03c9b81
--- /dev/null
+++ b/rspl/cw3.c
@@ -0,0 +1,325 @@
+
+/************************************************/
+/* Investigate various curve approximations */
+/************************************************/
+
+/* Discrete regularized spline versions */
+/* Test variable grid spacing in 3D
+
+/* Author: Graeme Gill
+ * Date: 28/11/2013
+ *
+ * Copyright 1995, 2013 Graeme W. Gill
+ *
+ * This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
+ * see the License.txt file for licencing details.
+ */
+
+#undef DIAG
+#undef DIAG2
+#undef GLOB_CHECK
+#define AVGDEV 0.0 /* Average deviation of function data */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <math.h>
+#include "copyright.h"
+#include "aconfig.h"
+#include "counters.h"
+#include "numlib.h"
+#include "plot.h"
+#include "rspl.h"
+
+double lin();
+void usage(void);
+
+#define TRIALS 1 /* Number of random trials */
+#define XRES 100 /* Plotting res */
+
+
+#define PNTS1 20
+#define GRES1 33
+
+/* Function that we're approximating */
+static double func(double val) {
+ double out;
+ int sgn = 0;
+
+ if (val < 0.0) {
+ sgn = 1;
+ val = -val;
+ }
+
+ out = pow(val, 2.4);
+
+ if (sgn)
+ out = -out;
+
+ return out;
+}
+
+/* Grid spacing power */
+#define GRIDPOW 1.8
+
+/* Scattered data sample spacing power */
+#define SAMPPOW 1.3
+
+
+co test_points[PNTS1 * PNTS1 * PNTS1];
+
+double ipos[GRES1];
+double *iposes[3] = { ipos, ipos, ipos };
+
+double powlike(double vv, double pp);
+
+void usage(void) {
+ fprintf(stderr,"Test 3D rspl interpolation variable grid spacing\n");
+ fprintf(stderr,"Author: Graeme W. Gill\n");
+ fprintf(stderr,"usage: c1 [options]\n");
+ fprintf(stderr," -s smooth Use given smoothness (default 1.0)\n");
+ exit(1);
+}
+
+int main(int argc, char *argv[]) {
+ int fa,nfa; /* argument we're looking at */
+ int i, j, e, f, n;
+ double x;
+ double xx1[XRES];
+ double yy1[6][XRES];
+ double xx2[XRES];
+ double yy2[6][XRES];
+ rspl *rss; /* incremental solution version */
+ datai low,high;
+ int gres[MXDI];
+ double smooth = 1.0;
+ double avgdev[MXDO];
+
+ low[0] = 0.0;
+ low[1] = 0.0;
+ low[2] = 0.0;
+ high[0] = 1.0;
+ high[1] = 1.0;
+ high[2] = 1.0;
+ avgdev[0] = AVGDEV;
+ avgdev[1] = AVGDEV;
+ avgdev[2] = AVGDEV;
+
+ error_program = "c1";
+ check_if_not_interactive();
+
+ /* 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 */
+ }
+ }
+ }
+
+ if (argv[fa][1] == '?')
+ usage();
+
+ /* smoothness */
+ else if (argv[fa][1] == 's' || argv[fa][1] == 'S') {
+ fa = nfa;
+ if (na == NULL) usage();
+ smooth = atof(na);
+ }
+ else
+ usage();
+ } else
+ break;
+ }
+
+ for (n = 0; n < TRIALS; n++) {
+ double lrand = 0.0; /* Amount of level randomness */
+ int di = 3;
+ int pnts = PNTS1;
+ int tpnts = PNTS1 * PNTS1 * PNTS1;
+ int fres;
+
+ fres = GRES1;
+ gres[0] = fres;
+ gres[1] = fres;
+ gres[2] = fres;
+
+ /* Create the object */
+ rss = new_rspl(RSPL_NOFLAGS,
+ 3, /* di */
+ 3); /* fdi */
+
+ /* For each grid spacing test */
+ for (j = 0; j < 2; j++) {
+ DCOUNT(gc, MXDIDO, di, 0, 0, pnts);
+
+ /* Set the scattered data points (actually grid) */
+ DC_INIT(gc);
+ for (i = 0; !DC_DONE(gc); i++) {
+
+ for (f = 0; f < 3; f++) {
+ double val, out;
+
+ val = gc[f]/(pnts - 1.0);
+
+ if (j == 0) { /* Linear */
+// out = func(val + d_rand(-0.001, 0.001));
+ out = func(val);
+ test_points[i].p[f] = val;
+ test_points[i].v[f] = out;
+
+ } else { /* power 2.0 grid spacing */
+ val = pow(val, SAMPPOW); /* sample point spacing */
+
+// out = func(val + d_rand(-0.001, 0.001));
+ out = func(val);
+ val = powlike(val, 1.0/GRIDPOW); /* To grid spacing */
+ test_points[i].p[f] = val;
+ test_points[i].v[f] = out;
+ }
+ }
+ DC_INC(gc);
+ }
+
+ /* Set grid position info. This is the same for each input axis */
+ for (i = 0; i < gres[0]; i++) {
+ double val, out;
+
+ val = i/(gres[0] - 1.0);
+ if (j == 1)
+ val = powlike(val, 1.0/GRIDPOW); /* To grid spacing */
+ ipos[i] = val;
+ }
+
+ printf("Fitting rspl....\n");
+ rss->fit_rspl(rss,
+ 0,
+ test_points, /* Test points */
+ tpnts, /* Number of test points */
+ low, high, gres, /* Low, high, resolution of grid */
+ NULL, NULL, /* Default data scale */
+ smooth, /* Smoothing */
+ avgdev, /* Average deviation */
+ j == 0 ? NULL : iposes); /* iwidth */
+
+ /* Show the result full scale of one axis and corresponding output */
+ for (i = 0; i < XRES; i++) {
+ co tp; /* Test point */
+ x = i/(double)(XRES-1);
+ xx1[i] = x;
+ yy1[0][i] = func(x);
+ tp.p[0] = x;
+ tp.p[1] = tp.p[2] = 0.0;
+ if (j == 1)
+ tp.p[0] = powlike(tp.p[0], 1.0/GRIDPOW); /* Grid spacing input */
+ rss->interp(rss, &tp);
+ yy1[1+j][i] = tp.v[0];
+ if (yy1[1+j][i] < -0.2)
+ yy1[1+j][i] = -0.2;
+ else if (yy1[1+j][i] > 1.2)
+ yy1[1+j][i] = 1.2;
+ }
+
+ /* Show the result magnified */
+ for (i = 0; i < XRES; i++) {
+ co tp; /* Test point */
+ x = i/(double)(XRES-1);
+ x *= 0.1;
+ xx2[i] = x;
+ yy2[0][i] = func(x);
+ tp.p[0] = x;
+ tp.p[1] = tp.p[2] = 0.0;
+ if (j == 1)
+ tp.p[0] = powlike(tp.p[0], 1.0/GRIDPOW); /* Grid spacing input */
+ rss->interp(rss, &tp);
+ yy2[1+j][i] = tp.v[0];
+ if (yy2[1+j][i] < -0.2)
+ yy2[1+j][i] = -0.2;
+ else if (yy2[1+j][i] > 1.2)
+ yy2[1+j][i] = 1.2;
+ }
+ }
+
+ printf("Full scale: Black = lin, Red = even, Green = pow2\n");
+ do_plot6(xx1,yy1[0],yy1[1],yy1[2],NULL,NULL,NULL,XRES);
+
+ printf("Magnified: Black = lin, Red = even, Green = pow2\n");
+ do_plot6(xx2,yy2[0],yy2[1],yy2[2],NULL,NULL,NULL,XRES);
+ }
+ return 0;
+}
+
+/* A power-like function, based on Graphics Gems adjustment curve. */
+/* Avoids "toe" problem of pure power. */
+/* Adjusted so that "power" 2 and 0.5 agree with real power at 0.5 */
+
+double powlike(double vv, double pp) {
+ double tt, g;
+
+ if (pp >= 1.0) {
+ g = 2.0 * (pp - 1.0);
+ vv = vv/(g - g * vv + 1.0);
+ } else {
+ g = 2.0 - 2.0/pp;
+ vv = (vv - g * vv)/(1.0 - g * vv);
+ }
+
+ return vv;
+}
+
+
+/******************************************************************/
+/* Error/debug output routines */
+/******************************************************************/
+
+/* Next u function done with optimization */
+
+/* Structure to hold data for optimization function */
+struct _edatas {
+ rspl *rss;
+ int j;
+ }; typedef struct _edatas edatas;
+
+#ifdef GLOB_CHECK
+/* Overall Global optimization method */
+/* Definition of the optimization function handed to powell() */
+double efunc2(void *edata, double p[])
+ {
+ int j;
+ double rv;
+ rspl *rss = (rspl *)edata;
+ for (j = 0; j < rss->nig; j++) /* Ugg */
+ rss->u[j].v = p[j];
+ rv = rss->efactor(rss);
+#ifdef DIAG2
+ /* printf("%c%e",cr_char,rv); */
+ printf("%e\n",rv);
+#endif
+ return rv;
+ }
+
+solveu(rss)
+rspl *rss;
+ {
+ int j;
+ double *cp;
+ double *s;
+
+ cp = dvector(0,rss->nig);
+ s = dvector(0,rss->nig);
+ for (j = 0; j < rss->nig; j++) /* Ugg */
+ {
+ cp[j] = rss->u[j].v;
+ s[j] = 0.1;
+ }
+ powell(rss->nig,cp,s,1e-7,1000,efunc2,(void *)rss);
+ }
+#endif /* GLOB_CHECK */
diff --git a/rspl/rev.c b/rspl/rev.c
index 237dbe3..1dbf6cc 100644
--- a/rspl/rev.c
+++ b/rspl/rev.c
@@ -22,11 +22,24 @@
Should fix the clipping case so that a direction weighting
funtion can be applied. This should be used just like
the perceptual case to increase L* constance for dark
- colors. Will this stuff up the geometric consistency though ?
- [ See fill_nncell(), fill_nncell() and users of calc_fwd_nn_cell_list(),
- ie. nnearest_clip_solve(), clipn_setsort() etc. ]
+ colors. This would entail large scale changes though,
+ since a lot of code assumes minimal euclidean distance
+ goal, from the cell selection structure [ See fill_nncell(),
+ fill_nncell() and users of calc_fwd_nn_cell_list() ] and
+ the within cell computation [ ie. See nnearest_clip_solve(),
+ clipn_setsort() etc. ]
+ XYZ PCS couldn't work with a simple weighting - it would have
+ to be a position dependent weighting.
The SVD least squares computation case makes this hard to change ?
Would have to feed in a weighting function, or can it be general ?
+ -
+ Can this be solved some other way, ie. by using gamut
+ mapping type look up ? Problem is precision.
+ -
+ Vector clip could be used (if intent can be turned
+ into computable vector clip direction), but it is slow,
+ because it search all cells from source until it
+ hits surface.
Allow function callback to set auxiliary values for
flag RSPL_AUXLOCUS.
@@ -1437,7 +1450,8 @@ unsigned int tcount /* grid touch count for this operation */
nunlk++;
}
fprintf(stdout,"Diagnostic: rev.sz = %lu, rev.max_sz = %lu, numlocked = %d, nunlk = %d\n",
- rc->s->rev.sz, rc->s->rev.max_sz, rc->nunlocked,nunlk);
+ (unsigned long)rc->s->rev.sz, (unsigned long)rc->s->rev.max_sz,
+ rc->nunlocked, nunlk);
error("Not enough memory to process in chunks");
}
break; /* cache has run out of room, so abandon, and do it next time */
@@ -4971,7 +4985,7 @@ rspl *s /* Pointer to rspl grid */
g_no_rev_cache_instances > 1 ? "are" : "is",
g_no_rev_cache_instances,
g_no_rev_cache_instances > 1 ? "s" : "",
- ram_portion/1000000);
+ (unsigned long)ram_portion/1000000);
}
}
@@ -6165,7 +6179,7 @@ if (prop != NULL) {
g_no_rev_cache_instances > 1 ? "are" : "is",
g_no_rev_cache_instances,
g_no_rev_cache_instances > 1 ? "s" : "",
- ram_portion/1000000);
+ (unsigned long)ram_portion/1000000);
}
s->rev.rev_valid = 1;
@@ -6233,7 +6247,7 @@ rspl *s /* Pointer to rspl grid */
g_no_rev_cache_instances > 1 ? "are" : "is",
g_no_rev_cache_instances,
g_no_rev_cache_instances > 1 ? "s" : "",
- ram_portion/1000000);
+ (unsigned long)ram_portion/1000000);
}
}
s->rev.rev_valid = 0;
@@ -6497,7 +6511,7 @@ rspl *s
if (g_avail_ram > safe_max_vmem) {
g_avail_ram = safe_max_vmem;
if (s->verbose && repsr == 0)
- fprintf(stdout,"%cTrimmed maximum cache RAM to %lu Mbytes to allow for VM limit\n",cr_char,g_avail_ram/1000000);
+ fprintf(stdout,"%cTrimmed maximum cache RAM to %lu Mbytes to allow for VM limit\n",cr_char,(unsigned long)g_avail_ram/1000000);
}
}
@@ -6516,7 +6530,7 @@ rspl *s
}
if (max_vmem != 0 && g_avail_ram > max_vmem && repsr == 0) {
g_avail_ram = (size_t)(0.95 * max_vmem);
- fprintf(stdout,"%cARGYLL_REV_CACHE_MULT * RAM trimmed to %lu Mbytes to allow for VM limit\n",cr_char,g_avail_ram/1000000);
+ fprintf(stdout,"%cARGYLL_REV_CACHE_MULT * RAM trimmed to %lu Mbytes to allow for VM limit\n",cr_char,(unsigned long)g_avail_ram/1000000);
}
}
@@ -6525,7 +6539,7 @@ rspl *s
DBG(("reverse cache max memory = %d Mbytes\n",s->rev.max_sz/1000000));
if (s->verbose && repsr == 0) {
- fprintf(stdout, "%cRev cache RAM = %lu Mbytes\n",cr_char,g_avail_ram/1000000);
+ fprintf(stdout, "%cRev cache RAM = %lu Mbytes\n",cr_char,(unsigned long)g_avail_ram/1000000);
repsr = 1;
}
diff --git a/rspl/rspl.c b/rspl/rspl.c
index 13a1776..23ef6b4 100644
--- a/rspl/rspl.c
+++ b/rspl/rspl.c
@@ -866,7 +866,7 @@ rspl *s
/* ============================================ */
/* Initialize the grid from a provided function. By default the grid */
-/* values are set to exactly the value returned fy func(), unless the */
+/* values are set to exactly the value returned by func(), unless the */
/* RSPL_SET_APXLS flag is set, in which case an attempt is made to have */
/* the grid points represent a least squares aproximation to the underlying */
/* surface, by using extra samples in the middle of grid cells. */
diff --git a/rspl/scat.c b/rspl/scat.c
index b4ed978..ec7e99c 100644
--- a/rspl/scat.c
+++ b/rspl/scat.c
@@ -128,10 +128,6 @@
/* algorithm parameters [Release defaults] */
#undef POINTWEIGHT /* [Undef] Increas smoothness weighting proportional to number of points */
#define INCURVEADJ /* [Defined] Adjust smoothness criteria for input curve grid spacing */
-#define EXTRA_SURFACE_SMOOTHING /* [Defined] Stiffen surface points to comp. for single ended. */
- /* The following are available, but the smoothing table is */
- /* not setup for them, and they are not sufficiently different */
- /* from the default smoothing to be useful. */
#define ENABLE_2PASSSMTH /* [Define] Enable 2 pass smooth using Gaussian filter */
#define ENABLE_EXTRAFIT /* [Undef] Enable the extra fit option. Good to combat high smoothness. */
@@ -142,12 +138,12 @@
/* Experimental set: */
-#pragma message("!!!!!!!!! Experimental config set !!!!!!!!!")
+#pragma message("!!!!!!!!! Experimental hi-accuracy config set !!!!!!!!!")
#define TOL 1e-12 /* Tollerance of result - usually 1e-5 is best. */
#define TOL_IMP 1.0 /* Minimum error improvement to continue - reduces accuracy (1.0 == off) */
#undef GRADUATED_TOL /* Speedup attemp - use reduced tollerance for prior grids. */
-#define GRATIO 2.0 /* Multi-grid resolution ratio */
+#define GRATIO 1.5 /* Multi-grid resolution ratio */
#undef OVERRLX /* Use over relaxation factor when progress slows (worse accuracy ?) */
#define JITTERS 0 /* Number of 1D conjugate solve itters */
#define CONJ_TOL 1.0 /* Extra tolereance on 1D conjugate solution times TOL. */
@@ -160,8 +156,8 @@
/* Release set: */
-#define TOL 1e-6 /* [1e-6] Tollerance of result - usually 1e-5 is best. */
-#define TOL_IMP 0.998 /* [0.998] Minimum error improvement to continue - reduces accuracy (1.0 == off) */
+#define TOL 1e-7 /* [1e-6] Tollerance of result - usually 1e-5 is best. */
+#define TOL_IMP 0.999 /* [0.998] Minimum error improvement to continue - reduces accuracy (1.0 == off) */
#undef GRADUATED_TOL /* [Undef] Speedup attemp - use reduced tollerance for prior grids. */
#define GRATIO 2.0 /* [2.0] Multi-grid resolution ratio */
#undef OVERRLX /* [Undef] Use over relaxation when progress slows (worse accuracy ?) */
@@ -262,7 +258,7 @@ static void free_cj_arrays(cj_arrays *ta);
static int add_rspl_imp(rspl *s, int flags, void *d, int dtp, int dno);
static mgtmp *new_mgtmp(rspl *s, int gres[MXDI], int f);
static void free_mgtmp(mgtmp *m);
-static void setup_solve(mgtmp *m, int final);
+static void setup_solve(mgtmp *m);
static void solve_gres(mgtmp *m, cj_arrays *ta, double tol, int final);
static void init_soln(mgtmp *m1, mgtmp *m2);
static void comp_ccv(mgtmp *m);
@@ -656,8 +652,7 @@ add_rspl_imp(
if (s->tpsm && s->tpsm2 != 0) { /* 2nd pass of 2 pass smoothing */
init_ccv(m); /* Downsample m->ccv from s->g.ccv */
}
-// setup_solve(m, nn == (s->niters-1));
- setup_solve(m, 1);
+ setup_solve(m);
if (nn == 0) { /* Make sure we have an initial x[] */
for (i = 0; i < m->g.no; i++)
@@ -921,9 +916,20 @@ free_data(rspl *s) {
/* to them, would have an average sample deviation of 0.05. */
/* For normally distributed errors, the average deviation is */
/* aproximately 0.564 times the standard deviation. (0.564 * sqrt(variance)) */
-/* This table is appropriate for the default rspl algorithm + slight EXTRA_SURFACE_SMOOTHING, */
+/* This table is appropriate for the default rspl algorithm, */
/* and is NOT setup for RSPL_2PASSSMTH or RSPL_EXTRAFIT2 !! */
/* SMOOTH */
+
+/* There are still issues with all this - the level of smoothing actually */
+/* depends on the degree of fit of the underlying model - ie. how close */
+/* to straight the mapping is. To get actual noise reduction under these */
+/* conditions is harder than when there is some curvature to "tension" things. */
+/* This is evident is Lab vs. XYZ display profiles, and there is code */
+/* in xlut.c that tries to adjust to this. */
+
+/* !!! Possible answer - should be using third order differences */
+/* for controlling smoothness, not second order (curvature) ?? */
+
// ~~99
static double opt_smooth(
rspl *s,
@@ -963,7 +969,7 @@ static double opt_smooth(
/* New for V1.10, from smtmpp using sRGB, EpsonR1800, Hitachi2112, */
- /* Fogra39L, Canon1180, Epson10K, with low EXTRA_SURFACE_SMOOTHING. */
+ /* Fogra39L, Canon1180, Epson10K (did use EXTRA_SURFACE_SMOOTHING). */
/* Main lookup table, by [di][ncix][adix]: */
/* Values are log of smoothness value. */
@@ -1349,8 +1355,7 @@ static void free_mgtmp(mgtmp *m) {
*/
static void setup_solve(
- mgtmp *m, /* initialized grid temp structure */
- int final /* nz if final resolution (activate EXTRA_SURFACE_SMOOTHING) */
+ mgtmp *m /* initialized grid temp structure */
) {
rspl *s = m->s;
int di = s->di;
@@ -1470,7 +1475,6 @@ static void setup_solve(
b[i] = 0.0;
}
-#ifdef NEVER
/* Production version, without extra edge weight */
/* Accumulate curvature dependent factors to the triangular A matrix. */
@@ -1499,20 +1503,46 @@ static void setup_solve(
ki-1 * w[i-1] * w[i-1] * u[i-1]
ki * -(w[i-1] + w[i]) * -(w[i-1] + w[i]) * u[i])
ki+1 * w[i] * w[i] * u[i+1]
+
+ The weighting is adjusted to compensate for increased
+ grid density by the dw weight, and for the different
+ scaling either side of a grid point with the w0 and w1 scale.
+ Both are normalised so that the overall smoothness scaling
+ factor applies.
*/
- { /* Setting this up from scratch */
+ { /* Setting this up from scratch */
+ double dwtw[MXDIDO]; /* Density weight normalizer */
+ int wtwc[MXDIDO];
ECOUNT(gc, MXDIDO, di, 0, gres, 0);
- EC_INIT(gc);
for (oawt = 0.0, i = 1; i < 21; i++)
oawt += wvals[i];
oawt *= wvals[0];
+#define EN_DW /* Enable grid density weighting */
+#define EN_CW /* Enable grid scale weighting */
+
+ /* Compute the ipos[] weight normalisation factors */
+ for (e = 0; e < di; e++) {
+ if (m->g.ipos[e] == NULL)
+ continue;
+ dwtw[e] = 0.0;
+ for (i = 1; i < gres[e]; i++) {
+ double w;
+ w = fabs(m->g.ipos[e][i] - m->g.ipos[e][i-1]);
+//printf("[%d][%d] w = %f\n",e,i,w);
+ dwtw[e] += w;
+ }
+ dwtw[e] /= (gres[e] - 1.0); /* Average weights */
+//printf("dwtw[%d] = %f\n",e,dwtw[e]);
+ }
+
+ EC_INIT(gc);
for (i = 0; i < gno; i++) {
for (e = 0; e < di; e++) { /* For each curvature direction */
- double w0, w1, tt;
+ double dw, w0, w1, tt;
double cw = 2.0 * m->sf.cw[e]; /* Overall curvature weight */
cw *= s->d.vw[f]; /* Scale curvature weight for data range */
@@ -1521,14 +1551,24 @@ static void setup_solve(
if ((gc[e]-2) >= 0) {
/* double kw = cw * gp[UO_C(e,1)].k; */ /* Cell bellow k value */
double kw = cw;
- w0 = w1 = 1.0;
+ dw = w1 = 1.0;
if (m->g.ipos[e] != NULL) {
+
w0 = fabs(m->g.ipos[e][gc[e]-1] - m->g.ipos[e][gc[e]-2]);
w1 = fabs(m->g.ipos[e][gc[e]-0] - m->g.ipos[e][gc[e]-1]);
- tt = sqrt(w0 * w1); /* Normalise overall width weighting effect */
+//printf("raw [%d][%d] w0 = %f, w1 = %f\n",gc[e],i,w0,w1);
+#ifdef EN_DW
+ dw = 0.5 * (w0 + w1); /* in this direction around -1 */
+ dw = dw/dwtw[e]; /* normalise */
+#endif
+ tt = sqrt(w0 * w1);
w1 = tt/w1;
+#ifndef EN_CW
+ w1 = 1.0;
+#endif
+//printf("[%d][%d] dw = %f, w1 = %f\n",gc[e],i,dw,w1);
}
- A[i][ixcol[0]] += w1 * w1 * kw;
+ A[i][ixcol[0]] += dw * w1 * w1 * kw;
if (ccv != NULL)
b[i] += kw * (w1) * ccv[i - gci[e]][e]; /* Curvature compensation value */
}
@@ -1537,16 +1577,25 @@ static void setup_solve(
if ((gc[e]-1) >= 0 && (gc[e]+1) < gres[e]) {
/* double kw = cw * gp->k; */ /* This cells k value */
double kw = cw;
- w0 = w1 = 1.0;
+ dw = w0 = w1 = 1.0;
if (m->g.ipos[e] != NULL) {
w0 = fabs(m->g.ipos[e][gc[e]-0] - m->g.ipos[e][gc[e]-1]);
w1 = fabs(m->g.ipos[e][gc[e]+1] - m->g.ipos[e][gc[e]-0]);
+//printf("raw [%d][%d] w0 = %f, w1 = %f\n",gc[e],i,w0,w1);
+#ifdef EN_DW
+ dw = 0.5 * (w0 + w1); /* in this direction around 0 */
+ dw = dw/dwtw[e]; /* normalise */
+#endif
tt = sqrt(w0 * w1);
w0 = tt/w0;
w1 = tt/w1;
+#ifndef EN_CW
+ w0 = w1 = 1.0;
+#endif
+//printf("[%d][%d] dw = %f, w0 = %f, w1 = %f\n",gc[e],i,dw,w0,w1);
}
- A[i][ixcol[0]] += -(w0 + w1) * -(w0 + w1) * kw;
- A[i][ixcol[gci[e]]] += -(w0 + w1) * w1 * kw * oawt;
+ A[i][ixcol[0]] += dw * -(w0 + w1) * -(w0 + w1) * kw;
+ A[i][ixcol[gci[e]]] += dw * -(w0 + w1) * w1 * kw * oawt;
if (ccv != NULL)
b[i] += kw * -(w0 + w1) * ccv[i][e]; /* Curvature compensation value */
}
@@ -1555,173 +1604,33 @@ static void setup_solve(
if ((gc[e]+2) < gres[e]) {
/* double kw = cw * gp[UO_C(e,2)].k; */ /* Cell above k value */
double kw = cw;
- w0 = w1 = 1.0;
+ dw = w0 = w1 = 1.0;
if (m->g.ipos[e] != NULL) {
w0 = fabs(m->g.ipos[e][gc[e]+1] - m->g.ipos[e][gc[e]+0]);
w1 = fabs(m->g.ipos[e][gc[e]+2] - m->g.ipos[e][gc[e]+1]);
- tt = sqrt(w0 * w1);
- w0 = tt/w0;
- w1 = tt/w1;
- }
- A[i][ixcol[0]] += w0 * w0 * kw;
- A[i][ixcol[gci[e]]] += w0 * -(w0 + w1) * kw;
- A[i][ixcol[2 * gci[e]]] += w0 * w1 * kw;
- if (ccv != NULL)
- b[i] += kw * -(w0 + w1) * ccv[i][e]; /* Curvature compensation value */
- }
- }
- EC_INC(gc);
- }
- }
-#endif /* NEVER */
-
-#ifdef ALWAYS
- /* Production version that allows for extra weight on grid edges */
-
- /* Accumulate curvature dependent factors to the triangular A matrix. */
- /* Because it's triangular, we compute and add in all the weighting */
- /* factors at and to the right of each cell. */
-
- /* The ipos[] factor is to allow for the possibility that the */
- /* grid spacing may be non-uniform in the colorspace where the */
- /* function being modelled is smooth. Our curvature computation */
- /* needs to make allowsance for this fact in computing the */
- /* node value differences that equate to zero curvature. */
- /*
- The old curvature fixed grid spacing equation was:
- ki * (u[i-1] - 2 * u[i] + u[i+1])^2
- with derivatives wrt each node:
- ki-1 * 1 * 2 * u[i-1]
- ki * -2 * 2 * u[i]
- ki+1 * 1 * 2 * u[i+1]
-
- Allowing for scaling of each grid difference by w[i-1] and w[i],
- where w[i-1] corresponds to the width of cell i-1 to i,
- and w[i] corresponds to the width of cell i to i+1:
- ki * (w[i-1] * (u[i-1] - u[i]) + w[i] * (u[i+1] - u[i[))^2
- = ki * (w[i-1] * u[i-1] - (w[i-1] + w[i]) * u[i]) + w[i] * u[i+1])^2
- with derivatives wrt each node:
- ki-1 * w[i-1] * w[i-1] * u[i-1]
- ki * -(w[i-1] + w[i]) * -(w[i-1] + w[i]) * u[i])
- ki+1 * w[i] * w[i] * u[i+1]
- */
- { /* Setting this up from scratch */
- ECOUNT(gc, MXDIDO, di, 0, gres, 0);
-#ifdef EXTRA_SURFACE_SMOOTHING
-// double k0w = 4.0, k1w = 1.3333; /* Extra stiffness */
-// double k0w = 3.0, k1w = 1.26; /* Some extra stiffness */
- double k0w = 2.0, k1w = 1.15; /* A little extra stiffness */
-#else
- double k0w = 1.0, k1w = 1.0; /* No extra weights */
+//printf("raw [%d][%d] w0 = %f, w1 = %f\n",gc[e],i,w0,w1);
+#ifdef EN_DW
+ dw = 0.5 * (w0 + w1); /* in this direction around +1 */
+ dw = dw/dwtw[e]; /* normalise */
#endif
-
- EC_INIT(gc);
- for (oawt = 0.0, i = 1; i < 21; i++)
- oawt += wvals[i];
- oawt *= wvals[0];
-
- if (final == 0)
- k0w = k1w = 1.0; /* Activate extra edge smoothing on final grid ? */
-
- for (i = 0; i < gno; i++) {
- int k;
-
- /* We're creating the equation cooeficients for solving the */
- /* partial derivative equation w.r.t. node point i. */
- /* Due to symetry in the smoothness interactions, only */
- /* the triangle cooeficients of neighbour nodes is needed. */
- for (e = 0; e < di; e++) { /* For each curvature direction */
- double kw, w0, w1, tt;
- double cw = 2.0 * m->sf.cw[e]; /* Overall curvature weight */
- double xx = 1.0; /* Extra edge weighing */
- cw *= s->d.vw[f]; /* Scale curvature weight for data range */
-
- /* weight factor for outer or 2nd outer in other dimensions */
- for (k = 0; k < di; k++) {
- if (k == e)
- continue;
- if (gc[k] == 0 || gc[k] == (gres[k]-1))
- xx *= k0w;
- else if (gc[k] == 1 || gc[k] == (gres[k]-2))
- xx *= k1w;
- }
-
- /* If at least two above lower edge in this dimension */
- /* Add influence on Curvature of cell below */
- if ((gc[e]-2) >= 0) {
- /* double kw = cw * gp[-gc[e]].k; */ /* Cell bellow k value */
- kw = cw * xx;
- w0 = w1 = 1.0;
- if (m->g.ipos[e] != NULL) {
- w0 = fabs(m->g.ipos[e][gc[e]-1] - m->g.ipos[e][gc[e]-2]);
- w1 = fabs(m->g.ipos[e][gc[e]-0] - m->g.ipos[e][gc[e]-1]);
- tt = sqrt(w0 * w1); /* Normalise overall width weighting effect */
- w1 = tt/w1;
- }
- if ((gc[e]-2) == 0 || (gc[e]+0) == (gres[e]-1))
- kw *= k0w;
- else if ((gc[e]-2) == 1 || (gc[e]-0) == (gres[e]-2))
- kw *= k1w;
- A[i][ixcol[0]] += kw * (w1) * w1;
- if (ccv != NULL) {
-//printf("~1 tweak b[%d] by %e\n",i,kw * (w1) * ccv[i - gci[e]][e]);
- b[i] += kw * (w1) * ccv[i - gci[e]][e]; /* Curvature compensation value */
- }
- }
- /* If not one from upper or lower edge in this dimension */
- /* Add influence on Curvature of this cell */
- if ((gc[e]-1) >= 0 && (gc[e]+1) < gres[e]) {
- /* double kw = cw * gp->k; */ /* This cells k value */
- kw = cw * xx;
- w0 = w1 = 1.0;
- if (m->g.ipos[e] != NULL) {
- w0 = fabs(m->g.ipos[e][gc[e]-0] - m->g.ipos[e][gc[e]-1]);
- w1 = fabs(m->g.ipos[e][gc[e]+1] - m->g.ipos[e][gc[e]-0]);
tt = sqrt(w0 * w1);
w0 = tt/w0;
w1 = tt/w1;
+#ifndef EN_CW
+ w0 = w1 = 1.0;
+#endif
+//printf("[%d][%d] dw = %f, w0 = %f, w1 = %f\n",gc[e],i,dw,w0,w1);
}
- if ((gc[e]-1) == 0 || (gc[e]+1) == (gres[e]-1))
- kw *= k0w;
- else if ((gc[e]-1) == 1 || (gc[e]+1) == (gres[e]-2))
- kw *= k1w;
- A[i][ixcol[0]] += kw * -(w0 + w1) * -(w0 + w1);
- A[i][ixcol[gci[e]]] += kw * -(w0 + w1) * w1 * oawt;
- if (ccv != NULL) {
-//printf("~1 tweak b[%d] by %e\n",i, kw * -(w0 + w1) * ccv[i][e]);
+ A[i][ixcol[0]] += dw * w0 * w0 * kw;
+ A[i][ixcol[gci[e]]] += dw * w0 * -(w0 + w1) * kw;
+ A[i][ixcol[2 * gci[e]]] += dw * w0 * w1 * kw;
+ if (ccv != NULL)
b[i] += kw * -(w0 + w1) * ccv[i][e]; /* Curvature compensation value */
- }
- }
- /* If at least two below the upper edge in this dimension */
- /* Add influence on Curvature of cell above */
- if ((gc[e]+2) < gres[e]) {
- /* double kw = cw * gp[gc[e]].k; */ /* Cell above k value */
- kw = cw * xx;
- w0 = w1 = 1.0;
- if (m->g.ipos[e] != NULL) {
- w0 = fabs(m->g.ipos[e][gc[e]+1] - m->g.ipos[e][gc[e]+0]);
- w1 = fabs(m->g.ipos[e][gc[e]+2] - m->g.ipos[e][gc[e]+1]);
- tt = sqrt(w0 * w1);
- w0 = tt/w0;
- w1 = tt/w1;
- }
- if ((gc[e]+0) == 0 || (gc[e]+2) == (gres[e]-1))
- kw *= k0w;
- else if ((gc[e]+0) == 1 || (gc[e]+2) == (gres[e]-2))
- kw *= k1w;
- A[i][ixcol[0]] += kw * (w0) * w0;
- A[i][ixcol[gci[e]]] += kw * (w0) * -(w0 + w1);
- A[i][ixcol[2 * gci[e]]] += kw * (w0) * w1;
- if (ccv != NULL) {
-//printf("~1 tweak b[%d] by %e\n",i, kw * (w0) * ccv[i + gci[e]][e]);
- b[i] += kw * (w0) * ccv[i + gci[e]][e]; /* Curvature compensation value */
- }
}
}
EC_INC(gc);
}
}
-#endif /* ALWAYS */
#ifdef DEBUG
printf("After adding curvature equations:\n");
@@ -1736,7 +1645,6 @@ static void setup_solve(
nbsum = 0.0; /* Zero sum of b[] squared */
-#ifdef ALWAYS
/* Accumulate weak default function factors. These are effectively a */
/* weak "data point" exactly at each grid point. */
/* (Note we're not currently doing this in a cache friendly order, */
@@ -1775,9 +1683,7 @@ static void setup_solve(
#endif /* DEBUG */
}
-#endif /* ALWAYS */
-#ifdef ALWAYS
/* Accumulate data point dependent factors */
for (n = 0; n < dno; n++) { /* Go through all the data points */
int j,k;
@@ -1815,8 +1721,6 @@ static void setup_solve(
nbsum = 1e-4;
m->q.normb = nbsum;
-#endif /* ALWAYS */
-
#ifdef DEBUG
printf("After adding data point equations:\n");
for (i = 0; i < gno; i++) {
diff --git a/scanin/ColorCheckerDC.ti2 b/scanin/ColorCheckerDC.ti2
new file mode 100644
index 0000000..f87284c
--- /dev/null
+++ b/scanin/ColorCheckerDC.ti2
@@ -0,0 +1,264 @@
+CTI2
+
+DESCRIPTOR "Argyll Calibration Target chart information 2"
+ORIGINATOR "Argyll printtarg"
+CREATED "Tue Nov 19 14:16:26 2013"
+KEYWORD "TARGET_INSTRUMENT"
+TARGET_INSTRUMENT "GretagMacbeth SpectroScan"
+APPROX_WHITE_POINT "95.106486 100.000000 108.844025"
+COLOR_REP "RGB"
+CHART_ID 26
+STEPS_IN_PASS 12
+PASSES_IN_STRIPS2 20
+STRIP_INDEX_PATTERN "A-Z, A-Z"
+PATCH_INDEX_PATTERN "@-9,0-9;01-99"
+INDEX_ORDER "STRIP_THEN_PATCH"
+
+NUMBER_OF_FIELDS 8
+BEGIN_DATA_FORMAT
+SAMPLE_ID SAMPLE_LOC RGB_R RGB_G RGB_B XYZ_X XYZ_Y XYZ_Z
+END_DATA_FORMAT
+
+NUMBER_OF_SETS 240
+BEGIN_DATA
+1 "A01" 95.27 94.34 100 74.79 77.56 64.46
+2 "A02" 10.1 12.72 15.23 3.08 3.19 2.77
+3 "A03" 50.01 49.47 53.83 18.98 19.71 16.53
+4 "A04" 95.19 94.25 100 74.57 77.34 64.38
+5 "A05" 10.25 12.82 15.3 3.1 3.21 2.78
+6 "A06" 49.76 49.32 53.63 18.88 19.62 16.44
+7 "A07" 95.23 94.31 100 74.65 77.43 64.37
+8 "A08" 9.95 12.59 14.99 3.05 3.16 2.74
+9 "A09" 49.73 49.25 53.58 18.86 19.59 16.42
+10 "A10" 95.1 94.22 99.98 74.33 77.13 64.18
+11 "A11" 9.95 12.59 14.99 3.05 3.16 2.74
+12 "A12" 49.93 49.4 53.72 18.94 19.67 16.48
+13 "B01" 50.01 49.47 53.83 18.98 19.71 16.53
+14 "B02" 46.36 12.46 22.34 9.28 6.32 3.27
+15 "B03" 32.74 22.03 19.37 7.34 6.63 3.64
+16 "B04" 56.14 48.21 40.46 19.71 19.69 11.13
+17 "B05" 35.71 36.78 28.68 10.69 11.58 6.54
+18 "B06" 19.44 26.18 17.23 5.55 6.26 3.53
+19 "B07" 9.63 29.83 19.36 4.69 6.4 3.88
+20 "B08" 5.03 29.78 29.99 4.45 6.24 5.6
+21 "B09" 11.74 26.06 33.69 5.26 6.13 6.71
+22 "B10" 7.48 17.09 38.75 4.16 4.4 7.55
+23 "B11" 31.81 19.87 28.2 7.13 6.18 5.2
+24 "B12" 95.28 94.35 100 74.68 77.45 64.31
+25 "C01" 9.86 12.49 14.83 3.03 3.14 2.72
+26 "C02" 78.87 8.12 37.96 22.27 12.45 5.91
+27 "C03" 50.95 30.12 24.15 13.73 11.57 5.26
+28 "C04" 44.44 34.21 17.16 12.35 11.83 4.46
+29 "C05" 46.22 52.19 26.89 16.62 19.15 7.75
+30 "C06" 23 40.19 25.32 8.81 11.49 5.72
+31 "C07" 9.34 43.53 27.72 7.38 11.51 5.94
+32 "C08" 9.06 40.65 41.35 7.96 11.09 9.57
+33 "C09" 8.24 25.27 43.76 5.61 6.35 9.68
+34 "C10" 4.46 23.9 51.18 5.49 6.22 12.37
+35 "C11" 39.09 18.2 33.1 8.5 6.58 6.19
+36 "C12" 9.9 12.54 14.91 3.04 3.15 2.73
+37 "D01" 95.25 94.34 100 74.7 77.48 64.38
+38 "D02" 83.18 3.28 29.2 23.6 12.43 3.41
+39 "D03" 58.04 28.35 19.08 15.71 12.25 4.16
+40 "D04" 60.64 50.58 1.68 19.85 19.78 4.3
+41 "D05" 44.66 55.44 3.99 15.7 19.2 4.89
+42 "D06" 50.68 71.99 20.2 22.07 30.17 8.05
+43 "D07" 1.82 46.45 32.24 6.22 11.44 6.34
+44 "D08" 2.68 60.96 59.88 11.56 19.31 16.65
+45 "D09" 6.74 22.7 51.61 5.69 6.13 12.53
+46 "D10" 5.74 20.48 57.17 5.6 5.88 14.72
+47 "D11" 43.58 14.07 38.16 9.13 6.35 7.28
+48 "D12" 49.85 49.34 53.67 18.91 19.64 16.46
+49 "E01" 49.93 49.45 53.76 18.95 19.69 16.5
+50 "E02" 98.18 12.49 38.48 35.41 20.25 6.45
+51 "E03" 83.15 34.43 11.22 28.25 20.38 3.83
+52 "E04" 62.85 47.43 3.48 20.73 19.59 4.47
+53 "E05" 49.17 54.51 0.58 16.4 19.03 4.34
+54 "E06" 67.94 82.3 53.02 34.81 43.02 17.75
+55 "E07" 7.82 61.12 45.54 11.78 19.58 11.32
+56 "E08" 0.06 48.5 61.14 6.88 11.75 14.39
+57 "E09" 0.19 40.75 67.67 7.88 11.31 19.64
+58 "E10" 3.32 36.11 77.29 9.22 11.09 27.08
+59 "E11" 65.18 18.84 54.73 17.84 11.47 13.98
+60 "E12" 95.25 94.3 100 74.56 77.32 64.24
+61 "F01" 9.9 12.54 14.91 3.04 3.15 2.73
+62 "F02" 99.74 26.47 46.59 48.3 30.25 11.41
+63 "F03" 62.95 20.45 23.38 16.14 10.93 3.9
+64 "F04" 76.63 60.56 22.07 31.33 29.91 8.52
+65 "F05" 36.63 55.19 18.02 14.11 18.71 6.4
+66 "F06" 78.75 80.96 20.26 38.16 43.99 9.51
+67 "F07" 7.01 62.38 35.44 10.52 19.33 8.14
+68 "F08" 1.48 41.62 59.96 7.96 11.49 16.13
+69 "F09" 4.66 38.88 62.1 8.63 11.3 17.86
+70 "F10" 8.56 33.53 76.84 10.41 11.24 27.64
+71 "F11" 76.83 8.82 46.69 21.49 12.15 9.52
+72 "F12" 9.9 12.54 14.91 3.04 3.15 2.73
+73 "G01" 95.27 94.34 100 74.73 77.5 64.38
+74 "G02" 98.55 34.63 57.21 44.51 29.8 15.52
+75 "G03" 71.71 37.83 33.38 24.34 19.34 8.11
+76 "G04" 74.92 38.56 10.79 25.26 19.88 4.38
+77 "G05" 36.15 59.64 1.53 13.65 19.52 4.62
+78 "G06" 79.26 82.87 1.12 36.49 43.18 5.73
+79 "G07" 31.42 73.13 50.51 19.42 29.58 14.51
+80 "G08" 5.45 70.76 91.77 19.86 28.9 37.67
+81 "G09" 9.76 53.95 72.09 14.15 18.75 25.13
+82 "G10" 12.93 35.04 69.77 10.69 11.62 23.13
+83 "G11" 91.13 23.55 63.45 31.57 19.76 17.91
+84 "G12" 49.85 49.34 53.67 18.91 19.64 16.46
+85 "H01" 50.01 49.47 53.83 18.98 19.71 16.53
+86 "H02" 94.23 19.84 47.13 33.5 20.33 9.91
+87 "H03" 84.08 49.98 45.1 34.67 28.65 13.17
+88 "H04" 63.04 25.22 10.51 16.86 12.12 2.75
+89 "H05" 49.17 72.98 8.29 21.16 30.06 6.66
+90 "H06" 90.01 92 51.94 52.08 58.65 19.39
+91 "H07" 51.68 69.17 35.96 22.63 29.16 10.83
+92 "H08" 22.67 69.1 84.54 21.74 29.15 34.08
+93 "H09" 2.08 53.56 85.09 13.59 18.65 33.2
+94 "H10" 18.2 48.01 90.52 17.32 18.86 39.16
+95 "H11" 84.22 29.36 61.76 29.3 19.82 17.88
+96 "H12" 95.28 94.34 100 74.65 77.41 64.27
+97 "I01" 9.95 12.59 14.99 3.05 3.16 2.74
+98 "I02" 63.39 42.06 52.1 22.03 19.1 15.09
+99 "I03" 76.57 55.72 50.91 31.97 28.79 15.9
+100 "I04" 98.78 37.3 25.86 42.69 29.41 6.24
+101 "I05" 97.3 98.04 99.89 82.21 85.41 69.86
+102 "I06" 65.58 65.98 70.9 30.96 32.15 26.58
+103 "I07" 44.74 45.12 49.16 16.49 17.18 14.34
+104 "I08" 24.98 26.86 30.43 7.03 7.28 6.15
+105 "I09" 39.67 65.7 88.49 24.91 29.34 38.48
+106 "I10" 52.39 60.56 94.9 29.04 29.31 45.2
+107 "I11" 95.98 42.83 73.82 41.09 29.82 26.18
+108 "I12" 9.92 12.58 15.07 3.05 3.16 2.75
+109 "J01" 95.23 94.32 100 74.72 77.5 64.44
+110 "J02" 77.57 32.64 54.49 26.91 19.35 14.94
+111 "J03" 83.29 53.78 37.02 34.54 29.66 11.16
+112 "J04" 100 52.92 30.05 58.1 42.93 8.71
+113 "J05" 92.1 89.96 96.97 64.14 66.75 54.99
+114 "J06" 98.88 99.51 99.69 87.06 90.39 72.76
+115 "J07" 98.8 99.45 99.69 86.82 90.15 72.56
+116 "J08" 15.3 18.64 21.56 4.28 4.47 3.84
+117 "J09" 35.08 63.84 96.62 24.87 28.59 45.17
+118 "J10" 65.98 70.7 100 41.47 42.2 57.7
+119 "J11" 99.15 59.59 84.68 53.38 42.55 36.49
+120 "J12" 49.87 49.36 53.7 18.92 19.65 16.47
+121 "K01" 49.99 49.46 53.81 18.97 19.7 16.52
+122 "K02" 86.58 49.77 60.7 36.7 29.69 19.45
+123 "K03" 88.67 51.5 28.75 36.83 30.22 8.83
+124 "K04" 98.88 62.08 32.27 53.42 43.05 10.13
+125 "K05" 85.31 83.06 90.88 51.78 53.86 44.86
+126 "K06" 98.81 99.46 99.68 86.85 90.18 72.55
+127 "K07" 98.82 99.48 99.69 86.91 90.25 72.64
+128 "K08" 12.06 14.95 17.22 3.45 3.59 3.07
+129 "K09" 6.92 67.52 99.04 21.49 28.73 46.46
+130 "K10" 50.08 42.95 86.74 21.85 19.42 36.39
+131 "K11" 75.42 56.11 68.02 32.48 29.05 24.22
+132 "K12" 95.27 94.32 100 74.63 77.39 64.28
+133 "L01" 9.84 12.49 14.92 3.03 3.14 2.73
+134 "L02" 98.98 57.11 74.4 53.85 42.1 29.27
+135 "L03" 99.89 50.46 60.72 58.21 42.93 21.15
+136 "L04" 99.29 46.21 3.17 40.96 30.79 3.87
+137 "L05" 75.24 75.43 81.94 40.79 42.45 35.04
+138 "L06" 57.21 57.01 61.15 23.51 24.47 20.31
+139 "L07" 34.32 36.31 40.46 11.1 11.62 9.8
+140 "L08" 9.82 12.45 14.75 3.02 3.13 2.71
+141 "L09" 33.27 77.33 99.89 31.86 41.84 53.57
+142 "L10" 33.9 16.63 45.96 7.9 6.16 10.17
+143 "L11" 98.43 80.02 96.18 62.34 57.68 47.93
+144 "L12" 9.86 12.49 14.83 3.03 3.14 2.72
+145 "M01" 95.25 94.34 100 74.74 77.52 64.43
+146 "M02" 99.99 73.82 90.19 68.21 58.76 45.3
+147 "M03" 99.19 58.74 71.9 54.32 42.79 26.91
+148 "M04" 99.98 75.49 34.17 68.17 58.65 13.41
+149 "M05" 99.35 99.63 30.25 76.51 80.88 14.08
+150 "M06" 25.3 54.85 59.81 15.06 19.36 18.82
+151 "M07" 12.74 75.9 44.48 16.03 29.31 11.79
+152 "M08" 79 86.77 95.63 52.05 57.11 51.73
+153 "M09" 42.83 80.8 96.51 32.54 42.52 46.33
+154 "M10" 29 19.89 40.72 7.2 6.19 8.57
+155 "M11" 97.05 93.04 100 78.01 78.48 67.07
+156 "M12" 49.89 49.41 53.72 18.93 19.67 16.48
+157 "N01" 50 49.45 53.79 18.97 19.7 16.51
+158 "N02" 99.34 79.72 88.26 65.97 60.13 42.01
+159 "N03" 96.25 63.6 74.67 50.5 42.33 28.58
+160 "N04" 99.27 81.88 42.08 63.78 59.07 15.95
+161 "N05" 99.65 82.63 11.45 62.58 58.72 7.2
+162 "N06" 26.24 70.63 78.27 21.33 29.57 29.73
+163 "N07" 9.82 75.76 59.79 17.06 29.9 17.13
+164 "N08" 76.26 84.42 99.75 54.05 58.63 61.58
+165 "N09" 68.69 87.9 99.27 49.41 57.82 58.22
+166 "N10" 58.46 25.45 64.62 16.9 12.02 19.29
+167 "N11" 97.22 42 83.28 41.76 29.82 32.52
+168 "N12" 95.29 94.35 100 74.67 77.43 64.28
+169 "O01" 9.82 12.45 14.75 3.02 3.13 2.71
+170 "O02" 91.01 68.56 77.87 47.1 42.51 31.08
+171 "O03" 97.63 62.78 50 51.87 42.51 15.81
+172 "O04" 98.83 97.18 92.89 77.2 77.91 50.55
+173 "O05" 98.9 73.19 0 45.99 42.6 4.49
+174 "O06" 40.94 68.1 75.26 23.64 29.5 29.06
+175 "O07" 41.16 87.88 60.49 26.97 42.73 19.28
+176 "O08" 59.59 63.21 73.49 27.97 29.35 28.33
+177 "O09" 75.74 88.91 93.15 50.32 57.45 48.38
+178 "O10" 63.01 42.18 68.33 23.06 19.58 23.21
+179 "O11" 69.87 57.18 83.37 32.18 29.25 34.95
+180 "O12" 9.77 12.4 14.67 3.01 3.12 2.7
+181 "P01" 95.25 94.32 100 74.64 77.41 64.32
+182 "P02" 84.46 72.89 80.48 44.39 42.98 33.4
+183 "P03" 100 72.99 59.81 71.49 59.42 23.1
+184 "P04" 100 97.78 79.43 79.86 78.26 38.44
+185 "P05" 80.84 60.67 1.37 31.59 29.6 5.37
+186 "P06" 25.93 70.68 69.27 20.07 28.76 23.92
+187 "P07" 50.83 83.03 73.17 31.22 42.07 27.31
+188 "P08" 37.02 50.17 67.49 17.15 18.99 23.19
+189 "P09" 65.74 78.01 85.01 37.97 42.95 38.15
+190 "P10" 54.49 46.66 57.66 19.91 19.24 17.99
+191 "P11" 79.86 72.98 93.2 44.36 43.41 45.48
+192 "P12" 49.95 49.42 53.74 18.95 19.68 16.49
+193 "Q01" 49.97 49.44 53.79 18.96 19.69 16.51
+194 "Q02" 95.79 84.32 88.88 59.99 58.87 41.85
+195 "Q03" 99.99 75.47 73.09 67.98 58.85 30.96
+196 "Q04" 100 95.41 90.21 82.15 79.03 48.34
+197 "Q05" 84.41 57.2 5.84 33.18 29.48 5.74
+198 "Q06" 9.17 72.73 77.86 18.92 29.39 27.97
+199 "Q07" 62.99 96.48 86.58 44.1 58.65 39.14
+200 "Q08" 71.85 77.1 70.94 37.51 41.38 26.69
+201 "Q09" 81.83 75.79 50.62 40.27 42.04 17.38
+202 "Q10" 53.2 64.94 64.37 24.86 28.48 22.3
+203 "Q11" 23.22 38.44 40.32 9.43 11.28 9.5
+204 "Q12" 95.28 94.33 100 74.61 77.37 64.24
+205 "R01" 9.95 12.59 14.99 3.05 3.16 2.74
+206 "R02" 71.47 61.11 61.93 31.16 30.09 20.86
+207 "R03" 93.36 84.53 83.13 56.92 56.98 36.53
+208 "R04" 99.7 95.07 97.1 79.37 78.57 56.95
+209 "R05" 89.21 74.18 15.19 42.68 42.54 8.26
+210 "R06" 35.67 84.82 81.93 28.15 41.91 31.53
+211 "R07" 77.72 93.12 78.3 48.61 58.02 33.46
+212 "R08" 62.64 63.77 53.68 26.81 28.91 16.95
+213 "R09" 81.95 77.86 34 39.83 43.08 12.47
+214 "R10" 41.4 34.94 25.31 11.8 11.72 5.87
+215 "R11" 40.7 52.5 53.8 17.1 19.71 16.41
+216 "R12" 9.82 12.45 14.75 3.02 3.13 2.71
+217 "S01" 95.25 94.32 100 74.66 77.43 64.34
+218 "S02" 78.68 76.08 69.89 40.67 42.42 26.09
+219 "S03" 94.62 94.65 86.45 65.09 68.67 41.71
+220 "S04" 0 10.44 63.73 3.01 3.34 15.4
+221 "S05" 0 57.08 10.66 3.26 11.22 2.89
+222 "S06" 82.88 0 10.83 17.7 8.11 0.42
+223 "S07" 99.49 100 99.75 89.01 92.27 74.63
+224 "S08" 0.01 0 0.02 0.28 0.29 0.24
+225 "S09" 99.68 99.73 0.01 72.92 74.82 4.56
+226 "S10" 81.93 0 35.68 17.03 7.57 3.05
+227 "S11" 0 45.14 76.9 6.56 11.29 24.29
+228 "S12" 49.85 49.34 53.67 18.91 19.64 16.46
+229 "T01" 49.85 49.34 53.67 18.91 19.64 16.46
+230 "T02" 9.97 12.59 14.91 3.05 3.16 2.73
+231 "T03" 95.15 94.21 99.99 74.38 77.15 64.2
+232 "T04" 49.92 49.43 53.72 18.94 19.68 16.48
+233 "T05" 10.35 13.04 15.35 3.12 3.24 2.79
+234 "T06" 95.13 94.16 99.93 74.2 76.97 63.98
+235 "T07" 49.74 49.3 53.61 18.87 19.61 16.43
+236 "T08" 9.84 12.67 14.89 3.04 3.16 2.73
+237 "T09" 95.22 94.29 99.96 74.41 77.19 64.05
+238 "T10" 49.82 49.33 53.67 18.9 19.63 16.46
+239 "T11" 10.16 12.77 15.31 3.09 3.2 2.78
+240 "T12" 95.28 94.32 100 74.57 77.32 64.19
+END_DATA
diff --git a/scanin/Jamfile b/scanin/Jamfile
index b6e58f1..57d90d2 100644
--- a/scanin/Jamfile
+++ b/scanin/Jamfile
@@ -8,7 +8,7 @@ PREF_LINKFLAGS += $(LINKDEBUGFLAG) ;
Libraries = libscanrd ;
Executables = scanin ;
Headers = scanrd.h ;
-Samples = it8.cht ColorChecker.cht ColorChecker.cie ColorCheckerDC.cht
+Samples = it8.cht ColorChecker.cht ColorChecker.cie ColorCheckerDC.cht ColorCheckerDC.ti2
ColorCheckerSG.cht Hutchcolor.cht i1_RGB_Scan_1.4.cht
ColorCheckerPassport.cht ColorCheckerPassport.cie
QPcard_201.cht QPcard_201.cie QPcard_202.cht QPcard_202.cie CMP_DT_003.cht
diff --git a/scanin/afiles b/scanin/afiles
index bc4d9c7..d644c32 100644
--- a/scanin/afiles
+++ b/scanin/afiles
@@ -10,6 +10,7 @@ it8.cht
ColorChecker.cht
ColorChecker.cie
ColorCheckerDC.cht
+ColorCheckerDC.ti2
ColorCheckerSG.cht
Hutchcolor.cht
i1_RGB_Scan_1.4.cht
diff --git a/scanin/scanin.c b/scanin/scanin.c
index 94771fe..cacbd7d 100644
--- a/scanin/scanin.c
+++ b/scanin/scanin.c
@@ -145,7 +145,7 @@ int main(int argc, char *argv[])
static char tiffin_name[MAXNAMEL+1] = { 0 }; /* TIFF Input file name (.tif) */
static char datin_name[MAXNAMEL+4+1] = { 0 }; /* Data input name (.cie/.q60) */
static char datout_name[MAXNAMEL+4+1] = { 0 }; /* Data output name (.ti3/.val) */
- static char recog_name[MAXNAMEL+1] = { 0 }; /* Reference chart name (.cht) */
+ static char recog_name[MAXNAMEL+1] = { 0 }; /* Reference chart name (.cht) */
static char prof_name[MAXNAMEL+1] = { 0 }; /* scanner profile name (.cht) */
static char diag_name[MAXNAMEL+1] = { 0 }; /* Diagnostic Output (.tif) name, if used */
int verb = 1;
@@ -337,9 +337,11 @@ int main(int argc, char *argv[])
if (fa >= argc || argv[fa][0] == '-') usage();
strncpy(tiffin_name,argv[fa],MAXNAMEL); tiffin_name[MAXNAMEL] = '\000';
+ /* Create a desination file path and name */
if (datout_name[0] == '\000' /* Not been overridden */
&& (flags & SI_BUILD_REF) == 0
- && repl == 0 && colm == 0) { /* Not generate ref or replacing .ti3 dev */
+ && repl == 0 && colm == 0) { /* Not generate ref or replacing .ti3 dev */
+ // ~~~99 Hmm. Should we honour -O ??
char *xl;
strncpy(datout_name,argv[fa],MAXNAMEL); datout_name[MAXNAMEL] = '\000';
if ((xl = strrchr(datout_name, '.')) == NULL) /* Figure where extention is */
@@ -369,7 +371,7 @@ int main(int argc, char *argv[])
if (repl != 0 || colm > 0) { /* Color from image or replacing .ti3 device data */
strcpy(datin_name,argv[fa]);
strcat(datin_name,".ti2");
- strcpy(datout_name,argv[fa]);
+ strcpy(datout_name,argv[fa]); // ~~~99 Hmm. Should we honour -O ??
strcat(datout_name,".ti3");
}
}
diff --git a/spectro/Jamfile b/spectro/Jamfile
index 87dee2f..b5ad548 100644
--- a/spectro/Jamfile
+++ b/spectro/Jamfile
@@ -10,13 +10,16 @@ if $(OS) = MACOSX {
ObjectCcFlags dispwin_dispwin : -ObjC ;
}
+MADVRSOURCE = ;
+
# Setup the right hardware access libraries
if $(NT) {
- if $(USE_NATIVE_USB) = true {
- DEFINES += NATIVE_USB ;
- LIBUSBHDRS = ../usb/driver ; # libusb-win32 kernel driver info
- } else {
+ MADVRSOURCE = madvrwin.c ;
+
+ if $(USE_LIBUSB) = true {
+ DEFINES += USE_LIBUSB ;
if $(USE_LIBUSB1) = true {
+ DEFINES += USE_LIBUSB1 ;
LIBUSBDIR = ../libusb1 ;
LIBUSBHDRS = ../libusb1 ;
if $(MSVCNT) {
@@ -28,19 +31,21 @@ if $(NT) {
} else {
LIBUSB = $(LIBUSB1NAME)$(SUFLIB) ;
}
- DEFINES += USE_LIBUSB1 ;
} else {
LIBUSBDIR = ../libusbw ;
LIBUSBHDRS = ../libusbw ;
LIBUSB = libusb ;
}
+ } else {
+ LIBUSBHDRS = ../usb/driver ; # libusb-win32 kernel driver info
}
}
+
if $(UNIX) {
- if $(USE_NATIVE_USB) = true {
- DEFINES += NATIVE_USB ;
- } else {
+ if $(USE_LIBUSB) = true {
+ DEFINES += USE_LIBUSB ;
if $(USE_LIBUSB1) = true {
+ DEFINES += USE_LIBUSB1 ;
LIBUSBDIR = ../libusb1 ;
LIBUSBHDRS = ../libusb1 ;
if $(LIBUSB_IS_DLL) = true {
@@ -49,7 +54,6 @@ if $(UNIX) {
} else {
LIBUSB = $(LIBUSB1NAME)$(SUFLIB) ;
}
- DEFINES += USE_LIBUSB1 ;
} else {
LIBUSBDIR = ../libusb ;
LIBUSBHDRS = ../libusb ;
@@ -84,12 +88,14 @@ HDRS = ../h ../numlib ../icc ../cgats ../rspl ../xicc ../gamut ../spectro
# Instrument access library library
SER_INSTS = dtp22.c dtp41.c dtp51.c ss.c ss_imp.c ;
-SER_USB_INSTS = dtp92.c ;
-
USB_INSTS = dtp20.c i1disp.c i1d3.c i1pro.c i1pro_imp.c
munki.c munki_imp.c hcfr.c spyd2.c huey.c
colorhug.c usbio.c hidio.c ;
+FAST_SER_INSTS = specbos.c ;
+
+SER_USB_INSTS = dtp92.c ;
+
if $(USE_SERIAL) = true {
DEFINES += ENABLE_SERIAL ;
INST_SRCS += $(SER_INSTS) ;
@@ -100,15 +106,26 @@ if $(USE_USB) = true {
INST_SRCS += $(USB_INSTS) ;
}
+if $(USE_FAST_SERIAL) = true || $(USE_SERIAL) = true {
+ DEFINES += ENABLE_FAST_SERIAL ;
+ INST_SRCS += $(FAST_SER_INSTS) ;
+}
+
if $(USE_SERIAL) = true || $(USE_USB) = true {
INST_SRCS += $(SER_USB_INSTS) ;
}
+if $(USE_DEMOINST) = true && [ GLOB . : demoinst.c ] {
+ echo "Compiling demo instrument support" ;
+ DEFINES += ENABLE_DEMOINST ;
+ INST_SRCS += demoinst.c ;
+}
+
Library libinst : inst.c insttypes.c icoms.c $(INST_SRCS) ;
# Display access library
ObjectKeep mongoose.c ;
-Library libdisp : dispsup.c dispwin.c webwin.c : : : $(LibWinH) : mongoose ;
+Library libdisp : dispsup.c dispwin.c webwin.c $(MADVRSOURCE) : : : $(LibWinH) : mongoose ;
# Instrument types utility functions library. Use this instead of libinst when */
# applications need to know about different instrument types, but not access them. */
@@ -173,7 +190,7 @@ Main dispread : dispread.c : : : : : libdisp ;
#display test window test/Lut loader utility
# [ Could avoid need for libisnt libusb etc.
# by separating system dependent utils to a separate library .]
-MainVariant dispwin : dispwin.c webwin.c : : STANDALONE_TEST : : mongoose : $(LibWin) ;
+MainVariant dispwin : dispwin.c webwin.c $(MADVRSOURCE) : : STANDALONE_TEST : : mongoose : $(LibWin) ;
LINKLIBS = libinsttypes ../xicc/libxicc ../gamut/libgamut ../rspl/librspl
../cgats/libcgats ../icc/libicc ../numlib/libnum ../plot/libplot
diff --git a/spectro/Makefile.OSX b/spectro/Makefile.OSX
index f98d078..485cbf4 100644
--- a/spectro/Makefile.OSX
+++ b/spectro/Makefile.OSX
@@ -26,10 +26,10 @@ LIBU = ar -r
LIBOF =
RANLIB = ranlib
AS = as
-CCFLAGSDEF = -DUNIX -c
+CCFLAGSDEF = -DUNIX -Wno-sign-compare -fpascal-strings -c
CC = cc $(CCFLAGS) $(STDHDRS)
CCOF = -o
-LINKFLAGSDEF = -lm -framework Carbon -framework IOKit -framework CoreFoundation -framework AudioToolbox
+LINKFLAGSDEF = -lm -framework Carbon -framework Cocoa -framework IOKit -framework CoreFoundation -framework AudioToolbox -framework AppKit
LINKLIBS =
LINK = cc $(LINKFLAGS) $(LINKLIBS)
LINKOF = -o
diff --git a/spectro/Makefile.SA b/spectro/Makefile.SA
index 4d253ec..b1fe55f 100644
--- a/spectro/Makefile.SA
+++ b/spectro/Makefile.SA
@@ -20,7 +20,7 @@ include Makefile.WNT
###############################
-CCDEFINES = $(DEFFLAG)SALONEINSTLIB $(DEFFLAG)ENABLE_SERIAL $(DEFFLAG)ENABLE_USB $(DEFFLAG)NATIVE_USB
+CCDEFINES = $(DEFFLAG)SALONEINSTLIB $(DEFFLAG)ENABLE_SERIAL $(DEFFLAG)ENABLE_FAST_SERIAL $(DEFFLAG)ENABLE_USB
#Set optimisation on
CCFLAGS = $(CCFLAGSDEF) $(CCOPTFLAG) $(CCDEFINES) $(BCONFIG)
@@ -38,8 +38,8 @@ WIN_STDHDRS = $(INCFLAG)usb$(SLASH)driver
all:: libinst$(SUFLIB) libinstappsup$(SUFLIB) spotread$(SUFEXE) oeminst$(SUFEXE)
-INSTHEADERS = dtp20.h dtp22.h dtp41.h dtp51.h dtp92.h ss.h ss_imp.h i1disp.h i1d3.h i1pro.h i1pro_imp.h munki.h munki_imp.h hcfr.h huey.h colorhug.h spyd2.h spyd2setup.h spyd2PLD.h
-INSOBJS = dtp20$(SUFOBJ) dtp22$(SUFOBJ) dtp41$(SUFOBJ) dtp51$(SUFOBJ) dtp92$(SUFOBJ) ss$(SUFOBJ) ss_imp$(SUFOBJ) i1disp$(SUFOBJ) i1d3$(SUFOBJ) i1pro$(SUFOBJ) i1pro_imp$(SUFOBJ) munki$(SUFOBJ) munki_imp$(SUFOBJ) hcfr$(SUFOBJ) huey$(SUFOBJ) colorhug$(SUFOBJ) spyd2$(SUFOBJ)
+INSTHEADERS = dtp20.h dtp22.h dtp41.h dtp51.h dtp92.h ss.h ss_imp.h i1disp.h i1d3.h i1pro.h i1pro_imp.h munki.h munki_imp.h hcfr.h huey.h colorhug.h spyd2.h spyd2setup.h spyd2PLD.h specbos.h
+INSOBJS = dtp20$(SUFOBJ) dtp22$(SUFOBJ) dtp41$(SUFOBJ) dtp51$(SUFOBJ) dtp92$(SUFOBJ) ss$(SUFOBJ) ss_imp$(SUFOBJ) i1disp$(SUFOBJ) i1d3$(SUFOBJ) i1pro$(SUFOBJ) i1pro_imp$(SUFOBJ) munki$(SUFOBJ) munki_imp$(SUFOBJ) hcfr$(SUFOBJ) huey$(SUFOBJ) colorhug$(SUFOBJ) spyd2$(SUFOBJ) specbos$(SUFOBJ)
HEADERS = pollem.h conv.h aglob.h hidio.h icoms.h inst.c inst.h insttypeinst.h insttypes.h $(INSTHEADERS) usbio.h xspect.h rspl1.h sort.h xdg_bds.h ccss.h ccmx.h pars.h cgats.h instappsup.h usb$(SLASH)driver$(SLASH)driver_api.h
@@ -139,6 +139,9 @@ colorhug$(SUFOBJ): colorhug.c $(HEADERS)
spyd2$(SUFOBJ): spyd2.c $(HEADERS)
$(CC) spyd2.c
+specbos$(SUFOBJ): specbos.c $(HEADERS)
+ $(CC) specbos.c
+
oemarch$(SUFOBJ): oemarch.c $(HEADERS)
$(CC) oemarch.c
@@ -168,7 +171,7 @@ instappsup$(SUFOBJ): instappsup.c $(HEADERS)
libinstappsup$(SUFLIB): $(SUPOBJS)
$(LIBU) $(LIBOF)$@ $(SUPOBJS)
- $(RANLIB) instappsup$(SUFLIB)
+ $(RANLIB) libinstappsup$(SUFLIB)
# test/example code
diff --git a/spectro/Makefile.UNIX b/spectro/Makefile.UNIX
index 5eaf6b5..adafa67 100644
--- a/spectro/Makefile.UNIX
+++ b/spectro/Makefile.UNIX
@@ -26,7 +26,7 @@ LIBU = ar -r
LIBOF =
RANLIB = echo
AS = as
-CCFLAGSDEF = -DUNIX -DNATIVE_USB -c
+CCFLAGSDEF = -DUNIX -c
CC = cc $(CCFLAGS) $(STDHDRS)
CCOF = -o
LINKFLAGSDEF = -lm -lpthread -lrt
diff --git a/spectro/afiles b/spectro/afiles
index 045614c..e3fee3e 100644
--- a/spectro/afiles
+++ b/spectro/afiles
@@ -17,6 +17,8 @@ dispsup.h
dispsup.c
webwin.h
webwin.c
+madvrwin.h
+madvrwin.c
mongoose.h
mongoose.c
insttypes.h
@@ -58,6 +60,8 @@ spyd2.c
spyd2.h
spyd2setup.h
spyd2PLD.h
+specbos.c
+specbos.h
oemarch.h
oemarch.c
oeminst.c
@@ -85,10 +89,10 @@ icoms_ux.c
iusb.h
usbio.h
usbio.c
-usbio_lusb.c
usbio_nt.c
usbio_ox.c
usbio_lx.c
+usbio_bsd.c
hidio.h
hidio.c
pollem.h
diff --git a/spectro/average.c b/spectro/average.c
index d031154..5e659b8 100644
--- a/spectro/average.c
+++ b/spectro/average.c
@@ -311,7 +311,7 @@ int main(int argc, char *argv[]) {
/* If merging, append all the values */
if (domerge) {
for (i = 0; i < inps[n].c->t[0].nsets; i++) {
- inps[n].c->get_setarr(inps[0].c, 0, i, setel);
+ inps[n].c->get_setarr(inps[n].c, 0, i, setel);
ocg->add_setarr(ocg, 0, setel);
}
diff --git a/spectro/ccxxmake.c b/spectro/ccxxmake.c
index 737600c..eff3afa 100644
--- a/spectro/ccxxmake.c
+++ b/spectro/ccxxmake.c
@@ -72,6 +72,9 @@
#include "inst.h"
#include "dispwin.h"
#include "webwin.h"
+#ifdef NT
+# include "madvrwin.h"
+#endif
#include "dispsup.h"
#include "ccss.h"
#include "ccmx.h"
@@ -144,6 +147,9 @@ usage(char *diag, ...) {
}
free_disppaths(dp);
fprintf(stderr," -dweb[:port] Display via a web server at port (default 8080)\n");
+#ifdef NT
+ fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n");
+#endif
// fprintf(stderr," -d fake Use a fake display device for testing, fake%s if present\n",ICC_FILE_EXT);
fprintf(stderr," -p Use telephoto mode (ie. for a projector) (if available)\n");
cap = inst_show_disptype_options(stderr, " -y c|l ", icmps, 1);
@@ -168,6 +174,7 @@ usage(char *diag, ...) {
fprintf(stderr," -T displaytech Set display technology description (ie. CRT, LCD etc.)\n");
fprintf(stderr," -U c Set UI selection character(s)\n");
fprintf(stderr," -Y r|n Set or override refresh/non-refresh display type\n");
+ fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
fprintf(stderr," -Y A Use non-adaptive integration time mode (if available).\n");
fprintf(stderr," correction.ccmx | calibration.ccss\n");
fprintf(stderr," File to save result to\n");
@@ -201,11 +208,15 @@ int main(int argc, char *argv[])
int highres = 0; /* High res mode if available */
int dtype = 0; /* Display kind, 0 = default, 1 = CRT, 2 = LCD */
int refrmode = -1; /* Refresh mode */
+ double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */
int cbid = 0; /* Calibration base display mode ID */
int nadaptive = 0; /* Use non-adaptive mode if available */
int tele = 0; /* NZ if telephoto mode */
int noinitcal = 0; /* Disable initial calibration */
int webdisp = 0; /* NZ for web display, == port number */
+#ifdef NT
+ int madvrdisp = 0; /* NZ for MadVR display */
+#endif
char *ccallout = NULL; /* Change color Shell callout */
int msteps = DEFAULT_MSTEPS; /* Patch surface size */
int npat = 0; /* Number of patches/colors */
@@ -289,6 +300,12 @@ int main(int argc, char *argv[])
usage("Web port number must be in range 1..65535");
}
fa = nfa;
+#ifdef NT
+ } else if (strncmp(na,"madvr",5) == 0
+ || strncmp(na,"MADVR",5) == 0) {
+ madvrdisp = 1;
+ fa = nfa;
+#endif
} else {
#if defined(UNIX_X11)
int ix, iv;
@@ -474,15 +491,22 @@ int main(int argc, char *argv[])
if (na == NULL)
usage("Flag '-Y' expects extra flag");
- if (na[0] == 'A') {
- nadaptive = 1;
- } else if (na[0] == 'r') {
+ if (na[0] == 'r') {
refrmode = 1;
} else if (na[0] == 'n') {
refrmode = 0;
+ } else if (na[0] == 'R') {
+ if (na[1] != ':')
+ usage("-Y R:rate syntax incorrect");
+ refrate = atof(na+2);
+ if (refrate < 5.0 || refrate > 150.0)
+ usage("-Y R:rate %f Hz not in valid range",refrate);
+ } else if (na[0] == 'A') {
+ nadaptive = 1;
} else {
usage("Flag '-Z %c' not recognised",na[0]);
}
+ fa = nfa;
/* UI selection character */
} else if (argv[fa][1] == 'U') {
@@ -911,9 +935,13 @@ int main(int argc, char *argv[])
/* No explicit display has been set */
if (
#ifndef SHOW_WINDOW_ONFAKE
- !fake &&
+ !fake &&
#endif
- webdisp == 0 && disp == NULL) {
+ webdisp == 0
+#ifdef NT
+ && madvrdisp == 0
+#endif
+ && disp == NULL) {
int ix = 0;
#if defined(UNIX_X11)
char *dn, *pp;
@@ -1143,15 +1171,20 @@ int main(int argc, char *argv[])
inst3_capability cap3 = inst3_none; /* Instrument capabilities 3 */
if (fake)
- comno = -99;
+ comno = FAKE_DEVICE_PORT;
if (icmps == NULL)
icmps = new_icompaths(g_log);
/* Should we use current cal rather than native ??? */
if ((dr = new_disprd(&errc, icmps->get_path(icmps, comno),
fc, dtype, 1, tele, nadaptive,
- noinitcal, highres, 2, NULL, NULL, 0, 0, disp, blackbg,
- override, webdisp, ccallout, NULL,
+ noinitcal, 0, highres, refrate, 3, NULL, NULL,
+ NULL, 0, disp, 0, blackbg,
+ override, webdisp,
+#ifdef NT
+ madvrdisp,
+#endif
+ ccallout, NULL,
100.0 * hpatscale, 100.0 * vpatscale, ho, vo,
NULL, NULL, 0, 2, icxOT_default, NULL,
0, 0, "fake" ICC_FILE_EXT, g_log)) == NULL)
diff --git a/spectro/chartread.c b/spectro/chartread.c
index 1c2117a..376fc1c 100644
--- a/spectro/chartread.c
+++ b/spectro/chartread.c
@@ -438,22 +438,6 @@ a1log *log /* verb, debug & error log */
printf("The battery charged level is %.0f%%\n",batstat * 100.0);
}
- /* Set it to the appropriate mode */
- if (highres) {
- if (IMODETST(cap, inst_mode_highres)) {
- inst_code ev;
- if ((ev = it->get_set_opt(it, inst_opt_highres)) != inst_ok) {
- printf("\nSetting high res mode failed with error :'%s' (%s)\n",
- it->inst_interp_error(it, ev), it->interp_error(it, ev));
- it->del(it);
- return -1;
- }
- highres = 1;
- } else {
- a1logv(log, 1, "high resolution ignored - instrument doesn't support high res. mode\n");
- }
- }
-
if (scan_tol != 1.0) {
if (cap2 & inst2_has_scan_toll) {
inst_code ev;
@@ -675,6 +659,14 @@ a1log *log /* verb, debug & error log */
if (spectral)
mode |= inst_mode_spectral;
+ if (highres) {
+ if (IMODETST(cap, inst_mode_highres)) {
+ mode |= inst_mode_highres;
+ } else {
+ a1logv(log, 1, "high resolution ignored - instrument doesn't support high res. mode\n");
+ }
+ }
+
// ~~~ i1pro2 test code ~~~ */
if (uvmode) {
if (!IMODETST(cap, inst_mode_ref_uv)) {
@@ -2068,7 +2060,7 @@ usage() {
if (icmps != NULL)
icmps->del(icmps);
exit(1);
- }
+}
int main(int argc, char *argv[]) {
int i, j;
@@ -2206,6 +2198,7 @@ int main(int argc, char *argv[]) {
/* Scan tolerance ratio */
else if (argv[fa][1] == 'T') {
+ fa = nfa;
if (na == NULL)
usage();
scan_tol = atof(na);
@@ -2333,6 +2326,7 @@ int main(int argc, char *argv[]) {
} else {
usage();
}
+ fa = nfa;
} else
usage();
diff --git a/spectro/colorhug.c b/spectro/colorhug.c
index dad7012..0152000 100644
--- a/spectro/colorhug.c
+++ b/spectro/colorhug.c
@@ -8,7 +8,7 @@
* Author: Richard Hughes
* Date: 30/11/2011
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* Copyright 2011, Richard Hughes
* All rights reserved.
*
@@ -157,7 +157,7 @@ colorhug_command(colorhug *p,
int i;
unsigned char buf[64];
int xwbytes, wbytes;
- int xrbytes, rbytes;
+ int xrbytes, xrbytes2, rbytes;
int se, ua = 0, rv = inst_ok;
int ishid = p->icom->port_type(p->icom) == icomt_hid;
@@ -177,6 +177,7 @@ colorhug_command(colorhug *p,
xwbytes = 64;
se = p->icom->usb_write(p->icom, NULL, 0x01, buf, xwbytes, &wbytes, timeout);
}
+ a1logd(p->log,8,"colorhug_command: Send %d bytes and %d sent\n",xwbytes,wbytes);
if (se != 0) {
a1logd(p->log,1,"colorhug_command: command send failed with ICOM err 0x%x\n",se);
return colorhug_interp_code((inst *)p, COLORHUG_COMS_FAIL);
@@ -199,14 +200,15 @@ colorhug_command(colorhug *p,
a1logd(p->log,6,"colorhug_command: Reading response\n");
if (ishid) {
- xrbytes = 64;
+ xrbytes = xrbytes2 = 64;
se = p->icom->hid_read(p->icom, buf, xrbytes, &rbytes, timeout);
} else {
-// xrbytes = out_size + 2;
xrbytes = 64;
+ xrbytes2 = out_size + 2; /* For backwards compatibility with fw <= 1.1.8 */
se = p->icom->usb_read(p->icom, NULL, 0x81, buf, xrbytes, &rbytes, timeout);
}
+ a1logd(p->log,8,"colorhug_command: Read %d bytes and %d read\n",xrbytes,rbytes);
if (rbytes >= 2) {
a1logd(p->log,6,"colorhug_command: recieved cmd '%s' error '%s' args '%s'\n",
inst_desc(buf[1]),
@@ -217,7 +219,6 @@ colorhug_command(colorhug *p,
if (se != 0) {
/* deal with command error */
-// if (rbytes == 2 && buf[0] != COLORHUG_OK) {
if (buf[0] != COLORHUG_OK) {
a1logd(p->log,1,"colorhug_command: Got Colorhug !OK\n");
rv = colorhug_interp_code((inst *)p, buf[0]);
@@ -225,15 +226,18 @@ colorhug_command(colorhug *p,
}
/* deal with underrun or overrun */
- if (rbytes != xrbytes) {
+ if (rbytes != xrbytes
+ && rbytes != xrbytes2) {
a1logd(p->log,1,"colorhug_command: got underrun or overrun\n");
rv = colorhug_interp_code((inst *)p, COLORHUG_BAD_RD_LENGTH);
return rv;
}
- /* there's another reason it failed */
- a1logd(p->log,1,"colorhug_command: read failed with ICOM err 0x%x\n",se);
- return colorhug_interp_code((inst *)p, COLORHUG_COMS_FAIL);
+ if (se != ICOM_SHORT) { /* Allow short read for firware compatibility */
+ /* there's another reason it failed */
+ a1logd(p->log,1,"colorhug_command: read failed with ICOM err 0x%x\n",se);
+ return colorhug_interp_code((inst *)p, COLORHUG_COMS_FAIL);
+ }
}
rv = colorhug_interp_code((inst *)p, icoms2colorhug_err(ua));
@@ -451,7 +455,7 @@ colorhug_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
} else {
a1logd(p->log, 1, "colorhug_init_coms: wrong communications type for device!\n");
- return colorhug_interp_code((inst *)p, COLORHUG_UNKNOWN_MODEL);
+ return inst_internal_error;
}
a1logd(p->log, 2, "colorhug_init_coms: inited coms OK\n");
@@ -467,7 +471,6 @@ colorhug_get_firmwareversion (colorhug *p)
inst_code ev;
unsigned char obuf[6];
- /* Hmm. The post scale is in the 2nd short returned */
ev = colorhug_command(p, ch_get_firmware_version,
NULL, 0,
obuf, 6,
@@ -484,6 +487,27 @@ colorhug_get_firmwareversion (colorhug *p)
return ev;
}
+/* Get the serial number */
+static inst_code
+colorhug_get_serialnumber (colorhug *p)
+{
+ inst_code ev;
+ unsigned char obuf[6];
+
+ ev = colorhug_command(p, ch_get_serial,
+ NULL, 0,
+ obuf, 4,
+ 2.0);
+ if (ev != inst_ok)
+ return ev;
+
+ p->ser_no = buf2uint_le(obuf + 0);
+
+ a1logd(p->log,2,"colorhug: Serial number = %d\n",p->ser_no);
+
+ return ev;
+}
+
/* Set the device multiplier */
static inst_code
colorhug_set_multiplier (colorhug *p, int multiplier)
@@ -553,6 +577,11 @@ colorhug_init_inst(inst *pp)
if (ev != inst_ok)
return ev;
+ /* Get the serial number */
+ ev = colorhug_get_serialnumber(p);
+ if (ev != inst_ok)
+ return ev;
+
/* Turn the LEDs off */
ev = colorhug_set_LEDs(p, 0x0);
if (ev != inst_ok)
@@ -591,6 +620,10 @@ colorhug_init_inst(inst *pp)
p->inited = 1;
a1logd(p->log, 2, "colorhug_init: inited coms OK\n");
+ a1logv(p->log,1,"Serial Number: %06u\n"
+ "Firmware Version: %d.%d.%d\n"
+ ,p->ser_no,p->maj,p->min,p->uro);
+
/* Flash the LEDs */
ev = colorhug_set_LEDs(p, 0x1);
if (ev != inst_ok)
@@ -670,6 +703,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
val->sp.spec_n = 0;
val->duration = 0.0;
+
if (user_trig)
return inst_user_trig;
return rv;
@@ -692,8 +726,8 @@ double mtx[3][3]
icmSetUnity3x3(p->ccmat);
} else {
if (p->cbid == 0) {
- a1loge(p->log, 1, "colorhug: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
+ a1loge(p->log, 1, "colorhug: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
}
icmCpy3x3(p->ccmat, mtx);
}
diff --git a/spectro/conv.c b/spectro/conv.c
index 0f56ff9..752d483 100644
--- a/spectro/conv.c
+++ b/spectro/conv.c
@@ -544,33 +544,48 @@ void msec_sleep(unsigned int msec) {
#endif
}
+/* Provide substitute for clock_gettime() in OS X */
+
+#if defined(__APPLE__) && !defined(CLOCK_MONOTONIC)
+#include <mach/mach_time.h>
+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 0
+static int clock_gettime(int clk_id, struct timespec *t){
+ mach_timebase_info_data_t timebase;
+ mach_timebase_info(&timebase);
+ uint64_t time;
+ time = mach_absolute_time();
+ double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
+ double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
+ t->tv_sec = seconds;
+ t->tv_nsec = nseconds;
+ return 0;
+}
+#endif
+
/* Return the current time in msec */
/* since the first invokation of msec_time() */
unsigned int msec_time() {
unsigned int rv;
- static struct timeval startup = { 0, 0 };
- struct timeval cv;
+ static struct timespec startup = { 0, 0 };
+ struct timespec cv;
- /* Is this monotonic ? */
- /* On Linux, should clock_gettime with CLOCK_MONOTONIC be used instead ? */
- /* On OS X, should mach_absolute_time() be used ? */
- /* or host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clk) */
- gettimeofday(&cv, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &cv);
/* Set time to 0 on first invocation */
- if (startup.tv_sec == 0 && startup.tv_usec == 0)
+ if (startup.tv_sec == 0 && startup.tv_nsec == 0)
startup = cv;
/* Subtract, taking care of carry */
cv.tv_sec -= startup.tv_sec;
- if (startup.tv_usec > cv.tv_usec) {
+ if (startup.tv_nsec > cv.tv_nsec) {
cv.tv_sec--;
- cv.tv_usec += 1000000;
+ cv.tv_nsec += 100000000;
}
- cv.tv_usec -= startup.tv_usec;
+ cv.tv_nsec -= startup.tv_nsec;
- /* Convert usec to msec */
- rv = cv.tv_sec * 1000 + cv.tv_usec / 1000;
+ /* Convert nsec to msec */
+ rv = cv.tv_sec * 1000 + cv.tv_nsec / 1000000;
return rv;
}
@@ -579,29 +594,25 @@ unsigned int msec_time() {
/* since the first invokation of usec_time() */
double usec_time() {
double rv;
- static struct timeval startup = { 0, 0 };
- struct timeval cv;
+ static struct timespec startup = { 0, 0 };
+ struct timespec cv;
- /* Is this monotonic ? */
- /* On Linux, should clock_gettime with CLOCK_MONOTONIC/CLOCK_REALTIME/CLOCK_REALTIME_HR ? */
- /* On OS X, should mach_absolute_time() be used ? */
- /* or host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clk) */
- gettimeofday(&cv, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &cv);
/* Set time to 0 on first invocation */
- if (startup.tv_sec == 0 && startup.tv_usec == 0)
+ if (startup.tv_sec == 0 && startup.tv_nsec == 0)
startup = cv;
/* Subtract, taking care of carry */
cv.tv_sec -= startup.tv_sec;
- if (startup.tv_usec > cv.tv_usec) {
+ if (startup.tv_nsec > cv.tv_nsec) {
cv.tv_sec--;
- cv.tv_usec += 1000000;
+ cv.tv_nsec += 1000000000;
}
- cv.tv_usec -= startup.tv_usec;
+ cv.tv_nsec -= startup.tv_nsec;
/* Convert to usec */
- rv = cv.tv_sec * 1000000.0 + cv.tv_usec;
+ rv = cv.tv_sec * 1000000.0 + cv.tv_nsec/1000;
return rv;
}
diff --git a/spectro/conv.h b/spectro/conv.h
index ab5e850..5d63efe 100644
--- a/spectro/conv.h
+++ b/spectro/conv.h
@@ -151,6 +151,7 @@ int set_normal_priority();
#ifdef NT
# define amutex CRITICAL_SECTION
+# define amutex_static(lock) CRITICAL_SECTION lock = { NULL, -1 }
# define amutex_init(lock) InitializeCriticalSection(&(lock))
# define amutex_del(lock) DeleteCriticalSection(&(lock))
# define amutex_lock(lock) EnterCriticalSection(&(lock))
@@ -160,6 +161,7 @@ int set_normal_priority();
#ifdef UNIX
# define amutex pthread_mutex_t
+# define amutex_static(lock) pthread_mutex_t (lock) = PTHREAD_MUTEX_INITIALIZER
# define amutex_init(lock) pthread_mutex_init(&(lock), NULL)
# define amutex_del(lock) pthread_mutex_destroy(&(lock))
# define amutex_lock(lock) pthread_mutex_lock(&(lock))
@@ -286,6 +288,10 @@ int sa_lu_psinvert(double **out, double **in, int m, int n);
#define lu_psinvert sa_lu_psinvert
#endif /* SALONEINSTLIB */
+
+/* - - - - - - - - - - - - - - - - - - -- */
+
+
/* - - - - - - - - - - - - - - - - - - -- */
diff --git a/spectro/dispcal.c b/spectro/dispcal.c
index accb79a..b8f3ebe 100644
--- a/spectro/dispcal.c
+++ b/spectro/dispcal.c
@@ -20,6 +20,21 @@
/* TTBD
+ Calibrating the black point of a true power response
+ device is very slow to converge - the jacobian is always
+ underestimating the actual delta RGB needed because the
+ slope is getting shallower and shallower. Need to
+ be able to figure when to increase rgain in those circumstances,
+ rather than reducing it ?
+
+ Dealing with noisy/inconsistent readings could probably
+ be improved - the statistical information from a iteration
+ series is being ignored. ie. do a linear regression/fit
+ on all the values for a given target, and then
+ at the end, use a weighted blend of the best solution
+ and the fit. Weight by something like the number used
+ for the fit. vs. 1.
+
Try to improve calibration speed by using adaptive
measurement set, rather than fixed resolution doubling ?
(ie. just measure at troublesome points using a "divide in half"
@@ -58,7 +73,7 @@
display gives about 18% output at 50% device input.]
- The verify (-E) may not be being done correctly.
+ The verify (-z) may not be being done correctly.
Like update, shouldn't it read the .cal file to set what's
being calibrated aganist ? (This would fix missing ambient value too!)
@@ -67,6 +82,13 @@
in "Figure out the black point target" - Yes they are !!
Verify probably shouldn't work this way.
+ Add DICOM support:
+
+ * Add 20% grey background full screen option + 10% patch recommendation
+ * Add "include Glare" option for contact instruments to dispsup.
+ * Add absolute DICOM function target.
+ * Add DICOM mode black point hue handling (? what policy ?)
+ * Add DICOM stats report (JND dE + mean + SD) to verify ??
*/
#ifdef __MINGW32__
@@ -119,17 +141,22 @@
#define COMPORT 1 /* Default com port 1..4 */
#define OPTIMIZE_MODEL /* Adjust model for best fit */
-#define REFINE_GAIN 0.80 /* Refinement correction damping/gain */
-#define MAX_RPTS 12 /* Maximum tries at making a sample meet the current threshold */
+#define REFINE_GAIN 0.90 /* Refinement correction damping/gain */
#define VER_RES 100 /* Verification resolution */
#define NEUTRAL_BLEND_RATE 4.0 /* Default rate of transition for -k factor < 1.0 (power) */
#define ADJ_JACOBIAN /* Adjust the Jacobian predictor matrix each time */
-#define JAC_COR_FACT 0.4 /* Amount to correct Jacobian by (to filter noise) */
-#define REMEAS_JACOBIAN /* Re-measure Jacobian */
+#define JAC_COMP_FACT 0.4 /* Amount to compound Jacobian correction */
+#define JAC_COR_FACT 0.4 /* Amount to damp Jacobian by (to filter noise) */
+#define REMEAS_JACOBIAN /* Re-measure Jacobian if it is a poor predictor */
#define MOD_DIST_POW 1.6 /* Power used to distribute test samples for model building */
#define REFN_DIST_POW 1.6 /* Power used to distribute test samples for grey axis refinement */
#define CHECK_DIST_POW 1.6 /* Power used to distribute test samples for grey axis checking */
#define THRESH_SCALE_POW 0.5 /* Amount to loosen threshold for first itterations */
+#define ADJ_THRESH /* Adjust threshold to be half a step */
+#define MIN_THRESH 0.05 /* Minimum stopping threshold to allow in ADJ_THRESH */
+#define POWERR_THR 0.05 /* Point near black to start weighting +ve error */
+#define POWERR_WEIGHT 999.0 /* Weight to give +ve delta E at black */
+#define POWERR_WEIGHT_POW 4.0 /* Curve to plend from equal weight to +ve extra weight */
#define CAL_RES 256 /* Resolution of calibration table to produce. */
#define CLIP /* Clip RGB during refinement */
#define RDAC_SMOOTH 0.3 /* RAMDAC curve fitting smoothness */
@@ -190,6 +217,7 @@ typedef struct {
double nwh[3]; /* Target white normalised XYZ value (Y = 1.0) */
double twh[3]; /* Target white absolute XYZ value */
+ double twYxy[3]; /* Target white Yxy (informational) */
icmXYZNumber twN; /* Same as above as XYZNumber */
double tbk[3]; /* Target black point color */
@@ -847,14 +875,16 @@ typedef struct {
double tXYZ[3]; /* Target XYZ */
double XYZ[3]; /* Read XYZ */
double deXYZ[3]; /* Delta XYZ wanted to target */
- double de; /* Delta Lab to neutral target */
- double dc; /* Delta XYZ to neutral target */
- double peqde; /* Delta Lab to previous point value (last pass) */
- double hde; /* Hybrid de composed of de and peqde */
+ double _de; /* Non-weighted Delta Lab */
+ double de; /* Weightd Delta Lab to neutral target */
+ double dc; /* Weightd Delta XYZ to neutral target */
+ double peqde; /* Weightd Delta Lab to last pass equivalent point value */
+ double hde; /* Weightd Hybrid de composed of de and peqde */
+ double prgb[3]; /* Previous measured RGB */
double pXYZ[3]; /* Previous measured XYZ */
double pdXYZ[3]; /* Delta XYZ intended from previous measure */
- double pdrgb[3]; /* Delta rgb made to previous */
+ double pdrgb[3]; /* Delta rgb made to previous to acorrect XYZ */
double dXYZ[3]; /* Actual delta XYZ resulting from previous delta rgb */
@@ -863,11 +893,12 @@ typedef struct {
double fb_ij[3][3]; /* Copy of initial inverse Jacobian, used as a fallback */
} csp;
+
/* All the sample points */
typedef struct {
int no; /* Number of samples */
int _no; /* Allocation */
- csp *s; /* List of samples */
+ csp *s; /* List of samples */
} csamp;
static void free_alloc_csamp(csamp *p) {
@@ -916,10 +947,13 @@ static void init_csamp_v(csamp *p, calx *x, int psrand) {
}
/* Initialise txyz values from v values */
-static void init_csamp_txyz(csamp *p, calx *x, int fixdev) {
+static void init_csamp_txyz(csamp *p, calx *x, int fixdev, int verb) {
int i, j;
double tbL[3]; /* tbk as Lab */
+ if (verb >= 3)
+ printf("init_csamp_txyz:\n");
+
/* Convert target black from XYZ to Lab here, */
/* in case twN has changed at some point. */
icmXYZ2Lab(&x->twN, tbL, x->tbk);
@@ -946,22 +980,22 @@ static void init_csamp_txyz(csamp *p, calx *x, int fixdev) {
/* Compute blended neutral target a* b* */
bl = pow((1.0 - vv), x->nbrate); /* Crossover near the black */
- Lab[1] = bl * tbL[1];
- Lab[2] = bl * tbL[2];
+ Lab[1] = (1.0 - bl) * 0.0 + bl * tbL[1];
+ Lab[2] = (1.0 - bl) * 0.0 + bl * tbL[2];
icmAry2Ary(XYZ, p->s[i].tXYZ); /* Save the existing values */
icmLab2XYZ(&x->twN, p->s[i].tXYZ, Lab); /* New XYZ Value to aim for */
-#ifdef DEBUG
- printf("%d: target XYZ %.2f %.2f %.2f, Lab %.2f %.2f %.2f\n",i, p->s[i].tXYZ[0],p->s[i].tXYZ[1],p->s[i].tXYZ[2], Lab[0],Lab[1],Lab[2]);
-#endif
+ if (verb >= 3) {
+ printf("%d: target XYZ %.4f %.4f %.4f, Lab %.3f %.3f %.3f\n",i, p->s[i].tXYZ[0],p->s[i].tXYZ[1],p->s[i].tXYZ[2], Lab[0],Lab[1],Lab[2]);
+ }
}
}
/* Allocate the sample points and initialise them with the */
/* target device and XYZ values, and first cut device values. */
-static void init_csamp(csamp *p, calx *x, int doupdate, int verify, int psrand, int no) {
+static void init_csamp(csamp *p, calx *x, int doupdate, int verify, int psrand, int no, int verb) {
int i, j;
p->_no = p->no = no;
@@ -971,7 +1005,7 @@ static void init_csamp(csamp *p, calx *x, int doupdate, int verify, int psrand,
/* Compute v and txyz */
init_csamp_v(p, x, psrand);
- init_csamp_txyz(p, x, 0);
+ init_csamp_txyz(p, x, 0, verb);
/* Generate the sample points */
for (i = 0; i < no; i++) {
@@ -1064,7 +1098,7 @@ static void csamp_interp(csamp *p, double xyz[3], double v) {
/* Re-initialise a CSP with a new number of points. */
/* Interpolate the device values and jacobian. */
/* Set the current rgb from the current RAMDAC curves if not verifying */
-static void reinit_csamp(csamp *p, calx *x, int verify, int psrand, int no) {
+static void reinit_csamp(csamp *p, calx *x, int verify, int psrand, int no, int verb) {
csp *os; /* Old list of samples */
int ono; /* Old number of samples */
int i, j, k, m;
@@ -1075,7 +1109,7 @@ static void reinit_csamp(csamp *p, calx *x, int verify, int psrand, int no) {
os = p->s; /* Save the existing per point information */
ono = p->no;
- init_csamp(p, x, 0, 2, psrand, no);
+ init_csamp(p, x, 0, 2, psrand, no, verb);
p->_no = p->no = no;
@@ -1151,7 +1185,7 @@ static void reinit_csamp(csamp *p, calx *x, int verify, int psrand, int no) {
/* Compute expected delta XYZ using new Jacobian */
icmMulBy3x3(p->s[i].pdXYZ, p->s[i].j, p->s[i].pdrgb);
- p->s[i].de = b * os[j+1].de + (1.0 - b) * os[j].de;
+ p->s[i]._de = p->s[i].de = b * os[j+1].de + (1.0 - b) * os[j].de;
p->s[i].dc = b * os[j+1].dc + (1.0 - b) * os[j].dc;
}
@@ -1223,6 +1257,20 @@ static double comp_ct(
/* =================================================================== */
+/* Return the normal Delta E given two XYZ values, but */
+/* exagerate the L* error if act L* > targ L* by a factor of fact */
+extern ICCLIB_API double bwXYZLabDE(icmXYZNumber *w, double *targ, double *act, double fact) {
+ double targlab[3], actlab[3], rv;
+
+ icmXYZ2Lab(w, targlab, targ);
+ icmXYZ2Lab(w, actlab, act);
+ if (actlab[0] > targlab[0])
+ actlab[0] = targlab[0] + fact * (actlab[0] - targlab[0]);
+ rv = icmLabDE(targlab, actlab);
+ return rv;
+}
+/* =================================================================== */
+
/* Default gamma */
double g_def_gamma = 2.4;
@@ -1232,7 +1280,7 @@ double g_def_gamma = 2.4;
ABCDEFGHIJKLMNOPQRSTUVWXYZ
upper .......... ....... . ...
- lower ....... . ...... .... .
+ lower ....... . ...... .... ..
*/
@@ -1276,6 +1324,9 @@ void usage(char *diag, ...) {
}
free_disppaths(dp);
fprintf(stderr," -dweb[:port] Display via a web server at port (default 8080)\n");
+#ifdef NT
+ fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n");
+#endif
// fprintf(stderr," -d fake Use a fake display device for testing, fake%s if present\n",ICC_FILE_EXT);
fprintf(stderr," -c listno Set communication port from the following list (default %d)\n",COMPORT);
if ((icmps = new_icompaths(g_log)) != NULL) {
@@ -1323,7 +1374,7 @@ void usage(char *diag, ...) {
fprintf(stderr," -A rate Rate of blending from neutral to black point. Default %.1f\n",NEUTRAL_BLEND_RATE);
fprintf(stderr," -B blkbright Set the target black brightness in cd/m^2\n");
fprintf(stderr," -e [n] Run n verify passes on final curves\n");
- fprintf(stderr," -E Run only verify pass on installed calibration curves\n");
+ fprintf(stderr," -z Run only verify pass on installed calibration curves\n");
fprintf(stderr," -P ho,vo,ss[,vs] Position test window and scale it\n");
fprintf(stderr," ho,vi: 0.0 = left/top, 0.5 = center, 1.0 = right/bottom etc.\n");
fprintf(stderr," ss: 0.5 = half, 1.0 = normal, 2.0 = double etc.\n");
@@ -1331,6 +1382,7 @@ void usage(char *diag, ...) {
#if defined(UNIX_X11)
fprintf(stderr," -n Don't set override redirect on test window\n");
#endif
+ fprintf(stderr," -E Encode the test values for video range 16..235/255\n");
fprintf(stderr," -J Run instrument calibration first (used rarely)\n");
fprintf(stderr," -N Disable initial calibration of instrument if possible\n");
fprintf(stderr," -H Use high resolution spectrum mode (if available)\n");
@@ -1343,7 +1395,9 @@ void usage(char *diag, ...) {
fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c\n");
}
fprintf(stderr," -I b|w Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw\n");
+ fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
fprintf(stderr," -Y A Use non-adaptive integration time mode (if available).\n");
+ fprintf(stderr," -Y p Don't wait for the instrument to be placed on the display\n");
fprintf(stderr," -C \"command\" Invoke shell \"command\" each time a color is set\n");
fprintf(stderr," -M \"command\" Invoke shell \"command\" each time a color is measured\n");
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
@@ -1360,6 +1414,7 @@ int main(int argc, char *argv[]) {
disppath *disp = NULL; /* Display being used */
double hpatscale = 1.0, vpatscale = 1.0; /* scale factor for test patch size */
double ho = 0.0, vo = 0.0; /* Test window offsets, -1.0 to 1.0 */
+ int out_tvenc = 0; /* 1 to use RGB Video Level encoding */
int blackbg = 0; /* NZ if whole screen should be filled with black */
int verb = 0;
int debug = 0;
@@ -1382,7 +1437,9 @@ int main(int argc, char *argv[]) {
int dtype = 0; /* Display type selection charater */
int tele = 0; /* nz if telephoto mode */
int nocal = 0; /* Disable auto calibration */
+ int noplace = 0; /* Disable initial user placement check */
int highres = 0; /* Use high res mode if available */
+ double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */
int nadaptive = 0; /* Use non-adaptive mode if available */
int bdrift = 0; /* Flag, nz for black drift compensation */
int wdrift = 0; /* Flag, nz for white drift compensation */
@@ -1393,7 +1450,7 @@ int main(int argc, char *argv[]) {
double tbright = 0.0; /* Target white brightness ( 0.0 == max) */
double gamma = 0.0; /* Advertised Gamma target */
double egamma = 0.0; /* Effective Gamma target, NZ if set */
- double ambient = 0.0; /* NZ if viewing cond. adjustment to be used (cd/m^2) */
+ double ambient = 0.0; /* NZ if viewing cond. adjustment to be used (Lux) */
double bkcorrect = -1.0; /* Level of black point correction, < 0 = auto */
double bkbright = 0.0; /* Target black brightness ( 0.0 == min) */
int quality = -99; /* Quality level, -2 = v, -1 = l, 0 = m, 1 = h, 2 = u */
@@ -1403,9 +1460,13 @@ int main(int argc, char *argv[]) {
int thrfail = 0; /* Set to NZ if failed to meet threshold target */
double failerr = 0.0; /* Delta E of worst failed target */
int mxits = 3; /* maximum iterations (medium) */
+ int mxrpts = 12; /* maximum repeats (medium) */
int verify = 0; /* Do a verify after last refinement, 2 = do only verify. */
int nver = 0; /* Number of verify passes after refinement */
int webdisp = 0; /* NZ for web display, == port number */
+#ifdef NT
+ int madvrdisp = 0; /* NZ for madvr display */
+#endif
char *ccallout = NULL; /* Change color Shell callout */
char *mcallout = NULL; /* Measure color Shell callout */
char outname[MAXNAMEL+1] = { 0 }; /* Output cgats file base name */
@@ -1421,9 +1482,12 @@ int main(int argc, char *argv[]) {
int it; /* verify & refine iteration */
int rv;
int fitord = 30; /* More seems to make curves smoother */
- int native = 1; /* 0 = use current or given calibration curve */
- /* 1 = set native linear op and use ramdac high prec'n */
+ int native = 3; /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high prec */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
int noramdac = 0; /* Will be set to nz if can't set ramdac */
+ int nocm = 0; /* Will be set to nz if can't set color managament */
int errc; /* Return value from new_disprd() */
calx x; /* Context for calibration solution */
@@ -1513,6 +1577,12 @@ int main(int argc, char *argv[]) {
usage("Web port number must be in range 1..65535");
}
fa = nfa;
+#ifdef NT
+ } else if (strncmp(na,"madvr",5) == 0
+ || strncmp(na,"MADVR",5) == 0) {
+ madvrdisp = 1;
+ fa = nfa;
+#endif
} else {
#if defined(UNIX_X11)
int ix, iv;
@@ -1554,6 +1624,9 @@ int main(int argc, char *argv[]) {
#endif
}
+ } else if (argv[fa][1] == 'E') {
+ out_tvenc = 1;
+
} else if (argv[fa][1] == 'J') {
docalib = 1;
@@ -1673,7 +1746,7 @@ int main(int argc, char *argv[]) {
fa = nfa;
}
- } else if (argv[fa][1] == 'E') {
+ } else if (argv[fa][1] == 'z') {
verify = 2;
mfa = 0;
@@ -1834,7 +1907,6 @@ int main(int argc, char *argv[]) {
ambient = atof(na);
if (ambient < 0.0)
usage("-a parameter %f out of range",ambient);
- ambient /= 3.141592654; /* Convert from Lux to cd/m^2 */
/* Test patch offset and size */
} else if (argv[fa][1] == 'P') {
@@ -1864,11 +1936,20 @@ int main(int argc, char *argv[]) {
if (na == NULL)
usage("Flag '-Y' expects extra flag");
- if (na[0] == 'A') {
+ if (na[0] == 'R') {
+ if (na[1] != ':')
+ usage("-Y R:rate syntax incorrect");
+ refrate = atof(na+2);
+ if (refrate < 5.0 || refrate > 150.0)
+ usage("-Y R:rate %f Hz not in valid range",refrate);
+ } else if (na[0] == 'A') {
nadaptive = 1;
+ } else if (na[0] == 'p') {
+ noplace = 1;
} else {
usage("Flag '-Y %c' not recognised",na[0]);
}
+ fa = nfa;
} else
usage("Flag '-%c' not recognised",argv[fa][1]);
@@ -1932,7 +2013,7 @@ int main(int argc, char *argv[]) {
}
if (fake)
- comport = -99;
+ comport = FAKE_DEVICE_PORT;
if ((icmps = new_icompaths(g_log)) == NULL)
error("Finding instrument paths failed");
if ((ipath = icmps->get_path(icmps, comport)) == NULL)
@@ -1940,7 +2021,11 @@ int main(int argc, char *argv[]) {
if (docalib) {
if ((rv = disprd_calibration(ipath, fc, dtype, 0, tele, nadaptive, nocal, disp,
- webdisp, blackbg, override,
+ webdisp,
+#ifdef NT
+ madvrdisp,
+#endif
+ out_tvenc, blackbg, override,
100.0 * hpatscale, 100.0 * vpatscale,
ho, vo, g_log)) != 0) {
error("docalibration failed with return value %d\n",rv);
@@ -1973,12 +2058,16 @@ int main(int argc, char *argv[]) {
/* Normally calibrate against native response */
if (verify == 2 || doreport == 2)
- native = 0; /* But measure calibrated response of verify or report calibrated */
+ native = 0; /* But measure current calibrated & CM response for verify or report calibrated */
/* Get ready to do some readings */
- if ((dr = new_disprd(&errc, ipath, fc, dtype, 0, tele, nadaptive, nocal,
- highres, native, &noramdac, NULL, 0, 0, disp, blackbg, override,
- webdisp, ccallout, mcallout,
+ if ((dr = new_disprd(&errc, ipath, fc, dtype, 0, tele, nadaptive, nocal, noplace,
+ highres, refrate, native, &noramdac, &nocm, NULL, 0,
+ disp, out_tvenc, blackbg, override, webdisp,
+#ifdef NT
+ madvrdisp,
+#endif
+ ccallout, mcallout,
100.0 * hpatscale, 100.0 * vpatscale, ho, vo,
cmx != NULL ? cmx->matrix : NULL,
ccs != NULL ? ccs->samples : NULL, ccs != NULL ? ccs->no_samp : 0,
@@ -1986,11 +2075,11 @@ int main(int argc, char *argv[]) {
"fake" ICC_FILE_EXT, g_log)) == NULL)
error("new_disprd() failed with '%s'\n",disprd_err(errc));
- if (native != 0 && noramdac) {
- warning("No access to VideoLUTs, so calibrating display as-is rather than native");
+ if ((native & 1) && noramdac) {
+ warning("Unable to access to VideoLUTs so can't be sure colors are native");
if (doprofile)
warning("Profile will reflect the as-is display response and not contain a 'vcgt' tag");
- native = 0;
+ native &= ~1;
if (doupdate && doprofile)
error("Can't update a profile that doesn't use the 'vcgt' tag for calibration");
@@ -2053,7 +2142,7 @@ int main(int argc, char *argv[]) {
if (doreport == 1) {
#define MAX_RES_SAMPS 24
col ttt[MAX_RES_SAMPS];
- int res_samps = 6;
+ int res_samps = 9;
double a0, a1, a2, dd;
int n;
int issig = 0;
@@ -2073,7 +2162,7 @@ int main(int argc, char *argv[]) {
gcc_bug_fix(sigbits);
#endif
/* Notional test value */
- v = (5 << (sigbits-3))/((1 << sigbits) - 1.0);
+ v = (7 << (sigbits-3))/((1 << sigbits) - 1.0);
/* And -1, 0 , +1 bit test values */
if ((n % 3) == 2)
v += 1.0/((1 << sigbits) - 1.0);
@@ -2102,6 +2191,7 @@ int main(int argc, char *argv[]) {
a0 /= (res_samps / 3.0);
a1 /= (res_samps / 3.0);
a2 /= (res_samps / 3.0);
+ DBG((dbgo,"Bits %d: -1: %f 0: %f +1 %f\n",sigbits, a0, a1, a2));
/* Judge significance of any differences */
dd = 0.0;
for (n = 0; n < res_samps; n++) {
@@ -2120,13 +2210,13 @@ int main(int argc, char *argv[]) {
issig = 1; /* Noticable difference */
else
issig = 0; /* No noticable difference */
- DBG((dbgo,"Bits %d: Between = %f, %f within = %f, sig = %s\n",sigbits, fabs(a1 - a0), fabs(a2 - a1),dd, issig ? "yes" : "no"));
+ DBG((dbgo,"Bits %d: Between = %f, %f within = %f, sig = %s\n",sigbits, fabs(a1 - a0), fabs(a2 - a1), dd, issig ? "yes" : "no"));
switch(sigbits) {
case 8: /* Do another trial */
if (issig) {
sigbits = 10;
- res_samps = 6;
+ res_samps = 9;
} else {
sigbits = 6;
}
@@ -2134,6 +2224,7 @@ int main(int argc, char *argv[]) {
case 6: /* Do another trial or give up */
if (issig) {
sigbits = 7;
+ res_samps = 6;
} else {
sigbits = 0;
issig = 2; /* Give up */
@@ -2147,7 +2238,7 @@ int main(int argc, char *argv[]) {
case 10: /* Do another trial */
if (issig) {
sigbits = 12;
- res_samps = 9;
+ res_samps = 12;
} else {
sigbits = 9;
}
@@ -2181,7 +2272,8 @@ int main(int argc, char *argv[]) {
printf("Current calibration response:\n");
else
printf("Uncalibrated response:\n");
- printf("Black level = %.2f cd/m^2\n",tcols[0].XYZ[1]);
+ printf("Black level = %.4f cd/m^2\n",tcols[0].XYZ[1]);
+ printf("50%% level = %.2f cd/m^2\n",tcols[1].XYZ[1]);
printf("White level = %.2f cd/m^2\n",tcols[2].XYZ[1]);
printf("Aprox. gamma = %.2f\n",cgamma);
printf("Contrast ratio = %.0f:1\n",tcols[2].XYZ[1]/tcols[0].XYZ[1]);
@@ -2239,6 +2331,13 @@ int main(int argc, char *argv[]) {
error("Can't update '%s' - there aren't two tables",outname);
}
+ out_tvenc = 0;
+ if ((fi = icg->find_kword(icg, 0, "TV_OUTPUT_ENCODING")) >= 0) {
+ if (strcmp(icg->t[0].kdata[fi], "YES") == 0
+ || strcmp(icg->t[0].kdata[fi], "yes") == 0)
+ out_tvenc = 1;
+ }
+
//printf("~1 reading previous cal, got 2 tables\n");
/* Read in the setup, user and model values */
@@ -2489,6 +2588,7 @@ int main(int argc, char *argv[]) {
isteps = 3;
rsteps = 9;
mxits = 1;
+ mxrpts = 8;
errthr = 2.0;
break;
case -2: /* Very low */
@@ -2499,6 +2599,7 @@ int main(int argc, char *argv[]) {
mxits = 1;
else
mxits = 1;
+ mxrpts = 10;
break;
case -1: /* Low */
if (verify != 2 && doprofile && !doupdate)
@@ -2511,6 +2612,7 @@ int main(int argc, char *argv[]) {
mxits = 1;
else
mxits = 2;
+ mxrpts = 10;
break;
default:
case 0: /* Medum */
@@ -2525,6 +2627,7 @@ int main(int argc, char *argv[]) {
mxits = 1;
else
mxits = 3;
+ mxrpts = 12;
break;
case 1: /* High */
if (verify != 2 && doprofile && !doupdate)
@@ -2537,6 +2640,7 @@ int main(int argc, char *argv[]) {
mxits = 1;
else
mxits = 4;
+ mxrpts = 16;
break;
case 2: /* Ultra */
if (verify != 2 && doprofile && !doupdate)
@@ -2549,6 +2653,7 @@ int main(int argc, char *argv[]) {
mxits = 1;
else
mxits = 5;
+ mxrpts = 24;
break;
}
@@ -2560,6 +2665,9 @@ int main(int argc, char *argv[]) {
/* Say something about what we're doing */
if (verb) {
+ if (out_tvenc)
+ printf("Using TV encoding range of (16-235)/255\n");
+
if (dtype > 0)
printf("Display type is '%c'\n",dtype);
@@ -2665,11 +2773,11 @@ int main(int argc, char *argv[]) {
}
if (verb) {
- printf("Black = XYZ %6.2f %6.2f %6.2f\n",tcols[0].XYZ[0],
+ printf("Black = XYZ %6.4f %6.4f %6.4f\n",tcols[0].XYZ[0],
tcols[0].XYZ[1], tcols[0].XYZ[2]);
- printf("Grey = XYZ %6.2f %6.2f %6.2f\n",tcols[1].XYZ[0],
+ printf("Grey = XYZ %6.3f %6.3f %6.3f\n",tcols[1].XYZ[0],
tcols[1].XYZ[1], tcols[1].XYZ[2]);
- printf("White = XYZ %6.2f %6.2f %6.2f\n",tcols[2].XYZ[0],
+ printf("White = XYZ %6.3f %6.3f %6.3f\n",tcols[2].XYZ[0],
tcols[2].XYZ[1], tcols[2].XYZ[2]);
}
@@ -2741,11 +2849,11 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("Red = XYZ %6.2f %6.2f %6.2f\n",ccols[0].XYZ[0],
+ printf("Red = XYZ %6.3f %6.3f %6.3f\n",ccols[0].XYZ[0],
ccols[0].XYZ[1], ccols[0].XYZ[2]);
- printf("Green = XYZ %6.2f %6.2f %6.2f\n",ccols[1].XYZ[0],
+ printf("Green = XYZ %6.3f %6.3f %6.3f\n",ccols[1].XYZ[0],
ccols[1].XYZ[1], ccols[1].XYZ[2]);
- printf("Blue = XYZ %6.2f %6.2f %6.2f\n",ccols[2].XYZ[0],
+ printf("Blue = XYZ %6.3f %6.3f %6.3f\n",ccols[2].XYZ[0],
ccols[2].XYZ[1], ccols[2].XYZ[2]);
}
for (i = 0; i < 3; i++)
@@ -2758,7 +2866,7 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("White = XYZ %6.2f %6.2f %6.2f\n",tcols[0].XYZ[0],
+ printf("White = XYZ %6.3f %6.3f %6.3f\n",tcols[0].XYZ[0],
tcols[0].XYZ[1], tcols[0].XYZ[2]);
}
@@ -2939,7 +3047,7 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("White = XYZ %6.2f %6.2f %6.2f\n",tcols[0].XYZ[0],
+ printf("White = XYZ %6.3f %6.3f %6.3f\n",tcols[0].XYZ[0],
tcols[0].XYZ[1], tcols[0].XYZ[2]);
}
@@ -3012,11 +3120,11 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("Red = XYZ %6.2f %6.2f %6.2f\n",ccols[0].XYZ[0],
+ printf("Red = XYZ %6.3f %6.3f %6.3f\n",ccols[0].XYZ[0],
ccols[0].XYZ[1], ccols[0].XYZ[2]);
- printf("Green = XYZ %6.2f %6.2f %6.2f\n",ccols[1].XYZ[0],
+ printf("Green = XYZ %6.3f %6.3f %6.3f\n",ccols[1].XYZ[0],
ccols[1].XYZ[1], ccols[1].XYZ[2]);
- printf("Blue = XYZ %6.2f %6.2f %6.2f\n",ccols[2].XYZ[0],
+ printf("Blue = XYZ %6.3f %6.3f %6.3f\n",ccols[2].XYZ[0],
ccols[2].XYZ[1], ccols[2].XYZ[2]);
}
for (i = 0; i < 3; i++)
@@ -3029,11 +3137,11 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("Black = XYZ %6.2f %6.2f %6.2f\n",tcols[0].XYZ[0],
+ printf("Black = XYZ %6.4f %6.4f %6.4f\n",tcols[0].XYZ[0],
tcols[0].XYZ[1], tcols[0].XYZ[2]);
- printf("Grey = XYZ %6.2f %6.2f %6.2f\n",tcols[1].XYZ[0],
+ printf("Grey = XYZ %6.3f %6.3f %6.3f\n",tcols[1].XYZ[0],
tcols[1].XYZ[1], tcols[1].XYZ[2]);
- printf("White = XYZ %6.2f %6.2f %6.2f\n",tcols[2].XYZ[0],
+ printf("White = XYZ %6.3f %6.3f %6.3f\n",tcols[2].XYZ[0],
tcols[2].XYZ[1], tcols[2].XYZ[2]);
}
@@ -3064,7 +3172,7 @@ int main(int argc, char *argv[]) {
}
printf("\nAdjust R,G & B offsets to get target x,y. Press space when done.\n");
- printf(" Target Br %.2f, x %.4f , y %.4f \n", tar1, tYxy[1],tYxy[2]);
+ printf(" Target Br %.4f, x %.4f , y %.4f \n", tar1, tYxy[1],tYxy[2]);
for (ff = 0;; ff ^= 1) {
double dir; /* Direction to adjust brightness */
double sv[3], val1; /* Scaled values */
@@ -3133,7 +3241,7 @@ int main(int argc, char *argv[]) {
rgbdir[0] = rgbdir[1] = rgbdir[2] = 0.0;
rgbxdir[bx] = rgbdir[bx];
- printf("%c%c Current Br %.2f, x %.4f%c, y %.4f%c DE %4.1f R%c%c G%c%c B%c%c ",
+ printf("%c%c Current Br %.4f, x %.4f%c, y %.4f%c DE %4.1f R%c%c G%c%c B%c%c ",
cr_char,
ff == 0 ? '/' : '\\',
val1,
@@ -3177,11 +3285,11 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("Black = XYZ %6.2f %6.2f %6.2f\n",tcols[0].XYZ[0],
+ printf("Black = XYZ %6.4f %6.4f %6.4f\n",tcols[0].XYZ[0],
tcols[0].XYZ[1], tcols[0].XYZ[2]);
- printf("Grey = XYZ %6.2f %6.2f %6.2f\n",tcols[1].XYZ[0],
+ printf("Grey = XYZ %6.3f %6.3f %6.3f\n",tcols[1].XYZ[0],
tcols[1].XYZ[1], tcols[1].XYZ[2]);
- printf("White = XYZ %6.2f %6.2f %6.2f\n",tcols[2].XYZ[0],
+ printf("White = XYZ %6.3f %6.3f %6.3f\n",tcols[2].XYZ[0],
tcols[2].XYZ[1], tcols[2].XYZ[2]);
}
@@ -3198,7 +3306,7 @@ int main(int argc, char *argv[]) {
error("display read failed with '%s'\n",disprd_err(rv));
}
if (verb) {
- printf("1%% = XYZ %6.2f %6.2f %6.2f\n",tcols[3].XYZ[0],
+ printf("1%% = XYZ %6.3f %6.3f %6.3f\n",tcols[3].XYZ[0],
tcols[3].XYZ[1], tcols[3].XYZ[2]);
}
@@ -3277,17 +3385,17 @@ int main(int argc, char *argv[]) {
printf("\n");
if (tbright > 0.0) /* Given brightness */
- printf(" Target Brightness = %.2f, Current = %5.2f, error = % .1f%%\n",
+ printf(" Target Brightness = %.3f, Current = %.3f, error = % .1f%%\n",
tarw, tcols[2].XYZ[1],
100.0 * (tcols[2].XYZ[1] - tarw)/tarw);
else
printf(" Current Brightness = %.2f\n", tcols[2].XYZ[1]);
- printf(" Target 50%% Level = %.2f, Current = %5.2f, error = % .1f%%\n",
+ printf(" Target 50%% Level = %.3f, Current = %.3f, error = % .1f%%\n",
tarh, tcols[1].XYZ[1],
100.0 * (tcols[1].XYZ[1] - tarh)/tarw);
- printf(" Target Near Black = %5.2f, Current = %5.2f, error = % .1f%%\n",
+ printf(" Target Near Black = %.4f, Current = %.4f, error = % .1f%%\n",
tar1, val1,
100.0 * (val1 - tar1)/tarw);
@@ -3312,7 +3420,7 @@ int main(int argc, char *argv[]) {
error("ambient measure failed with '%s'\n",disprd_err(rv));
}
} else {
- printf("Measured ambient level = %.1f Lux\n",ambient * 3.141592654);
+ printf("Measured ambient level = %.1f Lux\n",ambient);
}
} else if (c == '7') {
@@ -3349,14 +3457,26 @@ int main(int argc, char *argv[]) {
icmXYZNumber mwh;
ramdac *or = NULL;
- col base[6] = { /* Base set of test colors */
+ col base[9] = { /* Base set of test colors */
{ 0.0, 0.0, 0.0 }, /* 0 - Black */
{ 1.0, 0.0, 0.0 }, /* 1 - Red */
- { 0.0, 1.0, 0.0 }, /* 2 - Green */
- { 0.0, 0.0, 1.0 }, /* 3 - Blue */
- { 1.0, 1.0, 1.0 }, /* 4 - White */
- { 0.0, 0.0, 0.0 } /* 5 - Black */
+ { 1.0, 1.0, 1.0 }, /* 2 - White */
+ { 0.0, 0.0, 0.0 }, /* 3 - Black */
+ { 0.0, 1.0, 0.0 }, /* 4 - Green */
+ { 0.0, 0.0, 0.0 }, /* 5 - Black */
+ { 0.0, 0.0, 1.0 }, /* 6 - Blue */
+ { 1.0, 1.0, 1.0 }, /* 7 - White */
+ { 0.0, 0.0, 0.0 } /* 8 - Black */
};
+ int ix_k1 = 0;
+ int ix_r = 1;
+ int ix_w1 = 2;
+ int ix_k2 = 3;
+ int ix_g = 4;
+ int ix_k3 = 5;
+ int ix_b = 6;
+ int ix_w2 = 7;
+ int ix_k4 = 8;
if (verb) {
if (verify == 2)
@@ -3379,7 +3499,7 @@ int main(int argc, char *argv[]) {
}
/* Read the patches without clamping */
- if ((rv = dr->read(dr, base, 6, 1, 6, 1, 0, instNoClamp)) != 0) {
+ if ((rv = dr->read(dr, base, 9, 1, 9, 1, 0, instNoClamp)) != 0) {
dr->del(dr);
error("display read failed with '%s'\n",disprd_err(rv));
}
@@ -3391,35 +3511,49 @@ int main(int argc, char *argv[]) {
or->del(or);
}
- if (base[0].XYZ_v == 0) {
+ if (base[ix_k1].XYZ_v == 0) {
dr->del(dr);
error("Failed to get an XYZ value from the instrument!\n");
}
- /* Average black relative from 2 readings */
- x.bk[0] = 0.5 * (base[0].XYZ[0] + base[5].XYZ[0]);
- x.bk[1] = 0.5 * (base[0].XYZ[1] + base[5].XYZ[1]);
- x.bk[2] = 0.5 * (base[0].XYZ[2] + base[5].XYZ[2]);
+ if (verb >= 3) {
+ for (i = 0; i < 9; i++)
+ printf("Meas %d XYZ = %f %f %f\n",i,base[i].XYZ[0], base[i].XYZ[1], base[i].XYZ[2]);
+ }
+
+ /* Average black relative from 4 readings */
+ x.bk[0] = 0.25 * (base[ix_k1].XYZ[0] + base[ix_k2].XYZ[0]
+ + base[ix_k3].XYZ[0] + base[ix_k4].XYZ[0]);
+ x.bk[1] = 0.25 * (base[ix_k1].XYZ[1] + base[ix_k2].XYZ[1]
+ + base[ix_k3].XYZ[1] + base[ix_k4].XYZ[1]);
+ x.bk[2] = 0.25 * (base[ix_k1].XYZ[2] + base[ix_k2].XYZ[2]
+ + base[ix_k3].XYZ[2] + base[ix_k4].XYZ[2]);
icmClamp3(x.bk, x.bk); /* And clamp them */
- for (i = 1; i < 5; i++)
+
+ /* Average white reading from 2 readings */
+ base[ix_w1].XYZ[0] = 0.5 * (base[ix_w1].XYZ[0] + base[ix_w2].XYZ[0]);
+ base[ix_w1].XYZ[1] = 0.5 * (base[ix_w1].XYZ[1] + base[ix_w2].XYZ[1]);
+ base[ix_w1].XYZ[2] = 0.5 * (base[ix_w1].XYZ[2] + base[ix_w2].XYZ[2]);
+
+ for (i = 0; i < 9; i++)
icmClamp3(base[i].XYZ, base[i].XYZ);
/* Copy other readings into place */
- dispLum = base[4].XYZ[1]; /* White Y */
- icmAry2Ary(x.wh, base[4].XYZ);
+ dispLum = base[ix_w1].XYZ[1]; /* White Y */
+ icmAry2Ary(x.wh, base[ix_w1].XYZ);
icmAry2XYZ(x.twN, x.wh); /* Use this as Lab reference white until we establish target */
- icmAry2XYZ(mrd, base[1].XYZ);
- icmAry2XYZ(mgn, base[2].XYZ);
- icmAry2XYZ(mbl, base[3].XYZ);
- icmAry2XYZ(mwh, base[4].XYZ);
+ icmAry2XYZ(mrd, base[ix_r].XYZ);
+ icmAry2XYZ(mgn, base[ix_g].XYZ);
+ icmAry2XYZ(mbl, base[ix_b].XYZ);
+ icmAry2XYZ(mwh, base[ix_w1].XYZ);
if (verb) {
- printf("Black = XYZ %6.2f %6.2f %6.2f\n",x.bk[0],x.bk[1],x.bk[2]);
- printf("Red = XYZ %6.2f %6.2f %6.2f\n",base[1].XYZ[0], base[1].XYZ[1], base[1].XYZ[2]);
- printf("Green = XYZ %6.2f %6.2f %6.2f\n",base[2].XYZ[0], base[2].XYZ[1], base[2].XYZ[2]);
- printf("Blue = XYZ %6.2f %6.2f %6.2f\n",base[3].XYZ[0], base[3].XYZ[1], base[3].XYZ[2]);
- printf("White = XYZ %6.2f %6.2f %6.2f\n",base[4].XYZ[0], base[4].XYZ[1], base[4].XYZ[2]);
+ printf("Black = XYZ %6.4f %6.4f %6.4f\n",x.bk[0],x.bk[1],x.bk[2]);
+ printf("Red = XYZ %6.3f %6.3f %6.3f\n",base[ix_r].XYZ[0], base[ix_r].XYZ[1], base[ix_r].XYZ[2]);
+ printf("Green = XYZ %6.3f %6.3f %6.3f\n",base[ix_g].XYZ[0], base[ix_g].XYZ[1], base[ix_g].XYZ[2]);
+ printf("Blue = XYZ %6.3f %6.3f %6.3f\n",base[ix_b].XYZ[0], base[ix_b].XYZ[1], base[ix_b].XYZ[2]);
+ printf("White = XYZ %6.3f %6.3f %6.3f\n",base[ix_w1].XYZ[0], base[ix_w1].XYZ[1], base[ix_w1].XYZ[2]);
}
/* Setup forward matrix */
@@ -3427,6 +3561,7 @@ int main(int argc, char *argv[]) {
dr->del(dr);
error("Aprox. fwd matrix unexpectedly singular\n");
}
+ icmTranspose3x3(x.fm, x.fm); /* Convert [RGB][XYZ] to [XYZ][RGB] */
#ifdef DEBUG
if (verb) {
@@ -3783,8 +3918,11 @@ int main(int argc, char *argv[]) {
}
}
+ icmXYZ2Yxy(x.twYxy, x.twh); /* For information */
+
if (verb)
- printf("Target white value is XYZ %f %f %f\n",x.twh[0],x.twh[1],x.twh[2]);
+ printf("Target white value is XYZ %f %f %f [xy %f %f]\n",x.twh[0],x.twh[1],x.twh[2],
+ x.twYxy[1], x.twYxy[2]);
}
/* Need this for Lab conversions */
@@ -3800,6 +3938,7 @@ int main(int argc, char *argv[]) {
//printf("~1 black point Lab = %f %f %f\n", tbkLab[0], tbkLab[1], tbkLab[2]);
/* Now blend the a* b* with that of the target white point */
+ /* according to how much to try and correct the hue. */
tbL[0] = tbkLab[0];
tbL[1] = bkcorrect * 0.0 + (1.0 - bkcorrect) * tbkLab[1];
tbL[2] = bkcorrect * 0.0 + (1.0 - bkcorrect) * tbkLab[2];
@@ -3829,7 +3968,7 @@ int main(int argc, char *argv[]) {
icmLab2XYZ(&x.twN, x.tbk, tbL);
icmAry2XYZ(x.tbN, x.tbk);
if (verb)
- printf("Adjusted target black XYZ %.2f %.2f %.2f, Lab %.2f %.2f %.2f\n",
+ printf("Adjusted target black XYZ %.4f %.4f %.4f, Lab %.3f %.3f %.3f\n",
x.tbk[0], x.tbk[1], x.tbk[2], tbL[0], tbL[1], tbL[2]);
}
@@ -3857,11 +3996,17 @@ int main(int argc, char *argv[]) {
if (verb) {
double tbp[3], tbplab[3];
- tbp[0] = x.tbk[0] * tby/x.tbk[1];
+ if (fabs(x.tbk[1]) > 1e-9)
+ tbp[0] = x.tbk[0] * tby/x.tbk[1];
+ else
+ tbp[0] = x.tbk[0];
tbp[1] = tby;
- tbp[2] = x.tbk[2] * tby/x.tbk[1];
+ if (fabs(x.tbk[1]) > 1e-9)
+ tbp[2] = x.tbk[2] * tby/x.tbk[1];
+ else
+ tbp[2] = x.tbk[2];
icmXYZ2Lab(&x.twN, tbplab, tbp);
- printf("Target black after min adjust: XYZ %.3f %.3f %.3f, Lab %.3f %.3f %.3f\n",
+ printf("Target black after min adjust: XYZ %.4f %.4f %.4f, Lab %.3f %.3f %.3f\n",
tbp[0], tbp[1], tbp[2], tbplab[0], tbplab[1], tbplab[2]);
}
@@ -3896,7 +4041,7 @@ int main(int argc, char *argv[]) {
0.2 * 80.0, /* Adapting luminence, 20% of display 80 cd/m^2 */
0.2, /* Background relative to reference white */
80.0, /* Display is 80 cd/m^2 */
- 0.01, x.nwh, /* 1% flare same white point */
+ 0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */
0);
break;
@@ -3907,7 +4052,7 @@ int main(int argc, char *argv[]) {
0.2 * 1000.0/3.1415, /* Adapting luminence, 20% of 1000 lux in cd/m^2 */
0.2, /* Background relative to reference white */
1000.0/3.1415, /* Luminance of white in the Image field (cd/m^2) */
- 0.01, x.nwh, /* 1% flare same white point */
+ 0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */
0);
break;
@@ -3917,10 +4062,10 @@ int main(int argc, char *argv[]) {
/* The display we're calibratings situation */
x.dvc->set_view(x.dvc, vc_none,
x.nwh, /* Display normalised white point */
- 0.2 * ambient, /* Adapting luminence, 20% of ambient in cd/m^2 */
+ 0.2 * ambient/3.1415, /* Adapting luminence, 20% of ambient in cd/m^2 */
0.2, /* Background relative to reference white */
x.twh[1], /* Target white level (cd/m^2) */
- 0.01, x.nwh, /* 1% flare same white point */
+ 0.0, 0.01, x.nwh, /* 0% flare and 1% glare same white point */
0);
/* Compute the normalisation values */
@@ -3984,7 +4129,7 @@ int main(int argc, char *argv[]) {
}
/* Setup the initial calibration test point values */
- init_csamp(&asgrey, &x, doupdate, verify, verify == 2 ? 1 : 0, rsteps);
+ init_csamp(&asgrey, &x, doupdate, verify, verify == 2 ? 1 : 0, rsteps, verb);
/* Calculate the initial calibration curve values */
if (verify != 2 && !doupdate) {
@@ -4069,13 +4214,13 @@ int main(int argc, char *argv[]) {
/* Verify pass */
if (it >= mxits)
- rsteps = VER_RES; /* Fixed verification resolution */
+ rsteps = VER_RES; /* Fixed verification resolution */
else
- thrfail = 0; /* Not verify pass */
+ thrfail = 0; /* Not verify pass */
/* re-init asgrey if the number of test points has changed */
- reinit_csamp(&asgrey, &x, verify, (verify == 2 || it >= mxits) ? 1 : 0, rsteps);
+ reinit_csamp(&asgrey, &x, verify, (verify == 2 || it >= mxits) ? 1 : 0, rsteps, verb);
if (verb) {
if (it >= mxits)
@@ -4084,41 +4229,67 @@ int main(int argc, char *argv[]) {
printf("Doing iteration %d with %d sample points and repeat threshold of %f DE\n",
it+1,rsteps, errthr);
}
+
/* Read and adjust each step */
/* Do this white to black to track drift in native white point */
for (i = rsteps-1; i >= 0; i--) {
- double rpt;
+ int rpt;
double peqXYZ[3]; /* Previous steps equivalent aim point */
double bestrgb[3]; /* In case we fail */
double bestxyz[3];
double prevde = 1e7;
+ double best_de = 1e7;
double bestde = 1e7;
double bestdc = 1e7;
double bestpeqde = 1e7;
double besthde = 1e7;
double rgain = REFINE_GAIN; /* Scale down if lots of repeats */
int mjac = 0; /* We measured the Jacobian */
+ double ierrth = errthr; /* This points error threshold */
+
+ icmCpy3(asgrey.s[i].prgb, asgrey.s[i].rgb); /* Init previous */
- /* Setup a second termination threshold chriteria based on */
+ /* Setup a second termination threshold criteria based on */
/* the delta E to the previous step point for the last pass. */
+ /* This is to try and steer towards neutral axis consistency ? */
if (i == (rsteps-1) || it < (mxits-1)) {
icmAry2Ary(peqXYZ, asgrey.s[i].tXYZ); /* Its own aim point */
} else {
double Lab1[3], Lab2[3], Lab3[3];
icmXYZ2Lab(&x.twN, Lab1, asgrey.s[i+1].XYZ);
icmXYZ2Lab(&x.twN, Lab2, asgrey.s[i].tXYZ);
- Lab3[0] = Lab2[0];
- Lab3[1] = 0.5 * (Lab1[1] + Lab2[1]); /* Compute aim point between actual target */
- Lab3[2] = 0.5 * (Lab1[2] + Lab2[2]); /* and previous point. */
- icmLab2XYZ(&x.twN, asgrey.s[i].tXYZ, Lab3);
Lab1[0] = Lab2[0]; /* L of current target with ab of previous as 2nd threshold */
- icmLab2XYZ(&x.twN, peqXYZ, Lab1);
+ icmLab2XYZ(&x.twN, peqXYZ, Lab1); /* Previous equivalent */
}
+#ifdef ADJ_THRESH
+ /* Adjust the termination threshold to make sure it is less than */
+ /* half a step */
+ {
+ double de;
+ if (i < (rsteps-1)) {
+ de = 0.5 * icmXYZLabDE(&x.twN, asgrey.s[i].tXYZ, asgrey.s[i+1].tXYZ);
+ if (de < MIN_THRESH) /* Don't be silly */
+ de = MIN_THRESH;
+ if (de < ierrth)
+ ierrth = de;
+ }
+ if (i > 0) {
+ de = 0.5 * icmXYZLabDE(&x.twN, asgrey.s[i].tXYZ, asgrey.s[i-1].tXYZ);
+ if (de < MIN_THRESH) /* Don't be silly */
+ de = MIN_THRESH;
+ if (de < ierrth)
+ ierrth = de;
+ }
+ }
+#endif /* ADJ_THRESH */
+
/* Until we meet the necessary accuracy or give up */
- for (rpt = 0;rpt < MAX_RPTS; rpt++) {
+ for (rpt = 0; rpt < mxrpts; rpt++) {
+ double hlew = 1.0; /* high L* error weight */
int gworse = 0; /* information flag */
- double wde; /* informational */
+ double w_de, wde; /* informational */
+ double pjadj[3][3] = { 0.0 }; /* Previous jacobian adjustment */
set[0].r = asgrey.s[i].rgb[0];
set[0].g = asgrey.s[i].rgb[1];
@@ -4142,7 +4313,7 @@ int main(int argc, char *argv[]) {
icmAry2Ary(x.twh, asgrey.s[i].XYZ); /* Set current white */
icmAry2XYZ(x.twN, x.twh); /* Need this for Lab conversions */
- init_csamp_txyz(&asgrey, &x, 1); /* Recompute txyz's */
+ init_csamp_txyz(&asgrey, &x, 1, verb); /* Recompute txyz's */
icmAry2Ary(peqXYZ, asgrey.s[i].tXYZ); /* Fix peqXYZ */
//printf("~1 Just reset target white to native white\n");
if (wdrift) { /* Make sure white drift is reset on next read. */
@@ -4150,35 +4321,48 @@ int main(int argc, char *argv[]) {
}
}
- /* Compute the current change wanted to hit target */
+ /* Compute the next change wanted to hit target */
icmSub3(asgrey.s[i].deXYZ, asgrey.s[i].tXYZ, asgrey.s[i].XYZ);
- asgrey.s[i].de = icmXYZLabDE(&x.twN, asgrey.s[i].tXYZ, asgrey.s[i].XYZ);
- asgrey.s[i].peqde = icmXYZLabDE(&x.twN, peqXYZ, asgrey.s[i].XYZ);
+
+ /* For the darkest 5% of targets, weight the L* delta E so that */
+ /* we err on the darker side */
+ if (asgrey.s[i].v < POWERR_THR)
+ hlew = 1.0 + POWERR_WEIGHT * pow((POWERR_THR - asgrey.s[i].v)/POWERR_THR,
+ POWERR_WEIGHT_POW);
+ else
+ hlew = 1.0;
+//printf("~1 i %d, v %f, hlew %f\n",i,asgrey.s[i].v,hlew);
+ asgrey.s[i]._de = icmXYZLabDE(&x.twN, asgrey.s[i].tXYZ, asgrey.s[i].XYZ);
+ asgrey.s[i].de = bwXYZLabDE(&x.twN, asgrey.s[i].tXYZ, asgrey.s[i].XYZ, hlew);
+ asgrey.s[i].peqde = bwXYZLabDE(&x.twN, peqXYZ, asgrey.s[i].XYZ, hlew);
asgrey.s[i].hde = 0.8 * asgrey.s[i].de + 0.2 * asgrey.s[i].peqde;
/* Eudclidian difference of XYZ, because this doesn't always track Lab */
asgrey.s[i].dc = icmLabDE(asgrey.s[i].tXYZ, asgrey.s[i].XYZ);
- /* Compute change from last XYZ */
+ /* Compute actual change from last XYZ */
icmSub3(asgrey.s[i].dXYZ, asgrey.s[i].XYZ, asgrey.s[i].pXYZ);
-#ifdef DEBUG
- printf("\n\nTest point %d, v = %f\n",rsteps - i,asgrey.s[i].v);
- printf("Current rgb %f %f %f -> XYZ %f %f %f, de %f, dc %f\n",
- asgrey.s[i].rgb[0], asgrey.s[i].rgb[1], asgrey.s[i].rgb[2],
- asgrey.s[i].XYZ[0], asgrey.s[i].XYZ[1], asgrey.s[i].XYZ[2],
- asgrey.s[i].de, asgrey.s[i].dc);
- printf("Target XYZ %f %f %f, delta needed %f %f %f\n",
- asgrey.s[i].tXYZ[0], asgrey.s[i].tXYZ[1], asgrey.s[i].tXYZ[2],
- asgrey.s[i].deXYZ[0], asgrey.s[i].deXYZ[1], asgrey.s[i].deXYZ[2]);
- if (rpt > 0) {
- printf("Intended XYZ change %f %f %f, actual change %f %f %f\n",
- asgrey.s[i].pdXYZ[0], asgrey.s[i].pdXYZ[1], asgrey.s[i].pdXYZ[2],
- asgrey.s[i].dXYZ[0], asgrey.s[i].dXYZ[1], asgrey.s[i].dXYZ[2]);
+ w_de = asgrey.s[i]._de;
+ wde = asgrey.s[i].de;
+
+ if (verb >= 3) {
+ printf("\n\nTest point %d, v = %f, rpt %d\n",rsteps - i,asgrey.s[i].v,rpt);
+ printf("Current rgb %f %f %f -> XYZ %f %f %f, de %f, dc %f\n",
+ asgrey.s[i].rgb[0], asgrey.s[i].rgb[1], asgrey.s[i].rgb[2],
+ asgrey.s[i].XYZ[0], asgrey.s[i].XYZ[1], asgrey.s[i].XYZ[2],
+ asgrey.s[i]._de, asgrey.s[i].dc);
+ printf("Target XYZ %f %f %f, delta needed %f %f %f\n",
+ asgrey.s[i].tXYZ[0], asgrey.s[i].tXYZ[1], asgrey.s[i].tXYZ[2],
+ asgrey.s[i].deXYZ[0], asgrey.s[i].deXYZ[1], asgrey.s[i].deXYZ[2]);
+ if (rpt > 0) {
+ printf("Last intended XYZ change %f %f %f, actual change %f %f %f\n",
+ asgrey.s[i].pdXYZ[0], asgrey.s[i].pdXYZ[1], asgrey.s[i].pdXYZ[2],
+ asgrey.s[i].dXYZ[0], asgrey.s[i].dXYZ[1], asgrey.s[i].dXYZ[2]);
+ }
}
-#endif
if (it < mxits) { /* Not verify, apply correction */
- int impj = 0; /* We improved the Jacobian */
+ int impj = 0; /* We adjusted the Jacobian */
int dclip = 0; /* We clipped the new RGB */
#ifdef ADJ_JACOBIAN
int isclipped = 0;
@@ -4197,7 +4381,9 @@ int main(int argc, char *argv[]) {
#ifdef REMEAS_JACOBIAN
/* If the de hasn't improved, try and measure the Jacobian */
- if (it < (rsteps-1) && mjac == 0 && asgrey.s[i].de > (0.8 * prevde)) {
+// if (it < (rsteps-1) && mjac == 0 && asgrey.s[i].de > (0.8 * prevde))
+ if (mjac == 0 && asgrey.s[i].de > (0.8 * prevde))
+ {
double dd;
if (asgrey.s[i].v < 0.5)
dd = 0.05;
@@ -4224,18 +4410,20 @@ int main(int argc, char *argv[]) {
}
totmeas += 3;
+//printf("\n~1 remeasured jacobian\n");
/* Matrix organization is J[XYZ][RGB] for del RGB->del XYZ*/
for (j = 0; j < 3; j++) {
asgrey.s[i].j[0][j] = (set[j].XYZ[0] - asgrey.s[i].XYZ[0]) / dd;
asgrey.s[i].j[1][j] = (set[j].XYZ[1] - asgrey.s[i].XYZ[1]) / dd;
asgrey.s[i].j[2][j] = (set[j].XYZ[2] - asgrey.s[i].XYZ[2]) / dd;
}
+
+ /* Clear pjadj */
+ for (j = 0; j < 3; j++)
+ pjadj[3][0] = pjadj[3][1] = pjadj[3][2] = 0.0;
+
if (icmInverse3x3(asgrey.s[i].ij, asgrey.s[i].j)) {
/* Should repeat with bigger dd ? */
-//printf("~1 matrix =\n");
-//printf("~1 %f %f %f\n", asgrey.s[i].j[0][0], asgrey.s[i].j[0][1], asgrey.s[i].j[0][2]);
-//printf("~1 %f %f %f\n", asgrey.s[i].j[1][0], asgrey.s[i].j[1][1], asgrey.s[i].j[1][2]);
-//printf("~1 %f %f %f\n", asgrey.s[i].j[2][0], asgrey.s[i].j[2][1], asgrey.s[i].j[2][2]);
if (verb)
printf("dispcal: inverting Jacobian failed (3) - falling back\n");
@@ -4244,6 +4432,7 @@ int main(int argc, char *argv[]) {
}
/* Restart at the best we've had */
if (asgrey.s[i].hde > besthde) {
+ asgrey.s[i]._de = best_de;
asgrey.s[i].de = bestde;
asgrey.s[i].dc = bestdc;
asgrey.s[i].peqde = bestpeqde;
@@ -4257,13 +4446,13 @@ int main(int argc, char *argv[]) {
icmSub3(asgrey.s[i].deXYZ, asgrey.s[i].tXYZ, asgrey.s[i].XYZ);
}
mjac = 1;
- impj = 1;
+ impj = 1; /* Have remeasured */
}
#endif /* REMEAS_JACOBIAN */
/* Compute a correction to the Jacobian if we can. */
/* (Don't do this unless we have a solid previous */
- /* reading for this patch) */
+ /* reading for this patch, and we haven't remeasured it) */
if (impj == 0 && rpt > 0 && isclipped == 0) {
double nsdrgb; /* Norm squared of pdrgb */
double spdrgb[3]; /* Scaled previous delta rgb */
@@ -4272,6 +4461,10 @@ int main(int argc, char *argv[]) {
double tj[3][3]; /* Temp Jacobian */
double itj[3][3]; /* Temp inverse Jacobian */
+//printf("~1 Jacobian was: %f %f %f\n", asgrey.s[i].j[0][0], asgrey.s[i].j[0][1], asgrey.s[i].j[0][2]);
+//printf("~1 %f %f %f\n", asgrey.s[i].j[1][0], asgrey.s[i].j[1][1], asgrey.s[i].j[1][2]);
+//printf("~1 %f %f %f\n", asgrey.s[i].j[2][0], asgrey.s[i].j[2][1], asgrey.s[i].j[2][2]);
+
/* Use Broyden's Formula */
icmSub3(dXYZerr, asgrey.s[i].dXYZ, asgrey.s[i].pdXYZ);
//printf("~1 Jacobian error = %f %f %f\n", dXYZerr[0], dXYZerr[1], dXYZerr[2]);
@@ -4287,31 +4480,68 @@ int main(int argc, char *argv[]) {
{
double eXYZ[3];
+//printf("~1 del RGB %f %f %f got del XYZ %f %f %f\n", asgrey.s[i].pdrgb[0], asgrey.s[i].pdrgb[1], asgrey.s[i].pdrgb[2], asgrey.s[i].dXYZ[0], asgrey.s[i].dXYZ[1], asgrey.s[i].dXYZ[2]);
+
/* Make a full adjustment to temporary Jac */
icmAdd3x3(tj, asgrey.s[i].j, jadj);
+
+//printf("~1 Full Jacobian: %f %f %f\n", tj[0][0], tj[0][1], tj[0][2]);
+//printf("~1 %f %f %f\n", tj[1][0], tj[1][1], tj[1][2]);
+//printf("~1 %f %f %f\n", tj[2][0], tj[2][1], tj[2][2]);
+
icmMulBy3x3(eXYZ, tj, asgrey.s[i].pdrgb);
icmSub3(eXYZ, eXYZ, asgrey.s[i].dXYZ);
printf("Jac check resid %f %f %f\n", eXYZ[0], eXYZ[1], eXYZ[2]);
}
#endif /* DEBUG */
+ /* Add to portion of previous adjustment */
+ /* to counteract undershoot & overshoot */
+ icmScale3x3(pjadj, pjadj, JAC_COMP_FACT);
+ icmAdd3x3(jadj, jadj, pjadj);
+ icmCpy3x3(pjadj, jadj);
+
/* Add part of our correction to actual Jacobian */
+ /* to smooth out correction to counteract noise */
icmScale3x3(jadj, jadj, JAC_COR_FACT);
icmAdd3x3(tj, asgrey.s[i].j, jadj);
+
if (icmInverse3x3(itj, tj) == 0) { /* Invert OK */
icmCpy3x3(asgrey.s[i].j, tj); /* Use adjusted */
icmCpy3x3(asgrey.s[i].ij, itj);
impj = 1;
+
+#ifdef NEVER
+ /* Check how close new Jacobian predicts previous delta XYZ */
+ {
+ double eXYZ[3];
+ double ergb[3];
+
+ icmMulBy3x3(eXYZ, asgrey.s[i].j, asgrey.s[i].pdrgb);
+ icmSub3(eXYZ, eXYZ, asgrey.s[i].dXYZ);
+ printf("Jac check2 resid %f %f %f\n", eXYZ[0], eXYZ[1], eXYZ[2]);
+
+ icmMulBy3x3(ergb, asgrey.s[i].ij, asgrey.s[i].pdXYZ);
+ printf("Jac check2 drgb would have been %f %f %f\n", ergb[0], ergb[1], ergb[2]);
+ icmAdd3(ergb, ergb, asgrey.s[i].prgb);
+ printf("Jac check2 rgb would have been %f %f %f\n", ergb[0], ergb[1], ergb[2]);
+ }
+#endif
}
-//else printf("~1 ij failed\n");
+//else printf("~1 ij failed - reverted\n");
}
//else printf("~1 nsdrgb was below threshold\n");
}
//else if (isclipped) printf("~1 no j update: rgb is clipped\n");
+//printf("~1 Jacobian now: %f %f %f\n", asgrey.s[i].j[0][0], asgrey.s[i].j[0][1], asgrey.s[i].j[0][2]);
+//printf("~1 %f %f %f\n", asgrey.s[i].j[1][0], asgrey.s[i].j[1][1], asgrey.s[i].j[1][2]);
+//printf("~1 %f %f %f\n", asgrey.s[i].j[2][0], asgrey.s[i].j[2][1], asgrey.s[i].j[2][2]);
+
#endif /* ADJ_JACOBIAN */
/* Track the best solution we've found */
if (asgrey.s[i].hde <= besthde) {
+ best_de = asgrey.s[i]._de;
bestde = asgrey.s[i].de;
bestdc = asgrey.s[i].dc;
bestpeqde = asgrey.s[i].peqde;
@@ -4323,13 +4553,14 @@ int main(int argc, char *argv[]) {
bestxyz[1] = asgrey.s[i].XYZ[1];
bestxyz[2] = asgrey.s[i].XYZ[2];
+//printf("~1 new best\n");
} else if (asgrey.s[i].dc > bestdc) {
/* we got worse in Lab and XYZ ! */
- wde = asgrey.s[i].de;
-
/* If we've wandered too far, return to best we found */
if (asgrey.s[i].hde > (3.0 * besthde)) {
+//printf("~1 resetting to last best\n");
+ asgrey.s[i]._de = best_de;
asgrey.s[i].de = bestde;
asgrey.s[i].dc = bestdc;
asgrey.s[i].peqde = bestpeqde;
@@ -4344,22 +4575,26 @@ int main(int argc, char *argv[]) {
}
/* If the Jacobian hasn't changed, moderate the gain */
- if (impj == 0)
+ if (impj == 0) {
rgain *= 0.8; /* We might be overshooting */
+//printf("~1 reducing rgain to %f\n",rgain);
+ }
gworse = 1;
}
/* See if we need to repeat */
- if (asgrey.s[i].de <= errthr && asgrey.s[i].peqde < errthr) {
- if (verb > 1)
+ if (asgrey.s[i].de <= ierrth && asgrey.s[i].peqde < ierrth) {
+ if (verb > 1) {
if (it < (mxits-1))
- printf("Point %d Delta E %f, OK\n",rsteps - i,asgrey.s[i].de);
+ printf("Point %d DE %f, W.DE %f, OK ( < %f)\n",rsteps - i,asgrey.s[i]._de, asgrey.s[i].de, ierrth);
else
- printf("Point %d Delta E %f, peqDE %f, OK\n",rsteps - i,asgrey.s[i].de, asgrey.s[i].peqde);
+ printf("Point %d DE %f, W.DE %f, W.peqDE %f, OK ( < %f)\n",rsteps - i,asgrey.s[i]._de,asgrey.s[i].de, asgrey.s[i].peqde, ierrth);
+ }
break; /* No more retries */
}
- if ((rpt+1) >= MAX_RPTS) {
- asgrey.s[i].de = bestde; /* Restore to best we found */
+ if ((rpt+1) >= mxrpts) {
+ asgrey.s[i]._de = best_de; /* Restore to best we found */
+ asgrey.s[i].de = bestde;
asgrey.s[i].dc = bestdc;
asgrey.s[i].peqde = bestpeqde; /* Restore to best we found */
asgrey.s[i].hde = besthde; /* Restore to best we found */
@@ -4369,11 +4604,12 @@ int main(int argc, char *argv[]) {
asgrey.s[i].XYZ[0] = bestxyz[0];
asgrey.s[i].XYZ[1] = bestxyz[1];
asgrey.s[i].XYZ[2] = bestxyz[2];
- if (verb > 1)
+ if (verb > 1) {
if (it < (mxits-1))
- printf("Point %d Delta E %f, Fail\n",rsteps - i,asgrey.s[i].de);
+ printf("Point %d DE %f, W.DE %f, Fail ( > %f)\n",rsteps - i,asgrey.s[i]._de, asgrey.s[i].de, ierrth);
else
- printf("Point %d Delta E %f, peqDE %f, Fail\n",rsteps - i,asgrey.s[i].de,asgrey.s[i].peqde);
+ printf("Point %d DE %f, W.DE %f, W.peqDE %f, Fail ( > %f)\n",rsteps - i,asgrey.s[i]._de,asgrey.s[i].de,asgrey.s[i].peqde,ierrth);
+ }
thrfail = 1; /* Failed to meet target */
if (bestde > failerr)
failerr = bestde; /* Worst failed delta E */
@@ -4382,26 +4618,28 @@ int main(int argc, char *argv[]) {
if (verb > 1) {
if (gworse)
if (it < (mxits-1))
- printf("Point %d Delta E %f, Repeat (got worse)\n", rsteps - i, wde);
+ printf("Point %d DE %f, W.DE %f, Repeat (got worse)\n", rsteps - i, w_de, wde);
else
- printf("Point %d Delta E %f, peqDE %f, Repeat (got worse)\n", rsteps - i, wde,asgrey.s[i].peqde);
+ printf("Point %d DE %f, W.DE %f, peqDE %f, Repeat (got worse)\n", rsteps - i, w_de, wde,asgrey.s[i].peqde);
else
if (it < (mxits-1))
- printf("Point %d Delta E %f, Repeat\n", rsteps - i,asgrey.s[i].de);
+ printf("Point %d DE %f, W.DE %f, Repeat\n", rsteps - i,asgrey.s[i]._de,asgrey.s[i].de);
else
- printf("Point %d Delta E %f, peqDE %f, Repeat\n", rsteps - i,asgrey.s[i].de,asgrey.s[i].peqde);
+ printf("Point %d DE %f, W.DE %f, peqDE %f, Repeat\n", rsteps - i,asgrey.s[i]._de,asgrey.s[i].de,asgrey.s[i].peqde);
}
+//printf("~1 RGB Jacobian: %f %f %f\n", asgrey.s[i].j[0][0], asgrey.s[i].j[0][1], asgrey.s[i].j[0][2]);
+//printf("~1 %f %f %f\n", asgrey.s[i].j[1][0], asgrey.s[i].j[1][1], asgrey.s[i].j[1][2]);
+//printf("~1 %f %f %f\n", asgrey.s[i].j[2][0], asgrey.s[i].j[2][1], asgrey.s[i].j[2][2]);
/* Compute refinement of rgb */
icmMulBy3x3(asgrey.s[i].pdrgb, asgrey.s[i].ij, asgrey.s[i].deXYZ);
-//printf("~1 delta needed %f %f %f -> delta RGB %f %f %f\n",
+//printf("~1 XYZ delta needed %f %f %f -> delta RGB %f %f %f\n",
//asgrey.s[i].deXYZ[0], asgrey.s[i].deXYZ[1], asgrey.s[i].deXYZ[2],
//asgrey.s[i].pdrgb[0], asgrey.s[i].pdrgb[1], asgrey.s[i].pdrgb[2]);
/* Gain scale */
icmScale3(asgrey.s[i].pdrgb, asgrey.s[i].pdrgb, rgain);
-//printf("~1 delta RGB after gain scale %f %f %f\n",
-//asgrey.s[i].pdrgb[0], asgrey.s[i].pdrgb[1], asgrey.s[i].pdrgb[2]);
+//printf("~1 delta RGB after gain scale %f %f %f\n", asgrey.s[i].pdrgb[0], asgrey.s[i].pdrgb[1], asgrey.s[i].pdrgb[2]);
#ifdef CLIP
/* Component wise clip */
@@ -4415,28 +4653,39 @@ int main(int argc, char *argv[]) {
dclip = 1;
}
}
-#ifdef DEBUG
- if (dclip) printf("delta RGB after clip %f %f %f\n",
+ if (verb >= 3 && dclip) printf("delta RGB after clip %f %f %f\n",
asgrey.s[i].pdrgb[0], asgrey.s[i].pdrgb[1], asgrey.s[i].pdrgb[2]);
-#endif /* DEBUG */
#endif /* CLIP */
/* Compute next on the basis of this one RGB */
+ icmCpy3(asgrey.s[i].prgb, asgrey.s[i].rgb); /* Save previous */
icmAdd3(asgrey.s[i].rgb, asgrey.s[i].rgb, asgrey.s[i].pdrgb);
/* Save expected change in XYZ */
icmMulBy3x3(asgrey.s[i].pdXYZ, asgrey.s[i].j, asgrey.s[i].pdrgb);
-#ifdef DEBUG
- printf("New rgb %f %f %f from expected del XYZ %f %f %f\n",
- asgrey.s[i].rgb[0], asgrey.s[i].rgb[1], asgrey.s[i].rgb[2],
- asgrey.s[i].pdXYZ[0], asgrey.s[i].pdXYZ[1], asgrey.s[i].pdXYZ[2]);
-#endif
+ if (verb >= 3) {
+ printf("New rgb %f %f %f from expected del XYZ %f %f %f\n",
+ asgrey.s[i].rgb[0], asgrey.s[i].rgb[1], asgrey.s[i].rgb[2],
+ asgrey.s[i].pdXYZ[0], asgrey.s[i].pdXYZ[1], asgrey.s[i].pdXYZ[2]);
+ }
} else { /* Verification, so no repeat */
break;
}
prevde = asgrey.s[i].de;
} /* Next repeat */
- } /* Next resolution step */
+
+ if (verb >= 3) {
+ printf("After adjustment:\n");
+ printf("Current rgb %f %f %f -> XYZ %f %f %f, de %f, dc %f\n",
+ asgrey.s[i].rgb[0], asgrey.s[i].rgb[1], asgrey.s[i].rgb[2],
+ asgrey.s[i].XYZ[0], asgrey.s[i].XYZ[1], asgrey.s[i].XYZ[2],
+ asgrey.s[i].de, asgrey.s[i].dc);
+ printf("Target XYZ %f %f %f, delta needed %f %f %f\n",
+ asgrey.s[i].tXYZ[0], asgrey.s[i].tXYZ[1], asgrey.s[i].tXYZ[2],
+ asgrey.s[i].deXYZ[0], asgrey.s[i].deXYZ[1], asgrey.s[i].deXYZ[2]);
+ }
+
+ } /* Next patch/step */
if (verb)
printf("\n"); /* Final return for patch count */
@@ -4487,7 +4736,7 @@ int main(int argc, char *argv[]) {
/* We're checking against our given brightness and */
/* white point target. */
mnerr = anerr = 0.0;
- init_csamp_txyz(&asgrey, &x, 0); /* In case the targets were tweaked */
+ init_csamp_txyz(&asgrey, &x, 0, verb); /* In case the targets were tweaked */
for (i = 0; i < asgrey.no; i++) {
double err;
@@ -4518,7 +4767,7 @@ int main(int argc, char *argv[]) {
}
/* Verify loop exit */
- if (it >= (mxits + nver -1)) {
+ if (nver > 0 && it >= (mxits + nver -1)) {
break;
}
@@ -4546,7 +4795,6 @@ int main(int argc, char *argv[]) {
sdv[j][i].p = asgrey.s[i].v;
sdv[j][i].v = asgrey.s[i].rgb[j];
sdv[j][i].w = 1.0;
-// ~~999
#ifdef NEVER
printf("rdac %d point %d = %f, %f\n",j,i,sdv[j][i].p,sdv[j][i].v);
#endif
@@ -4623,6 +4871,8 @@ int main(int argc, char *argv[]) {
/* Tell downstream whether they can expect that this calibration */
/* will be applied in hardware or not. */
ocg->add_kword(ocg, 0, "VIDEO_LUT_CALIBRATION_POSSIBLE",noramdac ? "NO" : "YES", NULL);
+ /* Tell downstream whether the device range was actually (16-235)/255 */
+ ocg->add_kword(ocg, 0, "TV_OUTPUT_ENCODING",out_tvenc ? "YES" : "NO", NULL);
/* Put the target parameters in the CGATS file too */
if (dtype != 0) {
@@ -4833,6 +5083,16 @@ int main(int argc, char *argv[]) {
cc = 0.0;
else if (cc > 1.0)
cc = 1.0;
+ if (out_tvenc) {
+ cc = (cc * (235.0-16.0) + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit shifting */
+ /* rather than scaling, so we need to scale the fp value to account for this. */
+ /* We assume the precision is the vcgt table size = 16 */
+ /* ~~99 ideally we should tag the fact that this is video encoded, so that */
+ /* the vcgt loaded can adjust for a different bit precision ~~~~ */
+ cc = (cc * 255 * (1 << (16 - 8)))/((1 << 16) - 1.0);
+ }
((unsigned short*)wo->u.table.data)[CAL_RES * j + i] = (int)(cc * 65535.0 + 0.5);
}
}
@@ -5174,6 +5434,15 @@ int main(int argc, char *argv[]) {
cc = 0.0;
else if (cc > 1.0)
cc = 1.0;
+ if (out_tvenc) {
+ cc = (cc * (235.0-16.0) + 16.0)/255.0;
+ /* For video encoding the extra bits of precision are created by bit */
+ /* shifting rather than scaling, so we need to scale the fp value to */
+ /* account for this. We assume the precision is the vcgt table size = 16 */
+ /* ~~99 ideally we should tag the fact that this is video encoded, so */
+ /* that the vcgt loaded can adjust for a different bit precision ~~~~ */
+ cc = (cc * 255 * (1 << (16 - 8)))/((1 << 16) - 1.0);
+ }
((unsigned short*)wo->u.table.data)[CAL_RES * j + i] = (int)(cc * 65535.0 + 0.5);
}
}
@@ -5197,9 +5466,13 @@ int main(int argc, char *argv[]) {
wog->allocate((icmBase *)wog);
wob->allocate((icmBase *)wob);
- wor->data[0].X = mat[0][0]; wor->data[0].Y = mat[1][0]; wor->data[0].Z = mat[2][0];
- wog->data[0].X = mat[0][1]; wog->data[0].Y = mat[1][1]; wog->data[0].Z = mat[2][1];
- wob->data[0].X = mat[0][2]; wob->data[0].Y = mat[1][2]; wob->data[0].Z = mat[2][2];
+ /* Make sure rounding doesn't wreck white point */
+ icmTranspose3x3(mat, mat); /* Convert [XYZ][RGB] to [RGB][XYZ] */
+ quantizeRGBprimsS15Fixed16(mat);
+
+ wor->data[0].X = mat[0][0]; wor->data[0].Y = mat[0][1]; wor->data[0].Z = mat[0][2];
+ wog->data[0].X = mat[1][0]; wog->data[0].Y = mat[1][1]; wog->data[0].Z = mat[1][2];
+ wob->data[0].X = mat[2][0]; wob->data[0].Y = mat[2][1]; wob->data[0].Z = mat[2][2];
}
/* Red, Green and Blue Tone Reproduction Curve Tags: */
diff --git a/spectro/dispread.c b/spectro/dispread.c
index 4a8d364..990501f 100644
--- a/spectro/dispread.c
+++ b/spectro/dispread.c
@@ -84,7 +84,7 @@ static int gcc_bug_fix(int i) {
Flags used:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
- upper .. . .... .. .. ...
+ upper .... .... .. .. ...
lower .. . . . . .. .
*/
@@ -129,6 +129,9 @@ void usage(char *diag, ...) {
}
free_disppaths(dp);
fprintf(stderr," -dweb[:port] Display via a web server at port (default 8080)\n");
+#ifdef NT
+ fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n");
+#endif
// fprintf(stderr," -d fake Use a fake display device for testing, fake%s if present\n",ICC_FILE_EXT);
fprintf(stderr," -c listno Set communication port from the following list (default %d)\n",COMPORT);
if ((icmps = new_icompaths(g_log)) != NULL) {
@@ -150,6 +153,9 @@ void usage(char *diag, ...) {
cap2 = inst_show_disptype_options(stderr, " -y ", icmps, 0);
fprintf(stderr," -k file.cal Load calibration file into display while reading\n");
fprintf(stderr," -K file.cal Apply calibration file to test values while reading\n");
+#ifdef NT
+ fprintf(stderr," -V Enable MadVR color management (3dLut)\n");
+#endif
fprintf(stderr," -s Save spectral information (default don't save)\n");
fprintf(stderr," -P ho,vo,ss[,vs] Position test window and scale it\n");
fprintf(stderr," ho,vi: 0.0 = left/top, 0.5 = center, 1.0 = right/bottom etc.\n");
@@ -158,6 +164,7 @@ void usage(char *diag, ...) {
#if defined(UNIX_X11)
fprintf(stderr," -n Don't set override redirect on test window\n");
#endif
+ fprintf(stderr," -E Encode the test values for video range 16..235/255\n");
fprintf(stderr," -J Run instrument calibration first (used rarely)\n");
fprintf(stderr," -N Disable initial calibration of instrument if possible\n");
fprintf(stderr," -H Use high resolution spectrum mode (if available)\n");
@@ -171,7 +178,9 @@ void usage(char *diag, ...) {
fprintf(stderr," 1931_2 (def), 1964_10, S&B 1955_2, shaw, J&V 1978_2, 1964_10c\n");
}
fprintf(stderr," -I b|w Drift compensation, Black: -Ib, White: -Iw, Both: -Ibw\n");
+ fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
fprintf(stderr," -Y A Use non-adaptive integration time mode (if available).\n");
+ fprintf(stderr," -Y p Don't wait for the instrument to be placed on the display\n");
fprintf(stderr," -C \"command\" Invoke shell \"command\" each time a color is set\n");
fprintf(stderr," -M \"command\" Invoke shell \"command\" each time a color is measured\n");
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
@@ -188,6 +197,7 @@ int main(int argc, char *argv[]) {
disppath *disp = NULL; /* Display being used */
double hpatscale = 1.0, vpatscale = 1.0; /* scale factor for test patch size */
double ho = 0.0, vo = 0.0; /* Test window offsets, -1.0 to 1.0 */
+ int out_tvenc = 0; /* 1 to use RGB Video Level encoding */
int blackbg = 0; /* NZ if whole screen should be filled with black */
int verb = 0;
int debug = 0;
@@ -199,12 +209,14 @@ int main(int argc, char *argv[]) {
flow_control fc = fc_nc; /* Default flow control */
int docalib = 0; /* Do a calibration */
int highres = 0; /* Use high res mode if available */
+ double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */
int nadaptive = 0; /* Use non-adaptive mode if available */
int bdrift = 0; /* Flag, nz for black drift compensation */
int wdrift = 0; /* Flag, nz for white drift compensation */
int dtype = 0; /* Display type selection charater */
int tele = 0; /* NZ if telephoto mode */
int noautocal = 0; /* Disable auto calibration */
+ int noplace = 0; /* Disable user instrument placement */
int nonorm = 0; /* Disable normalisation */
char ccxxname[MAXNAMEL+1] = "\000"; /* Colorimeter Correction Matrix name */
ccmx *cmx = NULL; /* Colorimeter Correction Matrix */
@@ -212,12 +224,18 @@ int main(int argc, char *argv[]) {
int spec = 0; /* Don't save spectral information */
icxObserverType obType = icxOT_default;
int webdisp = 0; /* NZ for web display, == port number */
+#ifdef NT
+ int madvrdisp = 0; /* NZ for MadVR display */
+#endif
char *ccallout = NULL; /* Change color Shell callout */
char *mcallout = NULL; /* Measure color Shell callout */
char inname[MAXNAMEL+1] = "\000"; /* Input cgats file base name */
char outname[MAXNAMEL+1] = "\000"; /* Output cgats file base name */
char calname[MAXNAMEL+1] = "\000"; /* Calibration file name (if any) */
- int softcal = 0; /* nz if cal applied to values rather than hardware */
+ int native = 2; /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high prec */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
double cal[3][MAX_CAL_ENT]; /* Display calibration */
int ncal = 256; /* number of cal entries used */
cgats *icg; /* input cgats structure */
@@ -237,6 +255,7 @@ int main(int argc, char *argv[]) {
cgats_set_elem *setel; /* Array of set value elements */
disprd *dr; /* Display patch read object */
int noramdac = 0; /* Will be set to nz if can't set ramdac */
+ int nocm = 0; /* Will be set to nz if can't set color management */
int errc; /* Return value from new_disprd() */
int rv;
@@ -295,6 +314,12 @@ int main(int argc, char *argv[]) {
usage("Web port number must be in range 1..65535");
}
fa = nfa;
+#ifdef NT
+ } else if (strncmp(na,"madvr",5) == 0
+ || strncmp(na,"MADVR",5) == 0) {
+ madvrdisp = 1;
+ fa = nfa;
+#endif
} else {
#if defined(UNIX_X11)
int ix, iv;
@@ -358,17 +383,24 @@ int main(int argc, char *argv[]) {
dtype = na[0];
/* Calibration file */
- } else if (argv[fa][1] == 'k' || argv[fa][1] == 'K') {
- fa = nfa;
- if (na == NULL) usage("Parameter expected after -k/-K");
+ } else if (argv[fa][1] == 'k'
+ || argv[fa][1] == 'K') {
+ if (na == NULL) usage("Parameter expected after -%c",argv[fa][1]);
strncpy(calname,na,MAXNAMEL); calname[MAXNAMEL] = '\000';
- softcal = 0;
if (argv[fa][1] == 'K')
- softcal = 1;
- }
+ native |= 1; /* Use native linear & soft cal */
+ else
+ native &= ~1; /* Use HW cal */
+ fa = nfa;
+
+#ifdef NT
+ /* MadVR verify mode */
+ } else if (argv[fa][1] == 'V') {
+ native &= ~2;
+#endif
/* Save spectral data */
- else if (argv[fa][1] == 's') {
+ } else if (argv[fa][1] == 's') {
spec = 1;
/* Test patch offset and size */
@@ -394,6 +426,10 @@ int main(int argc, char *argv[]) {
} else if (argv[fa][1] == 'F') {
blackbg = 1;
+ /* Video encoded output */
+ } else if (argv[fa][1] == 'E') {
+ out_tvenc = 1;
+
/* Force calibration */
} else if (argv[fa][1] == 'J') {
docalib = 1;
@@ -406,10 +442,6 @@ int main(int argc, char *argv[]) {
} else if (argv[fa][1] == 'H') {
highres = 1;
- /* Adaptive mode - default, so flag is deprecated */
- } else if (argv[fa][1] == 'V') {
- warning("dispread -V flag is deprecated");
-
/* No normalisation */
} else if (argv[fa][1] == 'w') {
nonorm = 1;
@@ -495,11 +527,20 @@ int main(int argc, char *argv[]) {
if (na == NULL)
usage("Flag '-Y' expects extra flag");
- if (na[0] == 'A') {
+ if (na[0] == 'R') {
+ if (na[1] != ':')
+ usage("-Y R:rate syntax incorrect");
+ refrate = atof(na+2);
+ if (refrate < 5.0 || refrate > 150.0)
+ usage("-Y R:rate %f Hz not in valid range",refrate);
+ } else if (na[0] == 'p') {
+ noplace = 1;
+ } else if (na[0] == 'A') {
nadaptive = 1;
} else {
usage("Flag '-Y %c' not recognised",na[0]);
}
+ fa = nfa;
} else
usage("Flag '-%c' not recognised",argv[fa][1]);
@@ -560,15 +601,19 @@ int main(int argc, char *argv[]) {
}
if (fake)
- comport = -99;
+ comport = FAKE_DEVICE_PORT;
if ((icmps = new_icompaths(g_log)) == NULL)
error("Finding instrument paths failed");
if ((ipath = icmps->get_path(icmps, comport)) == NULL)
error("No instrument at port %d",comport);
if (docalib) {
- if ((rv = disprd_calibration(ipath, fc, dtype, 0, tele, nadaptive, noautocal, disp,
- webdisp, blackbg, override,
+ if ((rv = disprd_calibration(ipath, fc, dtype, 0, tele, nadaptive, noautocal,
+ disp, webdisp,
+#ifdef NT
+ madvrdisp,
+#endif
+ out_tvenc, blackbg, override,
100.0 * hpatscale, 100.0 * vpatscale, ho, vo,
g_log)) != 0) {
error("docalibration failed with return value %d\n",rv);
@@ -619,6 +664,9 @@ int main(int argc, char *argv[]) {
if ((ti = icg->find_kword(icg, 0, "FULL_SPREAD_PATCHES")) >= 0)
ocg->add_kword(ocg, 0, "FULL_SPREAD_PATCHES",icg->t[0].kdata[ti], NULL);
+ if ((ti = icg->find_kword(icg, 0, "DARK_REGION_EMPHASIS")) >= 0)
+ ocg->add_kword(ocg, 0, "DARK_REGION_EMPHASIS",icg->t[0].kdata[ti], NULL);
+
if (verb) {
printf("Number of patches = %d\n",npat);
}
@@ -717,11 +765,19 @@ int main(int argc, char *argv[]) {
if ((fi = ccg->find_kword(ccg, 0, "VIDEO_LUT_CALIBRATION_POSSIBLE")) >= 0) {
if (stricmp(ccg->t[0].kdata[fi],"NO") == 0) {
- softcal = 1;
+ native = 1;
if (verb) printf("Switching to soft cal because there is no access to VideoLUTs\n");
}
}
+ if ((fi = ccg->find_kword(ccg, 0, "TV_OUTPUT_ENCODING")) >= 0) {
+ if (!out_tvenc && (strcmp(ccg->t[0].kdata[fi], "YES") == 0
+ || strcmp(ccg->t[0].kdata[fi], "yes")) == 0) {
+ if (verb) printf("Using Video range (16-235)/255 range encoding because cal. used it\n");
+ out_tvenc = 1;
+ }
+ }
+
if ((fi = ccg->find_kword(ccg, 0, "COLOR_REP")) < 0)
error ("Calibration file '%s' doesn't contain keyword COLOR_REP",calname);
if (strcmp(ccg->t[0].kdata[fi],"RGB") != 0)
@@ -753,9 +809,14 @@ int main(int argc, char *argv[]) {
cal[0][0] = -1.0; /* Not used */
}
- if ((dr = new_disprd(&errc, ipath, fc, dtype, 0, tele, nadaptive, noautocal,
- highres, 0, &noramdac, cal, ncal, softcal, disp, blackbg, override,
- webdisp, ccallout, mcallout, 100.0 * hpatscale, 100.0 * vpatscale, ho, vo,
+ if ((dr = new_disprd(&errc, ipath, fc, dtype, 0, tele, nadaptive, noautocal, noplace,
+ highres, refrate, native, &noramdac, &nocm, cal, ncal, disp,
+ out_tvenc, blackbg, override, webdisp,
+#ifdef NT
+ madvrdisp,
+#endif
+ ccallout, mcallout,
+ 100.0 * hpatscale, 100.0 * vpatscale, ho, vo,
cmx != NULL ? cmx->matrix : NULL,
ccs != NULL ? ccs->samples : NULL, ccs != NULL ? ccs->no_samp : 0,
spec, obType, NULL, bdrift, wdrift,
@@ -768,7 +829,7 @@ int main(int argc, char *argv[]) {
ccs->del(ccs);
/* Test the CRT with all of the test points */
- if ((rv = dr->read(dr, cols, npat + xpat, 1, npat + xpat, 1, 0, instClamp)) != 0) {
+ if ((rv = dr->read(dr, cols, npat + xpat, 1, npat + xpat, 1, 0, instNoClamp)) != 0) {
dr->del(dr);
error("test_crt returned error code %d\n",rv);
}
@@ -824,7 +885,7 @@ int main(int argc, char *argv[]) {
nn = 1.0;
else {
if (cols[wpat].XYZ_v == 0)
- error("XYZ of white patch is not valid!",i);
+ error("XYZ of white patch is not valid!\nCan't normalise value to white",i);
nn = 100.0 / cols[wpat].XYZ[1]; /* Normalise Y of white to 100 */
}
@@ -832,7 +893,7 @@ int main(int argc, char *argv[]) {
for (i = 0; i < npat; i++) {
if (cols[i].XYZ_v == 0)
- error("XYZ %d is not valid!",i);
+ warning("XYZ patch %d is not valid!",i+1);
for (j = 0; j < 3; j++)
cols[i].XYZ[j] = nn * cols[i].XYZ[j];
@@ -881,6 +942,11 @@ int main(int argc, char *argv[]) {
for (i = 0; i < npat; i++) {
int k = 0;
+ if (cols[i].XYZ_v == 0) {
+ warning("Omitting patch %d from .ti3 file!",i+1);
+ continue;
+ }
+
setel[k++].c = cols[i].id;
setel[k++].d = 100.0 * cols[i].r;
setel[k++].d = 100.0 * cols[i].g;
diff --git a/spectro/dispsup.c b/spectro/dispsup.c
index 0dc29ad..a27dab0 100644
--- a/spectro/dispsup.c
+++ b/spectro/dispsup.c
@@ -44,6 +44,9 @@
#include "dispwin.h"
#include "dispsup.h"
#include "webwin.h"
+#ifdef NT
+# include "madvrwin.h"
+#endif
#include "instappsup.h"
#undef SIMPLE_MODEL /* Make fake device well behaved */
@@ -56,9 +59,11 @@
#ifdef SIMPLE_MODEL
# undef FAKE_NOISE /* Add noise to _fake_ devices XYZ */
+# undef FAKE_UNPREDIC /* Initialise random unpredictably */
# undef FAKE_BITS /* Number of bits of significance of fake device */
#else
# define FAKE_NOISE 0.01 /* Add noise to _fake_ devices XYZ */
+# define FAKE_UNPREDIC /* Initialise random unpredictably */
# define FAKE_BITS 9 /* Number of bits of significance of fake device */
#endif
@@ -75,7 +80,7 @@ inst_code setup_display_calibrate(
) {
inst_code rv = inst_ok, ev;
dispwin *dw; /* Display window to display test patches on, NULL if none. */
- a1logd(p->log,1,"setup_display_calibrate called\n");
+ a1logd(p->log,1,"setup_display_calibrate called with calc = 0x%x\n",calc);
switch (calc) {
case inst_calc_none: /* Use this as a cleanup flag */
@@ -86,75 +91,70 @@ inst_code setup_display_calibrate(
break;
case inst_calc_emis_white:
- if (dwi->dw == NULL) {
- if (dwi->webdisp != 0) {
- if ((dwi->_dw = new_webwin(dwi->webdisp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, dwi->blackbg,
- p->log->verb, p->log->debug)) == NULL) {
- a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
- return inst_other_error;
- }
- } else {
- if ((dwi->_dw = new_dispwin(dwi->disp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, 0, NULL, dwi->blackbg,
- dwi->override, p->log->debug)) == NULL) {
- a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
- return inst_other_error;
- }
- }
- printf("Frequency calibration, Place instrument on test window.\n");
- printf(" Hit any key to continue,\n");
- printf(" or hit Esc or Q to abort:");
- } else {
- dwi->_dw = dwi->dw;
- }
- p->cal_gy_level = 1.0;
- dwi->_dw->set_color(dwi->_dw, 1.0, 1.0, 1.0);
- break;
-
+ case inst_calc_emis_80pc:
case inst_calc_emis_grey:
case inst_calc_emis_grey_darker:
case inst_calc_emis_grey_ligher:
if (dwi->dw == NULL) {
if (dwi->webdisp != 0) {
if ((dwi->_dw = new_webwin(dwi->webdisp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, dwi->blackbg,
- p->log->verb, p->log->debug)) == NULL) {
+ dwi->ho, dwi->vo, 0, 0, NULL, NULL, dwi->out_tvenc, dwi->blackbg,
+ p->log->verb, p->log->debug)) == NULL) {
a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
return inst_other_error;
}
+#ifdef NT
+ } else if (dwi->madvrdisp != 0) {
+ if ((dwi->_dw = new_madvrwin(dwi->hpatsize, dwi->vpatsize,
+ dwi->ho, dwi->vo, 0, 0, NULL, NULL, dwi->out_tvenc, dwi->blackbg,
+ p->log->verb, p->log->debug)) == NULL) {
+ a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
+ return inst_other_error;
+ }
+#endif /* NT */
} else {
if ((dwi->_dw = new_dispwin(dwi->disp, dwi->hpatsize, dwi->vpatsize,
- dwi->ho, dwi->vo, 0, 0, NULL, dwi->blackbg,
- dwi->override, p->log->debug)) == NULL) {
+ dwi->ho, dwi->vo, 0, 0, NULL, NULL, dwi->out_tvenc, dwi->blackbg,
+ dwi->override, p->log->debug)) == NULL) {
a1logd(p->log,1,"inst_handle_calibrate failed to create test window 0x%x\n",inst_other_error);
return inst_other_error;
}
}
- printf("Cell ratio calibration, Place instrument on test window.\n");
+ printf("Calibration: Place instrument on test window.\n");
printf(" Hit any key to continue,\n");
printf(" or hit Esc or Q to abort:");
} else {
dwi->_dw = dwi->dw;
}
- if (calc == inst_calc_emis_grey) {
- p->cal_gy_level = 0.6;
- p->cal_gy_count = 0;
- } else if (calc == inst_calc_emis_grey_darker) {
- p->cal_gy_level *= 0.7;
- p->cal_gy_count++;
- } else if (calc == inst_calc_emis_grey_ligher) {
- p->cal_gy_level *= 1.4;
- if (p->cal_gy_level > 1.0)
- p->cal_gy_level = 1.0;
- p->cal_gy_count++;
- }
- if (p->cal_gy_count > 4) {
- printf("Cell ratio calibration failed - too many tries at setting grey level.\n");
- a1logd(p->log,1,"inst_handle_calibrate too many tries at setting grey level 0x%x\n",inst_internal_error);
- return inst_internal_error;
+
+ if (calc == inst_calc_emis_white) {
+ p->cal_gy_level = 1.0;
+ dwi->_dw->set_color(dwi->_dw, 1.0, 1.0, 1.0);
+
+ } else if (calc == inst_calc_emis_80pc) {
+ p->cal_gy_level = 0.8;
+ dwi->_dw->set_color(dwi->_dw, 0.8, 0.8, 0.8);
+
+ } else {
+ if (calc == inst_calc_emis_grey) {
+ p->cal_gy_level = 0.6;
+ p->cal_gy_count = 0;
+ } else if (calc == inst_calc_emis_grey_darker) {
+ p->cal_gy_level *= 0.7;
+ p->cal_gy_count++;
+ } else if (calc == inst_calc_emis_grey_ligher) {
+ p->cal_gy_level *= 1.4;
+ if (p->cal_gy_level > 1.0)
+ p->cal_gy_level = 1.0;
+ p->cal_gy_count++;
+ }
+ if (p->cal_gy_count > 4) {
+ printf("Cell ratio calibration failed - too many tries at setting grey level.\n");
+ a1logd(p->log,1,"inst_handle_calibrate too many tries at setting grey level 0x%x\n",inst_internal_error);
+ return inst_internal_error;
+ }
+ dwi->_dw->set_color(dwi->_dw, p->cal_gy_level, p->cal_gy_level, p->cal_gy_level);
}
- dwi->_dw->set_color(dwi->_dw, p->cal_gy_level, p->cal_gy_level, p->cal_gy_level);
break;
default:
@@ -180,6 +180,10 @@ int nadaptive, /* NZ for non-adaptive mode */
int noinitcal, /* NZ to disable initial instrument calibration */
disppath *disp, /* display to calibrate. */
int webdisp, /* If nz, port number for web display */
+#ifdef NT
+int madvrdisp, /* NZ for MadVR display */
+#endif
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* Override_redirect on X11 */
double hpatsize, /* Size of dispwin */
@@ -201,7 +205,11 @@ a1log *log /* Verb, debug & error log */
memset((void *)&dwi, 0, sizeof(disp_win_info));
dwi.webdisp = webdisp;
+#ifdef NT
+ dwi.madvrdisp = madvrdisp;
+#endif
dwi.disp = disp;
+ dwi.out_tvenc = out_tvenc;
dwi.blackbg = blackbg;
dwi.override = override;
dwi.hpatsize = hpatsize;
@@ -209,8 +217,6 @@ a1log *log /* Verb, debug & error log */
dwi.ho = ho;
dwi.vo = vo;
- p->log = new_a1log_d(log);
-
a1logv(log, 1, "Setting up the instrument\n");
if ((p = new_inst(ipath, 0, log, DUIH_FUNC_AND_CONTEXT)) == NULL) {
@@ -218,6 +224,8 @@ a1log *log /* Verb, debug & error log */
return -1;
}
+ p->log = new_a1log_d(log);
+
/* Establish communications */
if ((rv = p->init_coms(p, br, fc, 15.0)) != inst_ok) {
a1logd(p->log, 1, "init_coms returned '%s' (%s)\n",
@@ -234,6 +242,9 @@ a1log *log /* Verb, debug & error log */
return -1;
}
+// ~~~~9999 should we call config_inst_displ(p) instead of badly duplicating
+// the instrument setup here ???
+
itype = p->get_itype(p); /* Actual type */
p->capabilities(p, &cap, &cap2, &cap3);
@@ -243,6 +254,12 @@ a1log *log /* Verb, debug & error log */
tele = 0;
}
+ if (!tele && !IMODETST(cap, inst_mode_emis_spot)) {
+ printf("Want emissive spot measurement capability but instrument doesn't support it\n");
+ printf("so switching to telephoto spot mode.\n");
+ tele = 1;
+ }
+
/* Set to emission mode to read a display */
if (tele)
mode = inst_mode_emis_tele;
@@ -251,6 +268,9 @@ a1log *log /* Verb, debug & error log */
if (nadaptive)
mode |= inst_mode_emis_nonadaptive;
+// if (p->highres)
+// mode |= inst_mode_highres;
+
/* (We're assuming spectral doesn't affect calibration ?) */
if ((rv = p->set_mode(p, mode)) != inst_ok) {
@@ -308,13 +328,21 @@ a1log *log /* Verb, debug & error log */
return 0;
}
+/* Set color to black after 50msec delay */
+int del_set_black(void *cx) {
+ disprd *p = (disprd *)cx;
+ int rv;
+
+ msec_sleep(100);
+ if ((rv = p->dw->set_color(p->dw, 0.0, 0.0, 0.0)) != 0) {
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
+ return 3;
+ }
+ return 0;
+}
+
/* Take a series of readings from the display - implementation */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_read_imp(
disprd *p,
@@ -350,19 +378,20 @@ static int disprd_read_imp(
/* See if we should calibrate the display update */
if (!p->update_delay_set && (cap2 & inst2_meas_disp_update) != 0) {
int cdelay, mdelay;
+ athread *th;
/* Set white with a normal delay */
if ((rv = p->dw->set_color(p->dw, 1.0, 1.0, 1.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
- /* Set a zero delay */
+ /* Set a zero return delay */
cdelay = p->dw->set_update_delay(p->dw, 0);
- /* Set black with zero delay */
- if ((rv = p->dw->set_color(p->dw, 0.0, 0.0, 0.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ /* Set black 50msec after this call */
+ if ((th = new_athread(del_set_black, (void *)p)) == NULL) {
+ a1logd(p->log,1,"failed to create thread to set_color()\n");
return 3;
}
@@ -372,24 +401,29 @@ static int disprd_read_imp(
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
p->dw->set_update_delay(p->dw, cdelay); /* Restore the default */
} else {
+ mdelay -= 100; /* Correct for delay on set black */
+ if (mdelay < 0)
+ mdelay = 0;
a1logv(p->log, 1, "Measured display update delay of %d msec",mdelay);
- mdelay += mdelay/2 + 50;
+ mdelay += mdelay/2 + 100;
p->dw->set_update_delay(p->dw, mdelay);
a1logv(p->log, 1, ", using delay of %d msec\n",mdelay);
}
p->update_delay_set = 1;
+ th->del(th);
}
/* See if we should do a frequency calibration or display integration time cal. first */
if (p->it->needs_calibration(p->it) & inst_calt_ref_freq
&& npat > 0
- && (cols[0].r != 1.0 || cols[0].g != 1.0 || cols[0].b != 1.0)) {
+ && (cols[0].r != 0.8 || cols[0].g != 0.8 || cols[0].b != 0.8)) {
col tc;
inst_cal_type calt = inst_calt_ref_freq;
- inst_cal_cond calc = inst_calc_emis_white;
+ inst_cal_cond calc = inst_calc_emis_80pc;
- if ((rv = p->dw->set_color(p->dw, 1.0, 1.0, 1.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ /* Hmm. Should really ask the instrument what sort of calc it needs !!! */
+ if ((rv = p->dw->set_color(p->dw, 0.8, 0.8, 0.8)) != 0) {
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
/* Do calibrate, but ignore return code. Press on regardless. */
@@ -406,7 +440,7 @@ static int disprd_read_imp(
inst_cal_cond calc = inst_calc_emis_white;
if ((rv = p->dw->set_color(p->dw, 1.0, 1.0, 1.0)) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
/* Do calibrate, but ignore return code. Press on regardless. */
@@ -425,8 +459,11 @@ static int disprd_read_imp(
scb->sp.spec_n = 0;
scb->duration = 0.0;
- if (spat != 0 && tpat != 0)
+ if (spat != 0 && tpat != 0) {
a1logv(p->log, 1, "%cpatch %d of %d",cr_char,spat + (noinc != 0 ? 0 : patch),tpat);
+ if (p->dw->set_pinfo != NULL)
+ p->dw->set_pinfo(p->dw, spat + (noinc != 0 ? 0 : patch),tpat);
+ }
a1logd(p->log,1,"About to read patch %d\n",patch);
rgb[0] = scb->r;
@@ -434,7 +471,8 @@ static int disprd_read_imp(
rgb[2] = scb->b;
/* If we are doing a soft cal, apply it to the test color */
- if (p->softcal && p->cal[0][0] >= 0.0) {
+ /* (dispwin will apply any tvenc needed) */
+ if ((p->native & 1) && p->cal[0][0] >= 0.0) {
int j;
double inputEnt_1 = (double)(p->ncal-1);
@@ -456,7 +494,7 @@ static int disprd_read_imp(
}
}
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
@@ -599,12 +637,7 @@ typedef struct {
} dsamples;
/* Take a series of readings from the display - drift compensation */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_read_drift(
disprd *p,
@@ -627,7 +660,7 @@ static int disprd_read_drift(
if (p->bdrift == 0) { /* Must be just wdrift */
boff = eoff = 1;
dno = 1;
- } else if (p->bdrift == 0) { /* Must be just bdrift */
+ } else if (p->wdrift == 0) { /* Must be just bdrift */
boff = eoff = 0;
dno = 1;
} else { /* Must be both */
@@ -979,12 +1012,7 @@ static void disprd_change_drift_comp(disprd *p,
}
/* Take a series of readings from the display */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_read(
disprd *p,
@@ -1035,12 +1063,7 @@ static void disprd_get_disptype(disprd *p, int *refrmode, int *cbid) {
static int config_inst_displ(disprd *p);
/* Take an ambient reading if the instrument has the capability. */
-/* return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
-/* 8 = no ambient capability */
+/* return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
int disprd_ambient(
struct _disprd *p,
@@ -1246,12 +1269,7 @@ int disprd_ambient(
/* Test without a spectrometer using a fake device */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_fake_read(
disprd *p,
@@ -1301,9 +1319,9 @@ static int disprd_fake_read(
ooff[0] = ooff[1] = ooff[2] = 0.0; /* Output offset */
#else
/* Input offset, equivalent to RGB offsets having various values */
- doff[0] = 0.10;
+ doff[0] = 0.05;
doff[1] = 0.06;
- doff[2] = 0.08;
+ doff[2] = 0.07;
/* Output offset - equivalent to flare [range 0.0 - 1.0] */
ooff[0] = 0.03;
ooff[1] = 0.04;
@@ -1313,6 +1331,8 @@ static int disprd_fake_read(
if (icmRGBprim2matrix(white, red, green, blue, mat))
error("Fake read unexpectedly got singular matrix\n");
+ icmTranspose3x3(mat, mat); /* Convert [RGB][XYZ] to [XYZ][RGB] */
+
icmSetUnity3x3(xmat);
if (p->fake2 == 1) {
@@ -1390,14 +1410,14 @@ static int disprd_fake_read(
/* If we have a test window, display the patch color */
if (p->dw) {
inst_code rv;
- if (p->softcal) { /* Display value with calibration */
+ if (p->native & 1) { /* Apply soft calibration to display value */
if ((rv = p->dw->set_color(p->dw, crgb[0], crgb[1], crgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
} else { /* Hardware will apply calibration */
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
}
@@ -1461,12 +1481,7 @@ static int disprd_fake_read(
}
/* Test without a spectrometer using a fake ICC profile device */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see dispsup.h */
/* Use disprd_err() to interpret it */
static int disprd_fake_read_lu(
disprd *p,
@@ -1533,7 +1548,7 @@ static int disprd_fake_read_lu(
if (p->dw) {
inst_code rv;
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
}
@@ -1581,12 +1596,7 @@ static int disprd_fake_read_lu(
}
/* Use without a direct connect spectrometer using shell callout */
-/* Return nz on fail/abort */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 3 = window access failed */
-/* 4 = user hit terminate key */
-/* 5 = system error */
+/* Return nz on fail/abort - see duspsup.h */
/* Use disprd_err() to interpret it */
static int disprd_fake_read_co(disprd *p,
col *cols, /* Array of patch colors to be tested */
@@ -1655,7 +1665,7 @@ static int disprd_fake_read_co(disprd *p,
if (p->dw) {
inst_code rv;
if ((rv = p->dw->set_color(p->dw, rgb[0], rgb[1], rgb[2])) != 0) {
- a1logd(p->log,1,"set_color() returned %s\n",rv);
+ a1logd(p->log,1,"set_color() returned %d\n",rv);
return 3;
}
}
@@ -1726,7 +1736,7 @@ char *disprd_err(int en) {
case 2:
return "Instrument Access Failed";
case 22:
- return "Instrument Access Failed (No PLD Pattern - have you run spyd2en ?)";
+ return "Instrument Access Failed (No PLD Pattern - have you run oeminst ?)";
case 3:
return "Window Access Failed";
case 4:
@@ -1746,7 +1756,15 @@ char *disprd_err(int en) {
case 11:
return "Instrument has no CCSS capability";
case 12:
- return "Internal: trying to set calibration when not using calibration";
+ return "Video encoding requested using nonlinear current calibration curves";
+ case 13:
+ return "Video encoding requested for MadVR display - use MadVR to set video encoding";
+ case 14:
+ return "Instrument has no set refresh rate capability";
+ case 15:
+ return "Unknown calibration display type selection";
+ case 16:
+ return "Must use BASE calibration display type selection";
}
return "Unknown";
}
@@ -1782,8 +1800,6 @@ static void disprd_del(disprd *p) {
if (p->it != NULL)
p->it->del(p->it);
if (p->dw != NULL) {
- if (p->or != NULL)
- p->dw->set_ramdac(p->dw,p->or, 0);
p->dw->del(p->dw);
}
if (p->sp2cie != NULL)
@@ -1811,6 +1827,12 @@ static int config_inst_displ(disprd *p) {
p->tele = 0;
}
+ if (!p->tele && !IMODETST(cap, inst_mode_emis_spot)) {
+ printf("Want emissive spot measurement capability but instrument doesn't support it\n");
+ printf("so switching to telephoto spot mode.\n");
+ p->tele = 1;
+ }
+
if (( p->tele && !IMODETST(cap, inst_mode_emis_tele))
|| (!p->tele && !IMODETST(cap, inst_mode_emis_spot))) {
printf("Need %s emissive measurement capability,\n", p->tele ? "telephoto" : "spot");
@@ -1866,18 +1888,19 @@ static int config_inst_displ(disprd *p) {
}
/* Set the display type */
-
if (p->dtype != 0) {
if (cap2 & inst2_disptype) {
int ix;
if ((ix = inst_get_disptype_index(p->it, p->dtype, p->docbid)) < 0) {
a1logd(p->log,1,"Display type selection '%c' is not valid for instrument\n",p->dtype);
- return 2;
+ if (p->docbid)
+ return 16;
+ return 15;
}
if ((rv = p->it->set_disptype(p->it, ix)) != inst_ok) {
- a1logd(p->log,1,"Setting display type failed failed with '%s' (%s)\n",
+ a1logd(p->log,1,"Setting display type failed with '%s' (%s)\n",
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
- return 2;
+ return 15;
}
} else
printf("Display type ignored - instrument doesn't support display type\n");
@@ -1899,12 +1922,7 @@ static int config_inst_displ(disprd *p) {
if (p->highres) {
if (IMODETST(cap, inst_mode_highres)) {
- inst_code ev;
- if ((ev = p->it->get_set_opt(p->it, inst_opt_highres)) != inst_ok) {
- a1logd(p->log,1,"\nSetting high res mode failed with error :'%s' (%s)\n",
- p->it->inst_interp_error(p->it, ev), p->it->interp_error(p->it, ev));
- return 2;
- }
+ mode |= inst_mode_highres;
} else {
a1logv(p->log, 1, "high resolution ignored - instrument doesn't support high res. mode\n");
}
@@ -1928,19 +1946,29 @@ static int config_inst_displ(disprd *p) {
}
}
- if (p->sets != NULL
- || ((cap2 & inst2_ccss) != 0 && p->obType != icxOT_default)) {
+ /* Observer */
+ if ((cap2 & inst2_ccss) != 0 && p->obType != icxOT_default) {
if ((cap2 & inst2_ccss) == 0) {
- a1logd(p->log,1,"Instrument doesn't support ccss calibration\n");
+ a1logd(p->log,1,"Instrument doesn't support ccss calibration and we need it\n");
return 11;
}
if ((rv = p->it->get_set_opt(p->it, inst_opt_set_ccss_obs, p->obType, p->custObserver))
- != inst_ok) {
+ != inst_ok) {
a1logd(p->log,1,"inst_opt_set_ccss_obs returned '%s' (%s)\n",
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
return 2;
}
+ }
+
+ /* Custom CCSS */
+ if (p->sets != NULL) {
+
+ if ((cap2 & inst2_ccss) == 0) {
+ a1logd(p->log,1,"Instrument doesn't support ccss calibration and we need it\n");
+ return 11;
+ }
+
if ((rv = p->it->col_cal_spec_set(p->it, p->sets, p->no_sets)) != inst_ok) {
a1logd(p->log,1,"col_cal_spec_set returned '%s' (%s)\n",
p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
@@ -1948,6 +1976,19 @@ static int config_inst_displ(disprd *p) {
}
}
+ if (p->refrate > 0.0) {
+ if (!(cap2 & inst2_set_refresh_rate)) {
+ a1logd(p->log,1,"Instrument doesn't support setting refresh rate\n");
+ return 11;
+ } else {
+ if ((rv = p->it->set_refr_rate(p->it, p->refrate)) != inst_ok) {
+ a1logd(p->log,1,"set_refr_rate %f Hz returned '%s' (%s)\n",
+ p->refrate, p->it->inst_interp_error(p->it, rv), p->it->interp_error(p->it, rv));
+ return 2;
+ }
+ }
+ }
+
/* Set the trigger mode to program triggered */
if ((rv = p->it->get_set_opt(p->it,inst_opt_trig_prog)) != inst_ok) {
a1logd(p->log,1,"Setting program trigger mode failed failed with '%s' (%s)\n",
@@ -1964,20 +2005,7 @@ static int config_inst_displ(disprd *p) {
/* Create a display reading object. */
/* Return NULL if error */
-/* Set *errc to code: */
-/* 0 = no error */
-/* 1 = user aborted */
-/* 2 = instrument access failed */
-/* 22 = instrument access failed - no PLD pattern */
-/* 3 = window access failed */
-/* 4 = RAMDAC access failed */
-/* 5 = user hit terminate key */
-/* 6 = system error */
-/* 7 = CRT or LCD must be selected */
-/* 9 = spectral conversion failed */
-/* 10 = no ccmx support */
-/* 11 = no ccss support */
-/* 12 = cal to set but native != 0 */
+/* Set *errc to code. See dispsup.h */
/* Use disprd_err() to interpret *errc */
disprd *new_disprd(
int *errc, /* Error code. May be NULL (could use log for this instead?) */
@@ -1988,18 +2016,25 @@ int docbid, /* NZ to only allow cbid dtypes */
int tele, /* NZ for tele mode. Falls back to display mode */
int nadaptive, /* NZ for non-adaptive mode */
int noinitcal, /* No initial instrument calibration */
+int noinitplace, /* Don't wait for user to place instrument on screen */
int highres, /* Use high res mode if available */
-int native, /* 0 = use current current or given calibration curve */
- /* 1 = use native linear out & high precision */
-int *noramdac, /* Return nz if no ramdac access. native is set to 0 */
-double cal[3][MAX_CAL_ENT], /* Calibration set/return (cal[0][0] < 0.0 or NULL if not used) */
- /* native must be 0 if cal is set */
+double refrate, /* If != 0.0, set display refresh rate calibration */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+double cal[3][MAX_CAL_ENT], /* Calibration (cal == NULL or cal[0][0] < 0.0 if not valid) */
int ncal, /* Number of cal[] entries */
-int softcal, /* NZ if apply cal to readings rather than hardware */
disppath *disp, /* Display to calibrate. NULL if fake and no dispwin */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* Override_redirect on X11 */
int webdisp, /* If nz, port number for web color display */
+#ifdef NT
+int madvrdisp, /* NZ for MadVR display */
+#endif
char *ccallout, /* Shell callout on set color */
char *mcallout, /* Shell callout on measure color (forced fake) */
double hpatsize, /* Size of dispwin */
@@ -2020,14 +2055,10 @@ a1log *log /* Verb, debug & error log */
disprd *p = NULL;
int ch;
inst_code rv;
+ int uout_tvenc = out_tvenc; /* tvenc to use with dispwin value setting */
if (errc != NULL) *errc = 0; /* default return code = no error */
- if (cal != NULL && cal[0][0] >= 0.0 && native != 0) {
- if (errc != NULL) *errc = 12;
- return NULL;
- }
-
/* Allocate a disprd */
if ((p = (disprd *)calloc(sizeof(disprd), 1)) == NULL) {
a1logd(log, 1, "new_disprd failed due to malloc failure\n");
@@ -2058,7 +2089,9 @@ a1log *log /* Verb, debug & error log */
p->tele = tele;
p->nadaptive = nadaptive;
p->noinitcal = noinitcal;
+ p->noinitplace = noinitplace;
p->highres = highres;
+ p->refrate = refrate;
if (mcallout != NULL)
ipath = &icomFakeDevice; /* Force fake device */
p->mcallout = mcallout;
@@ -2066,7 +2099,16 @@ a1log *log /* Verb, debug & error log */
p->br = baud_19200;
p->fc = fc;
- /* Save this in case we are using a fake device */
+ p->native = native;
+
+#ifdef FAKE_NOISE
+# ifdef FAKE_UNPREDIC
+ rand32(time(NULL));
+# endif
+#endif
+
+ /* Save this so we can return current cal, or */
+ /* in case we are using a fake device */
if (cal != NULL && cal[0][0] >= 0.0) {
int j, i;
for (j = 0; j < 3; j++) {
@@ -2075,11 +2117,9 @@ a1log *log /* Verb, debug & error log */
}
}
p->ncal = ncal;
- p->softcal = softcal;
} else {
p->cal[0][0] = -1.0;
p->ncal = 0;
- p->softcal = 0;
}
/* If non-real instrument */
@@ -2179,28 +2219,103 @@ a1log *log /* Verb, debug & error log */
if (webdisp != 0) {
/* Open web display */
- if ((p->dw = new_webwin(webdisp, hpatsize, vpatsize, ho, vo, 0, 0,
- p->log->verb, p->log->debug)) == NULL) {
+ if ((p->dw = new_webwin(webdisp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm,
+ uout_tvenc, 0, p->log->verb, p->log->debug)) == NULL) {
a1logd(log,1,"new_disprd failed because new_webwin failed\n");
p->del(p);
if (errc != NULL) *errc = 3;
return NULL;
}
- if (noramdac != NULL)
- *noramdac = 1;
+#ifdef NT
+ } else if (madvrdisp != 0) {
+ if (out_tvenc) {
+ a1logd(log,1,"new_disprd failed because tv_enc & MadVR window\n");
+ p->del(p);
+ if (errc != NULL) *errc = 13;
+ return NULL;
+ }
+
+ if ((p->dw = new_madvrwin(hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm, out_tvenc,
+ blackbg, p->log->verb, p->log->debug)) == NULL) {
+ a1logd(log,1,"new_disprd failed because new_madvrwin failed\n");
+ p->del(p);
+ if (errc != NULL) *errc = 3;
+ return NULL;
+ }
+#endif
} else {
+ /* Don't do tvenc on test values if we are going to do it with RAMDAC curve */
+ if (out_tvenc && (p->native & 1) == 0 && p->cal[0][0] >= 0.0) {
+ uout_tvenc = 0;
+ }
+
/* Open display window for positioning (no blackbg) */
- if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, 0,
- override, p->log->debug)) == NULL) {
+ if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm,
+ uout_tvenc, 0, override, p->log->debug)) == NULL) {
a1logd(log,1,"new_disprd failed because new_dispwin failed\n");
p->del(p);
if (errc != NULL) *errc = 3;
return NULL;
}
+
+ /* If TV encoding using existing RAMDAC and it is not linear, */
+ /* error out, as TV encoding probably won't work properly. */
+ if (out_tvenc && (native & 1) == 0 && p->cal[0][0] < 0.0) {
+ ramdac *cr;
+ if ((cr = p->dw->get_ramdac(p->dw)) != NULL) {
+ int i, j;
+ for (i = 0; i < cr->nent; i++) {
+ double val = i/(cr->nent-1.0);
+ for (j = 0; j < 3; j++) {
+ if (fabs(val - cr->v[j][i]) > 1e-5)
+ break;
+ }
+ if (j < 3)
+ break;
+ }
+ if (i < cr->nent) {
+ a1logd(log,1,"new_disprd failed because tvenc and nonlinear RAMDAC");
+ cr->del(cr);
+ p->del(p);
+ if (errc != NULL) *errc = 12;
+ return NULL;
+ }
+ cr->del(cr);
+ }
+ }
+
+#ifdef NEVER // Don't do this - dispread doesn't save calibration when using existing.
+ /* If using exiting RAMDAC, return it */
+ if ((native & 1) == 0 && p->cal[0][0] < 0.0 && cal != NULL) {
+ ramdac *r;
+
+ if ((r = p->dw->get_ramdac(p->dw)) != NULL) {
+ int j, i;
+
+ /* Get the ramdac contents. */
+ /* We linearly interpolate from RAMDAC[nent] to cal[ncal] resolution */
+ for (i = 0; i < ncal; i++) {
+ double val, w;
+ unsigned int ix;
+
+ val = (r->nent-1.0) * i/(ncal-1.0);
+ ix = (unsigned int)floor(val); /* Coordinate */
+ if (ix > (r->nent-2))
+ ix = (r->nent-2);
+ w = val - (double)ix; /* weight */
+ for (j = 0; j < 3; j++) {
+ val = r->v[j][ix];
+ cal[j][i] = val + w * (r->v[j][ix+1] - val);
+ }
+ }
+ r->del(r);
+ }
+ }
+#endif
}
if (p->it != NULL) {
- /* Do a calibration up front, so as not to get in the users way, */
+ /* Do an instrument calibration up front, so as not to get in the users way, */
/* but ignore a CRT frequency or display integration calibration, */
/* since these will be done automatically. */
if (p->it->needs_calibration(p->it) & inst_calt_n_dfrble_mask) {
@@ -2223,30 +2338,50 @@ a1log *log /* Verb, debug & error log */
}
}
- /* Ask user to put instrument on screen */
- empty_con_chars();
- printf("Place instrument on test window.\n");
- printf("Hit Esc or Q to give up, any other key to continue:"); fflush(stdout);
- if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
+ if (!p->noinitplace) {
+ inst2_capability cap2;
+
+ p->it->capabilities(p->it, NULL, &cap2, NULL);
+
+ /* Turn target on */
+ if (cap2 & inst2_has_target)
+ p->it->get_set_opt(p->it, inst_opt_set_target_state, 1);
+
+ /* Ask user to put instrument on screen */
+ empty_con_chars();
+
+ printf("Place instrument on test window.\n");
+ printf("Hit Esc or Q to give up, any other key to continue:"); fflush(stdout);
+ if ((ch = next_con_char()) == 0x1b || ch == 0x3 || ch == 'q' || ch == 'Q') {
+ printf("\n");
+ a1logd(log,1,"new_disprd failed because user aborted when placing device\n");
+ if (cap2 & inst2_has_target) /* Turn target off */
+ p->it->get_set_opt(p->it, inst_opt_set_target_state, 0);
+ p->del(p);
+ if (errc != NULL) *errc = 1;
+ return NULL;
+ }
+
+ /* Turn target off */
+ if (cap2 & inst2_has_target)
+ p->it->get_set_opt(p->it, inst_opt_set_target_state, 0);
+
printf("\n");
- a1logd(log,1,"new_disprd failed because user aborted when placing device\n");
- p->del(p);
- if (errc != NULL) *errc = 1;
- return NULL;
}
- printf("\n");
- if (webdisp == 0) {
+ if (webdisp == 0
+#ifdef NT
+ && madvrdisp == 0
+#endif
+ ) {
/* Close the positioning window */
if (p->dw != NULL) {
- if (p->or != NULL)
- p->dw->set_ramdac(p->dw,p->or, 0);
p->dw->del(p->dw);
}
/* Open display window again for measurement */
- if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, blackbg,
- override, p->log->debug)) == NULL) {
+ if ((p->dw = new_dispwin(disp, hpatsize, vpatsize, ho, vo, 0, native, noramdac, nocm,
+ uout_tvenc, blackbg, override, p->log->debug)) == NULL) {
a1logd(log,1,"new_disprd failed new_dispwin failed\n");
p->del(p);
if (errc != NULL) *errc = 3;
@@ -2259,84 +2394,57 @@ a1log *log /* Verb, debug & error log */
p->dw->set_callout(p->dw, ccallout);
}
- /* If we have a calibration to set */
+ /* If we have a calibration to set using the RAMDAC */
/* (This is only typically the case for disread) */
- if (!p->softcal && cal != NULL && cal[0][0] >= 0.0) {
+ if ((p->native & 1) == 0 && p->cal[0][0] >= 0.0) {
/* Save current RAMDAC so that we can restore it */
- p->or = NULL;
- if ((p->or = p->dw->get_ramdac(p->dw)) == NULL) {
+ if (p->dw->r == NULL) {
warning("Unable to read or set display RAMDAC - switching to softcal");
- p->softcal = softcal = 1;
- }
+ p->native |= 1;
/* Set the given RAMDAC so we can characterise through it */
- if (p->or != NULL) {
- ramdac *r;
+ } else {
int j, i;
- r = p->or->clone(p->or);
-
/* Set the ramdac contents. */
/* We linearly interpolate from cal[ncal] to RAMDAC[nent] resolution */
- for (i = 0; i < r->nent; i++) {
+ for (i = 0; i < p->dw->r->nent; i++) {
double val, w;
unsigned int ix;
- val = (ncal-1.0) * i/(r->nent-1.0);
+ val = (ncal-1.0) * i/(p->dw->r->nent-1.0);
ix = (unsigned int)floor(val); /* Coordinate */
if (ix > (ncal-2))
ix = (ncal-2);
w = val - (double)ix; /* weight */
for (j = 0; j < 3; j++) {
- val = cal[j][ix];
- r->v[j][i] = val + w * (cal[j][ix+1] - val);
+ val = p->cal[j][ix];
+ p->dw->r->v[j][i] = val + w * (p->cal[j][ix+1] - val);
+ /* Implement tvenc here rather than dispwin, so that the order is correct */
+ if (out_tvenc) {
+ p->dw->r->v[j][i] = ((235.0 - 16.0) * p->dw->r->v[j][i] + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit */
+ /* shifting rather than scaling, so we need to scale the fp value to */
+ /* account for this. */
+ if (p->dw->edepth > 8)
+ p->dw->r->v[j][i] =
+ (p->dw->r->v[j][i] * 255 * (1 << (p->dw->edepth - 8)))
+ /((1 << p->dw->edepth) - 1.0);
+ }
}
}
- if (p->dw->set_ramdac(p->dw, r, 0)) {
+ if (p->dw->set_ramdac(p->dw, p->dw->r, 0)) {
a1logd(log,1,"new_disprd failed becayse set_ramdac failed\n");
a1logv(p->log, 1, "Failed to set RAMDAC to desired calibration.\n");
a1logv(p->log, 1, "Perhaps the operating system is being fussy ?\n");
- r->del(r);
- p->del(p);
if (errc != NULL) *errc = 4;
return NULL;
}
- r->del(r);
}
}
- /* Return the ramdac being used */
- if (p->or != NULL && cal != NULL) {
- ramdac *r;
- int j, i;
-
- if ((r = p->dw->get_ramdac(p->dw)) == NULL) {
- a1logd(log,1,"new_disprd failed becayse get_ramdac failed\n");
- a1logv(p->log, 1, "Failed to read current RAMDAC\n");
- p->del(p);
- if (errc != NULL) *errc = 4;
- return NULL;
- }
- /* Get the ramdac contents. */
- /* We linearly interpolate from RAMDAC[nent] to cal[ncal] resolution */
- for (i = 0; i < ncal; i++) {
- double val, w;
- unsigned int ix;
-
- val = (r->nent-1.0) * i/(ncal-1.0);
- ix = (unsigned int)floor(val); /* Coordinate */
- if (ix > (r->nent-2))
- ix = (r->nent-2);
- w = val - (double)ix; /* weight */
- for (j = 0; j < 3; j++) {
- val = r->v[j][ix];
- cal[j][i] = val + w * (r->v[j][ix+1] - val);
- }
- }
- r->del(r);
- }
-
a1logd(log,1,"new_disprd succeeded\n");
return p;
}
diff --git a/spectro/dispsup.h b/spectro/dispsup.h
index 837e16a..1d291af 100644
--- a/spectro/dispsup.h
+++ b/spectro/dispsup.h
@@ -18,7 +18,11 @@
/* A helper function to handle presenting a display test patch */
struct _disp_win_info {
int webdisp; /* nz if web display is to be used */
+#ifdef NT
+ int madvrdisp; /* NZ for MadVR display */
+#endif
disppath *disp; /* display to calibrate. */
+ int out_tvenc; /* 1 = use RGB Video Level encoding */
int blackbg; /* NZ if whole screen should be filled with black */
int override; /* Override_redirect on X11 */
double hpatsize; /* Size of dispwin */
@@ -49,6 +53,10 @@ int nadaptive, /* NZ for non-adaptive mode */
int noinitcal, /* NZ to disable initial instrument calibration */
disppath *screen, /* Screen to calibrate. */
int webdisp, /* If nz, port number for web display */
+#ifdef NT
+int madvrdisp, /* NZ for MadVR display */
+#endif
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* Override_redirect on X11 */
double hpatsize, /* Size of dispwin */
@@ -91,9 +99,12 @@ struct _disprd {
char *fake_name; /* Fake profile name */
icmFile *fake_fp;
icc *fake_icc; /* NZ if ICC profile is being used for fake */
+ int native; /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
double cal[3][MAX_CAL_ENT]; /* Calibration being worked through (cal[0][0] < 0.0 or NULL if not used) */
int ncal; /* Number of entries used in cal[] */
- int softcal; /* NZ if apply cal to readings rather than hardware */
icmLuBase *fake_lu;
char *mcallout; /* fake instrument shell callout */
icompath *ipath; /* Instrument path to open, &icomFakeDevice == fake */
@@ -107,6 +118,7 @@ struct _disprd {
int tele; /* NZ for tele mode */
int nadaptive; /* NZ for non-adaptive mode */
int highres; /* Use high res mode if available */
+ double refrate; /* If != 0.0, set display refresh rate calibration */
int update_delay_set; /* NZ if we've calibrated the disp. update delay, or tried and failed */
double (*ccmtx)[3]; /* Colorimeter Correction Matrix, NULL if none */
icxObserverType obType; /* CCSS Observer */
@@ -119,8 +131,8 @@ struct _disprd {
int bdrift; /* Flag, nz for black drift compensation */
int wdrift; /* Flag, nz for white drift compensation */
int noinitcal; /* No initial instrument calibration */
+ int noinitplace; /* Don't wait for user to place instrument on screen */
dispwin *dw; /* Window */
- ramdac *or; /* Original ramdac if we set one */
int serno; /* Reading serial number */
col ref_bw[2]; /* Reference black and white readings for drift comp. */
@@ -199,7 +211,11 @@ struct _disprd {
/* 9 = spectral conversion failed */
/* 10 = no ccmx support */
/* 11 = no ccss support */
-/* 12 = cal to set but native != 0 */
+/* 12 = out_tvenc & native = 0 && no cal but current RAMDAC is not linear */
+/* 13 = out_tvenc for MadVR window */
+/* 14 = no set refresh rate support */
+/* 15 = unknown calibration/display type */
+/* 16 = non based calibration/display type */
/* Use disprd_err() to interpret errc */
disprd *new_disprd(
int *errc, /* Error code. May be NULL */
@@ -210,18 +226,25 @@ int docbid, /* NZ to only allow cbid dtypes */
int tele, /* NZ for tele mode */
int nadaptive, /* NZ for non-adaptive mode */
int noinitcal, /* No initial instrument calibration */
+int noinitplace, /* Don't wait for user to place instrument on screen */
int highres, /* Use high res mode if available */
-int native, /* 0 = use current current or given calibration curve */
- /* 1 = use native linear out & high precision */
-int *noramdac, /* Return nz if no ramdac access. native is set to 0 */
-double cal[3][MAX_CAL_ENT], /* Calibration set/return (cal[0][0] < 0.0 if can't/not to be used) */
- /* native must be 0 if cal is set */
+double refrate, /* If != 0.0, set display refresh rate calibration */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+double cal[3][MAX_CAL_ENT], /* Calibration set (cal = NULL or cal[0][0] < 0.0 if not to be used) */
int ncal, /* number of entries use in cal */
-int softcal, /* NZ if apply cal to readings rather than hardware */
disppath *screen, /* Screen to calibrate. */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* Override_redirect on X11 */
int webdisp, /* If nz, port number for web display */
+#ifdef NT
+int madvrdisp, /* NZ for MadVR display */
+#endif
char *ccallout, /* Shell callout on set color */
char *mcallout, /* Shell callout on measure color (forced fake) */
double hpatsize, /* Size of dispwin */
diff --git a/spectro/dispwin.c b/spectro/dispwin.c
index 4a6acd6..74186cf 100644
--- a/spectro/dispwin.c
+++ b/spectro/dispwin.c
@@ -17,8 +17,6 @@
/* TTBD
*
- * Nice to have option to create non-square test window ?
- *
* Should probably check the display attributes (like visual depth)
* and complain if we aren't using 24 bit color or better.
*
@@ -30,6 +28,9 @@
*
* Is there a >8 bit way of getting/setting RAMDAC indexes ?
*
+ * Should add dithering support to overcome 8 bit limitations of
+ * non-RAMDAC access or limited RAMDAC depth. (How do we easily
+ * determine the latter ??)
*/
#include <stdio.h>
@@ -53,12 +54,34 @@
#include "conv.h"
#include "dispwin.h"
#include "webwin.h"
-#if defined(UNIX_X11) && defined(USE_UCMM)
-#include "ucmm.h"
+#ifdef NT
+# include "madvrwin.h"
+#endif
+#if defined(UNIX_X11)
+# include <dlfcn.h>
+# if defined(USE_UCMM)
+# include "ucmm.h"
+# endif
#endif
#ifdef __APPLE__
+/*
+ Note that the new ColorSync API is defined in
+ /System/Library/Frameworks/ApplicationServices.framework/Frameworks/ColorSync.framework/Headers
+
+ in
+ ColorSync.h
+ ColorSyncBase.h
+ ColorSyncCMM.h
+ ColorSyncDeprecated.h
+ ColorSyncDevice.h
+ ColorSyncProfile.h
+ ColorSyncTransform.h
+
+ and isn't documented by Apple anywhere else.
+ */
+
#include <Foundation/Foundation.h>
#include <AppKit/AppKit.h>
@@ -68,13 +91,23 @@
# endif
#ifndef CGFLOAT_DEFINED
-#ifdef __LP64__
+#ifdef __LP64__ || NS_BUILD_32_LIKE_64
typedef double CGFloat;
#else
typedef float CGFloat;
#endif /* defined(__LP64__) */
#endif /* !CGFLOAT_DEFINED */
+#ifndef NSINTEGER_DEFINED
+#if __LP64__ || NS_BUILD_32_LIKE_64
+ typedef long NSInteger;
+ typedef unsigned long NSUInteger;
+#else
+ typedef int NSInteger;
+ typedef unsigned int NSUInteger;
+#endif
+#endif /* !NSINTEGER_DEFINED */
+
#include <IOKit/Graphics/IOGraphicsLib.h>
#if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1060
@@ -572,10 +605,24 @@ disppath **get_displays() {
/* Go through all the screens */
for (i = 0; i < dcount; i++) {
+ static void *xrr_found = NULL; /* .so handle */
+ static XRRScreenResources *(*_XRRGetScreenResourcesCurrent)
+ (Display *dpy, Window window) = NULL;
XRRScreenResources *scrnres;
int jj; /* Screen index */
- if ((scrnres = XRRGetScreenResources(mydisplay, RootWindow(mydisplay,i))) == NULL) {
+ if (minv >= 3 && xrr_found == NULL) {
+ if ((xrr_found = dlopen("libXrandr.so", RTLD_LAZY)) != NULL)
+ _XRRGetScreenResourcesCurrent = dlsym(xrr_found, "XRRGetScreenResourcesCurrent");
+ }
+
+ if (minv >= 3 && _XRRGetScreenResourcesCurrent != NULL) {
+ scrnres = _XRRGetScreenResourcesCurrent(mydisplay, RootWindow(mydisplay,i));
+
+ } else {
+ scrnres = XRRGetScreenResources(mydisplay, RootWindow(mydisplay,i));
+ }
+ if (scrnres == NULL) {
debugrr("XRRGetScreenResources failed\n");
XCloseDisplay(mydisplay);
free_disppaths(disps);
@@ -1084,10 +1131,6 @@ void free_a_disppath(disppath *path) {
/* ----------------------------------------------- */
-static ramdac *dispwin_clone_ramdac(ramdac *r);
-static void dispwin_setlin_ramdac(ramdac *r);
-static void dispwin_del_ramdac(ramdac *r);
-
/* For VideoLUT/RAMDAC use, we assume that the number of entries in the RAMDAC */
/* meshes perfectly with the display raster depth, so that we can */
/* figure out how to apportion device values. We fail if they don't */
@@ -1122,9 +1165,9 @@ static ramdac *dispwin_get_ramdac(dispwin *p) {
}
r->pdepth = p->pdepth;
r->nent = (1 << p->pdepth);
- r->clone = dispwin_clone_ramdac;
+ r->clone = dispwin_clone_ramdac;
r->setlin = dispwin_setlin_ramdac;
- r->del = dispwin_del_ramdac;
+ r->del = dispwin_del_ramdac;
for (j = 0; j < 3; j++) {
@@ -1139,11 +1182,13 @@ static ramdac *dispwin_get_ramdac(dispwin *p) {
/* GetDeviceGammaRamp() is hard coded for 3 x 256 entries (Quantize) */
if (r->nent != 256) {
+ free(r);
debugr2((errout,"GetDeviceGammaRamp() is hard coded for nent == 256, and we've got nent = %d!\n",r->nent));
return NULL;
}
if (GetDeviceGammaRamp(p->hdc, vals) == 0) {
+ free(r);
debugr("dispwin_get_ramdac failed on GetDeviceGammaRamp()\n");
return NULL;
}
@@ -1171,7 +1216,7 @@ static ramdac *dispwin_get_ramdac(dispwin *p) {
}
if (nent != (1 << p->pdepth)) {
- debugr("CGGetDisplayTransferByTable number of entries mismatches screen depth\n");
+ debugr2((errout,"CGGetDisplayTransferByTable number of entries %d mismatches screen depth %d\n",nent,p->pdepth));
return NULL;
}
@@ -1183,9 +1228,9 @@ static ramdac *dispwin_get_ramdac(dispwin *p) {
r->pdepth = p->pdepth;
r->nent = (1 << p->pdepth);
- r->clone = dispwin_clone_ramdac;
+ r->clone = dispwin_clone_ramdac;
r->setlin = dispwin_setlin_ramdac;
- r->del = dispwin_del_ramdac;
+ r->del = dispwin_del_ramdac;
for (j = 0; j < 3; j++) {
if ((r->v[j] = (double *)calloc(sizeof(double), r->nent)) == NULL) {
@@ -1231,7 +1276,7 @@ static ramdac *dispwin_get_ramdac(dispwin *p) {
}
if (nent != (1 << p->pdepth)) {
- debugr2((errout,"XRRGetCrtcGammaSize number of entries %d mismatches screen depth %d\n",nent,(1 << p->pdepth)));
+ debugr2((errout,"XRRGetCrtcGammaSize number of entries %d mismatches screen depth %d bits\n",nent,(1 << p->pdepth)));
return NULL;
}
@@ -1292,7 +1337,7 @@ static ramdac *dispwin_get_ramdac(dispwin *p) {
}
if (nent != (1 << p->pdepth)) {
- debugr2((errout,"CGGetDisplayTransferByTable number of entries %d mismatches screen depth %d\n",nent,(1 << p->pdepth)));
+ debugr2((errout,"CGGetDisplayTransferByTable number of entries %d mismatches screen depth %d bits\n",nent,(1 << p->pdepth)));
return NULL;
}
}
@@ -1429,7 +1474,7 @@ typedef struct {
CFURLRef url; /* URL to return */
} diter_cntx_t;
-bool diter_callback(CFDictionaryRef dict, void *cntx) {
+static bool diter_callback(CFDictionaryRef dict, void *cntx) {
diter_cntx_t *cx = (diter_cntx_t *)cntx;
CFStringRef str;
CFUUIDRef uuid;
@@ -1475,7 +1520,7 @@ bool diter_callback(CFDictionaryRef dict, void *cntx) {
/* Return the url to the given displays current profile. */
/* Return NULL on error. CFRelease when done. */
/* Optionally return the ProfileID string */
-CFURLRef cur_profile_url(CFStringRef *idp, dispwin *p) {
+static CFURLRef cur_profile_url(CFStringRef *idp, dispwin *p) {
diter_cntx_t cx;
if ((cx.dispuuid = CGDisplayCreateUUIDFromDisplayID(p->ddid)) == NULL) {
@@ -1498,7 +1543,7 @@ CFURLRef cur_profile_url(CFStringRef *idp, dispwin *p) {
/* Convert a URL into a local POSIX path string */
/* Return NULL on error. Free returned string when done. */
-char *url_to_path(CFURLRef url) {
+static char *url_to_path(CFURLRef url) {
CFStringRef urlstr;
CFIndex bufSize;
char *dpath = NULL; /* return value */
@@ -1521,9 +1566,9 @@ char *url_to_path(CFURLRef url) {
return dpath;
}
-/* Return information about the given displays current profile */
+/* Return the local POSIX path to the given displays current profile */
/* Return NULL on error. Free returned string when done. */
-char *cur_profile(dispwin *p) {
+static char *cur_profile(dispwin *p) {
CFURLRef url;
char *dpath = NULL; /* return value */
@@ -1541,6 +1586,58 @@ char *cur_profile(dispwin *p) {
#endif /* >= 10.6 */
+/* Return a CMProfileRef/ColorSyncProfileRef for the */
+/* displays profile. Return NULL on error */
+static void *cur_colorsync_ref(dispwin *p) {
+ void *cspr = NULL;
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ CFURLRef url;
+ ColorSyncProfileRef ref;
+ CFErrorRef ev;
+
+ if ((url = cur_profile_url(NULL, p)) == NULL) {
+ debugr2((errout,"cur_colorsync_ref got NULL URL\n"));
+ return NULL;
+ }
+
+ if ((ref = ColorSyncProfileCreateWithURL(url, &ev)) == NULL) {
+ debugr2((errout,"ColorSyncProfileCreateWithURL failed\n"));
+ return NULL;
+ }
+ CFRelease(url);
+
+ cspr = (void *)ref;
+
+#else /* 10.5 and prior */
+ CMError ev;
+ CMDeviceProfileID curID; /* Current Device Default profile ID */
+ CMProfileLocation cploc; /* Current profile location */
+ CMProfileRef prof;
+
+ /* Get the default ID for the display */
+ if ((ev = CMGetDeviceDefaultProfileID(cmDisplayDeviceClass, (CMDeviceID)p->ddid, &curID)) != noErr) {
+ debugr2((errout,"CMGetDeviceDefaultProfileID() failed with error %d\n",ev));
+ return NULL;
+ }
+
+ /* Get the displays profile */
+ if ((ev = CMGetDeviceProfile(cmDisplayDeviceClass, (CMDeviceID)p->ddid, curID, &cploc)) != noErr) {
+ debugr2((errout,"CMGetDeviceDefaultProfileID() failed with error %d\n",ev));
+ return NULL;
+ }
+
+ if ((ev = CMOpenProfile(&prof, &cploc)) != noErr) {
+ debugr2((errout,"CMOpenProfile() failed with error %d\n",ev));
+ return NULL;
+ }
+ cspr = (void *)prof;
+
+#endif
+
+ return cspr;
+}
+
#endif /* __APPLE__ */
/* Set the RAMDAC values. */
@@ -1576,6 +1673,7 @@ static int dispwin_set_ramdac(dispwin *p, ramdac *r, int persist) {
debugr2((errout,"dispwin_set_ramdac failed on SetDeviceGammaRamp() with error %d\n",GetLastError()));
return 1;
}
+ GdiFlush();
#endif /* NT */
#ifdef __APPLE__
@@ -2071,13 +2169,14 @@ static int dispwin_set_ramdac(dispwin *p, ramdac *r, int persist) {
}
#endif /* UNXI X11 */
- debugr("XF86VidModeSetGammaRamp returning OK\n");
+ debugr("dispwin_set_ramdac returning OK\n");
+
return 0;
}
/* Clone ourselves */
-static ramdac *dispwin_clone_ramdac(ramdac *r) {
+ramdac *dispwin_clone_ramdac(ramdac *r) {
ramdac *nr;
int i, j;
@@ -2111,7 +2210,7 @@ static ramdac *dispwin_clone_ramdac(ramdac *r) {
}
/* Set the ramdac values to linear */
-static void dispwin_setlin_ramdac(ramdac *r) {
+void dispwin_setlin_ramdac(ramdac *r) {
int i, j;
debug("dispwin_setlin_ramdac called\n");
@@ -2125,7 +2224,7 @@ static void dispwin_setlin_ramdac(ramdac *r) {
}
/* We're done with a ramdac structure */
-static void dispwin_del_ramdac(ramdac *r) {
+void dispwin_del_ramdac(ramdac *r) {
int j;
debug("dispwin_del_ramdac called\n");
@@ -2138,7 +2237,7 @@ static void dispwin_del_ramdac(ramdac *r) {
}
/* ----------------------------------------------- */
-/* Useful function for X11 profie atom settings */
+/* Useful function for X11 profile atom settings */
#if defined(UNIX_X11)
/* Return NZ on error */
@@ -2216,6 +2315,50 @@ static int set_X11_atom(dispwin *p, char *fname) {
#endif /* UNXI X11 */
/* ----------------------------------------------- */
+/* See if colord is available */
+
+#if defined(UNIX_X11) && defined(USE_UCMM)
+
+/* colord libcolordcompat.so shim functions */
+
+ucmm_error (*cd_edid_install_profile)(unsigned char *edid, int edid_len,
+ ucmm_scope scope, char *profile_fn) = NULL;
+ucmm_error (*cd_edid_remove_profile)(unsigned char *edid, int edid_len, char *profile_fn) = NULL;
+ucmm_error (*cd_edid_get_profile)(unsigned char *edid, int edid_len, char **profile_fn) = NULL;
+int cd_init = 0; /* nz if we've looked for colord */
+void *cd_found = NULL; /* .so handle if we've found colord */
+
+/* Return nz if found colord functions */
+int dispwin_checkfor_colord() {
+
+ if (cd_init)
+ return (cd_found != NULL);
+
+ cd_found = NULL;
+
+ if ((cd_found = dlopen("libcolordcompat.so", RTLD_LAZY)) != NULL) {
+
+ cd_edid_install_profile = dlsym(cd_found, "cd_edid_install_profile");
+ cd_edid_remove_profile = dlsym(cd_found, "cd_edid_remove_profile");
+ cd_edid_get_profile = dlsym(cd_found, "cd_edid_get_profile");
+
+ if (cd_edid_install_profile == NULL
+ || cd_edid_remove_profile == NULL
+ || cd_edid_get_profile == NULL) {
+ cd_found = NULL;
+ }
+ }
+
+ cd_init = 1;
+
+ return (cd_found != NULL);
+}
+
+#endif
+
+
+
+/* ----------------------------------------------- */
/* Install a display profile and make */
/* it the default for this display. */
/* Set the display to the calibration in the profile */
@@ -2223,6 +2366,7 @@ static int set_X11_atom(dispwin *p, char *fname) {
/* (We assume that the caller has checked that it's an ICC profile) */
/* Return nz if failed */
int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
+ debugr2((errout,"dispwin_install_profile '%s'\n",fname));
#ifdef NT
{
char *fullpath;
@@ -2232,8 +2376,6 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
WCS_PROFILE_MANAGEMENT_SCOPE wcssc;
unsigned short *wpath, *wbname, *wmonid;
- debugr2((errout,"dispwin_install_profile got '%s'\n",fname));
-
if (GetColorDirectory(NULL, colpath, &colpathlen) == 0) {
debugr2((errout,"Getting color directory failed\n"));
return 1;
@@ -2555,7 +2697,12 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
else
sc = ucmm_user;
- if ((ev = ucmm_install_monitor_profile(sc, p->edid, p->edid_len, p->name, fname)) != ucmm_ok) {
+ if (cd_found)
+ ev = cd_edid_install_profile(p->edid, p->edid_len, sc, fname);
+ else
+ ev = ucmm_install_monitor_profile(sc, p->edid, p->edid_len, p->name, fname);
+
+ if (ev != ucmm_ok) {
debugr2((errout,"Installing profile '%s' failed with error %d '%s'\n",fname,ev,ucmm_error_string(ev)));
return 1;
}
@@ -2583,6 +2730,7 @@ int dispwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
/* 1 if not sucessfully deleted */
/* 2 if profile not found */
int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
+ debugr2((errout,"dispwin_uninstall_profile '%s'\n", fname));
#ifdef NT
{
char *fullpath;
@@ -2592,8 +2740,6 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
WCS_PROFILE_MANAGEMENT_SCOPE wcssc;
unsigned short *wbname, *wmonid;
- debugr2((errout,"Uninstalling '%s'\n", fname));
-
if (GetColorDirectory(NULL, colpath, &colpathlen) == 0) {
debugr2((errout,"Getting color directory failed\n"));
return 1;
@@ -2841,7 +2987,12 @@ int dispwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
else
sc = ucmm_user;
- if ((ev = ucmm_uninstall_monitor_profile(sc, p->edid, p->edid_len, p->name, fname)) != ucmm_ok) {
+ if (cd_found)
+ ev = cd_edid_remove_profile(p->edid, p->edid_len, fname);
+ else
+ ev = ucmm_uninstall_monitor_profile(sc, p->edid, p->edid_len, p->name, fname);
+
+ if (ev != ucmm_ok) {
debugr2((errout,"Installing profile '%s' failed with error %d '%s'\n",fname,ev,ucmm_error_string(ev)));
return 1;
}
@@ -3039,7 +3190,12 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) {
debugr2((errout,"dispwin_get_profile called\n"));
- if ((ev = ucmm_get_monitor_profile(p->edid, p->edid_len, p->name, &profile)) == ucmm_ok) {
+ if (cd_found)
+ ev = cd_edid_get_profile(p->edid, p->edid_len, &profile);
+ else
+ ev = ucmm_get_monitor_profile(p->edid, p->edid_len, p->name, &profile);
+
+ if (ev == ucmm_ok) {
if (name != NULL) {
strncpy(name, profile, mxlen);
@@ -3143,12 +3299,17 @@ icmFile *dispwin_get_profile(dispwin *p, char *name, int mxlen) {
/* ----------------------------------------------- */
-/* Restore the display state */
+/* Restore the display state and free ramdacs */
static void restore_display(dispwin *p) {
+ if (p->oor != NULL) {
+ p->oor->del(p->oor);
+ p->oor = NULL;
+ }
/* Restore the ramdac */
if (p->or != NULL) {
p->set_ramdac(p, p->or, 0);
+ p->set_ramdac(p, p->or, 0); /* Hmm. To be sure to be sure... */
p->or->del(p->or);
p->or = NULL;
debugr("Restored original ramdac\n");
@@ -3288,6 +3449,9 @@ typedef struct {
dispwin *p;
DWWin *window; /* Our NSWindow */
DWView *view; /* Our NSView */
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+ NSColorSpace *nscs; /* Colorspace from profile */
+#endif
} osx_cntx_t;
static void OSX_ProcessEvents(dispwin *p);
@@ -3316,9 +3480,10 @@ unsigned char emptyCursor[43] = {
/* Make cursor invisible over our window */
/*
* This doesn't work very well. The only way to work it properly
- * is to create a CGEventTap and do a hide/unkid cursor when
+ * is to create a CGEventTap and do a hide/unhide cursor when
* the mouse enters the window. This needs the main thread
- * to be dedicated to running the event loop.
+ * to be dedicated to running the event loop, so would involve
+ * some trickiness after main() in every program.
*/
- (void)resetCursorRects {
[super resetCursorRects];
@@ -3339,10 +3504,28 @@ unsigned char emptyCursor[43] = {
frect = NSMakeRect(p->tx, p->ty, (1.0 + p->tw), (1.0 + p->th));
- [[NSColor colorWithDeviceRed: p->r_rgb[0]
- green: p->r_rgb[1]
- blue: p->r_rgb[2]
- alpha: 1.0] setFill];
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+ /* Use matching profile to (hopefully) trigger null color transform */
+ /* This doesn't work on < 10.6 though. */
+ if (cx->nscs != NULL) {
+ CGFloat rgb[4];
+ NSInteger cnt = 4;
+ rgb[0] = p->r_rgb[0];
+ rgb[1] = p->r_rgb[1];
+ rgb[2] = p->r_rgb[2];
+ rgb[3] = 1.0;
+ cnt = [ cx->nscs numberOfColorComponents ] + 1;
+ [[NSColor colorWithColorSpace: cx->nscs components: rgb count: cnt] setFill];
+
+ /* This works for < 10.6, but not for >= 10.6 on non-primary display */
+ } else
+#endif
+ {
+ [[NSColor colorWithDeviceRed: p->r_rgb[0]
+ green: p->r_rgb[1]
+ blue: p->r_rgb[2]
+ alpha: 1.0] setFill];
+ }
[aPath appendBezierPathWithRect:frect];
[aPath fill];
}
@@ -3388,6 +3571,8 @@ unsigned char emptyCursor[43] = {
/* Create our window */
static void create_my_win(NSRect rect, osx_cntx_t *cx) {
dispwin *p = cx->p;
+ SInt32 MacVers;
+ void *cspr = NULL; /* ColorSync profile ref. */
int i;
/* We need to locate the NSScreen that corresponds to the */
@@ -3427,6 +3612,61 @@ static void create_my_win(NSRect rect, osx_cntx_t *cx) {
[cx->window setContentView: cx->view];
[cx->window makeKeyAndOrderFront: nil];
+
+ /* Use a null color transform to ensure device values */
+ /* on non-primary display for 10.6+ */
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+
+ /* Get the ColorSync profile for this display */
+ if ((cspr = cur_colorsync_ref(p)) == NULL) {
+ debugr2((errout,"cur_colorsync_ref failed\n"));
+
+ } else {
+
+#ifdef NEVER
+ /* This is buggy on 10.6 (returns gray space). it does work on 10.4-10.5 & 10.7+ */
+ cx->nscs = [[NSColorSpace alloc] initWithColorSyncProfile: cspr];
+#else
+ CGColorSpaceRef cgref;
+
+ /* This works on 10.6+ */
+ if ((cgref = CGColorSpaceCreateWithPlatformColorSpace(cspr)) == NULL) {
+ debugr2((errout,"CGColorSpaceCreateWithPlatformColorSpace failed\n"));
+ } else {
+ /* 10.4 doesn't declare initWithCGColorSpace, but does implement it */
+ cx->nscs = [[NSColorSpace alloc] initWithCGColorSpace: cgref];
+ }
+ CFRelease(cgref);
+#endif
+ if (cx->nscs == NULL) {
+ debugr2((errout,"initWithColorSyncProfile failed\n"));
+ } else {
+ if ([ cx->nscs numberOfColorComponents ] != 3) {
+ [cx->nscs release];
+ cx->nscs = NULL;
+ }
+ }
+
+ if (cspr != NULL) {
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ CFRelease((ColorSyncProfileRef)cspr);
+#else
+ CMCloseProfile((CMProfileRef)cspr);
+#endif
+ }
+ }
+#endif /* >= 10.6 */
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+ /* >= 10.6+ device colors don't work on secondary display, need null transform. */
+ /* < 10.6 null transform doesn't work. */
+ if (Gestalt(gestaltSystemVersion, &MacVers) == noErr
+ && MacVers >= 0x1060
+ && cx->nscs == NULL) {
+ warning("Unable to create null color transform - test colors may be wrong!");
+ }
+#endif
+
}
#endif /* __APPLE__ */
@@ -3440,40 +3680,70 @@ dispwin *p,
double r, double g, double b /* Color values 0.0 - 1.0 */
) {
int j;
+ double orgb[3]; /* Previous RGB value */
+ double kr, kf;
+ int update_delay = p->update_delay;
+ double xdelay = 0.0; /* Extra delay for response time */
debugr("dispwin_set_color called\n");
if (p->nowin)
return 1;
- p->rgb[0] = r;
- p->rgb[1] = g;
- p->rgb[2] = b;
+ orgb[0] = p->rgb[0]; p->rgb[0] = r;
+ orgb[1] = p->rgb[1]; p->rgb[1] = g;
+ orgb[2] = p->rgb[2]; p->rgb[2] = b;
+
+//printf("\n set rgb %f %f %f\n",p->rgb[0], p->rgb[1], p->rgb[2]);
for (j = 0; j < 3; j++) {
if (p->rgb[j] < 0.0)
p->rgb[j] = 0.0;
else if (p->rgb[j] > 1.0)
p->rgb[j] = 1.0;
- p->r_rgb[j] = p->rgb[j];
+ p->r_rgb[j] = p->s_rgb[j] = p->rgb[j];
+ if (p->out_tvenc) {
+ p->r_rgb[j] = p->s_rgb[j] = ((235.0 - 16.0) * p->s_rgb[j] + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit shifting */
+ /* rather than scaling, so we need to scale the fp value to account for this. */
+ if (p->pdepth > 8)
+ p->r_rgb[j] = (p->s_rgb[j] * 255 * (1 << (p->pdepth - 8)))
+ /((1 << p->pdepth) - 1.0);
+ }
}
+//if (p->out_tvenc) {
+//printf(" %d: 8 bit tv = s_rgb %f %f %f\n",j, p->s_rgb[0], p->s_rgb[1], p->s_rgb[2]);
+//printf(" %d: %d bitraster r_rgb %f %f %f\n",j, p->pdepth,p->r_rgb[0], p->r_rgb[1], p->r_rgb[2]);
+//}
+
/* Use ramdac for high precision native output. */
/* The ramdac is used to hold the lsb that the frame buffer */
/* doesn't hold. */
- if (p->native == 1) {
+ if ((p->native & 1) == 1) {
double prange = p->r->nent - 1.0;
+ p->r->setlin(p->r); /* In case something else altered this */
+
for (j = 0; j < 3; j++) {
int tt;
+ double vv;
-//printf("~1 %d: in %f, ",j,p->rgb[j]);
- tt = (int)(p->rgb[j] * prange);
- p->r->v[j][tt] = p->rgb[j];
+ vv = p->s_rgb[j];
+
+ /* For video encoding the extra bits of precision are created by bit shifting */
+ /* rather than scaling, so we need to scale the fp value to account for this. */
+ if (p->out_tvenc && p->edepth > 8)
+ vv = (vv * 255 * (1 << (p->edepth - 8)))/((1 << p->edepth) - 1.0);
+
+ tt = (int)(vv * prange + 0.5);
p->r_rgb[j] = (double)tt/prange; /* RAMDAC output Quantized value */
-//printf(" cell[%d], val %f, rast val %f\n",tt, p->rgb[j], p->r_rgb[j]);
+ p->r->v[j][tt] = vv;
+
+//printf(" cell[%d] = r_rgb %f, cell val %f\n",tt, p->r_rgb[j], vv);
}
- if (p->set_ramdac(p,p->r, 0)) {
+ if (p->set_ramdac(p, p->r, 0)) {
debugr("set_ramdac() failed\n");
return 1;
}
@@ -3487,10 +3757,15 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
/* Stop the system going to sleep */
- /* This used to work OK in reseting the screen saver, but not in Vista :-( */
+ /* This used to work OK in reseting the screen saver on */
+ /* all versions of MSWin. */
SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
- /* So we use a fake mouse non-movement reset the Vista screensaver. */
+#ifdef NEVER
+ /* (Some people use ES_CONTINUOUS | ES_AWAYMODE_REQUIRED as well ?? */
+ /* See also setting SPI_SETSCREENSAVEACTIVE? ) */
+
+ /* Another approach is a fake mouse non-movementr. */
SystemParametersInfo(SPI_SETBLOCKSENDINPUTRESETS, FALSE, NULL, 0);
fip.type = INPUT_MOUSE;
fip.mi.dx = 0;
@@ -3499,19 +3774,24 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
fip.mi.time = 0;
fip.mi.dwExtraInfo = 0;
SendInput(1, &fip, sizeof(INPUT));
+#endif
p->colupd++;
+//printf("~1 set color %f %f %f\n", p->r_rgb[0], p->r_rgb[1], p->r_rgb[2]);
/* Trigger a WM_PAINT */
if (!InvalidateRect(p->hwnd, NULL, FALSE)) {
debugr2((errout,"InvalidateRect failed, lasterr = %d\n",GetLastError()));
return 1;
}
+ UpdateWindow(p->hwnd);
+//printf("~1 waiting for paint\n");
/* Wait for WM_PAINT to be executed */
- while (p->colupd != p->colupde) {
- msec_sleep(20);
+ while (p->colupd != p->colupde && p->cberror == 0) {
+ msec_sleep(10);
}
+//printf("~1 paint done\n");
}
#endif /* NT */
@@ -3523,6 +3803,10 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
return 2;
}
+ /* We're creating and draining a pool here to ensure that all the */
+ /* auto release objects get drained when we're finished (?) */
+ NSAutoreleasePool *tpool = [NSAutoreleasePool new];
+
/* Stop the system going to sleep */
UpdateSystemActivity(OverallAct);
@@ -3552,6 +3836,8 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
/* Process events */
OSX_ProcessEvents(p);
+ [tpool release];
+
#endif /* __APPLE__ */
/* - - - - - - - - - - - - - - */
@@ -3597,11 +3883,48 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
free(cmd);
}
+ /* Don't want extra delay if we're measuring update delay */
+ if (update_delay != 0 && p->do_resp_time_del) {
+ /* Compute am expected response time for the change in level */
+ kr = DISPLAY_RISE_TIME/log(1 - 0.9); /* Exponent constant */
+ kf = DISPLAY_FALL_TIME/log(1 - 0.9); /* Exponent constant */
+//printf("~1 k2 = %f\n",k2);
+ for (j = 0; j < 3; j++) {
+ double el, dl, n, t;
+
+ el = pow(p->rgb[j], 2.2);
+ dl = el - pow(orgb[j], 2.2); /* Change in level */
+ if (fabs(dl) > 0.01) { /* More than 1% change in level */
+ n = DISPLAY_SETTLE_AIM * el;
+ if (n < DISPLAY_ABS_AIM)
+ n = DISPLAY_ABS_AIM;
+//printf("~1 sl %f, el %f, log (%f / %f)\n",sl,el,n,fabs(sl - el));
+ if (dl > 0.0)
+ t = kr * log(n/dl);
+ else
+ t = kf * log(n/-dl);
+
+ if (t > xdelay)
+ xdelay = t;
+ }
+ }
+//printf("~1 xdelay = %f secs\n",xdelay);
+ xdelay *= 1000.0; /* To msec */
+ /* This is kind of a fudge since update delay is after latency, */
+ /* but displays with long delay (ie. CRT) have short latency, and visa versa */
+ if ((int)xdelay > update_delay)
+ update_delay = (int)xdelay;
+ }
+
/* Allow some time for the display to update before */
/* a measurement can take place. This allows for CRT */
/* refresh, or LCD processing/update time, + */
/* display settling time (quite long for smaller LCD changes). */
- msec_sleep(p->update_delay);
+ msec_sleep(update_delay);
+
+ if (p->cberror) { /* Callback routine failed */
+ return 1;
+ }
return 0;
}
@@ -3633,7 +3956,7 @@ char *callout
/* ----------------------------------------------- */
/* Destroy ourselves */
-static void dispwin_del(
+void dispwin_del(
dispwin *p
) {
@@ -3682,6 +4005,12 @@ dispwin *p
p->winclose = 1;
[cx->window release];
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1040
+ if (cx->nscs != NULL)
+ [cx->nscs release];
+#endif
+
free(p->osx_cntx);
p->osx_cntx = NULL;
}
@@ -3730,6 +4059,11 @@ dispwin *p
#define SWP_STATECHANGED 0x8000
#endif
+/* MingW doesn't seem to have this, even though it's been there sine Win2k ... */
+#ifndef ICM_DONE_OUTSIDEDC
+# define ICM_DONE_OUTSIDEDC 4
+#endif
+
static LRESULT CALLBACK MainWndProc(
HWND hwnd,
UINT message,
@@ -3776,29 +4110,50 @@ static LRESULT CALLBACK MainWndProc(
vali[j] = (int)(255.0 * p->r_rgb[j] + 0.5);
}
- hdc = BeginPaint(hwnd, &ps);
+ if ((hdc = BeginPaint(hwnd, &ps)) == NULL) {
+ debugrr2l(4, (stderr,"BeginPaint failed\n"));
+ EndPaint(hwnd, &ps);
+ p->cberror = 2;
+ return 0;
+ }
- SaveDC(hdc);
+ if (SaveDC(hdc) == 0) {
+ debugrr2l(4, (stderr,"SaveDC failed\n"));
+ EndPaint(hwnd, &ps);
+ p->cberror = 3;
+ return 0;
+ }
- /* Try and turn ICM off */
-#ifdef ICM_DONE_OUTSIDEDC
+ /* Try and turn ICM & WCS off */
if (!SetICMMode(hdc, ICM_DONE_OUTSIDEDC)) {
+ OSVERSIONINFO osver;
+ osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ osver.dwMajorVersion = 5;
+ GetVersionEx(&osver);
/* This seems to fail with "invalid handle" under NT4 */
- /* Does it work under Win98 or Win2K ? */
- printf("SetICMMode failed, lasterr = %d\n",GetLastError());
+ /* so only report an error if Win2K or more */
+ if (osver.dwMajorVersion >= 5)
+ printf("SetICMMode failed, lasterr = %d\n",GetLastError());
}
-#endif
-
- hbr = CreateSolidBrush(RGB(vali[0],vali[1],vali[2]));
- SelectObject(hdc,hbr);
- SetRect(&rect, p->tx, p->ty, p->tx + p->tw, p->ty + p->th);
- FillRect(hdc, &rect, hbr);
+ if ((hbr = CreateSolidBrush(RGB(vali[0],vali[1],vali[2]))) == NULL) {
+ debugrr2l(4, (stderr,"CreateSolidBrush failed\n"));
+ RestoreDC(hdc,-1);
+ EndPaint(hwnd, &ps);
+ p->cberror = 4;
+ return 0;
+ }
+ if (SelectObject(hdc, hbr) == NULL
+ || SetRect(&rect, p->tx, p->ty, p->tx + p->tw, p->ty + p->th) == 0
+ || FillRect(hdc, &rect, hbr) == 0) {
+ debugrr2l(4, (stderr,"SelectObject/SetRect/FillRect failed\n"));
+ p->cberror = 5;
+ }
+ DeleteObject(hbr);
RestoreDC(hdc,-1);
- DeleteDC(hdc);
-
EndPaint(hwnd, &ps);
+ GdiFlush();
p->colupde = p->colupd; /* We're updated to this color */
@@ -3847,7 +4202,7 @@ static void OSX_ProcessEvents(dispwin *p) {
/* We're creating and draining a pool here to ensure that all the */
/* auto release objects get drained when we're finished (?) */
- NSAutoreleasePool *tpool = [NSAutoreleasePool new];
+// NSAutoreleasePool *tpool = [NSAutoreleasePool new];
/* Wait until the events are done */
to = [NSDate dateWithTimeIntervalSinceNow:0.01]; /* autorelease ? */
@@ -3860,7 +4215,7 @@ static void OSX_ProcessEvents(dispwin *p) {
break;
}
}
- [tpool release];
+// [tpool release];
}
#endif /* __APPLE__ */
@@ -3890,7 +4245,7 @@ int win_message_thread(void *pp) {
wc.hInstance = NULL; /* Application that owns the class. */
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_CROSS);
- wc.hbrBackground = GetStockObject(BLACK_BRUSH);
+ wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* So full screen black works */
wc.lpszMenuName = NULL;
wc.lpszClassName = p->AppName;
@@ -3913,7 +4268,9 @@ int win_message_thread(void *pp) {
p->AppName,
"Argyll Display Calibration Window",
WS_VISIBLE | WS_DISABLED | WS_POPUP,
-// WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+// WS_EX_TOPMOST
+// WS_EX_PALETTEWINDOW
+// WS_OVERLAPPEDWINDOW | WS_VISIBLE
// WS_POPUPWINDOW | WS_VISIBLE,
p->xo, p->yo, /* Location */
p->wi, p->he, /* Size */
@@ -3978,9 +4335,13 @@ disppath *disp, /* Display to calibrate. */
double width, double height, /* Width and height in mm */
double hoff, double voff, /* Offset from center in fraction of screen, range -1.0 .. 1.0 */
int nowin, /* NZ if no window should be created - RAMDAC access only */
-int native, /* 0 = use current current or given calibration curve */
- /* 1 = use native linear out & high precision */
-int *noramdac, /* Return nz if no ramdac access. native is set to 0 */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* NZ if override_redirect is to be used on X11 */
int ddebug /* >0 to print debug statements to stderr */
@@ -3990,6 +4351,16 @@ int ddebug /* >0 to print debug statements to stderr */
debug("new_dispwin called\n");
+#if defined(UNIX_X11) && defined(USE_UCMM)
+ dispwin_checkfor_colord(); /* Make colord functions available */
+ if (ddebug) {
+ if (cd_found)
+ fprintf(stderr,"using colord for profile installation\n");
+ else
+ fprintf(stderr,"using ucmm for profile installation\n");
+ }
+#endif
+
if ((p = (dispwin *)calloc(sizeof(dispwin), 1)) == NULL) {
if (ddebug) fprintf(stderr,"new_dispwin failed because malloc failed\n");
return NULL;
@@ -3998,6 +4369,7 @@ int ddebug /* >0 to print debug statements to stderr */
/* !!!! Make changes in webwin.c as well !!!! */
p->nowin = nowin;
p->native = native;
+ p->out_tvenc = out_tvenc;
p->blackbg = blackbg;
p->ddebug = ddebug;
p->get_ramdac = dispwin_get_ramdac;
@@ -4027,6 +4399,8 @@ int ddebug /* >0 to print debug statements to stderr */
if (p->update_delay < p->min_update_delay)
p->update_delay = p->min_update_delay;
+ p->do_resp_time_del = 1; /* Default this to on */
+
/* Basic object is initialised, so create a window */
/* -------------------------------------------------- */
@@ -4119,6 +4493,8 @@ int ddebug /* >0 to print debug statements to stderr */
else
p->pdepth = bpp/3;
+ p->edepth = 16;
+
if (nowin == 0) {
/* We use a thread to process the window messages, so that */
@@ -4167,12 +4543,30 @@ int ddebug /* >0 to print debug statements to stderr */
}
p->ddid = disp->ddid; /* Display we're working on */
+ /* Hmm. Could we use CGDisplayGammaTableCapacity() instead ? */
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
{
CGDisplayModeRef dispmode;
CFStringRef pixenc;
+ int cap = CGDisplayGammaTableCapacity(p->ddid);
+ int fbdepth = 0;
- p->pdepth = 0;
+ debugr2((errout,"new_dispwin: CGDisplayGammaTableCapacity = %d\n",cap));
+
+ /* Compute GammaTable depth */
+ {
+ for (p->pdepth = 1; p->pdepth < 17; p->pdepth++) {
+ if ((1 << p->pdepth) == cap)
+ break;
+ }
+ if (p->pdepth >= 17) {
+ debugr2((errout,"new_dispwin: failed to extract depth from GammaTableCapacity %d\n",cap));
+ dispwin_del(p);
+ return NULL;
+ }
+ debugr2((errout,"new_dispwin: found pixel depth %d bits\n",p->pdepth));
+ }
+ /* Get frame buffer depth for sanity check */
dispmode = CGDisplayCopyDisplayMode(p->ddid);
pixenc = CGDisplayModeCopyPixelEncoding(dispmode);
@@ -4180,23 +4574,42 @@ int ddebug /* >0 to print debug statements to stderr */
/* Hmm. Don't know what to do with kIO16BitFloatPixels or kIO32BitFloatPixels */
if (CFStringCompare(pixenc, CFSTR(kIO64BitDirectPixels), kCFCompareCaseInsensitive)
== kCFCompareEqualTo)
- p->pdepth = 16;
+ fbdepth = 16;
else if (CFStringCompare(pixenc, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive)
== kCFCompareEqualTo)
- p->pdepth = 10;
+ fbdepth = 10;
else if (CFStringCompare(pixenc, CFSTR(IO32BitDirectPixels), kCFCompareCaseInsensitive)
== kCFCompareEqualTo)
- p->pdepth = 8;
+ fbdepth = 8;
else if (CFStringCompare(pixenc, CFSTR(IO16BitDirectPixels), kCFCompareCaseInsensitive)
== kCFCompareEqualTo)
- p->pdepth = 5;
+ fbdepth = 5;
+#ifndef DEBUG
+ if (p->ddebug)
+#endif
+ {
+ char buf[200];
+ CFStringGetCString(pixenc, buf, 200, kCFStringEncodingUTF8);
+ debugr2((errout,"new_dispwin: CGDisplayModePixelEncoding = '%s'\n",buf));
+ }
+
CFRelease(pixenc);
CGDisplayModeRelease(dispmode);
+
+ if (p->pdepth != fbdepth) {
+ static int warned = 0;
+ if (!warned) {
+ warning("new_dispwin: frame buffer depth %d != GammaTable depth %d\n",fbdepth, p->pdepth);
+ warned = 1;
+ }
+ }
}
#else
p->pdepth = CGDisplayBitsPerSample(p->ddid);
#endif
+ p->edepth = 16; /* By experiment it seems to be 16 bits too */
+
if (nowin == 0) { /* Create a window */
osx_cntx_t *cx;
CGSize sz; /* Display size in mm */
@@ -4206,13 +4619,17 @@ int ddebug /* >0 to print debug statements to stderr */
debugr2((errout, "new_dispwin: About to open display '%s'\n",disp->name));
+ /* We're creating and draining a pool here to ensure that all the */
+ /* auto release objects get drained when we're finished (?) */
+ NSAutoreleasePool *tpool = [NSAutoreleasePool new];
+
/* If we don't have an application object, create one. */
/* (This should go in a common library) */
/* Note that we don't actually clean this up on exit - */
/* possibly we can't. */
if (NSApp == nil) {
- static NSAutoreleasePool *pool; /* Pool used for NSApp */
- pool = [NSAutoreleasePool new];
+// static NSAutoreleasePool *pool; /* Pool used for NSApp */
+// pool = [NSAutoreleasePool new];
NSApp = [NSApplication sharedApplication]; /* Creates NSApp */
[NSApp finishLaunching];
/* We seem to need this, because otherwise we don't get focus automatically */
@@ -4220,6 +4637,7 @@ int ddebug /* >0 to print debug statements to stderr */
}
if ((cx = (osx_cntx_t *)calloc(sizeof(osx_cntx_t), 1)) == NULL) {
+ [tpool release];
debugr2((errout,"new_dispwin: Malloc failed (osx_cntx_t)\n"));
dispwin_del(p);
return NULL;
@@ -4268,6 +4686,8 @@ int ddebug /* >0 to print debug statements to stderr */
OSX_ProcessEvents(p);
+ [tpool release];
+
p->winclose = 0;
}
@@ -4362,6 +4782,7 @@ int ddebug /* >0 to print debug statements to stderr */
//p->pdepth = DefaultDepth(p->mydisplay, p->myscreen)/3;
myvisual = DefaultVisual(p->mydisplay, p->myscreen);
p->pdepth = myvisual->bits_per_rgb;
+ p->edepth = 16;
if (nowin == 0) { /* Create a window */
rootwindow = RootWindow(p->mydisplay, p->myscreen);
@@ -4625,32 +5046,47 @@ int ddebug /* >0 to print debug statements to stderr */
#endif /* UNIX X11 */
/* -------------------------------------------------- */
- if (!p->nowin) {
- /* Setup for native mode */
- if (p->native) {
- debug("About to setup native mode\n");
- if ((p->or = p->get_ramdac(p)) == NULL
- || (p->r = p->or->clone(p->or)) == NULL) {
- if (noramdac != NULL)
- *noramdac = 1;
- debugr("new_dispwin: Accessing VideoLUT failed, so no way to guarantee that calibration is turned off!!\n");
- warning("new_dispwin: Accessing VideoLUT failed, so no way to guarantee that calibration is turned off!!");
- p->native = 0;
- } else {
- p->r->setlin(p->r);
- if (noramdac != NULL)
- *noramdac = 0;
- debug("Saved original VideoLUT\n");
- }
- } else {
- if (p->get_ramdac(p) == NULL) {
- if (noramdac != NULL)
- *noramdac = 1;
- }
+ /* Save the original ramdac, which gets restored on exit */
+ if ((p->or = p->get_ramdac(p)) != NULL) {
+
+ if (noramdac != NULL)
+ *noramdac = 0;
+
+ debugr("Saved original VideoLUT\n");
+
+ /* Copy original ramdac that never gets altered */
+ if ((p->oor = p->or->clone(p->or)) == NULL) {
+ dispwin_del(p);
+ debugr("ramdac clone failed - memory ?\n");
+ return NULL;
}
-
+
+ /* Create a working ramdac for native or other use */
+ if ((p->r = p->or->clone(p->or)) == NULL) {
+ dispwin_del(p);
+ debugr("ramdac clone failed - memory ?\n");
+ return NULL;
+ }
+
+ } else {
+ debugr("Unable to access VideoLUT\n");
+ if (noramdac != NULL)
+ *noramdac = 1;
+ p->oor = p->or = p->r = NULL;
+ }
+
+ if (!p->nowin) {
+
/* Make sure initial test color is displayed */
dispwin_set_color(p, p->rgb[0], p->rgb[1], p->rgb[2]);
+
+ /* Hmm. Could we add this ?? */
+ /* Hard to know whether OS CM is active though. By default */
+ /* dispwin disables it. */
+ if (nocm != NULL)
+ *nocm = 1;
+
+ p->native &= ~2;
}
debugr("new_dispwin: return sucessfully\n");
@@ -4705,6 +5141,16 @@ int x11_daemon_mode(disppath *disp, int verb, int ddebug) {
&& XRRQueryExtension(mydisplay, &evb, &erb) != 0
&& XRRQueryVersion(mydisplay, &majv, &minv)
&& majv == 1 && minv >= 2) {
+ static void *xrr_found = NULL; /* .so handle */
+ static XRRScreenResources *(*_XRRGetScreenResourcesCurrent)
+ (Display *dpy, Window window) = NULL;
+ XRRScreenResources *scrnres;
+
+ if (minv >= 3 && xrr_found == NULL) {
+ if ((xrr_found = dlopen("libXrandr.so", RTLD_LAZY)) != NULL)
+ _XRRGetScreenResourcesCurrent = dlsym(xrr_found, "XRRGetScreenResourcesCurrent");
+ }
+
if (verb) printf("Found XRandR 1.2 or latter\n");
XRRSelectInput(mydisplay,RootWindow(mydisplay,0),
@@ -4721,7 +5167,12 @@ int x11_daemon_mode(disppath *disp, int verb, int ddebug) {
if (update_profiles == 0) {
if (dopoll) {
for (;;) {
- XRRGetScreenResources(mydisplay, RootWindow(mydisplay,0));
+ if (minv >= 3 && _XRRGetScreenResourcesCurrent != NULL) {
+ _XRRGetScreenResourcesCurrent(mydisplay, RootWindow(mydisplay,0));
+
+ } else {
+ XRRGetScreenResources(mydisplay, RootWindow(mydisplay,0));
+ }
if(XPending(mydisplay) > 0)
break;
sleep(2);
@@ -4777,7 +5228,7 @@ int x11_daemon_mode(disppath *disp, int verb, int ddebug) {
break;
if (verb) printf("Updating display %d = '%s'\n",i+1,dp[i]->description);
- if ((dw = new_dispwin(dp[i], 0.0, 0.0, 0.0, 0.0, 1, 0, NULL, 0, 0, ddebug)) == NULL) {
+ if ((dw = new_dispwin(dp[i], 0.0, 0.0, 0.0, 0.0, 1, 0, NULL, NULL, 0, 0, 0, ddebug)) == NULL) {
if (verb) printf("Failed to access screen %d of display '%s'\n",i+1,dnbuf);
continue;
}
@@ -4814,7 +5265,7 @@ int x11_daemon_mode(disppath *disp, int verb, int ddebug) {
}
if ((wo = (icmVideoCardGamma *)icco->read_tag(icco, icSigVideoCardGammaTag)) == NULL) {
- if (verb) printf("Failed to fined vcgt tagd in profile for screen %d for display '%s' so setting linear\n",i+1,dnbuf);
+ if (verb) printf("Failed to find vcgt tagd in profile for screen %d for display '%s' so setting linear\n",i+1,dnbuf);
for (j = 0; j < r->nent; j++) {
iv = j/(r->nent-1.0);
r->v[0][j] = iv;
@@ -4927,14 +5378,19 @@ static void usage(char *diag, ...) {
}
free_disppaths(dp);
fprintf(stderr," -dweb[:port] Display via a web server at port (default 8080)\n");
+#ifdef NT
+ fprintf(stderr," -dmadvr Display via MadVR Video Renderer\n");
+#endif
+
fprintf(stderr," -P ho,vo,ss[,vs] Position test window and scale it\n");
fprintf(stderr," -F Fill whole screen with black background\n");
fprintf(stderr," -i Run forever with random values\n");
fprintf(stderr," -G filename Display RGB colors from CGATS file\n");
+ fprintf(stderr," -C r.rr,g.gg,b.bb Add this RGB color to list to be displayed\n");
fprintf(stderr," -m Manually cycle through values\n");
fprintf(stderr," -f Test grey ramp fade\n");
fprintf(stderr," -r Test just Video LUT loading & Beeps\n");
- fprintf(stderr," -n Test native output (rather than through Video LUT)\n");
+ fprintf(stderr," -n Test native output (rather than through Video LUT and C.M.)\n");
fprintf(stderr," -s filename Save the currently loaded Video LUT to 'filename'\n");
fprintf(stderr," -c Load a linear display calibration\n");
fprintf(stderr," -V Verify that calfile/profile cal. is currently loaded in LUT\n");
@@ -4944,7 +5400,7 @@ static void usage(char *diag, ...) {
fprintf(stderr," d is one of: n = network, l = local system, u = user (default)\n");
fprintf(stderr," -L Load installed profiles cal. into Video LUT\n");
#if defined(UNIX_X11)
- fprintf(stderr," -E Run in daemon loader mode for given X11 server\n");
+ fprintf(stderr," -X Run in daemon loader mode for given X11 server\n");
#endif /* X11 */
fprintf(stderr," -D [level] Print debug diagnostics to stderr\n");
fprintf(stderr," calfile Load calibration (.cal or %s) into Video LUT\n",ICC_FILE_EXT);
@@ -4961,19 +5417,27 @@ main(int argc, char *argv[]) {
int verb = 0; /* Verbose flag */
int ddebug = 0; /* debug level */
int webdisp = 0; /* NZ for web display, == port number */
+#ifdef NT
+ int madvrdisp = 0; /* NZ for MadVR display */
+#endif
disppath *disp = NULL; /* Display being used */
double hpatscale = 1.0, vpatscale = 1.0; /* scale factor for test patch size */
double ho = 0.0, vo = 0.0; /* Test window offsets, -1.0 to 1.0 */
+ int out_tvenc = 0; /* 1 to use RGB Video Level encoding */
int blackbg = 0; /* NZ if whole screen should be filled with black */
int nowin = 0; /* Don't create test window */
int ramd = 0; /* Just test ramdac */
int fade = 0; /* Test greyramp fade */
- int native = 0; /* 0 = use current current or given calibration curve */
- /* 1 = set native linear output and use ramdac high prec'n */
- /* 2 = set native linear output */
- int noramdac = 0; /* Set to nz if there is no VideoLUT access */
+ int native = 0; /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+ int noramdac = 0; /* nz if no ramdac access. native is set to X0 */
+ int nocm = 0; /* nz if no CM cLUT access. native is set to 0X */
int inf = 0; /* Infnite/manual patches flag */
char pcname[MAXNAMEL+1] = "\000"; /* CGATS patch color name */
+ int nmrgb = 0; /* Number of manual RGB values */
+ double mrgb[10][3]; /* Manual RGB values */
int clear = 0; /* Clear any display calibration (any calname is ignored) */
char sname[MAXNAMEL+1] = "\000"; /* Current cal save name */
int verify = 0; /* Verify that calname is currently loaded */
@@ -4986,7 +5450,7 @@ main(int argc, char *argv[]) {
dispwin *dw;
unsigned int seed = 0x56781234;
int i, j;
- ramdac *or = NULL, *r = NULL;
+// ramdac *r = NULL;
int is_ok_icc = 0; /* The profile is OK */
error_program = "Dispwin";
@@ -5038,6 +5502,12 @@ main(int argc, char *argv[]) {
usage("Web port number must be in range 1..65535");
}
fa = nfa;
+#ifdef NT
+ } else if (strncmp(na,"madvr",5) == 0
+ || strncmp(na,"MADVR",5) == 0) {
+ madvrdisp = 1;
+ fa = nfa;
+#endif
} else {
#if defined(UNIX_X11)
int ix, iv;
@@ -5096,10 +5566,14 @@ main(int argc, char *argv[]) {
} else if (argv[fa][1] == 'F') {
blackbg = 1;
+ /* Video mode encoding */
+ } else if (argv[fa][1] == 'E') {
+ out_tvenc = 1;
+
} else if (argv[fa][1] == 'i')
inf = 1;
- else if (argv[fa][1] == 'm' || argv[fa][1] == 'M')
+ else if (argv[fa][1] == 'm')
inf = 2;
/* CGATS patch color file */
@@ -5108,16 +5582,28 @@ main(int argc, char *argv[]) {
if (na == NULL) usage("-G parameter is missing");
strncpy(pcname,na,MAXNAMEL); pcname[MAXNAMEL] = '\000';
}
+ /* Manual color */
+ else if (argv[fa][1] == 'C') {
+ fa = nfa;
+ if (nmrgb >= 10)
+ usage("Can only be up to 10 -C values");
+ if (na == NULL) usage("-C parameters are missing");
+ if (sscanf(na, "%lf,%lf,%lf ",&mrgb[nmrgb][0],&mrgb[nmrgb][1],&mrgb[nmrgb][2]) != 3)
+ usage("-C parameters '%s' are badly formatted",na);
+ if (mrgb[nmrgb][0] < 0.0 || mrgb[nmrgb][0] > 1.0
+ || mrgb[nmrgb][1] < 0.0 || mrgb[nmrgb][1] > 1.0
+ || mrgb[nmrgb][2] < 0.0 || mrgb[nmrgb][2] > 1.0)
+ usage("-C parameters %f %f %f are out of range 0.0 - 1.0",mrgb[nmrgb][0],mrgb[nmrgb][1],mrgb[nmrgb][2]);
+ nmrgb++;
+ }
else if (argv[fa][1] == 'f')
fade = 1;
- else if (argv[fa][1] == 'r' || argv[fa][1] == 'R')
+ else if (argv[fa][1] == 'r')
ramd = 1;
- else if (argv[fa][1] == 'n' || argv[fa][1] == 'N') {
- native = 1;
- if (argv[fa][1] == 'N')
- native = 2;
+ else if (argv[fa][1] == 'n') {
+ native = 3; /* Disable cal & any CM */
}
else if (argv[fa][1] == 's') {
@@ -5141,7 +5627,7 @@ main(int argc, char *argv[]) {
else if (argv[fa][1] == 'L')
loadprofile = 1;
- else if (argv[fa][1] == 'E')
+ else if (argv[fa][1] == 'X')
daemonmode = 1;
else if (argv[fa][1] == 'S') {
@@ -5162,7 +5648,11 @@ main(int argc, char *argv[]) {
}
/* No explicit display has been set */
- if (webdisp == 0 && disp == NULL) {
+ if (disp == NULL
+#ifdef NT
+ && madvrdisp == 0
+#endif
+ && webdisp == 0) {
int ix = 0;
#if defined(UNIX_X11)
char *dn, *pp;
@@ -5212,22 +5702,36 @@ main(int argc, char *argv[]) {
if (webdisp != 0) {
- if ((dw = new_webwin(webdisp, 100.0 * hpatscale, 100.0 * vpatscale, ho, vo, nowin, blackbg, verb, ddebug)) == NULL) {
- printf("Error - new_webpwin failed!\n");
+ if ((dw = new_webwin(webdisp, 100.0 * hpatscale, 100.0 * vpatscale, ho, vo, nowin, native,
+ &noramdac, &nocm, out_tvenc, blackbg, verb, ddebug)) == NULL) {
+ printf("Error - new_webwin failed!\n");
return -1;
}
- noramdac = 1;
+#ifdef NT
+ } else if (madvrdisp != 0) {
+ if (out_tvenc) {
+ printf("Error - Set TV encodfing in MadVR\n");
+ return -1;
+ }
+
+ if ((dw = new_madvrwin(100.0 * hpatscale, 100.0 * vpatscale, ho, vo, nowin, native,
+ &noramdac, &nocm, out_tvenc, blackbg, verb, ddebug)) == NULL) {
+ printf("Error - new_madvrwin failed!\n");
+ return -1;
+ }
+#endif
} else {
if (verb) printf("About to open dispwin object on the display\n");
- if ((dw = new_dispwin(disp, 100.0 * hpatscale, 100.0 * vpatscale, ho, vo, nowin, native, &noramdac, blackbg, 1, ddebug)) == NULL) {
+ if ((dw = new_dispwin(disp, 100.0 * hpatscale, 100.0 * vpatscale, ho, vo, nowin, native,
+ &noramdac, &nocm, out_tvenc, blackbg, 1, ddebug)) == NULL) {
printf("Error - new_dispwin failed!\n");
return -1;
}
}
- if (native != 0 && noramdac) {
- error("We don't have access to the VideoLUT so can't display native colors\n");
+ if ((native & 1) != 0 && noramdac) {
+ warning("Unable to access to VideoLUTs so can't be sure colors are native");
}
/* Save the current Video LUT to the calfile */
@@ -5242,7 +5746,7 @@ main(int argc, char *argv[]) {
if (verb)
printf("About to save current loaded calibration to file '%s'\n",sname);
- if ((r = dw->get_ramdac(dw)) == NULL) {
+ if (dw->oor == NULL) {
error("We don't have access to the VideoLUT");
}
@@ -5267,16 +5771,16 @@ main(int argc, char *argv[]) {
error("Malloc failed!");
/* Write the video lut curve values */
- for (i = 0; i < r->nent; i++) {
- double iv = i/(r->nent-1.0);
+ for (i = 0; i < dw->oor->nent; i++) {
+ double iv = i/(dw->oor->nent-1.0);
#if defined(__APPLE__) && defined(__POWERPC__)
gcc_bug_fix(i);
#endif
setel[0].d = iv;
- setel[1].d = r->v[0][i];
- setel[2].d = r->v[1][i];
- setel[3].d = r->v[2][i];
+ setel[1].d = dw->oor->v[0][i];
+ setel[2].d = dw->oor->v[1][i];
+ setel[3].d = dw->oor->v[2][i];
ocg->add_setarr(ocg, 0, setel);
}
@@ -5287,8 +5791,6 @@ main(int argc, char *argv[]) {
error("Write error to '%s' : %s",sname,ocg->err);
ocg->del(ocg); /* Clean up */
- r->del(r);
- r = NULL;
/* Fall through, as we may want to do other stuff too */
}
@@ -5297,28 +5799,24 @@ main(int argc, char *argv[]) {
if (clear != 0) {
int rv;
- if ((r = dw->get_ramdac(dw)) == NULL) {
- error("We don't have access to the VideoLUT");
- }
+ if (dw->or == NULL)
+ error("We don't have access to the VideoLUT for clearing");
- for (i = 0; i < r->nent; i++) {
- double iv = i/(r->nent-1.0);
- r->v[0][i] = iv;
- r->v[1][i] = iv;
- r->v[2][i] = iv;
+ for (i = 0; i < dw->or->nent; i++) {
+ double iv = i/(dw->or->nent-1.0);
+ dw->or->v[0][i] = iv;
+ dw->or->v[1][i] = iv;
+ dw->or->v[2][i] = iv;
}
if (verb)
printf("About to clear the calibration\n");
- if ((rv = dw->set_ramdac(dw,r,1)) != 0) {
+ if ((rv = dw->set_ramdac(dw,dw->or,1)) != 0) {
if (rv == 2)
warning("Failed to set VideoLUTs persistently because current System Profile can't be renamed");
else
error("Failed to set VideoLUTs");
}
- r->del(r);
- r = NULL;
-
/* Fall through, as we may want to do other stuff too */
}
@@ -5338,15 +5836,14 @@ main(int argc, char *argv[]) {
/* Get any calibration from the provided .cal file or .profile, */
/* or calibration from the current default display profile, */
- /* and put it in r */
+ /* and put it in dw->or */
if (loadfile != 0 || verify != 0 || loadprofile != 0 || installprofile == 1) {
icmFile *rd_fp = NULL;
icc *icco = NULL;
cgats *ccg = NULL; /* calibration cgats structure */
- /* Get a calibration that's compatible with the display. */
- /* This can fail and return NULL - error if we later need it */
- r = dw->get_ramdac(dw);
+ if (dw->r == NULL)
+ error("We don't have access to the VideoLUT for loading");
/* Should we load calfile instead of installed profile if it's present ??? */
if (loadprofile) {
@@ -5377,46 +5874,41 @@ main(int argc, char *argv[]) {
if ((wo = (icmVideoCardGamma *)icco->read_tag(icco, icSigVideoCardGammaTag)) == NULL) {
warning("No vcgt tag found in profile - assuming linear\n");
- if (r != NULL) {
- for (i = 0; i < r->nent; i++) {
- iv = i/(r->nent-1.0);
- r->v[0][i] = iv;
- r->v[1][i] = iv;
- r->v[2][i] = iv;
- }
+ for (i = 0; i < dw->r->nent; i++) {
+ iv = i/(dw->r->nent-1.0);
+ dw->r->v[0][i] = iv;
+ dw->r->v[1][i] = iv;
+ dw->r->v[2][i] = iv;
}
} else {
- /* Hmm. Perhaps we should ignore this if the vcgt is linear ?? */
- if (r == NULL)
- error("We don't have access to the VideoLUT");
-
if (wo->u.table.channels == 3) {
- for (i = 0; i < r->nent; i++) {
- iv = i/(r->nent-1.0);
- r->v[0][i] = wo->lookup(wo, 0, iv);
- r->v[1][i] = wo->lookup(wo, 1, iv);
- r->v[2][i] = wo->lookup(wo, 2, iv);
-//printf("~1 entry %d = %f %f %f\n",i,r->v[0][i],r->v[1][i],r->v[2][i]);
+ for (i = 0; i < dw->r->nent; i++) {
+ iv = i/(dw->r->nent-1.0);
+ dw->r->v[0][i] = wo->lookup(wo, 0, iv);
+ dw->r->v[1][i] = wo->lookup(wo, 1, iv);
+ dw->r->v[2][i] = wo->lookup(wo, 2, iv);
+//printf("~1 entry %d = %f %f %f\n",i,dw->r->v[0][i],dw->r->v[1][i],dw->r->v[2][i]);
}
debug("Got color vcgt calibration\n");
} else if (wo->u.table.channels == 1) {
- for (i = 0; i < r->nent; i++) {
- iv = i/(r->nent-1.0);
- r->v[0][i] =
- r->v[1][i] =
- r->v[2][i] = wo->lookup(wo, 0, iv);
+ for (i = 0; i < dw->r->nent; i++) {
+ iv = i/(dw->r->nent-1.0);
+ dw->r->v[0][i] =
+ dw->r->v[1][i] =
+ dw->r->v[2][i] = wo->lookup(wo, 0, iv);
}
debug("Got monochrom vcgt calibration\n");
- } else {
- r->del(r);
- r = NULL;
}
+ /* ~~~ Ideally the vcgt should have been tagged if it is TV encoded, so */
+ /* that the scaling can be adjusted here if the RAMDAC depth differs from */
+ /* the vcgt depth. ~~~ */
}
} else { /* See if it's a .cal file */
int ncal;
int ii, fi, ri, gi, bi;
double cal[3][256];
+ int out_tvenc = 0; /* nz to use (16-235)/255 video encoding */
icco->del(icco); /* Don't need these now */
icco = NULL;
@@ -5447,6 +5939,12 @@ main(int argc, char *argv[]) {
if (strcmp(ccg->t[0].kdata[fi],"DISPLAY") != 0)
error("Calibration file '%s' doesn't have DEVICE_CLASS of DISPLAY",calname);
+ if ((fi = ccg->find_kword(ccg, 0, "TV_OUTPUT_ENCODING")) >= 0) {
+ if (strcmp(ccg->t[0].kdata[fi], "YES") == 0
+ || strcmp(ccg->t[0].kdata[fi], "yes") == 0)
+ out_tvenc = 1;
+ }
+
if ((ii = ccg->find_field(ccg, 0, "RGB_I")) < 0)
error("Calibration file '%s' doesn't contain field RGB_I",calname);
if (ccg->t[0].ftype[ii] != r_t)
@@ -5469,24 +5967,38 @@ main(int argc, char *argv[]) {
cal[2][i] = *((double *)ccg->t[0].fdata[i][bi]);
}
- if (r == NULL)
- error("We don't have access to the VideoLUT");
-
/* Interpolate from cal value to RAMDAC entries */
- for (i = 0; i < r->nent; i++) {
+ for (i = 0; i < dw->r->nent; i++) {
double val, w;
unsigned int ix;
- val = (ncal-1.0) * i/(r->nent-1.0);
+ val = (ncal-1.0) * i/(dw->r->nent-1.0);
ix = (unsigned int)floor(val); /* Coordinate */
if (ix > (ncal-2))
ix = (ncal-2);
w = val - (double)ix; /* weight */
for (j = 0; j < 3; j++) {
val = cal[j][ix];
- r->v[j][i] = val + w * (cal[j][ix+1] - val);
+ dw->r->v[j][i] = val + w * (cal[j][ix+1] - val);
}
}
+ /* If the calibration was created with a restricted range video encoding, */
+ /* ensure that the installed calibration applies this encoding. */
+ if (out_tvenc) {
+ for (i = 0; i < dw->r->nent; i++) {
+ for (j = 0; j < 3; j++) {
+ dw->r->v[j][i] = (dw->r->v[j][i] * (235.0-16.0) + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit */
+ /* shifting rather than scaling, so we need to scale the fp value to */
+ /* account for this. */
+ if (dw->edepth > 8)
+ dw->r->v[j][i] = (dw->r->v[j][i] * 255 * (1 << (dw->edepth - 8)))
+ /((1 << dw->edepth) - 1.0);
+ }
+ }
+ }
+
debug("Got cal file calibration\n");
}
if (ccg != NULL)
@@ -5502,27 +6014,35 @@ main(int argc, char *argv[]) {
if (is_ok_icc == 0)
error("File '%s' doesn't seem to be an ICC profile!",calname);
- if (verb)
- printf("About to install '%s' as display's default profile\n",calname);
- if (dw->install_profile(dw, calname, r, scope)) {
- error("Failed to install profile '%s'!",calname);
- }
- if (verb) {
- printf("Installed '%s' and made it the default\n",calname);
+ if (dw->r== NULL) {
+ warning("Unable to access VideoLUT so can't install calibration");
+ } else {
+ if (verb)
+ printf("About to install '%s' as display's default profile\n",calname);
+ if (dw->or)
+ dw->or->del(dw->or);
+ if ((dw->or = dw->r->clone(dw->r)) == NULL)
+ error("Failed to clone VideoLUT - memory ?");
+ if (dw->install_profile(dw, calname, dw->or, scope))
+ error("Failed to install profile '%s'!",calname);
+ if (verb)
+ printf("Installed '%s' and made it the default\n",calname);
}
/* load the LUT with the calibration from the given file or the current display profile. */
- /* (But don't load profile calibration if we're verifying against it) */
- } else if (loadfile != 0 || (loadprofile != 0 && verify == 0)) {
+ } else if (loadfile != 0 || loadprofile != 0) {
int rv;
- /* r == NULL if no VideoLUT access and ICC profile without vcgt */
- if (r == NULL) {
- warning("No linear calibration loaded because there is no access to the VideoLUT");
+ if (dw->or == NULL) {
+ warning("Calibration not loaded because there is no access to the VideoLUT");
} else {
if (verb)
printf("About to set display to given calibration\n");
- if ((rv = dw->set_ramdac(dw,r,1)) != 0) {
+ if (dw->or)
+ dw->or->del(dw->or);
+ if ((dw->or = dw->r->clone(dw->r)) == NULL)
+ error("Failed to clone VideoLUT - memory ?");
+ if ((rv = dw->set_ramdac(dw,dw->or,1)) != 0) {
if (rv == 2)
error("Failed to set VideoLUTs persistently because current System Profile can't be renamed");
else
@@ -5536,16 +6056,20 @@ main(int argc, char *argv[]) {
if (verify != 0) {
int ver = 1;
double berr = 0.0;
- if ((or = dw->get_ramdac(dw)) == NULL)
- error("Unable to get current VideoLUT for verify");
+
+ if (dw->oor == NULL)
+ error("Unable to get original VideoLUT for verify");
- if (r == NULL)
+ if (dw->r == NULL)
error("No calibration to verify against");
+ if (dw->r->nent != dw->oor->nent)
+ error("VideoLUTs have different size");
+
for (j = 0; j < 3; j++) {
- for (i = 0; i < r->nent; i++) {
+ for (i = 0; i < dw->oor->nent; i++) {
double err;
- err = fabs(r->v[j][i] - or->v[j][i]);
+ err = fabs(dw->oor->v[j][i] - dw->r->v[j][i]);
if (err > berr)
berr = err;
if (err > VERIFY_TOL) {
@@ -5557,12 +6081,6 @@ main(int argc, char *argv[]) {
printf("Verify: '%s' IS loaded (discrepancy %.1f%%)\n", calname, berr * 100);
else
printf("Verify: '%s' is NOT loaded (discrepancy %.1f%%)\n", calname, berr * 100);
- or->del(or);
- or = NULL;
- }
- if (r != NULL) {
- r->del(r);
- r = NULL;
}
/* If no other command selected, do a Window or VideoLUT test */
@@ -5637,7 +6155,9 @@ main(int argc, char *argv[]) {
printf("Patch no %d",i+1);
printf(" color %f %f %f\n",r,g,b);
- dw->set_color(dw, r, g, b);
+ if (dw->set_color(dw, r, g, b) != 0) {
+ error ("set_color failed");
+ }
if (inf == 2)
getchar();
@@ -5646,6 +6166,37 @@ main(int argc, char *argv[]) {
}
icg->del(icg);
+ /* Manually define patche colors */
+ } else if (nmrgb > 0) {
+ int i;
+ int ri, gi, bi;
+
+ if (inf == 2)
+ printf("\nHit return to advance each color\n");
+
+ if (inf == 2) {
+ printf("\nHit return to start\n");
+ getchar();
+ }
+ for (i = 0; i < nmrgb; i++) {
+ double r, g, b;
+ r = mrgb[i][0];
+ g = mrgb[i][1];
+ b = mrgb[i][2];
+
+ printf("Patch no %d",i+1);
+ printf(" color %f %f %f\n",r,g,b);
+
+ if (dw->set_color(dw, r, g, b) != 0) {
+ error ("set_color failed");
+ }
+
+ if (inf == 2)
+ getchar();
+ else
+ sleep(2);
+ }
+
/* Preset and random patch colors */
} else {
@@ -5796,32 +6347,30 @@ main(int argc, char *argv[]) {
if (inf != 2) {
/* Test out the VideoLUT access */
- if ((dw->or = dw->get_ramdac(dw)) != NULL) { /* Use dw->or so signal will restore */
+ if (dw->r != NULL) { /* Working ramdac to use */
- r = dw->or->clone(dw->or);
-
/* Try darkening it */
for (j = 0; j < 3; j++) {
- for (i = 0; i < r->nent; i++) {
- r->v[j][i] = pow(dw->or->v[j][i], 2.0);
+ for (i = 0; i < dw->r->nent; i++) {
+ dw->r->v[j][i] = pow(dw->or->v[j][i], 2.0);
}
}
printf("Darkening screen\n");
- if (dw->set_ramdac(dw,r,0)) {
- dw->set_ramdac(dw,or,0);
+ if (dw->set_ramdac(dw, dw->r, 0)) {
+ dw->set_ramdac(dw, dw->or, 0); /* is this needed ? */
error("Failed to set VideoLUTs");
}
sleep(1);
/* Try lightening it */
for (j = 0; j < 3; j++) {
- for (i = 0; i < r->nent; i++) {
- r->v[j][i] = pow(dw->or->v[j][i], 0.5);
+ for (i = 0; i < dw->r->nent; i++) {
+ dw->r->v[j][i] = pow(dw->or->v[j][i], 0.5);
}
}
printf("Lightening screen\n");
- if (dw->set_ramdac(dw,r,0)) {
- dw->set_ramdac(dw,or,0);
+ if (dw->set_ramdac(dw,dw->r,0)) {
+ dw->set_ramdac(dw,dw->or,0); /* is this needed ? */
error("Failed to set VideoLUTs");
}
sleep(1);
@@ -5832,10 +6381,6 @@ main(int argc, char *argv[]) {
error("Failed to set VideoLUTs");
}
- r->del(r);
- dw->or->del(dw->or);
- dw->or = NULL;
-
} else {
printf("We don't have access to the VideoLUT\n");
}
diff --git a/spectro/dispwin.h b/spectro/dispwin.h
index 096547f..1206661 100644
--- a/spectro/dispwin.h
+++ b/spectro/dispwin.h
@@ -15,7 +15,13 @@
* see the License.txt file for licencing details.
*/
-#define DISPLAY_UPDATE_DELAY 200 /* default display update delay allowance */
+#define DISPLAY_UPDATE_DELAY 200 /* default minimum display update delay allowance */
+
+/* Display rise and fall time model. This is CRT like */
+#define DISPLAY_RISE_TIME 0.03 /* Assumed rise time to 90% of target level */
+#define DISPLAY_FALL_TIME 0.12 /* Assumed fall time to 90% of target level */
+#define DISPLAY_SETTLE_AIM 0.01 /* Aim for 1% of true level */
+#define DISPLAY_ABS_AIM 0.0001 /* Aim for .01% of true absolute level */
int do_plot(double *x, double *y1, double *y2, double *y3, int n);
@@ -145,7 +151,11 @@ extern int callback_ddebug; /* Diagnostic global for get_displays() and get_a_d
/* - - - - - - - - - - - - - - - - - - - - - - - */
/* Structure to handle RAMDAC values */
struct _ramdac {
- int pdepth; /* Plane depth, usually 8 */
+
+ /* Should have separate frame buffer depth + representation to account */
+ /* for floating point frame buffers, even though this isn't currently used. */
+
+ int pdepth; /* Frame buffer depth into RAMDAC, usually 8 */
int nent; /* Number of entries, = 2^pdepth */
double *v[3]; /* 2^pdepth entries for RGB, values 0.0 - 1.0 */
@@ -163,7 +173,7 @@ struct _ramdac {
/* - - - - - - - - - - - - - - - - - - - - - - - */
/* Dispwin object */
-/* !!!! Make changes in dispwin.c and webwin.c !!!! */
+/* !!!! Make changes in dispwin.c, webwin.c & madvrwin.c !!!! */
struct _dispwin {
@@ -179,15 +189,21 @@ struct _dispwin {
int tx,ty; /* Test area within window offset in pixels */
int tw,th; /* Test area width and height in pixels */
- double rgb[3]; /* Current color (full resolution) */
+ double rgb[3]; /* Current color (full resolution, full range) */
+ double s_rgb[3]; /* Current color (possibly scaled range) */
double r_rgb[3]; /* Current color (raster value) */
- int update_delay; /* Update delay in msec, default 200 */
- int min_update_delay; /* Minimum update delay, default 20, overriden by EV */
+ int out_tvenc; /* 1 to use RGB Video Level encoding */
+ int update_delay; /* Update latency delay in msec, default 200 */
+ int min_update_delay; /* Minimum update latency delay, default 20, overriden by EV */
+ int do_resp_time_del; /* NZ to compute and use expected display response time */
int nowin; /* Don't create a test window */
- int native; /* 0 = use current current or given calibration curve */
- /* 1 = set native linear output and use ramdac high precision */
- ramdac *or; /* Original ramdac contents, NULL if none */
- ramdac *r; /* Ramdac in use for native mode */
+ int native; /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precision */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+ ramdac *oor; /* Original orgininal ramdac contents, NULL if not accessible */
+ ramdac *or; /* Original ramdac contents, NULL if not accessible, restored on exit */
+ ramdac *r; /* Ramdac in use for native mode or general use */
int blackbg; /* NZ if black full screen background */
char *callout; /* if not NULL - set color Shell callout routine */
@@ -210,8 +226,8 @@ struct _dispwin {
int inited;
int quit; /* Request to quit */
- int colupd; /* Color update count */
- int colupde; /* Color update count echo */
+ volatile int colupd; /* Color update count */
+ volatile int colupde; /* Color update count echo */
#endif /* NT */
@@ -265,10 +281,13 @@ struct _dispwin {
volatile unsigned int ncix, ccix; /* Counters to trigger webwin colorchange */
volatile int mg_stop; /* Stop flag */
+ volatile int cberror; /* NZ if error detected in a callback routine */
int ddebug; /* >0 to print debug to stderr */
/* public: */
- int pdepth; /* Plane depth of display */
+ int pdepth; /* Frame buffer plane depth of display */
+ int edepth; /* Notional ramdac entry size in bits. (Bits actually used may be less) */
+ /* This is used to scale out_tvenc appropriately */
/* Get RAMDAC values. ->del() when finished. */
/* Return NULL if not possible */
@@ -296,7 +315,14 @@ struct _dispwin {
/* Return nz on error */
int (*set_color)(struct _dispwin *p, double r, double g, double b);
+ /* Optional - may be NULL */
+ /* set patch info */
+ /* Return nz on error */
+ int (*set_pinfo)(struct _dispwin *p, int pno, int tno);
+
/* Set an update delay, and return the previous value */
+ /* Note that 0 is a special case and forces a zero delay */
+ /* in spite of min_update_delay and do_resp_time_del */
int (*set_update_delay)(struct _dispwin *p, int update_delay);
/* Set a shell set color callout command line */
@@ -313,14 +339,23 @@ dispwin *new_dispwin(
double width, double height, /* Width and height in mm */
double hoff, double voff, /* Offset from c. in fraction of screen, range -1.0 .. 1.0 */
int nowin, /* NZ if no window should be created - RAMDAC access only */
- int native, /* 0 = use current current or given calibration curve */
- /* 1 = use native linear out & high precision */
- int *noramdac, /* Return nz if no ramdac access. native is set to 0 */
+ int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+ int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+ int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+ int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int override, /* NZ if override_redirect is to be used on X11 */
int ddebug /* >0 to print debug statements to stderr */
);
+/* Shared implementation */
+ramdac *dispwin_clone_ramdac(ramdac *r);
+void dispwin_setlin_ramdac(ramdac *r);
+void dispwin_del_ramdac(ramdac *r);
+
#define DISPWIN_H
#endif /* DISPWIN_H */
diff --git a/spectro/dtp20.c b/spectro/dtp20.c
index 84c4f2b..b378f50 100644
--- a/spectro/dtp20.c
+++ b/spectro/dtp20.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 10/3/2001
*
- * Copyright 1996 - 2013, Graeme W. Gill
+ * Copyright 1996 - 2014, Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -108,7 +108,7 @@ char *in, /* In string */
char *out, /* Out string buffer */
int bsize, /* Out buffer size */
double to) { /* Timout in seconts */
- char tc = '>'; /* Terminating character */
+ char *tc = ">"; /* Terminating character */
int ntc = 1; /* Number of terminating characters */
int rv, se, insize;
@@ -128,7 +128,7 @@ double to) { /* Timout in seconts */
}
rv = DTP20_OK;
- if (tc == '>' && ntc == 1) { /* Expecting DTP type error code */
+ if (tc[0] == '>' && ntc == 1) { /* Expecting DTP type error code */
rv = extract_ec(out);
if (rv > 0) {
rv &= inst_imask;
@@ -221,8 +221,8 @@ dtp20_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
dtp20_command(p, "0PR\r", buf, MAX_MES_SIZE, 0.5);
} else {
- a1logd(p->log, 1, "dtp20: Failed to find connection to instrument\n");
- return inst_coms_fail;
+ a1logd(p->log, 1, "dtp20: wrong communications type for device\n");
+ return inst_internal_error;
}
/* Check instrument is responding */
@@ -551,6 +551,7 @@ ipatch *vals) { /* Pointer to array of values */
if ((ev = dtp20_command(p, "0518CF\r", buf, MAX_RD_SIZE, 0.5)) != inst_ok)
return ev;
}
+
}
a1logv(p->log, 1, "All saved strips read\n");
@@ -779,6 +780,7 @@ ipatch *vals) { /* Pointer to array of instrument patch values */
return ev;
}
+
/* Wait for status to change */
for (;;) {
if ((ev = dtp20_command(p, "CS\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok) {
@@ -1006,6 +1008,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
return ev;
}
+
if (!IMODETST(p->mode, inst_mode_s_ref_spot)) {
/* Clear the spot database so our reading doesn't appear as a stored reading */
diff --git a/spectro/dtp22.c b/spectro/dtp22.c
index 5831a1d..927d833 100644
--- a/spectro/dtp22.c
+++ b/spectro/dtp22.c
@@ -126,7 +126,7 @@ dtp22_fcommand(
char *in, /* In string */
char *out, /* Out string buffer */
int bsize, /* Out buffer size */
- char tc, /* Terminating character */
+ char *tc, /* Terminating characters */
int ntc, /* Number of terminating characters */
double to) { /* Timout in seconds */
int se, rv = DTP22_OK;
@@ -135,7 +135,7 @@ dtp22_fcommand(
a1logd(p->log, 1, "dtp22_fcommand: serial i/o failure on write_read '%s'\n",icoms_fix(in));
return icoms2dtp22_err(se);
}
- if (tc == '>' && ntc == 1) {
+ if (tc[0] == '>' && ntc == 1) {
rv = extract_ec(out);
#ifdef NEVER /* Simulate an error ?? */
if (strcmp(in, "0PR\r") == 0)
@@ -145,7 +145,7 @@ dtp22_fcommand(
rv &= inst_imask;
if (rv != DTP22_OK) { /* Clear the error */
char buf[MAX_MES_SIZE];
- p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
}
}
}
@@ -158,7 +158,7 @@ dtp22_fcommand(
/* Return the dtp error code */
static inst_code
dtp22_command(dtp22 *p, char *in, char *out, int bsize, double to) {
- int rv = dtp22_fcommand(p, in, out, bsize, '>', 1, to);
+ int rv = dtp22_fcommand(p, in, out, bsize, ">", 1, to);
return dtp22_interp_code((inst *)p, rv);
}
@@ -249,7 +249,7 @@ dtp22_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
return ev;
/* Change the baud rate to the rate we've been told */
- if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, .2)) != 0) {
+ if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, ">", 1, .2)) != 0) {
if (extract_ec(buf) != DTP22_OK)
return inst_coms_fail;
}
@@ -261,7 +261,7 @@ dtp22_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
/* Loose a character (not sure why) */
- p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, '>', 1, 0.1);
+ p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, ">", 1, 0.1);
/* Check instrument is responding, and reset it again. */
if ((ev = dtp22_command(p, "\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok
@@ -481,7 +481,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
/* Wait for the microswitch to be triggered, or the user to trigger */
for (;;) {
- if ((se = p->icom->read(p->icom, buf, MAX_MES_SIZE, '>', 1, 1.0)) != 0) {
+ if ((se = p->icom->read(p->icom, buf, MAX_MES_SIZE, ">", 1, 1.0)) != 0) {
if ((se & ICOM_TO) == 0) { /* Some sort of read error */
/* Disable the read microswitch */
dtp22_command(p, "2PB\r", buf, MAX_MES_SIZE, 0.2);
@@ -708,7 +708,7 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
/* Wait for the microswitch to be triggered, or a user trigger via uicallback */
for (;;) {
- if ((se = p->icom->read(p->icom, buf, MAX_MES_SIZE, '>', 1, 1.0)) != 0) {
+ if ((se = p->icom->read(p->icom, buf, MAX_MES_SIZE, ">", 1, 1.0)) != 0) {
if ((se & ICOM_TO) == 0) { /* Some sort of read error */
ev = dtp22_interp_code((inst *)p, icoms2dtp22_err(se));
goto do_exit;
diff --git a/spectro/dtp41.c b/spectro/dtp41.c
index 4487124..4717ed4 100644
--- a/spectro/dtp41.c
+++ b/spectro/dtp41.c
@@ -110,7 +110,7 @@ dtp41 *p,
char *in, /* In string */
char *out, /* Out string buffer */
int bsize, /* Out buffer size */
-char tc, /* Terminating character */
+char *tc, /* Terminating characters */
int ntc, /* Number of terminating characters */
double to) { /* Timout in seconts */
int rv, se;
@@ -120,13 +120,13 @@ double to) { /* Timout in seconts */
return icoms2dtp41_err(se);
}
rv = DTP41_OK;
- if (tc == '>' && ntc == 1) {
+ if (tc[0] == '>' && ntc == 1) {
rv = extract_ec(out);
if (rv > 0) {
rv &= inst_imask;
if (rv != DTP41_OK) { /* Clear the error */
char buf[MAX_MES_SIZE];
- p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
}
}
}
@@ -139,7 +139,7 @@ double to) { /* Timout in seconts */
/* Return the instrument error code */
static inst_code
dtp41_command(dtp41 *p, char *in, char *out, int bsize, double to) {
- int rv = dtp41_fcommand(p, in, out, bsize, '>', 1, to);
+ int rv = dtp41_fcommand(p, in, out, bsize, ">", 1, to);
return dtp41_interp_code((inst *)p, rv);
}
@@ -228,13 +228,13 @@ dtp41_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
return ev;
/* Set the handshaking (cope with coms breakdown) */
- if ((se = p->icom->write_read(p->icom, fcc, buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
+ if ((se = p->icom->write_read(p->icom, fcc, buf, MAX_MES_SIZE, ">", 1, 1.5)) != 0) {
if (extract_ec(buf) != DTP41_OK)
return inst_coms_fail;
}
/* Change the baud rate to the rate we've been told (cope with coms breakdown) */
- if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
+ if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, ">", 1, 1.5)) != 0) {
if (extract_ec(buf) != DTP41_OK)
return inst_coms_fail;
}
@@ -247,7 +247,7 @@ dtp41_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
/* Loose a character (not sure why) */
- p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
/* Check instrument is responding */
if ((ev = dtp41_command(p, "\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok) {
diff --git a/spectro/dtp51.c b/spectro/dtp51.c
index 7e49f3e..ac497d9 100644
--- a/spectro/dtp51.c
+++ b/spectro/dtp51.c
@@ -113,7 +113,7 @@ dtp51_fcommand(
char *in, /* In string */
char *out, /* Out string buffer */
int bsize, /* Out buffer size */
- char tc, /* Terminating character */
+ char *tc, /* Terminating character */
int ntc, /* Number of terminating characters */
double to) { /* Timout in seconts */
int rv, se;
@@ -123,13 +123,13 @@ dtp51_fcommand(
return icoms2dtp51_err(se);
}
rv = DTP51_OK;
- if (tc == '>' && ntc == 1) {
+ if (tc[0] == '>' && ntc == 1) {
rv = extract_ec(out);
if (rv > 0) {
rv &= inst_imask;
if (rv != DTP51_OK) { /* Clear the error */
char buf[MAX_MES_SIZE];
- p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
}
}
}
@@ -142,7 +142,7 @@ dtp51_fcommand(
/* Return the dtp error code */
static inst_code
dtp51_command(dtp51 *p, char *in, char *out, int bsize, double to) {
- int rv = dtp51_fcommand(p, in, out, bsize, '>', 1, to);
+ int rv = dtp51_fcommand(p, in, out, bsize, ">", 1, to);
return dtp51_interp_code((inst *)p, rv);
}
@@ -154,7 +154,7 @@ struct _dtp51 *p,
char *out, /* Out string buffer */
int bsize, /* Out buffer size */
double to) { /* Timout in seconts */
- char tc = '>'; /* Terminating character */
+ char *tc = ">"; /* Terminating character */
int ntc = 1; /* Number of terminating characters */
int rv, se;
@@ -163,13 +163,13 @@ double to) { /* Timout in seconts */
return icoms2dtp51_err(se);
}
rv = DTP51_OK;
- if (tc == '>' && ntc == 1) {
+ if (tc[0] == '>' && ntc == 1) {
rv = extract_ec(out);
if (rv > 0) {
rv &= inst_imask;
if (rv != DTP51_OK) { /* Clear the error */
char buf[MAX_MES_SIZE];
- p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
}
}
}
@@ -262,7 +262,7 @@ dtp51_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
return ev;
/* Change the baud rate to the rate we've been told */
- if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, 1.5)) != 0) {
+ if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, ">", 1, 1.5)) != 0) {
if (extract_ec(buf) != DTP51_OK)
return inst_coms_fail;
}
@@ -275,7 +275,7 @@ dtp51_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
/* Loose a character (not sure why) */
- p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
/* Check instrument is responding */
if ((ev = dtp51_command(p, "\r", buf, MAX_MES_SIZE, 1.5)) != inst_ok)
@@ -440,7 +440,7 @@ dtp51_init_inst(inst *pp) {
/* Set a strip length of 1, to ensure parsing is invalidated */
build_strip(tbuf, " ", 1, " ", 30);
- if ((rv = dtp51_fcommand(p, "0105DS\r", buf, MAX_MES_SIZE, '*', 1, 0.5)) != DTP51_OK)
+ if ((rv = dtp51_fcommand(p, "0105DS\r", buf, MAX_MES_SIZE, "*", 1, 0.5)) != DTP51_OK)
return dtp51_interp_code(pp, rv);
/* Expect '*' as response */
@@ -486,7 +486,7 @@ ipatch *vals) { /* Pointer to array of instrument patch values */
build_strip(tbuf, name, npatch, pname, sguide);
- if ((rv = dtp51_fcommand(p, "0105DS\r", buf, MAX_RD_SIZE, '*', 1, 0.5)) != DTP51_OK)
+ if ((rv = dtp51_fcommand(p, "0105DS\r", buf, MAX_RD_SIZE, "*", 1, 0.5)) != DTP51_OK)
return dtp51_interp_code(pp, rv);
/* Expect '*' as response */
diff --git a/spectro/dtp92.c b/spectro/dtp92.c
index 441c0eb..f86672e 100644
--- a/spectro/dtp92.c
+++ b/spectro/dtp92.c
@@ -6,7 +6,7 @@
* Author: Graeme W. Gill
* Date: 5/10/1996
*
- * Copyright 1996 - 2013, Graeme W. Gill
+ * Copyright 1996 - 2014, Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -60,6 +60,8 @@
/* Default flow control */
#define DEFFC fc_none
+#define DEF_TIMEOUT 0.5
+
#define IGNORE_NEEDS_OFFSET_DRIFT_CAL_ERR
static inst_code dtp92_interp_code(inst *pp, int ec);
@@ -113,7 +115,7 @@ dtp92_fcommand(
char *in, /* In string */
char *out, /* Out string buffer */
int bsize, /* Out buffer size */
- char tc, /* Terminating character */
+ char *tc, /* Terminating characters */
int ntc, /* Number of terminating characters */
double to) { /* Timout in seconds */
int rv, se;
@@ -123,7 +125,7 @@ dtp92_fcommand(
return icoms2dtp92_err(se);
}
rv = DTP92_OK;
- if (tc == '>' && ntc == 1) {
+ if (tc != NULL && tc[0] == '>' && ntc >= 1) {
rv = extract_ec(out);
#ifdef NEVER
@@ -135,7 +137,7 @@ dtp92_fcommand(
rv &= inst_imask;
if (rv != DTP92_OK) { /* Clear the error */
char buf[MAX_MES_SIZE];
- p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, '>', 1, 0.5);
+ p->icom->write_read(p->icom, "CE\r", buf, MAX_MES_SIZE, ">", 1, 0.5);
}
}
}
@@ -159,7 +161,7 @@ dtp92_fcommand(
/* Return the dtp error code */
static inst_code
dtp92_command(dtp92 *p, char *in, char *out, int bsize, double to) {
- int rv = dtp92_fcommand(p, in, out, bsize, '>', 1, to);
+ int rv = dtp92_fcommand(p, in, out, bsize, ">", 1, to);
return dtp92_interp_code((inst *)p, rv);
}
@@ -210,11 +212,11 @@ dtp92_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
dtp92_command(p, "0PR\r", buf, MAX_MES_SIZE, 0.5);
dtp92_command(p, "0PR\r", buf, MAX_MES_SIZE, 0.5);
#else /* !ENABLE_USB */
- a1logd(p->log, 1, "dtp20: Failed to find USB connection to instrument\n");
+ a1logd(p->log, 1, "dtp92: Failed to find USB connection to instrument\n");
return inst_coms_fail;
#endif /* !ENABLE_USB */
- } else {
+ } else if (p->icom->port_type(p->icom) == icomt_serial) {
#ifdef ENABLE_SERIAL
a1logd(p->log, 2, "dtp92_init_coms: About to init Serial I/O\n");
@@ -287,11 +289,11 @@ dtp92_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
/* Set the handshaking */
- if ((ev = dtp92_command(p, fcc, buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, fcc, buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Change the baud rate to the rate we've been told */
- if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, '>', 1, .2)) != 0) {
+ if ((se = p->icom->write_read(p->icom, brc[bi], buf, MAX_MES_SIZE, ">", 1, .2)) != 0) {
if (extract_ec(buf) != DTP92_OK)
return inst_coms_fail;
}
@@ -304,15 +306,18 @@ dtp92_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
/* Loose a character (not sure why) */
- p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, '>', 1, 0.1);
+ p->icom->write_read(p->icom, "\r", buf, MAX_MES_SIZE, ">", 1, 0.1);
#else /* !ENABLE_SERIAL */
- a1logd(p->log, 1, "dtp20: Failed to find serial connection to instrument\n");
+ a1logd(p->log, 1, "dtp92: Failed to find serial connection to instrument\n");
return inst_coms_fail;
#endif /* !ENABLE_SERIAL */
+ } else {
+ a1logd(p->log, 1, "dtp92: wrong communications type for device!\n");
+ return inst_coms_fail;
}
/* Check instrument is responding, and reset it again. */
- if ((ev = dtp92_command(p, "\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok
+ if ((ev = dtp92_command(p, "\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok
|| (ev = dtp92_command(p, "0PR\r", buf, MAX_MES_SIZE, 2.0)) != inst_ok) {
a1logd(p->log, 1, "dtp92_init_coms: failed with ICOM 0x%x\n",ev);
@@ -348,8 +353,8 @@ dtp92_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
#endif /* NEVER */
- p->icom->del(p->icom); /* Since caller may not clean up */
- p->icom = NULL;
+// p->icom->del(p->icom); /* Since caller may not clean up */
+// p->icom = NULL;
return inst_coms_fail;
}
@@ -379,7 +384,7 @@ dtp92_init_inst(inst *pp) {
return ev;
/* Get the model and version number */
- if ((ev = dtp92_command(p, "SV\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "SV\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Check that it is a DTP92, DTP92Q or DTP94 */
@@ -395,36 +400,36 @@ dtp92_init_inst(inst *pp) {
if (p->itype == instDTP92) {
/* Turn echoing of characters off */
- if ((ev = dtp92_command(p, "DEC\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "DEC\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
}
if (p->itype == instDTP92) {
/* Set decimal point on */
- if ((ev = dtp92_command(p, "0106CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0106CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
}
/* Set color data separator to TAB */
- if ((ev = dtp92_command(p, "0207CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0207CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Set delimeter to CR */
- if ((ev = dtp92_command(p, "0008CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0008CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Set extra digit resolution (X10) */
- if ((ev = dtp92_command(p, "010ACF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "010ACF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
if (p->itype == instDTP92) {
/* Set absolute (luminance) calibration */
- if ((ev = dtp92_command(p, "0118CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0118CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
}
/* Set no black point subtraction */
- if ((ev = dtp92_command(p, "0019CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0019CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Set to factory calibration */
@@ -439,43 +444,43 @@ dtp92_init_inst(inst *pp) {
if (p->itype == instDTP92) {
/* Enable ABS mode (in case firmware doesn't default to this after EFC) */
- if ((ev = dtp92_command(p, "0118CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0118CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Disable -BLK mode (in case firmware doesn't default to this after EFC) */
- if ((ev = dtp92_command(p, "0019CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0019CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Set to transmit just the colorimetric data */
- if ((ev = dtp92_command(p, "0120CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0120CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Transmit colorimetric data as XYZ */
- if ((ev = dtp92_command(p, "0221CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0221CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Disable Luminance group */
- if ((ev = dtp92_command(p, "0022CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0022CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Disable Frequency group */
- if ((ev = dtp92_command(p, "0023CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0023CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Disable color temperature group */
- if ((ev = dtp92_command(p, "0024CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0024CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Disable RGB group */
- if ((ev = dtp92_command(p, "0025CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0025CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Disable pushbutton */
- if ((ev = dtp92_command(p, "DPB\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "DPB\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
/* Set sample size to 16 (default is 16) */
- if ((ev = dtp92_command(p, "10SS\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "10SS\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
}
p->trig = inst_opt_trig_user;
@@ -493,7 +498,7 @@ dtp92_init_inst(inst *pp) {
for (i = 0; i < 0x800; i++) {
sprintf(tb,"%04xRN\r",i);
- if ((ev = dtp92_command(p, tb, buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, tb, buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
if (sscanf(buf,"%x",&val) != 1)
return inst_coms_fail;
@@ -506,8 +511,8 @@ dtp92_init_inst(inst *pp) {
if (p->log->verb) {
int i, j;
- if ((ev = dtp92_command(p, "GI\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok) {
- a1logd(p->log, 1, "dtp20: GI command failed with ICOM err 0x%x\n",ev);
+ if ((ev = dtp92_command(p, "GI\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok) {
+ a1logd(p->log, 1, "dtp92: GI command failed with ICOM err 0x%x\n",ev);
return ev;
}
for (j = i = 0; ;i++) {
@@ -555,7 +560,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
#ifdef NEVER
if (p->itype == instDTP92) {
/* Set sample size to 31 (default is 16) for low level readings */
- if ((rv = dtp92_command(p, "1fSS\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((rv = dtp92_command(p, "1fSS\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return rv;
}
#endif
@@ -628,7 +633,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
#ifdef NEVER
if (p->itype == instDTP92) {
/* Set sample size back to 16 */
- if ((rv = dtp92_command(p, "10SS\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((rv = dtp92_command(p, "10SS\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return rv;
}
#endif
@@ -850,18 +855,6 @@ double *ref_rate
return inst_ok;
}
-/* Set the calibrated refresh rate in Hz. */
-/* Set refresh rate to 0.0 to mark it as invalid */
-/* Rates outside the range 5.0 to 150.0 Hz will return an error */
-static inst_code dtp92_set_refr_rate(inst *pp,
-double ref_rate
-) {
- dtp92 *p = (dtp92 *)pp;
-
- /* The DTP92 can't have a refresh rate set */
- return inst_unsupported;
-}
-
/* Error codes interpretation */
static char *
dtp92_interp_error(inst *pp, int ec) {
@@ -952,6 +945,7 @@ dtp92_interp_code(inst *pp, int ec) {
case DTP92_INTERNAL_ERROR:
return inst_internal_error | ec;
+ case DTP92_TIMEOUT:
case DTP92_COMS_FAIL:
return inst_coms_fail | ec;
@@ -1013,7 +1007,7 @@ inst3_capability *pcap3) {
if (p->itype == instDTP94) {
cap2 |= inst2_disptype;
} else {
- cap2 |= inst2_refresh_rate;
+ cap2 |= inst2_get_refresh_rate;
cap2 |= inst2_emis_refr_meas;
}
@@ -1163,13 +1157,13 @@ static inst_code set_disp_type(dtp92 *p, inst_disptypesel *dentry) {
inst_code ev;
if (p->icx == 0) { /* Generic/Non-specific */
- if ((ev = dtp92_command(p, "0016CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0016CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
} else if (p->icx == 1) { /* CRT */
- if ((ev = dtp92_command(p, "0116CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0116CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
} else if (p->icx == 2) { /* LCD */
- if ((ev = dtp92_command(p, "0216CF\r", buf, MAX_MES_SIZE, 0.2)) != inst_ok)
+ if ((ev = dtp92_command(p, "0216CF\r", buf, MAX_MES_SIZE, DEF_TIMEOUT)) != inst_ok)
return ev;
} else {
return inst_unsupported;
@@ -1310,7 +1304,6 @@ extern dtp92 *new_dtp92(icoms *icom, instType itype) {
p->calibrate = dtp92_calibrate;
p->col_cor_mat = dtp92_col_cor_mat;
p->get_refr_rate = dtp92_get_refr_rate;
- p->set_refr_rate = dtp92_set_refr_rate;
p->interp_error = dtp92_interp_error;
p->del = dtp92_del;
diff --git a/spectro/fakeread.c b/spectro/fakeread.c
index df77930..ce06e93 100644
--- a/spectro/fakeread.c
+++ b/spectro/fakeread.c
@@ -1,4 +1,4 @@
-/*
+ /*
* Argyll Color Correction System
* Fake print target chart reader - use ICC or MPP profile rather than instrument
*
@@ -15,6 +15,10 @@
/*
* TTBD:
+ This utility should really be merged with cctiff ?
+ ie. Add cgats i/o to cctiff
+ Add other processing steps such as TV, BT.1886, random to cctiff.
+
Do we need to deterct & mark display values normalized to Y = 100 ??
*/
@@ -46,21 +50,36 @@ void usage(char *diag, ...) {
va_end(args);
fprintf(stderr,"\n");
}
- fprintf(stderr,"usage: fakeread [-v] [-s] [separation.icm] profile.[%s|mpp|ti3] outfile\n",ICC_FILE_EXT_ND);
- fprintf(stderr," -v Verbose mode\n");
- fprintf(stderr," -s Lookup MPP spectral values\n");
- fprintf(stderr," -p Use separation profile\n");
+ /* Keep options in order of processing */
+ fprintf(stderr,"usage: fakeread [-options] profile.[%s|mpp|ti3] outfile\n",ICC_FILE_EXT_ND);
+ fprintf(stderr," -v [n] Verbose mode [level]\n");
+ fprintf(stderr," -e flag Video encode device input to sepration as:\n");
+ fprintf(stderr," n normal 0..1 full range RGB levels (default)\n");
+ fprintf(stderr," t (16-235)/255 \"TV\" RGB levels\n");
+ fprintf(stderr," 6 Rec601 YCbCr SD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 7 Rec709 1125/60Hz YCbCr HD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 5 Rec709 1250/50Hz YCbCr HD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 2 Rec2020 YCbCr UHD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," C Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," -p separation.%s Use device link separation profile on input\n",ICC_FILE_EXT_ND);
+ fprintf(stderr," -E flag Video decode separation device output. See -e above\n");
+ fprintf(stderr," -k file.cal Apply calibration (include in .ti3 output)\n");
+ fprintf(stderr," -i file.cal Include calibration in .ti3 output, but don't apply it\n");
+ fprintf(stderr," -K file.cal Apply inverse calibration\n");
+
+ fprintf(stderr," -r level Add average random deviation of <level>%% to device values (after sep. & cal.)\n");
+ fprintf(stderr," -0 pow Apply power to device chanel 0-9\n");
+ fprintf(stderr," -b output.%s Apply BT.1886-like mapping with effective gamma 2.2\n",ICC_FILE_EXT_ND);
+ fprintf(stderr," -b g.g:output.%s Apply BT.1886-like mapping with effective gamma g.g\n",ICC_FILE_EXT_ND);
+ fprintf(stderr," -B output.%s Apply BT.1886 mapping with technical gamma 2.4\n",ICC_FILE_EXT_ND);
+ fprintf(stderr," -B g.g:output.%s Apply BT.1886 mapping with technical gamma g.g\n",ICC_FILE_EXT_ND);
+ fprintf(stderr," -I intent r = relative colorimetric, a = absolute (default)\n");
+ fprintf(stderr," -A L,a,b Scale black point to target Lab value\n");
fprintf(stderr," -l Output Lab rather than XYZ\n");
- fprintf(stderr," -k file.cal Apply calibration (after sep.) and include in .ti3\n");
- fprintf(stderr," -i file.cal Include calibration in .ti3 (but don't apply it)\n");
- fprintf(stderr," -r level Add average random deviation of <level>%% to input device values (after sep. & cal.)\n");
- fprintf(stderr," -0 pow Apply power to input device chanel 0-9 (after sep. cal. & rand)\n");
+ fprintf(stderr," -s Lookup MPP spectral values\n");
fprintf(stderr," -R level Add average random deviation of <level>%% to output PCS values\n");
fprintf(stderr," -u Make random deviations have uniform distributions rather than normal\n");
fprintf(stderr," -S seed Set random seed\n");
- fprintf(stderr," -b L,a,b Scale black point to target Lab value\n");
- fprintf(stderr," -I intent r = relative colorimetric, a = absolute (default)\n");
- fprintf(stderr," [separation.%s] Device link separation profile\n",ICC_FILE_EXT_ND);
fprintf(stderr," profile.[%s|mpp|ti3] ICC, MPP profile or TI3 to use\n",ICC_FILE_EXT_ND);
fprintf(stderr," outfile Base name for input[ti1]/output[ti3] file\n");
exit(1);
@@ -69,9 +88,14 @@ void usage(char *diag, ...) {
int main(int argc, char *argv[])
{
int j;
- int fa,nfa; /* current argument we're looking at */
+ int fa, nfa, mfa; /* current argument we're looking at */
int verb = 0; /* Verbose flag */
int dosep = 0; /* Use separation before profile */
+ int bt1886 = 0; /* 1 to apply BT.1886 black point & effective gamma to input */
+ /* 2 to apply BT.1886 black point & technical gamma to input */
+ double egamma = 2.2; /* effective BT.1886 style gamma to ain for */
+ double tgamma = 2.4; /* technical BT.1886 style gamma to ain for */
+ bt1886_info bt; /* BT.1886 adjustment info */
int dolab = 0; /* Output Lab rather than XYZ */
int gfudge = 0; /* Do grey fudge, 1 = W->RGB, 2 = K->xxxK */
double chpow[10] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
@@ -80,12 +104,13 @@ int main(int argc, char *argv[])
int unidist = 0; /* Use uniform distribution of errors */
unsigned int seed = time(NULL); /* Random seed value */
double tbp[3] = { -1.0, 0.0, 0.0 }; /* Target black point */
- int applycal = 0; /* NZ to apply calibration */
+ int applycal = 0; /* 1 to apply calibration, 2 to apply inverse calibration */
static char sepname[MAXNAMEL+1] = { 0 }; /* ICC separation profile */
static char calname[MAXNAMEL+1] = { 0 }; /* device calibration */
static char profname[MAXNAMEL+1] = { 0 }; /* ICC or MPP Profile name */
static char inname[MAXNAMEL+1] = { 0 }; /* Input cgats file base name */
static char outname[MAXNAMEL+1] = { 0 }; /* Output cgats file base name */
+ static char oprofname[MAXNAMEL+1] = { 0 }; /* BT.1886 output profile name */
cgats *icg; /* input cgats structure */
cgats *ocg; /* output cgats structure */
int nmask = 0; /* Test chart device colorant mask */
@@ -96,7 +121,11 @@ int main(int argc, char *argv[])
int fi; /* Colorspace index */
int inti3 = 0; /* Input is a renamed .ti3 file rather than .ti1 */
- /* ICC separation device link profile */
+ /* TV encode/decode of separation/calibration device link */
+ int in_tvenc = 0; /* 1 to use RGB Video Level encoding, 2 = Rec601, etc. */
+ int out_tvenc = 0; /* 1 to use RGB Video Level encoding, 2 = Rec601, etc. */
+
+ /* ICC separation/calibration device link profile */
icmFile *sep_fp = NULL; /* Color profile file */
icc *sep_icco = NULL; /* Profile object */
icmLuBase *sep_luo = NULL; /* Conversion object */
@@ -114,6 +143,7 @@ int main(int argc, char *argv[])
icmFile *icc_fp = NULL; /* Color profile file */
icc *icc_icco = NULL; /* Profile object */
icmLuBase *icc_luo = NULL; /* Conversion object */
+ icmLuAlgType alg; /* Algorithm */
/* MPP profile based */
mpp *mlu = NULL; /* Conversion object */
@@ -146,6 +176,7 @@ int main(int argc, char *argv[])
usage("Too few arguments");
/* Process the arguments */
+ mfa = 2; /* Minimum final 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 */
@@ -155,7 +186,7 @@ int main(int argc, char *argv[])
na = &argv[fa][2]; /* next is directly after flag */
else
{
- if ((fa+1) < argc)
+ if ((fa+1+mfa) < argc)
{
if (argv[fa+1][0] != '-')
{
@@ -169,17 +200,93 @@ int main(int argc, char *argv[])
usage("Usage requested");
/* Verbose */
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V')
+ else if (argv[fa][1] == 'v') {
verb = 1;
+ if (na != NULL && na[0] >= '0' && na[0] <= '9') {
+ verb = atoi(na);
+ fa = nfa;
+ }
+ }
+
/* Spectral MPP lookup */
else if (argv[fa][1] == 's')
dospec = 1;
+ /* Video RGB encoding */
+ else if (argv[fa][1] == 'e'
+ || argv[fa][1] == 'E') {
+ int enc;
+ if (na == NULL) usage("Video encodong flag (-e/E) needs an argument");
+ switch (na[0]) {
+ case 'n': /* Normal */
+ enc = 0;
+ break;
+ case 't': /* TV 16 .. 235 */
+ enc = 1;
+ break;
+ case '6': /* Rec601 YCbCr */
+ enc = 2;
+ break;
+ case '7': /* Rec709 1150/60/2:1 YCbCr */
+ enc = 3;
+ break;
+ case '5': /* Rec709 1250/50/2:1 YCbCr (HD) */
+ enc = 4;
+ break;
+ case '2': /* Rec2020 Non-constant Luminance YCbCr (UHD) */
+ enc = 5;
+ break;
+ case 'C': /* Rec2020 Constant Luminance YCbCr (UHD) */
+ enc = 6;
+ break;
+ default:
+ usage("Video encoding (-E) argument not recognised");
+ }
+ if (argv[fa][1] == 'e')
+ in_tvenc = enc;
+ else
+ out_tvenc = enc;
+ fa = nfa;
+ }
+
/* Separation */
- else if (argv[fa][1] == 'p' || argv[fa][1] == 'P')
+ else if (argv[fa][1] == 'p') {
dosep = 1;
+ fa = nfa;
+ if (na == NULL) usage("Expected an argument to -p");
+ strncpy(sepname,na,MAXNAMEL); sepname[MAXNAMEL] = '\000';
+ }
+
+ /* BT.1886 modifier */
+ else if (argv[fa][1] == 'b'
+ || argv[fa][1] == 'B') {
+ char *cp;
+
+ bt1886 = 1;
+ if (argv[fa][1] == 'B')
+ bt1886 = 2;
+
+ if (na == NULL) usage("BT.1886 flag (-%c) needs an argument",argv[fa][1]);
+ fa = nfa;
+
+ if ((cp = strchr(na, ':')) != NULL) {
+ double gamma = 0.0;
+ *cp = '\000';
+ cp++;
+ gamma = atof(na);
+ if (gamma < 0.01 || gamma > 10.0) usage("BT.1886 gamma is out of range");
+ if (bt1886 == 1)
+ egamma = gamma;
+ else
+ tgamma = gamma;
+ } else {
+ cp = na;
+ }
+ strncpy(oprofname,cp,MAXNAMEL); oprofname[MAXNAMEL] = '\000';
+ }
+
/* Lab */
else if (argv[fa][1] == 'l' || argv[fa][1] == 'L')
dolab = 1;
@@ -197,8 +304,12 @@ int main(int argc, char *argv[])
}
/* calibration to device values */
- else if (argv[fa][1] == 'k' || argv[fa][1] == 'i') {
- if (argv[fa][1] == 'k')
+ else if (argv[fa][1] == 'k'
+ || argv[fa][1] == 'K'
+ || argv[fa][1] == 'i') {
+ if (argv[fa][1] == 'K')
+ applycal = 2;
+ else if (argv[fa][1] == 'k')
applycal = 1;
else
applycal = 0;
@@ -233,8 +344,8 @@ int main(int argc, char *argv[])
}
/* Black point scale */
- else if (argv[fa][1] == 'b' || argv[fa][1] == 'B') {
- if (na == NULL) usage("Expect argument to -b");
+ else if (argv[fa][1] == 'A') {
+ if (na == NULL) usage("Expect argument to -A");
fa = nfa;
if (sscanf(na, " %lf , %lf , %lf ",&tbp[0], &tbp[1], &tbp[2]) != 3)
usage("Couldn't parse argument to -b");
@@ -266,12 +377,6 @@ int main(int argc, char *argv[])
break;
}
- /* Get the file name argument */
- if (dosep) {
- if (fa >= argc || argv[fa][0] == '-') usage("Missing separation profile filename argument");
- strncpy(sepname,argv[fa++],MAXNAMEL); sepname[MAXNAMEL] = '\000';
- }
-
if (fa >= argc || argv[fa][0] == '-') usage("Missing profile filename argument");
strncpy(profname,argv[fa++],MAXNAMEL); profname[MAXNAMEL] = '\000';
@@ -302,6 +407,13 @@ int main(int argc, char *argv[])
sep_luo->spaces(sep_luo, &sep_ins, &sep_inn, &sep_outs, NULL, NULL, NULL, NULL, NULL, NULL);
sep_nmask = icx_icc_to_colorant_comb(sep_ins, sep_icco->header->deviceClass);
}
+ if (in_tvenc && sep_ins != icSigRgbData)
+ error("Can only use TV encoding on sepration RGB input");
+ if (out_tvenc && sep_outs != icSigRgbData)
+ error("Can only use TV decoding on sepration RGB output");
+ } else {
+ if (in_tvenc || out_tvenc)
+ warning("TV encoding ignored because there is no sepration file");
}
/* Deal with calibration */
@@ -310,11 +422,14 @@ int main(int argc, char *argv[])
error("new_xcal failed");
if ((cal->read(cal, calname)) != 0)
error("%s",cal->err);
- if (verb)
- if (applycal)
+ if (verb) {
+ if (applycal == 1)
printf("Applying calibration curves from '%s'\n",calname);
+ else if (applycal == 2)
+ printf("Applying inverse calibration curves from '%s'\n",calname);
else
printf("Embedding calibration curves from '%s' in output\n",calname);
+ }
}
/* Deal with ICC profile */
@@ -345,7 +460,8 @@ int main(int argc, char *argv[])
}
/* Get details of conversion */
- icc_luo->spaces(icc_luo, &ins, &inn, &outs, &outn, NULL, NULL, NULL, NULL, NULL);
+ icc_luo->spaces(icc_luo, &ins, &inn, &outs, &outn, &alg, NULL, NULL, NULL, NULL);
+
cnv_nmask = icx_icc_to_colorant_comb(ins, icc_icco->header->deviceClass);
if (dospec)
@@ -531,6 +647,105 @@ int main(int argc, char *argv[])
free(ti3_bident);
}
+ /* Dealy with BT.1886 processing */
+ if (bt1886) {
+ icmFile *ofp = NULL; /* Output Color profile file */
+ icc *oicco = NULL; /* Output Profile object */
+ icmLuBase *oluo = NULL; /* Output Conversion object */
+ icmLuMatrix *lu; /* Input profile lookup */
+ double bp[3], rgb[3];
+
+ if (icc_luo == NULL)
+ error ("Can only use BT.1886 with an ICC profile");
+
+ /* Check input profile is an RGB matrix profile */
+ if (alg != icmMatrixFwdType
+ || ins != icSigRgbData)
+ error("BT.1886 mode only works with an RGB matrix input profile");
+
+ lu = (icmLuMatrix *)icc_luo; /* Safe to coerce - we have checked it's matrix. */
+
+ /* Open up output profile used for BT.1886 black point */
+ if ((ofp = new_icmFileStd_name(oprofname,"r")) == NULL)
+ error ("Can't open file '%s'",oprofname);
+
+ if ((oicco = new_icc()) == NULL)
+ error ("Creation of ICC object failed");
+
+ if (oicco->read(oicco,ofp,0))
+ error ("Unable to read '%s'",oprofname);
+
+ if ((oluo = oicco->get_luobj(oicco, icmFwd, icRelativeColorimetric,
+ icSigXYZData, icmLuOrdNorm)) == NULL)
+ error("get output ICC lookup object failed: %d, %s",oicco->errc,oicco->err);
+
+ /* We're assuming that the input space has a perfect black point... */
+
+ /* Lookup the ouput black point in XYZ PCS. We're assuming monotonicity.. */
+ bp[0] = bp[1] = bp[2] = 0.0;
+ oluo->lookup(oluo, bp, bp);
+
+ /* Done with output profile */
+ oluo->del(oluo);
+ oicco->del(oicco);
+ ofp->del(ofp);
+
+ if (bt1886 == 1) { /* Using effective gamma */
+ tgamma = xicc_tech_gamma(egamma, bp[1]);
+ if (verb)
+ printf("BT.1886: Technical gamma %f used to achieve effective gamma %f\n",
+ tgamma, egamma);
+ } else {
+ if (verb)
+ printf("BT.1886: Using technical gamma %f\n",tgamma);
+ }
+
+ bt1886_setup(&bt, bp, tgamma);
+
+ if (verb) {
+ printf("BT.1886: target out black rel XYZ = %f %f %f, Lab %f %f %f\n",
+ bp[0],bp[1],bp[2], bt.outL, bt.tab[0], bt.tab[1]);
+ printf("BT.1886: Y input offset = %f\n", bt.ingo);
+ printf("BT.1886: Y output scale = %f\n", bt.outsc);
+ }
+
+ /* Check black point now produced by input profile with bt.1886 adjustment */
+ rgb[0] = rgb[1] = rgb[2] = 0.0;
+ lu->fwd_curve(lu, rgb, rgb);
+ lu->fwd_matrix(lu, rgb, rgb);
+ bt1886_apply(&bt, lu, rgb, rgb);
+ if (verb) printf("BT.1886: check input black point rel. XYZ %f %f %f\n", rgb[0],rgb[1],rgb[2]);
+ if (verb > 1) {
+ int i, no = 21;
+
+ /* Overral rendering curve from video in to output target */
+ printf("BT.1886: overall rendering\n");
+ for (i = 0; i < no; i++) {
+ double v = i/(no-1.0), vv;
+ double vi[3], vo[3], Lab[3];
+ double loglog = 0.0;
+
+ if (v <= 0.081)
+ vv = v/4.5;
+ else
+ vv = pow((0.099 + v)/1.099, 1.0/0.45);
+
+ vi[0] = vv * 0.9642; /* To D50 XYZ */
+ vi[1] = vv * 1.0000;
+ vi[2] = vv * 0.8249;
+
+ bt1886_apply(&bt, lu, vo, vi); /* BT.1886 mapping */
+
+ icmXYZ2Lab(&icmD50, Lab, vo);
+
+ if (v > 1e-9 && vo[1] > 1e-9 && fabs(v - 1.0) > 1e-9)
+ loglog = log(vo[1])/log(v);
+
+ printf(" In %5.1f%% -> XYZ in %f -> bt.1886 %f, log/log %.3f, Lab %f %f %f \n",v * 100.0,vi[1],vo[1], loglog, Lab[0], Lab[1], Lab[2]);
+ }
+ }
+ }
+
/* Some sanity checking */
if (tbp[0] >= 0.0 && icc_luo == NULL)
error("Black scaling only works with ICC profile");
@@ -642,6 +857,9 @@ int main(int argc, char *argv[])
if ((ti = icg->find_kword(icg, 0, "FULL_SPREAD_PATCHES")) >= 0)
ocg->add_kword(ocg, 0, "FULL_SPREAD_PATCHES",icg->t[0].kdata[ti], NULL);
+ if ((ti = icg->find_kword(icg, 0, "DARK_REGION_EMPHASIS")) >= 0)
+ ocg->add_kword(ocg, 0, "DARK_REGION_EMPHASIS",icg->t[0].kdata[ti], NULL);
+
if (icc_luo == NULL) { /* If MPP profile, we know what the target instrument is */
ocg->add_kword(ocg, 0, "TARGET_INSTRUMENT", inst_name(itype) , NULL);
}
@@ -842,13 +1060,62 @@ int main(int argc, char *argv[])
}
}
- if (dosep)
+ if (dosep) {
+ if (in_tvenc != 0) {
+ if (in_tvenc == 1) { /* Video 16-235 range */
+ icmRGB_2_VidRGB(dev, dev);
+ } else if (in_tvenc == 2) { /* Rec601 YCbCr */
+ icmRec601_RGBd_2_YPbPr(dev, dev);
+ icmRecXXX_YPbPr_2_YCbCr(dev, dev);
+ } else if (in_tvenc == 3) { /* Rec709 YCbCr */
+ icmRec709_RGBd_2_YPbPr(dev, dev);
+ icmRecXXX_YPbPr_2_YCbCr(dev, dev);
+ } else if (out_tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ icmRec709_50_RGBd_2_YPbPr(dev, dev);
+ icmRecXXX_YPbPr_2_YCbCr(dev, dev);
+ } else if (out_tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRec2020_NCL_RGBd_2_YPbPr(dev, dev);
+ icmRecXXX_YPbPr_2_YCbCr(dev, dev);
+ } else if (out_tvenc == 6) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRec2020_CL_RGBd_2_YPbPr(dev, dev);
+ icmRecXXX_YPbPr_2_YCbCr(dev, dev);
+ }
+ }
+
if (sep_luo->lookup(sep_luo, sep, dev) > 1)
error ("%d, %s",icc_icco->errc,icc_icco->err);
+ if (out_tvenc != 0) {
+ if (out_tvenc == 1) { /* Video 16-235 range */
+ icmVidRGB_2_RGB(sep, sep);
+ } else if (out_tvenc == 2) { /* Rec601 YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(sep, sep);
+ icmRec601_YPbPr_2_RGBd(sep, sep);
+ } else if (out_tvenc == 3) { /* Rec709 1150/60/2:1 YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(sep, sep);
+ icmRec709_YPbPr_2_RGBd(sep, sep);
+ } else if (out_tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(sep, sep);
+ icmRec709_50_YPbPr_2_RGBd(sep, sep);
+ } else if (out_tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(sep, sep);
+ icmRec2020_NCL_YPbPr_2_RGBd(sep, sep);
+ } else if (out_tvenc == 6) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(sep, sep);
+ icmRec2020_CL_YPbPr_2_RGBd(sep, sep);
+ }
+ }
+ }
+
/* Do calibration */
- if (applycal && cal != NULL)
- cal->interp(cal, sep, sep);
+ if (applycal && cal != NULL) {
+ if (applycal == 1)
+ cal->interp(cal, sep, sep);
+ else if (applycal == 2) {
+ if (cal->inv_interp(cal, sep, sep))
+ warning("Inverse calibration of patch %d failed",i+1);
+ }
+ }
/* Add randomness and non-linearity to device values. */
/* rdlevel = avg. dev. */
@@ -875,8 +1142,21 @@ int main(int argc, char *argv[])
/* Do color conversion */
if (icc_luo != NULL) {
- if (icc_luo->lookup(icc_luo, PCS, sep) > 1)
- error ("%d, %s",icc_icco->errc,icc_icco->err);
+ if (bt1886) {
+ icmLuMatrix *lu = (icmLuMatrix *)icc_luo; /* Safe to coerce */
+//printf("Matrix dev in: %s\n",icmPdv(inn, sep));
+ lu->fwd_curve(lu, sep, sep);
+//printf("Matrix after in curve: %s\n",icmPdv(inn, sep));
+ lu->fwd_matrix(lu, PCS, sep);
+//printf("Matrix after matrix XYZ %s Lab %s\n",icmPdv(3, PCS), icmPLab(PCS));
+ bt1886_apply(&bt, lu, PCS, PCS);
+//printf("Matrix after bt1186 XYZ %s Lab %s\n",icmPdv(3, PCS), icmPLab(PCS));
+ lu->fwd_abs(lu, PCS, PCS);
+//printf("Matrix after abs %s\n",icmPdv(3, PCS));
+ } else {
+ if (icc_luo->lookup(icc_luo, PCS, sep) > 1)
+ error ("%d, %s",icc_icco->errc,icc_icco->err);
+ }
if (tbp[0] >= 0) { /* Doing black point scaling */
@@ -913,7 +1193,7 @@ int main(int argc, char *argv[])
}
}
/* Copy best value over */
- if (!dosep) /* Doesn't make sense for separation */
+ if (!dosep) /* Doesn't make sense for separation ??? */
for (j = 0; j < nchan; j++) {
dev[j] = *((double *)ti3->t[0].fdata[bix][ti3_chix[j]]) / 100.0;
}
@@ -949,8 +1229,12 @@ int main(int argc, char *argv[])
/* Add randomness. rplevel is avg. dev. */
/* Note PCS is 0..100 XYZ or Lab at this point */
+ /* Adding uniform error to XYZ produces unreasonable */
+ /* bumpiness near black, so scale it by Y */
if (rplevel > 0.0) {
- double opcs[3];
+ double opcs[3], ll = 1.0;
+ if (!dolab)
+ ll = 0.01 * PCS[1];
for (j = 0; j < 3; j++) {
double dv = PCS[j];
double rr;
@@ -959,7 +1243,7 @@ int main(int argc, char *argv[])
rr = 100.0 * d_rand(-2.0 * rplevel, 2.0 * rplevel);
else
rr = 100.0 * 1.2533 * rplevel * norm_rand();
- dv += rr;
+ dv += ll * rr;
/* Don't let L*, X, Y or Z go negative */
if ((!dolab || j == 0) && dv < 0.0)
diff --git a/spectro/hcfr.c b/spectro/hcfr.c
index 9ec6be9..c67a419 100644
--- a/spectro/hcfr.c
+++ b/spectro/hcfr.c
@@ -78,7 +78,7 @@ hcfr_command(
) {
int rv, se;
- if ((se = p->icom->write_read(p->icom, in, out, bsize, '\n', 1, to)) != 0) {
+ if ((se = p->icom->write_read(p->icom, in, out, bsize, "\n", 1, to)) != 0) {
int ec;
a1logd(p->log, 1, "hcfr_command: serial i/o failure on write_read '%s'\n",icoms_fix(in));
return hcfr_interp_code((inst *)p, icoms2hcfr_err(se));
@@ -370,6 +370,9 @@ hcfr_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
if (p->icom->port_type(p->icom) != icomt_usb) {
a1logd(p->log, 1, "hcfr_init_coms: expect hcfr to be USB\n");
return hcfr_interp_code((inst *)p, HCFR_UNKNOWN_MODEL);
+ } else {
+ a1logd(p->log, 1, "hcfr_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
/* Set config, interface, "Serial" write & read end points */
@@ -530,8 +533,8 @@ double mtx[3][3]
icmSetUnity3x3(p->ccmat);
} else {
if (p->cbid == 0) {
- a1loge(p->log, 1, "hcfr: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
+ a1loge(p->log, 1, "hcfr: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
}
icmCpy3x3(p->ccmat, mtx);
}
diff --git a/spectro/hidio.c b/spectro/hidio.c
index 595b707..918bb83 100644
--- a/spectro/hidio.c
+++ b/spectro/hidio.c
@@ -18,11 +18,38 @@
/*
* TTBD:
- * As usual, Apple seem to have deprecated the routines used here.
+ * As usual, Apple seem to have deprecated the routines used here,
+ * and reccommend a new API for 10.5 and latter, so we should
+ * switch to using this if compiled on 10.6 or latter.
* See IOHIDDeviceGetReportWithCallback & IOHIDDeviceSetReportWithCallback
+ * <https://developer.apple.com/library/mac/technotes/tn2187/_index.html>
* for info on the replacements.
*/
+/*
+ New 10.5 and later code is not completely developed/debugged
+ - the read and write routines simply error out.
+
+ Perhaps we should try using
+
+ IOHIDDeviceRegisterInputReportCallback()
+ + Handle_IOHIDDeviceIOHIDReportCallback()
+ + what triggers it ?? How is this related to GetReport ?
+
+ + OHIDDeviceGetReportWithCallback()
+ + Handle_IOHIDDeviceGetReportCallback()
+
+ + IOHIDDeviceSetReportWithCallback()
+ + Handle_IOHIDDeviceSetReportCallback()
+
+ Plus IOHIDQueueScheduleWithRunLoop()
+ IOHIDQueueUnscheduleFromRunLoop()
+
+ + we probably have to call the run loop ?
+
+*/
+#undef USE_NEW_OSX_CODE
+
/* These routines supliement the class code in ntio.c and unixio.c */
/* with HID specific access routines for devices running on operating */
/* systems where this is desirable. */
@@ -234,6 +261,88 @@ int hid_get_paths(icompaths *p) {
#endif /* NT */
#ifdef __APPLE__
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ {
+ CFAllocatorContext alocctx;
+ IOHIDManagerRef mref;
+ CFSetRef setref;
+ CFIndex count, i;
+ IOHIDDeviceRef *values;
+
+ /* Create HID Manager reference */
+ if ((mref = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "hid_get_paths() IOHIDManagerCreate returned NULL\n");
+ return ICOM_SYS;
+ }
+
+ /* Set to match all HID devices */
+ IOHIDManagerSetDeviceMatching(mref, NULL);
+
+ /* Enumerate the devices (doesn't seem to have to open) */
+ if ((setref = IOHIDManagerCopyDevices(mref)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "hid_get_paths() IOHIDManagerCopyDevices failed\n");
+ CFRelease(mref);
+ return ICOM_SYS;
+ }
+
+ count = CFSetGetCount(setref);
+ if ((values = (IOHIDDeviceRef *)calloc(sizeof(IOHIDDeviceRef), count)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "hid_get_paths() calloc failed!\n");
+ CFRelease(setref);
+ CFRelease(mref);
+ return ICOM_SYS;
+ }
+
+ CFSetGetValues(setref, (const void **)values);
+
+ for (i = 0; i < count; i++) {
+ CFNumberRef vref, pref; /* HID Vendor and Product ID propeties */
+ CFNumberRef lidpref; /* Location ID properties */
+ unsigned int vid = 0, pid = 0, lid = 0;
+ instType itype;
+ IOHIDDeviceRef ioob = values[i]; /* HID object found */
+
+ if ((vref = IOHIDDeviceGetProperty(ioob, CFSTR(kIOHIDVendorIDKey))) != NULL) {
+ CFNumberGetValue(vref, kCFNumberSInt32Type, &vid);
+ CFRelease(vref);
+ }
+ if ((pref = IOHIDDeviceGetProperty(ioob, CFSTR(kIOHIDProductIDKey))) != NULL) {
+ CFNumberGetValue(pref, kCFNumberSInt32Type, &pid);
+ CFRelease(vref);
+ }
+ if ((lidpref = IOHIDDeviceGetProperty(ioob, CFSTR("LocationID"))) != NULL) {
+ CFNumberGetValue(lidpref, kCFNumberIntType, &lid);
+ CFRelease(lidpref);
+ }
+
+ /* If it's a device we're looking for */
+ if ((itype = inst_usb_match(vid, pid, 0)) != instUnknown) {
+ struct hid_idevice *hidd;
+ char pname[400];
+
+ a1logd(p->log, 2, "found HID device '%s' lid 0x%x that we're looking for\n",inst_name(itype), lid);
+
+ /* Create human readable path/identification */
+ sprintf(pname,"hid%d: (%s)", lid >> 20, inst_name(itype));
+
+ if ((hidd = (struct hid_idevice *)calloc(sizeof(struct hid_idevice), 1)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "hid_get_paths calloc failed!\n");
+ return ICOM_SYS;
+ }
+ hidd->lid = lid;
+ CFRetain(ioob); /* We're retaining it */
+ hidd->ioob = ioob;
+
+ /* Add the path to the list */
+ p->add_hid(p, pname, vid, pid, 0, hidd, itype);
+ }
+ }
+ /* Clean up */
+ free(values);
+ CFRelease(setref);
+ CFRelease(mref);
+ }
+#else /* < 1060 */
{
kern_return_t kstat;
CFMutableDictionaryRef sdict; /* HID Device dictionary */
@@ -307,6 +416,7 @@ int hid_get_paths(icompaths *p) {
}
IOObjectRelease(mit); /* Release the itterator */
}
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
#endif /* __APPLE__ */
#if defined(UNIX_X11)
@@ -371,47 +481,35 @@ int hid_get_paths(icompaths *p) {
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Close an open HID port */
-/* If we don't do this, the port and/or the device may be left in an unusable state. */
-void hid_close_port(icoms *p) {
-
- a1logd(p->log, 8, "hid_close_port: called\n");
-
- if (p->is_open && p->hidd != NULL) {
-
-#if defined(NT)
- CloseHandle(p->hidd->ols.hEvent);
- CloseHandle(p->hidd->fh);
-#endif /* NT */
-
#ifdef __APPLE__
- IOObjectRelease(p->hidd->port);
- p->hidd->port = 0;
-
- if (p->hidd->evsrc != NULL)
- CFRelease(p->hidd->evsrc);
- p->hidd->evsrc = NULL;
- p->hidd->rlr = NULL;
+/* HID Interrupt callback for OS X */
+/* This seems to only get called when the run loop is active. */
+static void hid_read_callback(
+void *target,
+IOReturn result,
+void *refcon,
+void *sender,
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+uint32_t size
+#else
+UInt32 size
+#endif
+) {
+ icoms *p = (icoms *)target;
- if ((*p->hidd->device)->close(p->hidd->device) != kIOReturnSuccess) {
- a1loge(p->log, ICOM_SYS, "hid_close_port: closing HID port '%s' failed",p->name);
- return;
- }
+ a1logd(p->log, 8, "HID callback called with size %d, result 0x%x\n",size,result);
+ p->hidd->result = result;
+ p->hidd->bread = size;
+ if (p->hidd->rlr != NULL)
+ CFRunLoopStop(p->hidd->rlr); /* We're done */
+ else
+ a1logd(p->log, 8, "HID callback has no run loop\n");
+}
- if ((*p->hidd->device)->Release(p->hidd->device) != kIOReturnSuccess) {
- a1loge(p->log, ICOM_SYS, "hid_close_port: Releasing HID port '%s' failed",p->name);
- }
- p->hidd->device = NULL;
#endif /* __APPLE__ */
- p->is_open = 0;
- a1logd(p->log, 8, "hid_close_port: has been released and closed\n");
- }
-
- /* Find it and delete it from our static cleanup list */
- usb_delete_from_cleanup_list(p);
-}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Open an HID port for all our uses. */
@@ -461,6 +559,15 @@ char **pnames /* List of process names to try and kill before opening */
#endif /* NT */
#ifdef __APPLE__
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ {
+ /* Open the device */
+ if (IOHIDDeviceOpen(p->hidd->ioob, kIOHIDOptionsTypeSeizeDevice) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "hid_open_port: Opening HID device '%s' failed",p->name);
+ return ICOM_SYS;
+ }
+ }
+#else /* < 1060 */
{
IOCFPlugInInterface **piif = NULL;
IOReturn result;
@@ -505,7 +612,25 @@ char **pnames /* List of process names to try and kill before opening */
return ICOM_SYS;
}
+ /* Setup for read callback */
+ p->hidd->result = -1;
+ p->hidd->bread = 0;
+
+ /* And set read callback routine */
+ if ((*(p->hidd->device))->setInterruptReportHandlerCallback(p->hidd->device,
+ p->hidd->rbuf, 256, hid_read_callback, (void *)p, NULL) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "icoms_hid_read: Setting callback handler for "
+ "HID '%s' failed\n", p->name);
+ return ICOM_SYS;
+ }
+
+ if ((*(p->hidd->device))->startAllQueues(p->hidd->device) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "icoms_hid_read: Starting queues for "
+ "HID '%s' failed\n", p->name);
+ return ICOM_SYS;
+ }
}
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
#endif /* __APPLE__ */
p->is_open = 1;
@@ -518,32 +643,64 @@ char **pnames /* List of process names to try and kill before opening */
return ICOM_OK;
}
-/* ========================================================= */
+/* Close an open HID port */
+/* If we don't do this, the port and/or the device may be left in an unusable state. */
+void hid_close_port(icoms *p) {
+
+ a1logd(p->log, 8, "hid_close_port: called\n");
+
+ if (p->is_open && p->hidd != NULL) {
+
+#if defined(NT)
+ CloseHandle(p->hidd->ols.hEvent);
+ CloseHandle(p->hidd->fh);
+#endif /* NT */
#ifdef __APPLE__
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ if (IOHIDDeviceClose(p->hidd->ioob, kIOHIDOptionsTypeNone) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "hid_close_port: closing HID port '%s' failed",p->name);
+ return;
+ }
+#else /* < 1060 */
+ if ((*(p->hidd->device))->stopAllQueues(p->hidd->device) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "icoms_hid_read: Stopping queues for "
+ "HID '%s' failed\n", p->name);
+ return;
+ }
-/* HID Interrupt callback for OS X */
-static void hid_read_callback(
-void *target,
-IOReturn result,
-void *refcon,
-void *sender,
-#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
-uint32_t size
-#else
-UInt32 size
-#endif
-) {
- icoms *p = (icoms *)target;
+ IOObjectRelease(p->hidd->port);
+ p->hidd->port = 0;
- a1logd(p->log, 8, "HID callback called with size %d, result 0x%x\n",size,result);
- p->hidd->result = result;
- p->hidd->bread = size;
- CFRunLoopStop(p->hidd->rlr); /* We're done */
-}
+ if (p->hidd->evsrc != NULL)
+ CFRelease(p->hidd->evsrc);
+ p->hidd->evsrc = NULL;
+
+ p->hidd->rlr = NULL;
+ if ((*p->hidd->device)->close(p->hidd->device) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "hid_close_port: closing HID port '%s' failed",p->name);
+ return;
+ }
+
+ if ((*p->hidd->device)->Release(p->hidd->device) != kIOReturnSuccess) {
+ a1loge(p->log, ICOM_SYS, "hid_close_port: Releasing HID port '%s' failed",p->name);
+ }
+ p->hidd->device = NULL;
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
#endif /* __APPLE__ */
+ p->is_open = 0;
+ a1logd(p->log, 8, "hid_close_port: has been released and closed\n");
+ }
+
+ /* Find it and delete it from our static cleanup list */
+ usb_delete_from_cleanup_list(p);
+}
+
+
+/* ========================================================= */
+
/* HID Interrupt pipe Read */
/* Don't retry on a short read, return ICOM_SHORT. */
/* [Probably uses the control pipe. We need a different */
@@ -558,6 +715,8 @@ icoms_hid_read(icoms *p,
int retrv = ICOM_OK; /* Returned error value */
int bread = 0;
+ a1logd(p->log, 8, "icoms_hid_read: %d bytes, tout %f\n",bsize,tout);
+
if (!p->is_open) {
a1loge(p->log, ICOM_SYS, "icoms_hid_read: device not initialised\n");
return ICOM_SYS;
@@ -599,52 +758,108 @@ icoms_hid_read(icoms *p,
#endif /* NT */
#ifdef __APPLE__
-#ifndef NEVER
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
{
IOReturn result;
+ CFIndex lbsize = bsize;
+
+ /* Normally the _write should have set the ->rlr */
+ /* but this may not be so if we are doing a flush ? */
+ if (p->hidd->rlr == NULL) {
+ p->hidd->rlr = CFRunLoopGetCurrent();
+ p->hidd->result = -1;
+ p->hidd->bread = 0;
+ }
- /* Setup for callback */
- p->hidd->result = -1;
- p->hidd->bread = 0;
+ IOHIDDeviceScheduleWithRunLoop(p->hidd->ioob, p->hidd->rlr, kCFRunLoopDefaultMode);
- if ((*(p->hidd->device))->setInterruptReportHandlerCallback(p->hidd->device,
- rbuf, bsize, hid_read_callback, (void *)p, NULL) != kIOReturnSuccess) {
- a1loge(p->log, ICOM_SYS, "icoms_hid_read: Setting callback handler for "
- "HID '%s' failed\n", p->name);
- return ICOM_SYS;
+#ifndef NEVER
+ /* This doesn't work. Don't know why */
+ /* Returns 0xe000404f = kIOUSBPipeStalled, Pipe has stalled, error needs to be cleared */
+ if ((result = IOHIDDeviceGetReportWithCallback(
+ p->hidd->ioob,
+ kIOHIDReportTypeInput,
+ 9, /* Bulk or Interrupt transfer ??? - or wbuf[0] ?? */
+ (uint8_t *)rbuf,
+ &lbsize,
+ tout,
+ NULL, NULL)) != kIOReturnSuccess) {
+printf("~1 IOHIDDeviceGetReportWithCallback returned 0x%x\n",result);
+ /* (We could detect other error codes and translate them to ICOM) */
+ if (result == kIOReturnTimeout)
+ retrv = ICOM_TO;
+ else
+ retrv = ICOM_USBR;
+ } else {
+ bsize = lbsize;
+ bread = bsize;
}
- /* Call runloop, but exit after handling one callback */
- p->hidd->rlr = CFRunLoopGetCurrent();
- CFRunLoopAddSource(p->hidd->rlr, p->hidd->evsrc, kCFRunLoopDefaultMode);
+#else
+ /* This doesn't work. Don't know why */
+ /* Returns 0xe000404f = kIOUSBPipeStalled, Pipe has stalled, error needs to be cleared */
+ if ((result = IOHIDDeviceGetReport(
+ p->hidd->ioob,
+ kIOHIDReportTypeInput,
+ 9, /* Bulk or Interrupt transfer ??? - or wbuf[0] ?? */
+ (uint8_t *)rbuf,
+ &lbsize)) != kIOReturnSuccess) {
+printf("~1 IOHIDDeviceGet returned 0x%x\n",result);
+ /* (We could detect other error codes and translate them to ICOM) */
+ if (result == kIOReturnTimeout)
+ retrv = ICOM_TO;
+ else
+ retrv = ICOM_USBR;
+ } else {
+ bsize = lbsize;
+ bread = bsize;
+ }
+#endif
+
+ IOHIDDeviceUnscheduleFromRunLoop(p->hidd->ioob, p->hidd->rlr, kCFRunLoopDefaultMode);
+ p->hidd->rlr = NULL;
+ }
+#else /* < 1060 */
+#ifndef NEVER /* This works */
+ {
+ IOReturn result;
- if ((*(p->hidd->device))->startAllQueues(p->hidd->device) != kIOReturnSuccess) {
- a1loge(p->log, ICOM_SYS, "icoms_hid_read: Starting queues for "
- "HID '%s' failed\n", p->name);
+ if (bsize > HID_RBUF_SIZE) {
+ a1loge(p->log, ICOM_SYS, "icoms_hid_read: Requested more bytes that HID_RBUF_SIZE\n", p->name);
return ICOM_SYS;
}
+ /* Normally the _write should have set the ->rlr */
+ /* but this may not be so if we are doing a flush ? */
+ if (p->hidd->rlr == NULL) {
+ p->hidd->rlr = CFRunLoopGetCurrent();
+ p->hidd->result = -1;
+ p->hidd->bread = 0;
+ }
+
+ CFRunLoopAddSource(p->hidd->rlr, p->hidd->evsrc, kCFRunLoopDefaultMode);
+
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, tout, false);
- if ((*(p->hidd->device))->stopAllQueues(p->hidd->device) != kIOReturnSuccess) {
- a1loge(p->log, ICOM_SYS, "icoms_hid_read: Stopping queues for "
- "HID '%s' failed\n", p->name);
- return ICOM_SYS;
- }
if (result == kCFRunLoopRunTimedOut) {
retrv = ICOM_TO;
} else if (result != kCFRunLoopRunStopped) {
retrv = ICOM_USBR;
}
CFRunLoopRemoveSource(p->hidd->rlr, p->hidd->evsrc, kCFRunLoopDefaultMode);
+ p->hidd->rlr = NULL; /* Callback is invalid now */
if (p->hidd->result == -1) { /* Callback wasn't called */
retrv = ICOM_TO;
} else if (p->hidd->result != kIOReturnSuccess) {
a1loge(p->log, ICOM_SYS, "icoms_hid_read: Callback for "
"HID '%s' got unexpected return value\n", p->name);
+ p->hidd->result = -1; /* Result is now invalid */
+ p->hidd->bread = 0;
return ICOM_SYS;
}
bread = p->hidd->bread;
+ if (bread > 0)
+ memcpy(rbuf, p->hidd->rbuf, bread > HID_RBUF_SIZE ? HID_RBUF_SIZE : bread);
}
#else // NEVER
/* This doesn't work. Don't know why */
@@ -670,6 +885,7 @@ icoms_hid_read(icoms *p,
}
}
#endif // NEVER
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
#endif /* __APPLE__ */
if (breadp != NULL)
@@ -695,6 +911,8 @@ icoms_hid_write(icoms *p,
int retrv = ICOM_OK; /* Returned error value */
int bwritten = 0;
+ a1logd(p->log, 8, "icoms_hid_write: %d bytes, tout %f\n",bsize,tout);
+
if (!p->is_open) {
a1loge(p->log, ICOM_SYS, "icoms_hid_write: device not initialised\n");
return ICOM_SYS;
@@ -738,7 +956,57 @@ icoms_hid_write(icoms *p,
#endif /* NT */
#ifdef __APPLE__
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ {
+ IOReturn result;
+#ifdef NEVER
+ /* This doesn't work. Don't know why */
+ /* Returns 0xe000404f = kIOUSBPipeStalled, Pipe has stalled, error needs to be cleared */
+ /* if we did a read that has timed out */
+ /* Returns 0xe00002c7 = kIOReturnUnsupported, without the failed read
+ if ((result = IOHIDDeviceSetReportWithCallback(
+ p->hidd->ioob,
+ kIOHIDReportTypeOutput,
+ 9, /* Bulk or Interrupt transfer ??? - or wbuf[0] ?? */
+ (uint8_t *)wbuf,
+ bsize,
+ tout,
+ NULL, NULL)) != kIOReturnSuccess) {
+printf("~1 IOHIDDeviceSetReportWithCallback returned 0x%x\n",result);
+ /* (We could detect other error codes and translate them to ICOM) */
+ if (result == kIOReturnTimeout)
+ retrv = ICOM_TO;
+ else
+ retrv = ICOM_USBW;
+ } else {
+ bwritten = bsize;
+ }
+#else
+ /* This works, but has no timeout */
+ if ((result = IOHIDDeviceSetReport(
+ p->hidd->ioob,
+ kIOHIDReportTypeOutput,
+ 9, /* Bulk or Interrupt transfer ??? - or wbuf[0] ?? */
+ (uint8_t *)wbuf,
+ bsize)) != kIOReturnSuccess) {
+ /* (We could detect other error codes and translate them to ICOM) */
+ if (result == kIOReturnTimeout)
+ retrv = ICOM_TO;
+ else
+ retrv = ICOM_USBW;
+ } else {
+ bwritten = bsize;
+ }
+#endif
+ }
+#else /* < 1060 */
{
+ /* Clear any existing read message */
+ /* (We're assuming it's all write then read measages !!) */
+ p->hidd->rlr = CFRunLoopGetCurrent(); // Our thread's run loop
+ p->hidd->result = -1;
+ p->hidd->bread = 0;
+
IOReturn result;
if ((result = (*p->hidd->device)->setReport(
p->hidd->device,
@@ -757,6 +1025,7 @@ icoms_hid_write(icoms *p,
bwritten = bsize;
}
}
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
#endif /* __APPLE__ */
if (bwrittenp != NULL)
@@ -820,9 +1089,14 @@ int hid_copy_hid_idevice(icoms *d, icompath *s) {
}
#endif
#if defined(__APPLE__)
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ d->hidd->ioob = s->hidd->ioob;
+ CFRetain(d->hidd->ioob);
+#else
d->hidd->ioob = s->hidd->ioob;
IOObjectRetain(d->hidd->ioob);
-#endif
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
+#endif /* __APPLE__ */
#if defined (UNIX_X11)
#endif
return ICOM_OK;
@@ -838,9 +1112,14 @@ void hid_del_hid_idevice(struct hid_idevice *hidd) {
free(hidd->dpath);
#endif
#if defined(__APPLE__)
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ if (hidd->ioob != 0)
+ CFRelease(hidd->ioob);
+#else
if (hidd->ioob != 0)
IOObjectRelease(hidd->ioob);
-#endif
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
+#endif /* __APPLE__ */
#if defined (UNIX_X11)
#endif
free(hidd);
diff --git a/spectro/hidio.h b/spectro/hidio.h
index b25fe03..a7e94c8 100644
--- a/spectro/hidio.h
+++ b/spectro/hidio.h
@@ -60,6 +60,12 @@ struct hid_idevice {
OVERLAPPED ols; /* Overlapped structure for write/read */
#endif
#if defined(__APPLE__)
+# if defined(USE_NEW_OSX_CODE) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ int lid; /* Location ID */
+ IOHIDDeviceRef ioob; /* Object to open */
+ /* Stuff setup when device is open: */
+ CFRunLoopRef rlr;
+#else
int lid; /* Location ID */
io_object_t ioob; /* Object to open */
/* Stuff setup when device is open: */
@@ -68,7 +74,10 @@ struct hid_idevice {
CFRunLoopSourceRef evsrc;
CFRunLoopRef rlr;
IOReturn result;
+# define HID_RBUF_SIZE 1024
+ unsigned char rbuf[HID_RBUF_SIZE]; /* Buffer for read callback */
int bread; /* Bytes read by callback */
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED < 1060 */
#endif
#if defined (UNIX) && !defined(__APPLE__)
int temp; /* Shut the compiler up */
diff --git a/spectro/huey.c b/spectro/huey.c
index f8d8308..8c307ac 100644
--- a/spectro/huey.c
+++ b/spectro/huey.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 18/10/2006
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* (Based on i1disp.c)
@@ -61,7 +61,8 @@ static inst_code huey_interp_code(inst *pp, int ec);
static inst_code huey_check_unlock(huey *p);
#define CALFACTOR 3.428 /* Emissive magic calibration factor */
-#define AMB_SCALE_FACTOR 5.772e-3 /* Ambient mode scale factor */
+//#define AMB_SCALE_FACTOR 5.772e-3 /* Ambient mode scale factor Lux/pi*/
+#define AMB_SCALE_FACTOR 18.1333e-3 /* Ambient mode scale factor (Lux) */
/* This is only approximate, and were derived */
/* by matching readings from the i1pro. */
@@ -392,7 +393,7 @@ huey_rdreg_float(
if ((ev = huey_rdreg_word(p, &val, addr)) != inst_ok)
return ev;
- if (ev == 0xffffffff) {
+ if (val == 0xffffffff) {
return inst_ok;
}
@@ -823,7 +824,7 @@ huey_take_XYZ_measurement(
if (IMODETST(p->mode, inst_mode_emis_ambient)) {
if ((ev = huey_take_amb_measurement(p, 0, &XYZ[1])) != inst_ok)
return ev;
- XYZ[1] *= AMB_SCALE_FACTOR; /* Times aproximate fudge factor */
+ XYZ[1] *= AMB_SCALE_FACTOR; /* Times aproximate fudge factor to Lux */
XYZ[0] = icmD50.X * XYZ[1]; /* Convert to D50 neutral */
XYZ[2] = icmD50.Z * XYZ[1];
} else {
@@ -1048,7 +1049,7 @@ huey_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
} else {
a1logd(p->log, 1, "huey_init_coms: wrong communications type for device!\n");
- return huey_interp_code((inst *)p, HUEY_UNKNOWN_MODEL);
+ return inst_coms_fail;
}
if ((p->icom->vid == 0x0765 && p->icom->pid == 0x5001)
@@ -1146,7 +1147,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
int user_trig = 0;
int rv = inst_protocol_error;
-a1logd(p->log, 1, "huey: huey_read_sample called\n");
+ a1logd(p->log, 1, "huey: huey_read_sample called\n");
if (!p->gotcoms)
return inst_no_coms;
@@ -1160,7 +1161,6 @@ a1logd(p->log, 1, "huey: huey_read_sample called\n");
return inst_unsupported;
}
-a1logd(p->log, 1, "huey: about to wait for user trigger\n");
for (;;) {
if ((rv = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
if (rv == inst_user_abort)
@@ -1178,14 +1178,12 @@ a1logd(p->log, 1, "huey: about to wait for user trigger\n");
/* Progromatic Trigger */
} else {
-a1logd(p->log, 1, "huey: checking for abort\n");
/* Check for abort */
if (p->uicallback != NULL
&& (rv = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
return rv; /* Abort */
}
-a1logd(p->log, 1, "huey: about to call huey_take_XYZ_measurement\n");
/* Read the XYZ value */
if ((rv = huey_take_XYZ_measurement(p, val->XYZ)) != inst_ok) {
return rv;
@@ -1226,8 +1224,8 @@ double mtx[3][3]
icmSetUnity3x3(p->ccmat);
} else {
if (p->cbid == 0) {
- a1loge(p->log, 1, "huey: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
+ a1loge(p->log, 1, "huey: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
}
icmCpy3x3(p->ccmat, mtx);
}
diff --git a/spectro/i1d3.c b/spectro/i1d3.c
index 53b2f0c..cf0fc08 100644
--- a/spectro/i1d3.c
+++ b/spectro/i1d3.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 28/7/2011
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* (Based on huey.c)
@@ -58,6 +58,14 @@
#undef PLOT_SPECTRA /* Plot the sensor senitivity spectra */
#undef SAVE_SPECTRA /* Save the sensor senitivity spectra to "sensors.cmf" */
#undef PLOT_REFRESH /* Plot data used to determine refresh rate */
+#undef PLOT_UPDELAY /* Plot data used to determine display update delay */
+
+#undef DEBUG_TWEAKS /* Allow environment variable tweaks to int time etc. */
+/* I1D3_MIN_REF_QUANT_TIME in seconds. Default 0.05 */
+/* I1D3_MIN_INT_TIME in seconds. Default 0.4 for refresh displays */
+
+#define I1D3_MEAS_TIMEOUT 40.0 /* Longest reading timeout in seconds */
+ /* Typically 20.0 is the maximum needed. */
static inst_code i1d3_interp_code(inst *pp, int ec);
static inst_code i1d3_check_unlock(i1d3 *p);
@@ -145,7 +153,7 @@ static char *inst_desc(i1Disp3CC cc) {
case i1d3_rd_sensor:
return "ReadAnalogSensor";
case i1d3_get_diff:
- return "GetDiffuserPositio";
+ return "GetDiffuserPosition";
case i1d3_lockchal:
return "GetLockChallenge";
case i1d3_lockresp:
@@ -186,8 +194,14 @@ i1d3_command(
if (cmd == 0x00)
send[1] = (cc & 0xff); /* Minor command */
- if (!nd) a1logd(p->log, 4, "i1d3_command: Sending cmd '%s' args '%s'\n",
- inst_desc(cc), icoms_tohex(send, 8));
+ if (!nd) {
+ if (cc == i1d3_lockresp)
+ a1logd(p->log, 4, "i1d3_command: Sending cmd '%s' args '%s'\n",
+ inst_desc(cc), icoms_tohex(send, 64));
+ else
+ a1logd(p->log, 4, "i1d3_command: Sending cmd '%s' args '%s'\n",
+ inst_desc(cc), icoms_tohex(send, 8));
+ }
if (p->icom->port_type(p->icom) == icomt_hid) {
se = p->icom->hid_write(p->icom, send, 64, &wbytes, to);
@@ -196,6 +210,12 @@ i1d3_command(
}
if (se != 0) {
if (!nd) a1logd(p->log, 1, "i1d3_command: Command send failed with ICOM err 0x%x\n",se);
+ /* Flush any response */
+ if (ishid) {
+ p->icom->hid_read(p->icom, recv, 64, &rbytes, to);
+ } else {
+ p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, to);
+ }
amutex_unlock(p->lock);
return i1d3_interp_code((inst *)p, I1D3_COMS_FAIL);
}
@@ -213,7 +233,7 @@ i1d3_command(
p->icom->hid_read(p->icom, recv, 64, &rbytes, to);
} else {
p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, to);
- }
+ }
amutex_unlock(p->lock);
return rv;
}
@@ -228,6 +248,12 @@ i1d3_command(
}
if (se != 0) {
if (!nd) a1logd(p->log, 1, "i1d3_command: response read failed with ICOM err 0x%x\n",se);
+ /* Flush any extra response, in case responses are out of sync */
+ if (ishid) {
+ p->icom->hid_read(p->icom, recv, 64, &rbytes, 0.2);
+ } else {
+ p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, 0.2);
+ }
amutex_unlock(p->lock);
return i1d3_interp_code((inst *)p, I1D3_COMS_FAIL);
}
@@ -237,12 +263,13 @@ i1d3_command(
}
/* The first byte returned seems to be a command result error code. */
- /* The second byte is usually the command code being echo'd back, but not always. */
if (rv == inst_ok && recv[0] != 0x00) {
if (!nd) a1logd(p->log, 1, "i1d3_command: status byte != 00 = 0x%x\n",recv[0]);
rv = i1d3_interp_code((inst *)p, I1D3_BAD_RET_STAT);
}
+ /* The second byte is usually the command code being echo'd back, but not always. */
+ /* ie., get i1d3_get_diff returns the status instead. */
if (rv == inst_ok) {
if (cc != i1d3_get_diff) {
if (recv[1] != cmd) {
@@ -250,31 +277,35 @@ i1d3_command(
cmd,recv[1]);
rv = i1d3_interp_code((inst *)p, I1D3_BAD_RET_CMD);
}
+ } else { /* i1d3_get_diff as special case */
+ int i;
+ for (i = 2; i < 64; i++) {
+ if (recv[i] != 0x00) {
+ if (!nd) a1logd(p->log, 1, "i1d3_command: i1d3_get_diff not zero filled\n");
+ rv = i1d3_interp_code((inst *)p, I1D3_BAD_RET_CMD);
+ break;
+ }
+ }
}
}
- if (!nd) a1logd(p->log, 4, "i1d3_command: got '%s' ICOM err 0x%x\n",icoms_tohex(recv, 14),ua);
-
- amutex_unlock(p->lock);
- return rv;
-}
-
-/* Read a packet and time out or throw it away */
-static inst_code
-i1d3_dummy_read(
- i1d3 *p /* i1d3 object */
-) {
- unsigned char buf[64];
- int rbytes; /* bytes read from ep */
- int se, rv = inst_ok;
- int ishid = p->icom->port_type(p->icom) == icomt_hid;
+ if (!nd) {
+ if (cc == i1d3_lockchal)
+ a1logd(p->log, 4, "i1d3_command: got '%s' ICOM err 0x%x\n",icoms_tohex(recv, 64),ua);
+ else
+ a1logd(p->log, 4, "i1d3_command: got '%s' ICOM err 0x%x\n",icoms_tohex(recv, 14),ua);
+ }
- if (ishid) {
- se = p->icom->hid_read(p->icom, buf, 64, &rbytes, 0.1);
- } else {
- se = p->icom->usb_read(p->icom, NULL, 0x81, buf, 64, &rbytes, 0.1);
- }
+ if (rv != inst_ok) {
+ /* Flush any extra response, in case responses are out of sync */
+ if (ishid) {
+ p->icom->hid_read(p->icom, recv, 64, &rbytes, 0.2);
+ } else {
+ p->icom->usb_read(p->icom, NULL, 0x81, recv, 64, &rbytes, 0.2);
+ }
+ }
+ amutex_unlock(p->lock);
return rv;
}
@@ -534,19 +565,26 @@ i1d3_unlock(
{ "i1Display3 ", { 0xcaa62b2c, 0x30815b61 }, i1d3_disppro, i1d3_oem },
{ "i1Display3 ", { 0xa9119479, 0x5b168761 }, i1d3_disppro, i1d3_nec_ssp },
{ "i1Display3 ", { 0x160eb6ae, 0x14440e70 }, i1d3_disppro, i1d3_quato_sh3 },
+ { "i1Display3 ", { 0x291e41d7, 0x51937bdd }, i1d3_disppro, i1d3_hp_dreamc },
{ NULL }
};
inst_code ev;
- int ix;
+ int ix, nix;
a1logd(p->log, 2, "i1d3_unlock: called\n");
+ /* Count the keys */
+ for (nix = 0;;nix++) {
+ if (codes[nix].pname == NULL)
+ break;
+ }
+
/* Until we give up */
for (ix = 0;;ix++) {
/* If we've run out of unlock keys */
if (codes[ix].pname == NULL) {
- a1logd(p->log, 1, "i1d3: Unknown lock code. Please contact ArgyllCMS for help\n");
+ a1logw(p->log, "i1d3: Unknown lock code. Please contact ArgyllCMS for help\n");
return i1d3_interp_code((inst *)p, I1D3_UNKNOWN_UNLOCK);
}
@@ -559,6 +597,7 @@ i1d3_unlock(
// a1logd(p->log, 3, "i1d3_unlock: Trying unlock key 0x%08x 0x%08x\n",
// codes[ix].key[0], codes[ix].key[1]);
+ a1logd(p->log, 3, "i1d3_unlock: Trying unlock key %d/%d\n", ix+1, nix);
p->dtype = codes[ix].dtype;
p->stype = codes[ix].stype;
@@ -734,7 +773,7 @@ i1d3_freq_measure(
todev[23] = 0; /* Unknown parameter, always 0 */
- if ((ev = i1d3_command(p, i1d3_measure1, todev, fromdev, 20.0, 0)) != inst_ok)
+ if ((ev = i1d3_command(p, i1d3_measure1, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok)
return ev;
rgb[0] = (double)buf2uint(fromdev + 2);
@@ -771,7 +810,7 @@ i1d3_period_measure(
todev[7] = (unsigned char)mask;
todev[8] = 0; /* Unknown parameter, always 0 */
- if ((ev = i1d3_command(p, i1d3_measure2, todev, fromdev, 20.0, 0)) != inst_ok)
+ if ((ev = i1d3_command(p, i1d3_measure2, todev, fromdev, I1D3_MEAS_TIMEOUT, 0)) != inst_ok)
return ev;
rgb[0] = (double)buf2uint(fromdev + 2);
@@ -911,6 +950,7 @@ i1d3_imp_measure_refresh(
int npeaks = 0; /* Number of peaks */
double pval; /* Period value */
int isdeb;
+ int isth;
if (prefrate != NULL)
*prefrate = 0.0;
@@ -922,14 +962,17 @@ i1d3_imp_measure_refresh(
return inst_internal_error;
}
- /* Turn debug off so that it doesn't intefere with measurement timing */
+ /* Turn debug and thread off so that they doesn't intefere with measurement timing */
isdeb = p->log->debug;
p->icom->log->debug = 0;
+ isth = p->th_en;
+ p->th_en = 0;
/* Do some measurement and throw them away, to make sure the code is in cache. */
for (i = 0; i < 5; i++) {
if ((ev = i1d3_freq_measure(p, &inttimeh, samp[i].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
}
@@ -945,6 +988,7 @@ i1d3_imp_measure_refresh(
if ((ev = i1d3_freq_measure(p, &inttime1, samp[0].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
@@ -952,6 +996,7 @@ i1d3_imp_measure_refresh(
if ((ev = i1d3_freq_measure(p, &inttime2, samp[0].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
@@ -977,10 +1022,10 @@ i1d3_imp_measure_refresh(
if ((ev = i1d3_freq_measure(p, &samp[i].itime, samp[i].rgb)) != inst_ok) {
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
cutime = (usec_time() - sutime) / 1000000.0;
-// ~~999
samp[i].sec = 0.5 * (putime + cutime); /* Mean of before and after stamp */
//samp[i].sec *= 85.0/20.0; /* Test 20 Hz */
//samp[i].sec *= 85.0/100.0; /* Test 100 Hz */
@@ -988,7 +1033,9 @@ i1d3_imp_measure_refresh(
if (cutime > NFMXTIME)
break;
}
+ /* Restore debug & thread */
p->log->debug = isdeb;
+ p->th_en = isth;
nfsamps = i;
if (nfsamps < 100) {
@@ -1354,6 +1401,7 @@ i1d3_imp_measure_refresh(
} else {
int mul;
double refrate;
+ double pval;
pval = avg/ano;
pval /= 1000.0; /* Convert to seconds */
@@ -1365,10 +1413,25 @@ i1d3_imp_measure_refresh(
/* Error against my 85Hz CRT - GWG */
// a1logd(p->log, 1, "Refresh rate error = %.4f%%\n",100.0 * fabs(refrate - 85.0)/(85.0));
- /* Scale to just above 20 Hz */
- mul = floor((1.0/20) / pval);
- if (mul > 1)
+ /* Scale to just above 20 Hz, but make it multiple of 2 or 4 */
+#ifdef DEBUG_TWEAKS
+ {
+ double quanttime = 1.0/20.0;
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_REF_QUANT_TIME")) != NULL)
+ quanttime = atof(cp);
+ mul = (int)floor(quanttime / pval);
+ }
+#else
+ mul = (int)floor((1.0/20.0) / pval);
+#endif
+ if (mul > 1) {
+ if (mul >= 8)
+ mul = (mul + 3) & ~3; /* Round up to mult of 4 */
+ else
+ mul = (mul + 1) & ~1; /* Round up to mult of 2 */
pval *= mul;
+ }
a1logd(p->log, 1, "Refresh rate = %f Hz, quantizing to %f msec\n",refrate,pval);
a1logv(p->log, 1, "Refresh rate = %f Hz, quantizing to %f msec\n",refrate,pval);
@@ -1411,6 +1474,8 @@ i1d3_measure_set_refresh(
/* - - - - - - - - - - - - - - - - - - - - - - */
+#ifdef NEVER /* No longer used - use general measurement instead */
+
/* Take an ambient measurement and return the cooked reading */
/* The cooked reading is the frequency of the L2V */
static inst_code
@@ -1451,11 +1516,11 @@ i1d3_take_amb_measurement(
return inst_ok;
}
-
+#endif
/* - - - - - - - - - - - - - - - - - - - - - - */
-/* Take an display measurement and return the cooked reading */
+/* Take a general measurement and return the cooked reading */
/* The cooked reading is the frequency of the L2V */
static inst_code
i1d3_take_emis_measurement(
@@ -1464,26 +1529,22 @@ i1d3_take_emis_measurement(
double *rgb /* Return the cooked emsissive RGB values */
) {
int i, k;
- int pos;
inst_code ev;
double rmeas[3] = { -1.0, -1.0, -1.0 }; /* raw measurement */
int edgec[3] = {2,2,2}; /* Measurement edge count for each channel (not counting start edge) */
int mask = 0x7; /* Period measure mask */
int msecstart = msec_time(); /* Debug */
double rgb2[3] = { 0.0, 0.0, 0.0 }; /* Trial measurement RGB values */
+ int isth;
if (p->inited == 0)
return i1d3_interp_code((inst *)p, I1D3_NOT_INITED);
a1logd(p->log,3,"\ntake_emis_measurement called\n");
- /* Check that the ambient filter is not in place */
- if ((ev = i1d3_get_diffpos(p, &pos, 0)) != inst_ok)
- return ev;
-
- if (pos != 0)
- return i1d3_interp_code((inst *)p, I1D3_SPOS_EMIS);
-
+ /* Suspend thread so that it doesn't intefere with measurement timing */
+ isth = p->th_en;
+ p->th_en = 0;
/* If we should take a frequency measurement first */
if (mode == i1d3_adaptive || mode == i1d3_frequency) {
@@ -1492,8 +1553,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing fixed period frequency measurement over %f secs\n",p->inttime);
/* Take a frequency measurement over a fixed period */
- if ((ev = i1d3_freq_measure(p, &p->inttime, rmeas)) != inst_ok)
+ if ((ev = i1d3_freq_measure(p, &p->inttime, rmeas)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
/* Convert to frequency (assume raw meas is both edges count over integration time) */
for (i = 0; i < 3; i++) {
@@ -1555,8 +1618,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing 1st period pre-measurement mask 0x%x, edgec %d %d %d\n",mask2,edgec[0],edgec[1],edgec[2]);
/* Take an initial period pre-measurement over 2 edges */
- if ((ev = i1d3_period_measure(p, edgec, mask2, rmeas2)) != inst_ok)
+ if ((ev = i1d3_period_measure(p, edgec, mask2, rmeas2)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
a1logd(p->log,3,"Got %f %f %f raw %f %f %f Hz\n",rmeas2[0],rmeas2[1],rmeas2[2],
0.5 * edgec[0] * p->clk_freq/rmeas2[0],
@@ -1627,8 +1692,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing 2nd initial period measurement mask 0x%x, edgec %d %d %d\n",mask2,edgec[0],edgec[1],edgec[2]);
/* Take a 2nd initial period measurement */
- if ((ev = i1d3_period_measure(p, edgec, mask3, rmeas2)) != inst_ok)
+ if ((ev = i1d3_period_measure(p, edgec, mask3, rmeas2)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
a1logd(p->log,3,"Got %f %f %f raw %f %f %f Hz\n",rmeas2[0],rmeas2[1],rmeas2[2],
0.5 * edgec[0] * p->clk_freq/rmeas2[0],
@@ -1659,7 +1726,7 @@ i1d3_take_emis_measurement(
continue;
/* Compute number of edges needed for a clock count */
- /* of p->inttime (0.2 secs) */
+ /* of p->inttime (0.2/0.4 secs) */
nedgec = edgec[i] * p->inttime * p->clk_freq/rmeas[i];
/* If we will get less than 200 edges, raise the target integration */
@@ -1780,8 +1847,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing freq re-measure inttime %f\n",tinttime);
/* Take a frequency measurement over a fixed period */
- if ((ev = i1d3_freq_measure(p, &tinttime, rmeas)) != inst_ok)
+ if ((ev = i1d3_freq_measure(p, &tinttime, rmeas)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
/* Convert raw measurement to frequency */
for (i = 0; i < 3; i++) {
@@ -1799,8 +1868,10 @@ i1d3_take_emis_measurement(
a1logd(p->log,3,"Doing period re-measure mask 0x%x, edgec %d %d %d\n",mask,edgec[0],edgec[1],edgec[2]);
/* Measure again with desired precision, taking up to 0.4/0.8 secs */
- if ((ev = i1d3_period_measure(p, edgec, mask, rmeas)) != inst_ok)
+ if ((ev = i1d3_period_measure(p, edgec, mask, rmeas)) != inst_ok) {
+ p->th_en = isth;
return ev;
+ }
for (i = 0; i < 3; i++) {
double tt;
@@ -1820,6 +1891,7 @@ i1d3_take_emis_measurement(
}
}
}
+ p->th_en = isth;
a1logd(p->log,3,"Took %d msec to measure\n", msec_time() - msecstart);
@@ -1843,27 +1915,35 @@ i1d3_take_XYZ_measurement(
i1d3 *p, /* Object */
double XYZ[3] /* Return the XYZ values */
) {
+ int pos;
inst_code ev;
if (IMODETST(p->mode, inst_mode_emis_ambient)) {
- if ((ev = i1d3_take_amb_measurement(p, XYZ)) != inst_ok)
+
+ /* Check that the ambient filter is in place */
+ if ((ev = i1d3_get_diffpos(p, &pos, 0)) != inst_ok)
+ return ev;
+
+ if (pos != 1)
+ return i1d3_interp_code((inst *)p, I1D3_SPOS_EMIS);
+
+ /* Best type of reading, including refresh support */
+ if ((ev = i1d3_take_emis_measurement(p, i1d3_adaptive, XYZ)) != inst_ok)
return ev;
/* Multiply by ambient calibration matrix */
- icmMulBy3x3(XYZ, p->ambi_cal, XYZ);
- icmScale3(XYZ, XYZ, 1/3.141592654); /* Convert from Lux to cd/m^2 */
+ icmMulBy3x3(XYZ, p->ambi_cal, XYZ); /* Values in Lux */
} else {
- /* Constant fast speed, poor accuracy for black */
-// if ((ev = i1d3_take_emis_measurement(p, i1d3_frequency, XYZ)) != inst_ok)
-// return ev;
-
- /* Most accurate ? */
-// if ((ev = i1d3_take_emis_measurement(p, i1d3_period, XYZ)) != inst_ok)
-// return ev;
+ /* Check that the ambient filter is not in place */
+ if ((ev = i1d3_get_diffpos(p, &pos, 0)) != inst_ok)
+ return ev;
+
+ if (pos != 0)
+ return i1d3_interp_code((inst *)p, I1D3_SPOS_EMIS);
- /* Best combination */
+ /* Best type of reading, including refresh support */
if ((ev = i1d3_take_emis_measurement(p, i1d3_adaptive, XYZ)) != inst_ok)
return ev;
@@ -1892,6 +1972,9 @@ static inst_code i1d3_decode_intEE(
strncpy(p->serial_no, (char *)buf + 0x10, 20);
p->serial_no[20] = '\000';
+ strncpy(p->vers_no, (char *)buf + 0x2C, 10);
+ p->serial_no[10] = '\000';
+
/* Read the black level offset */
for (i = 0; i < 3; i++) {
t1 = buf2uint(buf + 0x0004 + 4 * i);
@@ -1915,16 +1998,22 @@ static inst_code i1d3_decode_extEE(
unsigned int chsum, rchsum;
xspect tmp;
- for (chsum = 0, i = 4; i < 6042; i++)
- chsum += buf[i];
+ rchsum = buf2short(buf + 2);
- chsum &= 0xffff; /* 16 bit sum */
+ /* For the "A-01" revsions the checksum is from 4 to 0x179a */
+ /* The "A-02" seems to have abandoned reliable checksums ?? */
+ for (chsum = 0, i = 4; i < 0x179a; i++) {
+ chsum += buf[i];
+ }
- rchsum = buf2short(buf + 2);
+ chsum &= 0xffff;
if (rchsum != chsum) {
- a1logd(p->log, 3, "i1d3_decode_extEE: checksum failed\n");
- return i1d3_interp_code((inst *)p, I1D3_BAD_EX_CHSUM);
+ a1logd(p->log, 3, "i1d3_decode_extEE: checksum failed, is 0x%x, should be 0x%x\n",chsum,rchsum);
+ if (strcmp(p->vers_no, "A-01") == 0)
+ return i1d3_interp_code((inst *)p, I1D3_BAD_EX_CHSUM);
+
+ /* Else ignore checksum error */
}
/* Read 3 x sensor spectral sensitivits */
@@ -2116,6 +2205,108 @@ i1d3_comp_calmat(
return inst_ok;
}
+/* Preset the calibration to a spectral sample type. */
+/* ccmat[][] is set to unity */
+static inst_code
+i1d3_set_speccal(
+ i1d3 *p,
+ xspect *samples, /* Array of nsamp spectral samples, or RGBcmfs for MIbLSr */
+ int nsamp /* Number of samples */
+) {
+ int i;
+
+ /* Save a the spectral samples to the current state */
+ if (p->samples != NULL)
+ free(p->samples);
+ p->nsamp = 0;
+ if ((p->samples = (xspect *)calloc(sizeof(xspect), nsamp)) == NULL) {
+ a1loge(p->log, inst_internal_error, "i1d3_set_speccal: malloc failed\n");
+ return inst_internal_error;
+ }
+ for (i = 0; i < nsamp; i++ )
+ p->samples[i] = samples[i]; /* Struct copy */
+ p->nsamp = nsamp;
+
+ icmSetUnity3x3(p->ccmat); /* No matrix */
+
+ return inst_ok;
+}
+
+
+/* Preset the calibration to a matrix. The spectral type is set to none */
+static inst_code
+i1d3_set_matcal(i1d3 *p, double mtx[3][3]) {
+ if (mtx == NULL)
+ icmSetUnity3x3(p->ccmat);
+ else {
+ if (p->cbid == 0) {
+ a1loge(p->log, 1, "i1d3: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
+ }
+ icmCpy3x3(p->ccmat, mtx);
+ }
+ return inst_ok;
+}
+
+
+/* Set the calibration to the currently preset type */
+static inst_code
+i1d3_set_cal(i1d3 *p) {
+ inst_code ev = inst_ok;
+
+ if (p->samples != NULL && p->nsamp > 0) {
+
+ /* Create matrix for specified samples */
+ if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
+ p->sens, p->samples, p->nsamp)) != inst_ok) {
+ a1logd(p->log, 1, "i1d3_set_cal: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ return ev;
+ }
+ /* Use MIbLSr for ambient */
+ if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver,
+ p->ambi, p->ambi, 3)) != inst_ok)
+ return ev;
+
+ icmSetUnity3x3(p->ccmat); /* to be sure to be sure... */
+
+ } else { /* Assume matrix */
+
+ /* Create the default MIbLSr calibration matrix */
+ if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
+ p->sens, p->sens, 3)) != inst_ok) {
+ a1logd(p->log, 1, "i1d3_set_disp_type: comp_calmat dflt failed with rv = 0x%x\n",ev);
+ return ev;
+ }
+ /* Use MIbLSr for ambient */
+ if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver,
+ p->ambi, p->ambi, 3)) != inst_ok)
+ return ev;
+ }
+
+ if (p->log->debug >= 4) {
+ a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
+ p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
+ a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
+ p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
+ a1logd(p->log,4,"ccmat = %f %f %f\n",
+ p->ccmat[0][0], p->ccmat[0][1], p->ccmat[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ccmat[1][0], p->ccmat[1][1], p->ccmat[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ccmat[2][0], p->ccmat[2][1], p->ccmat[2][2]);
+ a1logd(p->log,4,"\n");
+ }
+
+ return inst_ok;
+}
/* ------------------------------------------------------------------------ */
@@ -2175,15 +2366,10 @@ i1d3_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
}
} else {
- a1logd(p->log, 1, "i1d3_init_coms: wrong sort of coms!\n");
- return i1d3_interp_code((inst *)p, I1D3_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "i1d3_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
-#if defined(__APPLE__)
- /* We seem to have to clear any pending messages for OS X HID */
- i1d3_dummy_read(p);
-#endif
-
/* Check instrument is responding */
if ((ev = i1d3_check_status(p,&stat)) != inst_ok) {
a1logd(p->log, 1, "i1d3_init_coms: failed with rv = 0x%x\n",ev);
@@ -2214,7 +2400,7 @@ static void dump_bytes(a1log *log, char *pfx, unsigned char *buf, int len) {
bp += sprintf(bp,".");
}
bp += sprintf(bp,"\n");
- a1logd(log,0,oline);
+ a1logd(log,0, "%s", oline);
bp = oline;
}
}
@@ -2230,20 +2416,25 @@ int i1d3_diff_thread(void *pp) {
for (nfailed = 0; nfailed < 5;) {
int pos;
- rv = i1d3_get_diffpos(p, &pos, 1);
- if (p->th_term) {
- p->th_termed = 1;
- break;
- }
- if (rv != inst_ok) {
- nfailed++;
- a1logd(p->log,3,"Diffuser thread failed with 0x%x\n",rv);
- continue;
- }
- if (pos != p->dpos) {
- p->dpos = pos;
- if (p->eventcallback != NULL) {
- p->eventcallback(p->event_cntx, inst_event_mconf);
+ /* Don't get diffpos if we're doing something else that */
+ /* is timing critical */
+ if (p->th_en) {
+//a1logd(p->log,3,"Diffuser thread loop debug = %d\n",p->log->debug);
+ rv = i1d3_get_diffpos(p, &pos, p->log->debug < 8 ? 1 : 0);
+ if (p->th_term) {
+ p->th_termed = 1;
+ break;
+ }
+ if (rv != inst_ok) {
+ nfailed++;
+ a1logd(p->log,3,"Diffuser thread failed with 0x%x\n",rv);
+ continue;
+ }
+ if (pos != p->dpos) {
+ p->dpos = pos;
+ if (p->eventcallback != NULL) {
+ p->eventcallback(p->event_cntx, inst_event_mconf);
+ }
}
}
msec_sleep(100);
@@ -2262,7 +2453,7 @@ i1d3_init_inst(inst *pp) {
int i, stat;
unsigned char buf[8192];
- a1logd(p->log, 2, "i1d3_init_inst: called\n");
+ a1logd(p->log, 2, "i1d3_init_inst: called, debug = %d\n",p->log->debug);
p->rrset = 0;
@@ -2329,9 +2520,11 @@ i1d3_init_inst(inst *pp) {
return ev;
/* Set known constants */
- p->clk_freq = 12e6; /* 12 Mhz */
- p->dinttime = 0.2; /* 0.2 second integration time default */
- p->inttime = p->dinttime; /* Start in non-refresh mode */
+ p->clk_freq = 12e6; /* 12 Mhz */
+ p->omininttime = 0.0; /* No override */
+ p->dinttime = 0.2; /* 0.2 second integration time default */
+ p->inttime = p->dinttime; /* Start in non-refresh mode */
+ p->mininttime = p->inttime; /* Current value */
/* Create the default calibrations */
@@ -2353,29 +2546,32 @@ i1d3_init_inst(inst *pp) {
if (p->log->debug >= 4) {
a1logd(p->log,4,"Default calibration:\n");
- a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
- p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n\n",
- p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
a1logd(p->log,4," %f %f %f\n",
p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
a1logd(p->log,4," %f %f %f\n",
p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
+ a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
+ p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
a1logd(p->log,4,"\n");
}
/* Start the diffuser monitoring thread */
+ p->th_en = 1;
if ((p->th = new_athread(i1d3_diff_thread, (void *)p)) == NULL)
- return I1D3_INT_THREADFAILED;
+ return i1d3_interp_code((inst *)p, I1D3_INT_THREADFAILED);
/* Flash the LED, just cos we can! */
if ((ev = i1d3_set_LEDs(p, i1d3_flash, 0.2, 0.05, 2)) != inst_ok)
return ev;
+ a1logd(p->log, 2, "i1d3_init_inst: done\n");
+
return ev;
}
@@ -2422,26 +2618,40 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
} else {
/* Check for abort */
if (p->uicallback != NULL
- && (rv = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort)
+ && (rv = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort) {
return rv; /* Abort */
+ }
}
/* Attempt a refresh display frame rate calibration if needed */
if (p->dtype != i1d3_munkdisp && p->refrmode != 0 && p->rrset == 0) {
inst_code ev = inst_ok;
+ p->mininttime = 2.0 * p->dinttime;
+
+ if (p->omininttime != 0.0)
+ p->mininttime = p->omininttime; /* Override */
+
+#ifdef DEBUG_TWEAKS
+ {
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL)
+ p->mininttime = atof(cp);
+ }
+#endif
+
if ((ev = i1d3_measure_set_refresh(p)) != inst_ok)
return ev;
/* Quantize the sample time */
if (p->refperiod > 0.0) { /* If we have a refresh period */
int n;
- n = (int)ceil(p->dinttime/p->refperiod);
- p->inttime = 2.0 * n * p->refperiod;
+ n = (int)ceil(p->mininttime/p->refperiod);
+ p->inttime = n * p->refperiod;
a1logd(p->log, 3, "i1d3: integration time quantize to %f secs\n",p->inttime);
- } else { /* We don't have a period, so simply double the default */
- p->inttime = 2.0 * p->dinttime;
+ } else { /* We don't have a period, so simply use the double default */
+ p->inttime = p->mininttime;
a1logd(p->log, 3, "i1d3: integration time integration time doubled to %f secs\n",p->inttime);
}
}
@@ -2463,6 +2673,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
val->sp.spec_n = 0;
val->duration = 0.0;
+
if (user_trig)
return inst_user_trig;
@@ -2491,6 +2702,7 @@ double *ref_rate) {
if (*ref_rate == 0.0)
return inst_misread;
+
return inst_ok;
}
@@ -2502,23 +2714,19 @@ inst *pp,
double mtx[3][3]
) {
i1d3 *p = (i1d3 *)pp;
+ inst_code ev = inst_ok;
+
+ a1logd(p->log, 4, "i1d3_col_cor_mat%s\n",mtx == NULL ? " (noop)": "");
if (!p->gotcoms)
return inst_no_coms;
if (!p->inited)
return inst_no_init;
- if (mtx == NULL)
- icmSetUnity3x3(p->ccmat);
- else {
- if (p->cbid == 0) {
- a1loge(p->log, 1, "i1d3: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
- }
- icmCpy3x3(p->ccmat, mtx);
- }
-
- return inst_ok;
+ if ((ev = i1d3_set_matcal(p, mtx)) != inst_ok)
+ return ev;
+
+ return i1d3_set_cal(p);
}
/* Use a Colorimeter Calibration Spectral Set to set the */
@@ -2533,6 +2741,8 @@ int no_sets
i1d3 *p = (i1d3 *)pp;
inst_code ev = inst_ok;
+ a1logd(p->log, 4, "i1d3_col_cal_spec_set%s\n",sets == NULL ? " (default)": "");
+
if (!p->gotcoms)
return inst_no_coms;
if (!p->inited)
@@ -2543,31 +2753,12 @@ int no_sets
return ev;
}
} else {
- /* Use given spectral samples */
- if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver, p->sens,
- sets, no_sets)) != inst_ok)
- return ev;
- /* Use MIbLSr */
- if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver, p->ambi,
- p->ambi, 3)) != inst_ok)
- return ev;
- }
- if (p->log->debug >= 4) {
- a1logd(p->log,4,"CCSS update calibration:\n");
- a1logd(p->log,4,"Ambient matrix = %f %f %f\n",
- p->ambi_cal[0][0], p->ambi_cal[0][1], p->ambi_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->ambi_cal[1][0], p->ambi_cal[1][1], p->ambi_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n\n",
- p->ambi_cal[2][0], p->ambi_cal[2][1], p->ambi_cal[2][2]);
- a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
- p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
- a1logd(p->log,4,"\n");
+ if ((ev = i1d3_set_speccal(p, sets, no_sets)) != inst_ok)
+ return ev;
+
+ ev = i1d3_set_cal(p);
}
+
return ev;
}
@@ -2638,11 +2829,24 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
if ((*calt & inst_calt_ref_freq) && p->dtype != i1d3_munkdisp && p->refrmode != 0) {
inst_code ev = inst_ok;
- if (*calc != inst_calc_emis_white) {
- *calc = inst_calc_emis_white;
+ p->mininttime = 2.0 * p->dinttime;
+
+ if (*calc != inst_calc_emis_80pc) {
+ *calc = inst_calc_emis_80pc;
return inst_cal_setup;
}
+ if (p->omininttime != 0.0)
+ p->mininttime = p->omininttime; /* Override */
+
+#ifdef DEBUG_TWEAKS
+ {
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL)
+ p->mininttime = atof(cp);
+ }
+#endif
+
/* Do refresh display rate calibration */
if ((ev = i1d3_measure_set_refresh(p)) != inst_ok)
return ev;
@@ -2650,11 +2854,11 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
/* Quantize the sample time */
if (p->refperiod > 0.0) {
int n;
- n = (int)ceil(p->dinttime/p->refperiod);
- p->inttime = 2.0 * n * p->refperiod;
+ n = (int)ceil(p->mininttime/p->refperiod);
+ p->inttime = n * p->refperiod;
a1logd(p->log, 3, "i1d3: integration time quantize to %f secs\n",p->inttime);
} else {
- p->inttime = 2.0 * p->dinttime; /* Double default integration time */
+ p->inttime = p->mininttime; /* Double default integration time */
a1logd(p->log, 3, "i1d3: integration time integration time doubled to %f secs\n",p->inttime);
}
*calt &= ~inst_calt_ref_freq;
@@ -2665,11 +2869,11 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
/* Measure a display update delay. It is assumed that a */
/* white to black change has been made to the displayed color, */
/* and this will measure the time it took for the update to */
-/* be noticed by the instrument, up to 0.5 seconds. */
+/* be noticed by the instrument, up to 0.6 seconds. */
/* inst_misread will be returned on failure to find a transition to black. */
-#define NDSAMPS 60
-#define DINTT 0.010
-#define NDMXTIME 0.6 /* Maximum time to take */
+#define NDSAMPS 200
+#define DINTT 0.005 /* Too short hits blanking */
+#define NDMXTIME 1.0 /* Maximum time to take */
inst_code i1d3_meas_delay(
inst *pp,
@@ -2681,21 +2885,25 @@ int *msecdelay) { /* Return the number of msec */
struct {
double sec;
double rgb[3];
+ double tot;
} samp[NDSAMPS];
int ndsamps;
double inttime = DINTT;
- double rgb[3];
+ double stot, etot, del, thr;
double etime;
int isdeb;
+ int isth;
if (usec_time() < 0.0) {
a1loge(p->log, inst_internal_error, "i1d3_meas_delay: No high resolution timers\n");
return inst_internal_error;
}
- /* Turn debug off so that it doesn't intefere with measurement timing */
+ /* Turn debug and thread off so that they doesn't intefere with measurement timing */
isdeb = p->log->debug;
p->icom->log->debug = 0;
+ isth = p->th_en;
+ p->th_en = 0;
/* Read the samples */
sutime = usec_time();
@@ -2704,71 +2912,85 @@ int *msecdelay) { /* Return the number of msec */
if ((ev = i1d3_freq_measure(p, &inttime, samp[i].rgb)) != inst_ok) {
a1logd(p->log, 1, "i1d3_meas_delay: measurement failed\n");
p->log->debug = isdeb;
+ p->th_en = isth;
return ev;
}
cutime = (usec_time() - sutime) / 1000000.0;
samp[i].sec = 0.5 * (putime + cutime); /* Mean of before and after stamp */
putime = cutime;
+ samp[i].tot = samp[i].rgb[0] + samp[i].rgb[1] + samp[i].rgb[2];
if (cutime > NDMXTIME)
break;
}
ndsamps = i;
- /* Restore debugging */
+ /* Restore debugging & thread */
p->log->debug = isdeb;
+ p->th_en = isth;
if (ndsamps == 0) {
a1logd(p->log, 1, "i1d3_meas_delay: No measurement samples returned in time\n");
return inst_internal_error;
}
-#ifdef NEVER
+#ifdef PLOT_UPDELAY
/* Plot the raw sensor values */
{
double xx[NDSAMPS];
double y1[NDSAMPS];
double y2[NDSAMPS];
double y3[NDSAMPS];
+ double y4[NDSAMPS];
for (i = 0; i < ndsamps; i++) {
xx[i] = samp[i].sec;
y1[i] = samp[i].rgb[0];
y2[i] = samp[i].rgb[1];
y3[i] = samp[i].rgb[2];
- //printf("%d: %f -> %f\n",i,samp[i].sec, samp[i].rgb[0]);
+ y4[i] = samp[i].tot;
+ //printf("%d: %f -> %f\n",i,samp[i].sec, samp[i].tot);
}
printf("Display update delay measure sensor values and time (sec)\n");
- do_plot6(xx, y1, y2, y3, NULL, NULL, NULL, ndsamps);
+ do_plot6(xx, y1, y2, y3, y4, NULL, NULL, ndsamps);
}
#endif
+ /* Over the first 100msec, locate the maximum value */
+ etime = samp[ndsamps-1].sec;
+ stot = -1e9;
+ for (i = 0; i < ndsamps; i++) {
+ if (samp[i].tot > stot)
+ stot = samp[i].tot;
+ if (samp[i].sec > 0.1)
+ break;
+ }
+
/* Over the last 100msec, locate the maximum value */
etime = samp[ndsamps-1].sec;
- for (j = 0; j < 3; j++)
- rgb[j] = 0.0;
+ etot = -1e9;
for (i = ndsamps-1; i >= 0; i--) {
- for (j = 0; j < 3; j++) {
- if (samp[i].rgb[j] > rgb[j])
- rgb[j] = samp[i].rgb[j];
- }
+ if (samp[i].tot > etot)
+ etot = samp[i].tot;
if ((etime - samp[i].sec) > 0.1)
break;
}
-// a1logd(p->log, 3, "i1d3_meas_delay: end rgb = %f %f %f stopped at %d\n", rgb[0], rgb[1], rgb[2], i);
+ del = stot - etot;
+ thr = etot + 0.2 * del; /* 20% of transition threshold */
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1d3_meas_delay: start tot %f end tot %f del %f, thr %f\n", stot, etot, del, thr);
+#endif
- if (rgb[0] > 10.0 || rgb[1] > 10.0 || rgb[2] > 10.0) {
- a1logd(p->log, 1, "i1d3_meas_delay: measurement delay doesn't seem to be black\n");
+ /* Check that there has been a transition */
+ if (del < 10.0) {
+ a1logd(p->log, 1, "i1d3_meas_delay: can't detect change from white to black\n");
return inst_misread;
}
- /* Locate the time at which the values are above this */
+ /* Working from the end, locate the time at which the level was above the threshold */
for (i = ndsamps-1; i >= 0; i--) {
- for (j = 0; j < 3; j++) {
- if (samp[i].rgb[j] > (1.5 * rgb[j]))
- break;
- }
- if (j < 3)
+ if (samp[i].tot > thr)
break;
}
if (i < 0) /* Assume the update was so fast that we missed it */
@@ -2778,6 +3000,10 @@ int *msecdelay) { /* Return the number of msec */
*msecdelay = (int)(samp[i].sec * 1000.0 + 0.5);
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1d3_meas_delay: returning %d msec\n",*msecdelay);
+#endif
+
return inst_ok;
}
#undef NDSAMPS
@@ -2819,13 +3045,27 @@ double ref_rate
int mul;
double pval;
- /* Scale to just above 20 Hz */
+ /* Scale to just above 20 Hz, but make it multiple of 2 or 4 */
pval = 1.0/ref_rate;
- mul = floor((1.0/20) / pval);
- if (mul > 1)
+#ifdef DEBUG_TWEAKS
+ {
+ double quanttime = 1.0/20.0;
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_REF_QUANT_TIME")) != NULL)
+ quanttime = atof(cp);
+ mul = (int)floor(quanttime / pval);
+ }
+#else
+ mul = (int)floor((1.0/20.0) / pval);
+#endif
+ if (mul > 1) {
+ if (mul >= 8)
+ mul = (mul + 3) & ~3; /* Round up to mult of 4 */
+ else
+ mul = (mul + 1) & ~1; /* Round up to mult of 2 */
pval *= mul;
+ }
p->refperiod = pval;
-
p->refrvalid = 1;
}
p->rrset = 1;
@@ -2994,6 +3234,8 @@ i1d3_del(inst *pp) {
if (p->icom != NULL)
p->icom->del(p->icom);
inst_del_disptype_list(p->dtlist, p->ndtlist);
+ if (p->samples != NULL)
+ free(p->samples);
amutex_del(p->lock);
free(p);
}
@@ -3011,7 +3253,7 @@ inst3_capability *pcap3) {
cap1 |= inst_mode_emis_spot
| inst_mode_emis_tele
| inst_mode_emis_ambient
- | inst_mode_emis_refresh_ovd
+ | inst_mode_emis_refresh_ovd /* (allow override ccmx & ccss mode) */
| inst_mode_emis_norefresh_ovd
| inst_mode_colorimeter
;
@@ -3023,11 +3265,14 @@ inst3_capability *pcap3) {
| inst2_disptype
| inst2_ccmx
| inst2_ccss
+ | inst2_get_min_int_time
+ | inst2_set_min_int_time
;
if (p->dtype != i1d3_munkdisp) {
cap2 |= inst2_meas_disp_update;
- cap2 |= inst2_refresh_rate;
+ cap2 |= inst2_get_refresh_rate;
+ cap2 |= inst2_set_refresh_rate;
cap2 |= inst2_emis_refr_meas;
}
if (pcap1 != NULL)
@@ -3075,8 +3320,8 @@ int *conf_ix
/* Add the extra dependent and independent modes */
mval |= inst_mode_emis_refresh_ovd
- | inst_mode_emis_norefresh_ovd
- | inst_mode_colorimeter;
+ | inst_mode_emis_norefresh_ovd
+ | inst_mode_colorimeter;
if (mmodes != NULL)
*mmodes = mval;
@@ -3139,11 +3384,15 @@ inst_code i1d3_set_mode(inst *pp, inst_mode m) {
}
p->refrmode = refrmode;
+ /* default before any refresh rate calibration */
if (p->refrmode) {
p->inttime = 2.0 * p->dinttime; /* Double default integration time */
} else {
p->inttime = p->dinttime; /* Normal integration time */
}
+ if (p->omininttime != 0.0)
+ p->inttime = p->omininttime; /* Override */
+ p->mininttime = p->inttime; /* Current value */
return inst_ok;
}
@@ -3152,7 +3401,7 @@ inst_disptypesel i1d3_disptypesel[3] = {
{
inst_dtflags_default,
1,
- "n",
+ "nl",
"Non-Refresh display",
0,
0
@@ -3160,7 +3409,7 @@ inst_disptypesel i1d3_disptypesel[3] = {
{
inst_dtflags_none, /* flags */
2, /* cbid */
- "r", /* sel */
+ "rc", /* sel */
"Refresh display", /* desc */
1, /* refr */
1 /* ix */
@@ -3186,7 +3435,7 @@ int recreate /* nz to re-check for new ccmx & ccss files */
i1d3 *p = (i1d3 *)pp;
inst_code rv = inst_ok;
- if (!allconfig && p->dpos) { /* If set to Ambient */
+ if (!allconfig && p->dpos) { /* If set to Ambient, there are no display types ? */
if (pnsels != NULL)
*pnsels = 0;
@@ -3233,59 +3482,31 @@ static inst_code set_disp_type(i1d3 *p, inst_disptypesel *dentry) {
p->rrset = 0; /* This is a hint we may have swapped displays */
p->refrmode = refrmode;
-// if (p->refrmode && p->dtype == i1d3_munkdisp) {
if (p->refrmode) {
p->inttime = 2.0 * p->dinttime; /* Double integration time */
} else {
p->inttime = p->dinttime; /* Normal integration time */
}
+ if (p->omininttime != 0.0)
+ p->inttime = p->omininttime; /* Override */
+ p->mininttime = p->inttime; /* Current value */
- if (dentry->flags & inst_dtflags_ccss) {
+ if (dentry->flags & inst_dtflags_ccss) { /* Spectral sample */
- if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
- p->sens, dentry->sets, dentry->no_sets)) != inst_ok) {
- a1logd(p->log, 1, "i1d3_set_disp_type: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ if ((ev = i1d3_set_speccal(p, dentry->sets, dentry->no_sets)) != inst_ok)
return ev;
- }
- /* Use MIbLSr for ambient */
- if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver, p->ambi,
- p->ambi, 3)) != inst_ok)
- return ev;
-
- icmSetUnity3x3(p->ccmat);
- if (p->log->debug >= 4) {
- a1logd(p->log,4,"Display type set CCSS:\n");
- a1logd(p->log,4,"Emissive matrix = %f %f %f\n",
- p->emis_cal[0][0], p->emis_cal[0][1], p->emis_cal[0][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[1][0], p->emis_cal[1][1], p->emis_cal[1][2]);
- a1logd(p->log,4," %f %f %f\n",
- p->emis_cal[2][0], p->emis_cal[2][1], p->emis_cal[2][2]);
- a1logd(p->log,4,"\n");
- }
-
- } else { /* Assume matrix */
-
- /* Create the default calibration matrix */
- if ((ev = i1d3_comp_calmat(p, p->emis_cal, p->obType, p->custObserver,
- p->sens, p->sens, 3)) != inst_ok) {
- a1logd(p->log, 1, "i1d3_set_disp_type: comp_calmat dflt failed with rv = 0x%x\n",ev);
- return ev;
- }
- /* Use MIbLSr for ambient */
- if ((ev = i1d3_comp_calmat(p, p->ambi_cal, p->obType, p->custObserver, p->ambi,
- p->ambi, 3)) != inst_ok)
- return ev;
+ } else { /* Matrix */
if (dentry->flags & inst_dtflags_ccmx) {
- icmCpy3x3(p->ccmat, dentry->mat);
+ if ((ev = i1d3_set_matcal(p, dentry->mat)) != inst_ok)
+ return ev;
} else {
- icmSetUnity3x3(p->ccmat);
+ if ((ev = i1d3_set_matcal(p, NULL)) != inst_ok) /* Noop */
+ return ev;
}
}
-
- return inst_ok;
+ return i1d3_set_cal(p);
}
/* Setup the default display type */
@@ -3386,6 +3607,66 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...)
return inst_ok;
}
+ /* Get the current minimum integration time */
+ if (m == inst_opt_get_min_int_time) {
+ va_list args;
+ double *dpoint;
+
+ va_start(args, m);
+ dpoint = va_arg(args, double *);
+ va_end(args);
+
+ if (dpoint != NULL)
+ *dpoint = p->mininttime;
+
+ return inst_ok;
+ }
+
+ /* Set the minimum integration time */
+ if (m == inst_opt_set_min_int_time) {
+ va_list args;
+ double dval;
+
+ va_start(args, m);
+ dval = va_arg(args, double);
+ va_end(args);
+
+ p->omininttime = dval;
+
+ /* Hmm. This code is duplicated a lot.. */
+ if (p->dtype != i1d3_munkdisp && p->refrmode != 0) {
+ inst_code ev = inst_ok;
+
+ p->mininttime = 2.0 * p->dinttime;
+
+ if (p->omininttime != 0.0)
+ p->mininttime = p->omininttime; /* Override */
+
+#ifdef DEBUG_TWEAKS
+ {
+ char *cp;
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL)
+ p->mininttime = atof(cp);
+ }
+#endif
+
+ /* Quantize the sample time if we have a refresh rate */
+ if (p->rrset && p->refperiod > 0.0) { /* If we have a refresh period */
+ int n;
+ n = (int)ceil(p->mininttime/p->refperiod);
+ p->inttime = n * p->refperiod;
+ a1logd(p->log, 3, "i1d3: integration time quantize to %f secs\n",p->inttime);
+
+ } else { /* We don't have a period, so simply use the double default */
+ p->inttime = p->mininttime;
+ a1logd(p->log, 3, "i1d3: integration time integration time doubled to %f secs\n",p->inttime);
+ }
+ }
+
+ return inst_ok;
+ }
+
+
/* Set the ccss observer type */
if (m == inst_opt_set_ccss_obs) {
va_list args;
@@ -3406,7 +3687,9 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...)
p->custObserver[2] = custObserver[2];
}
- return inst_ok;
+ a1logd(p->log, 4, "inst_opt_set_ccss_obs\n");
+
+ return i1d3_set_cal(p); /* Recompute calibration */
}
/* Operate the LEDS */
@@ -3436,6 +3719,7 @@ i1d3_get_set_opt(inst *pp, inst_opt_type m, ...)
mask = va_arg(args, int);
va_end(args);
+ p->led_state = mask;
if (p->led_state & 0x1)
return i1d3_set_LEDs(p, i1d3_flash, 0.0, 100.0, 0x80);
else
@@ -3595,9 +3879,9 @@ static void create_unlock_response(unsigned int *k, unsigned char *c, unsigned c
/* Minus the two key values as bytes */
sum += (0xff & -k[0]) + (0xff & (-k[0] >> 8))
- + (0xff & (-k[0] >> 16)) + (0xff & (-k[0] >> 24));
+ + (0xff & (-k[0] >> 16)) + (0xff & (-k[0] >> 24));
sum += (0xff & -k[1]) + (0xff & (-k[1] >> 8))
- + (0xff & (-k[1] >> 16)) + (0xff & (-k[1] >> 24));
+ + (0xff & (-k[1] >> 16)) + (0xff & (-k[1] >> 24));
/* Convert sum to bytes. Only need 2, because sum of 16 bytes can't exceed 16 bits. */
s0 = sum & 0xff;
diff --git a/spectro/i1d3.h b/spectro/i1d3.h
index 96de478..6d0eb85 100644
--- a/spectro/i1d3.h
+++ b/spectro/i1d3.h
@@ -80,7 +80,8 @@ typedef enum {
i1d3_munkdisp = 1, /* ColorMunki Display */
i1d3_oem = 2, /* OEM */
i1d3_nec_ssp = 3, /* NEC SpectraSensor Pro */
- i1d3_quato_sh3 = 4 /* Quato Silver Haze 3 */
+ i1d3_quato_sh3 = 4, /* Quato Silver Haze 3 */
+ i1d3_hp_dreamc = 5 /* HP DreameColor */
} i1d3_dtype;
/* Measurement mode */
@@ -106,6 +107,7 @@ struct _i1d3 {
/* (Only accurate if it needed unlocking). */
int status; /* 0 if status is ok (not sure what this is) */
char serial_no[21]; /* "I1-11.A-01.100999.02" or "CM-11.A-01.100999.02" */
+ char vers_no[11]; /* "A-01", "A-02" */
char prod_name[32]; /* "i1Display3 " or "ColorMunki Display" */
int prod_type; /* 16 bit product type number. i1d3_disppro = 0x0001, */
/* i1d3_munkdisp = 0x0002 */
@@ -126,9 +128,11 @@ struct _i1d3 {
int icx; /* Internal calibration matrix index, 11 = Raw */
int cbid; /* calibration base ID, 0 if not a base */
int refrmode; /* nz if in refresh display mode/double int. time */
- double ccmat[3][3]; /* Optional colorimeter correction matrix */
icxObserverType obType; /* ccss observer to use */
xspect custObserver[3]; /* Custom ccss observer to use */
+ double ccmat[3][3]; /* Optional colorimeter correction matrix, unity if none. */
+ xspect *samples; /* Copy of current calibration spectral samples, NULL if none */
+ int nsamp; /* Number of samples, 0 if none */
/* Computed factors and state */
int rrset; /* Flag, nz if the refresh rate has been determined */
@@ -136,8 +140,10 @@ struct _i1d3 {
double refrate; /* Measured refresh rate in Hz */
int refrvalid; /* nz if refrate is valid */
double clk_freq; /* Clock frequency (12Mhz) */
+ double omininttime; /* Override minimum integration time = 0.0 = none */
double dinttime; /* default integration time = 0.2 seconds */
- double inttime; /* current integration time = 0.2 seconds */
+ double mininttime; /* current minimum integration time (doubled for refresh) */
+ double inttime; /* current (quantized, doubled) integration time = 0.2 seconds */
double transblend; /* Blend between fixed and adaptive integration */
/* at low light levels */
@@ -147,6 +153,7 @@ struct _i1d3 {
double led_period, led_on_time_prop, led_trans_time_prop; /* Pulse state */
athread *th; /* Diffuser position monitoring thread */
+ volatile int th_en; /* Enable updating diffuser possition */
volatile int th_term; /* nz to terminate thread */
volatile int th_termed; /* nz when thread terminated */
int dpos; /* Diffuser position, 0 = display, 1 = ambient */
diff --git a/spectro/i1disp.c b/spectro/i1disp.c
index b9da1e1..cb5472b 100644
--- a/spectro/i1disp.c
+++ b/spectro/i1disp.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 18/10/2006
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -368,7 +368,7 @@ i1disp_rdreg_float(
if ((ev = i1disp_rdreg_word(p, &val, addr)) != inst_ok)
return ev;
- if (ev == 0xffffffff) {
+ if (val == 0xffffffff) {
return I1DISP_FLOAT_NOT_SET;
}
@@ -1233,13 +1233,8 @@ i1disp_take_XYZ_measurement(
if ((ev = i1d1_take_measurement(p, 0, rgb)) != inst_ok)
return ev;
} else { /* i1 disp 2 or ColorMunki Smile */
- int refreshm = 0; /* Assume non-refresh mode */
- if (p->refrmode && !IMODETST(p->mode, inst_mode_emis_ambient)) {
- refreshm = 1;
- }
-
- if ((ev = i1d2_take_measurement(p, refreshm, rgb)) != inst_ok)
+ if ((ev = i1d2_take_measurement(p, p->refrmode, rgb)) != inst_ok)
return ev;
}
@@ -1703,9 +1698,9 @@ i1disp_compute_factors(
if (p->reg90_W == 0xffffffff)
return i1disp_interp_code((inst *)p, I1DISP_BAD_CRT_CALIBRATION);
- /* Compute ambient matrix */
+ /* Compute ambient matrix for Lux */
for (i = 0; i < 9; i++)
- p->amb[i] = p->reg144_F[i % 3] * 0.5 * (p->reg4_F[i] + p->reg54_F[i]);
+ p->amb[i] = 3.141592654 * p->reg144_F[i % 3] * 0.5 * (p->reg4_F[i] + p->reg54_F[i]);
/* Integration clock frequency */
p->iclk_freq = 1.0/(p->reg40_S * 1e-9);
@@ -1746,8 +1741,8 @@ i1disp_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
a1logd(p->log, 2, "i1disp: About to init coms\n");
if (p->icom->port_type(p->icom) != icomt_usb) {
- a1logd(p->log, 1, "i1disp_init_coms: coms is not the right type!\n");
- return i1disp_interp_code((inst *)p, I1DISP_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "i1disp_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
/* Set config, interface, write end point, read end point */
@@ -1904,6 +1899,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
val->sp.spec_n = 0;
val->duration = 0.0;
+
if (user_trig)
return inst_user_trig;
return rv;
@@ -1927,8 +1923,8 @@ double mtx[3][3]
icmSetUnity3x3(p->ccmat);
} else {
if (p->cbid == 0) {
- a1loge(p->log, 1, "spyd2: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
+ a1loge(p->log, 1, "spyd2: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
}
icmCpy3x3(p->ccmat, mtx);
}
@@ -2029,8 +2025,8 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
} else { /* Eye-One Display 2 */
if ((*calt & inst_calt_ref_freq) && p->refrmode != 0) {
- if (*calc != inst_calc_emis_white) {
- *calc = inst_calc_emis_white;
+ if (*calc != inst_calc_emis_80pc) {
+ *calc = inst_calc_emis_80pc;
return inst_cal_setup;
}
@@ -2243,7 +2239,8 @@ inst3_capability *pcap3) {
| inst_mode_emis_norefresh_ovd
;
- cap2 |= inst2_refresh_rate
+ cap2 |= inst2_get_refresh_rate
+ | inst2_set_refresh_rate
| inst2_emis_refr_meas
;
}
@@ -2331,7 +2328,7 @@ inst_disptypesel smile_disptypesel[3] = {
{
inst_dtflags_default, /* flags */
1, /* cbix */
- "f", /* sel */
+ "fl", /* sel */
"LCD with CCFL backlight", /* desc */
0, /* refr */
1 /* ix */
@@ -2580,7 +2577,7 @@ static void dump_bytes(a1log *log, char *pfx, unsigned char *buf, int base, int
bp += sprintf(bp,".");
}
bp += sprintf(bp,"\n");
- a1logd(log,0,oline);
+ a1logd(log,0,"%s",oline);
bp = oline;
}
}
diff --git a/spectro/i1pro.c b/spectro/i1pro.c
index 99dd61b..2cac518 100644
--- a/spectro/i1pro.c
+++ b/spectro/i1pro.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 24/11/2006
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -100,8 +100,8 @@ i1pro_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
a1logd(p->log, 2, "i1pro_init_coms: called\n");
if (p->icom->port_type(p->icom) != icomt_usb) {
- a1logd(p->log, 1, "i1pro_init_coms: wrong sort of coms!\n");
- return i1pro_interp_code(p, I1PRO_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "i1pro_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
a1logd(p->log, 2, "i1pro_init_coms: about to init USB\n");
@@ -168,8 +168,10 @@ i1pro_determine_capabilities(i1pro *p) {
if (p->m != NULL) {
i1proimp *m = (i1proimp *)p->m;
i1pro_state *s = &m->ms[m->mmode];
- if (s->emiss)
+ if (s->emiss) {
+ p->cap2 |= inst2_meas_disp_update;
p->cap2 |= inst2_emis_refr_meas;
+ }
}
p->cap3 = inst3_none;
@@ -273,6 +275,25 @@ double *ref_rate) {
rv = i1pro_imp_meas_refrate(p, ref_rate);
+
+ return i1pro_interp_code(p, rv);
+}
+
+/* Read the display update delay */
+static inst_code
+i1pro_meas_delay(
+inst *pp,
+int *msecdelay) {
+ i1pro *p = (i1pro *)pp;
+ i1pro_code rv;
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ rv = i1pro_imp_meas_delay(p, msecdelay);
+
return i1pro_interp_code(p, rv);
}
@@ -417,6 +438,8 @@ i1pro_interp_error(inst *pp, i1pro_code ec) {
return "No ambient found before first flash";
case I1PRO_RD_NOREFR_FOUND:
return "No refresh rate detected or failed to measure it";
+ case I1PRO_RD_NOTRANS_FOUND:
+ return "No delay calibration transition found";
case I1PRO_INT_NO_COMS:
return "Communications hasn't been established";
@@ -538,6 +561,7 @@ i1pro_interp_code(i1pro *p, i1pro_code ec) {
case I1PRO_RD_NOFLASHES:
case I1PRO_RD_NOAMBB4FLASHES:
case I1PRO_RD_NOREFR_FOUND:
+ case I1PRO_RD_NOTRANS_FOUND:
return inst_misread | ec;
case I1PRO_RD_NEEDS_CAL:
@@ -790,6 +814,7 @@ extern i1pro *new_i1pro(icoms *icom, instType itype) {
p->read_refrate = i1pro_read_refrate;
p->get_n_a_cals = i1pro_get_n_a_cals;
p->calibrate = i1pro_calibrate;
+ p->meas_delay = i1pro_meas_delay;
p->interp_error = i1pro_interp_error;
p->del = i1pro_del;
diff --git a/spectro/i1pro_imp.c b/spectro/i1pro_imp.c
index 2211bd4..b6d6747 100644
--- a/spectro/i1pro_imp.c
+++ b/spectro/i1pro_imp.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 24/11/2006
*
- * Copyright 2006 - 2013 Graeme W. Gill
+ * Copyright 2006 - 2014 Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -100,21 +100,25 @@
#undef ENABLE_WRITE /* [Und] Enable writing of calibration and log data to the EEProm */
#define ENABLE_NONVCAL /* [Def] Enable saving calibration state between program runs in a file */
#define ENABLE_NONLINCOR /* [Def] Enable non-linear correction */
+#define ENABLE_BKDRIFTC /* [Def] Enable Emis. Black drift compensation using sheilded cell values */
+#define HEURISTIC_BKDRIFTC /* [Def] Enable heusristic black drift correction */
#define WLCALTOUT (24 * 60 * 60) /* [24 Hrs] Wavelength calibration timeout in seconds */
#define DCALTOUT ( 60 * 60) /* [60 Minuites] Dark Calibration timeout in seconds */
#define DCALTOUT2 ( 1 * 60 * 60) /* [1 Hr] i1pro2 Dark Calibration timeout in seconds */
#define WCALTOUT ( 1 * 60 * 60) /* [1 Hr] White Calibration timeout in seconds */
-#define MAXSCANTIME 15.0 /* [15] Maximum scan time in seconds */
+#define MAXSCANTIME 20.0 /* [20] Maximum scan time in seconds */
#define SW_THREAD_TIMEOUT (10 * 60.0) /* [10 Min] Switch read thread timeout */
#define SINGLE_READ /* [Def] Use a single USB read for scan to eliminate latency issues. */
#define HIGH_RES /* [Def] Enable high resolution spectral mode code. Dissable */
/* to break dependency on rspl library. */
+# undef FAST_HIGH_RES_SETUP /* Slightly better accuracy ? */
/* Debug [Und] */
#undef DEBUG /* Turn on debug printfs */
#undef PLOT_DEBUG /* Use plot to show readings & processing */
#undef PLOT_REFRESH /* Plot refresh rate measurement info */
+#undef PLOT_UPDELAY /* Plot data used to determine display update delay */
#undef DUMP_SCANV /* Dump scan readings to a file "i1pdump.txt" */
#undef DUMP_DARKM /* Append raw dark readings to file "i1pddump.txt" */
#undef APPEND_MEAN_EMMIS_VAL /* Append averaged uncalibrated reading to file "i1pdump.txt" */
@@ -124,6 +128,7 @@
#undef IGNORE_WHITE_INCONS /* Ignore define reference reading inconsistency */
#undef HIGH_RES_DEBUG
#undef HIGH_RES_PLOT
+#undef ANALIZE_EXISTING /* Analize the manufacturers existing filter shape */
#undef PLOT_BLACK_SUBTRACT /* Plot temperature corrected black subtraction */
#undef FAKE_AMBIENT /* Fake the ambient mode for a Rev A */
@@ -143,18 +148,18 @@
#define ADARKINT_MAX2 4.0 /* Max cal time for adaptive dark cal Rev E or no high gain */
#define EMIS_SCALE_FACTOR 1.0 /* Emission mode scale factor */
-#define AMB_SCALE_FACTOR (1.0/3.141592654) /* Ambient mode scale factor - convert */
- /* from Lux to Lux/PI */
- /* These factors get the same behaviour as the GMB drivers. */
+#define AMB_SCALE_FACTOR 1.0 /* Ambient mode scale factor for Lux */
+//#define AMB_SCALE_FACTOR (1.0/3.141592654) /* Ambient mode scale factor - convert */
+// /* from Lux to Lux/PI */
+// /* These factors get the same behaviour as the GMB drivers. */
#define NSEN_MAX 140 /* Maximum nsen value we can cope with */
/* High res mode settings */
-#define HIGHRES_SHORT 350
-#define HIGHRES_LONG 740
+#define HIGHRES_SHORT 370.0 /* i1pro2 uses more of the CCD, */
+#define HIGHRES_LONG 730.0 /* leaving less scope for extenion */
#define HIGHRES_WIDTH (10.0/3.0) /* (The 3.3333 spacing and lanczos2 seems a good combination) */
#define HIGHRES_REF_MIN 375.0 /* Too much stray light below this in reflective mode */
- /* (i1pro2 could go lower with different correction) */
#include "i1pro.h"
#include "i1pro_imp.h"
@@ -162,6 +167,8 @@
/* - - - - - - - - - - - - - - - - - - */
#define LAMP_OFF_TIME 1500 /* msec to make sure lamp is dark for dark measurement */
#define PATCH_CONS_THR 0.1 /* Dark measurement consistency threshold */
+
+#define USE_RD_SYNC /* Use mutex syncronisation, else depend on TRIG_DELAY */
#define TRIG_DELAY 10 /* Measure trigger delay to allow pending read, msec */
/* - - - - - - - - - - - - - - - - - - */
@@ -260,6 +267,58 @@ void plot_wav_2(i1proimp *m, int hires, double *data1, double *data2) {
/* ============================================================ */
+/* Return a linear interpolated spectral value. Clip to ends */
+static double wav_lerp(i1proimp *m, int hires, double *ary, double wl) {
+ int jj;
+ double wl0, wl1, bl;
+ double rv;
+
+ jj = (int)floor(XSPECT_DIX(m->wl_short[hires], m->wl_long[hires], m->nwav[hires], wl));
+ if (jj < 0)
+ jj = 0;
+ else if (jj > (m->nwav[hires]-2))
+ jj = m->nwav[hires]-2;
+
+ wl0 = XSPECT_WL(m->wl_short[hires], m->wl_long[hires], m->nwav[hires], jj);
+ wl1 = XSPECT_WL(m->wl_short[hires], m->wl_long[hires], m->nwav[hires], jj+1);
+
+ bl = (wl - wl0)/(wl1 - wl0);
+ if (bl < 0.0)
+ bl = 0;
+ else if (bl > 1.0)
+ bl = 1.0;
+
+ rv = (1.0 - bl) * ary[jj] + bl * ary[jj+1];
+
+ return rv;
+}
+
+/* Same as above, but return cv value on clip */
+static double wav_lerp_cv(i1proimp *m, int hires, double *ary, double wl, double cv) {
+ int jj;
+ double wl0, wl1, bl;
+ double rv;
+
+ jj = (int)floor(XSPECT_DIX(m->wl_short[hires], m->wl_long[hires], m->nwav[hires], wl));
+ if (jj < 0)
+ jj = 0;
+ else if (jj > (m->nwav[hires]-2))
+ jj = m->nwav[hires]-2;
+
+ wl0 = XSPECT_WL(m->wl_short[hires], m->wl_long[hires], m->nwav[hires], jj);
+ wl1 = XSPECT_WL(m->wl_short[hires], m->wl_long[hires], m->nwav[hires], jj+1);
+
+ bl = (wl - wl0)/(wl1 - wl0);
+ if (bl < 0.0 || bl > 1.0)
+ return cv;
+
+ rv = (1.0 - bl) * ary[jj] + bl * ary[jj+1];
+
+ return rv;
+}
+
+/* ============================================================ */
+
/* Implementation struct */
/* Add an implementation structure */
@@ -316,7 +375,8 @@ void del_i1proimp(i1pro *p) {
a1logd(p->log,5,"i1pro switch thread termination failed\n");
}
m->th->del(m->th);
- usb_uninit_cancel(&m->cancelt); /* Don't need cancel token now */
+ usb_uninit_cancel(&m->sw_cancel); /* Don't need cancel token now */
+ usb_uninit_cancel(&m->rd_sync); /* Don't need sync token now */
}
a1logd(p->log,5,"i1pro switch thread terminated\n");
@@ -403,7 +463,8 @@ i1pro_code i1pro_imp_init(i1pro *p) {
if ((ev = i1pro_reset(p, 0x1f)) != I1PRO_OK)
return ev;
- usb_init_cancel(&m->cancelt); /* Init cancel token */
+ usb_init_cancel(&m->sw_cancel); /* Init switch cancel token */
+ usb_init_cancel(&m->rd_sync); /* Init reading sync token */
#ifdef USE_THREAD
/* Setup the switch monitoring thread */
@@ -1246,7 +1307,7 @@ i1pro_code i1pro_imp_set_mode(
) {
i1proimp *m = (i1proimp *)p->m;
- a1logd(p->log,2,"i1pro_imp_set_mode called with %d\n",mmode);
+ a1logd(p->log,2,"i1pro_imp_set_mode called with mode no %d and mask 0x%x\n",mmode,m);
switch(mmode) {
case i1p_refl_spot:
case i1p_refl_scan:
@@ -1266,6 +1327,15 @@ i1pro_code i1pro_imp_set_mode(
return I1PRO_INT_ILLEGALMODE;
}
m->spec_en = (mode & inst_mode_spectral) != 0;
+
+ if ((mode & inst_mode_highres) != 0) {
+ i1pro_code rv;
+ if ((rv = i1pro_set_highres(p)) != I1PRO_OK)
+ return rv;
+ } else {
+ i1pro_set_stdres(p); /* Ignore any error */
+ }
+
m->uv_en = 0;
if (mmode == i1p_refl_spot
@@ -1356,6 +1426,19 @@ i1pro_code i1pro_imp_get_n_a_cals(i1pro *p, inst_cal_type *pn_cals, inst_cal_typ
a_cals |= inst_calt_emis_int_time;
}
+ /* Special case high res. emissive cal fine calibration, */
+ /* needs reflective cal. */
+ /* Hmmm. Should we do this every time for emission, in case */
+ /* we switch to hires mode ??? */
+ if ((cs->emiss || cs->trans) /* We're in an emissive mode */
+ && m->hr_inited /* and hi-res has been setup */
+ && (!m->emis_hr_cal || (n_cals & inst_calt_em_dark)) /* and the emis cal hasn't been */
+ /* fine tuned or we will be doing a dark cal */
+ && p->itype != instI1Monitor) { /* i1Monitor doesn't have reflective cal capability */
+ n_cals |= inst_calt_ref_white; /* Need a reflective white calibration */
+ a_cals |= inst_calt_ref_white;
+ }
+
if (pn_cals != NULL)
*pn_cals = n_cals;
@@ -1380,7 +1463,7 @@ i1pro_code i1pro_imp_calibrate(
i1proimp *m = (i1proimp *)p->m;
int mmode = m->mmode;
i1pro_state *cs = &m->ms[m->mmode];
- int sx1, sx2, sx;
+ int sx1, sx2, sx3, sx;
time_t cdate = time(NULL);
int nummeas = 0;
int ltocmode = 0; /* 1 = Lamp turn on compensation mode */
@@ -1403,7 +1486,7 @@ i1pro_code i1pro_imp_calibrate(
else if (*calt == inst_calt_available)
*calt = available & inst_calt_n_dfrble_mask;
- a1logd(p->log,4,"i1pro_imp_calibrate: doing calt 0x%x\n",calt);
+ a1logd(p->log,4,"i1pro_imp_calibrate: doing calt 0x%x\n",*calt);
if ((*calt & inst_calt_n_dfrble_mask) == 0) /* Nothing todo */
return I1PRO_OK;
@@ -1411,17 +1494,26 @@ i1pro_code i1pro_imp_calibrate(
/* See if it's a calibration we understand */
if (*calt & ~available & inst_calt_all_mask) {
+ a1logd(p->log,4,"i1pro_imp_calibrate: unsupported, calt 0x%x, available 0x%x\n",*calt,available);
return I1PRO_UNSUPPORTED;
}
if (*calt & inst_calt_ap_flag) {
- sx1 = 0; sx2 = i1p_no_modes; /* Go through all the modes */
+ sx1 = 0; sx2 = sx3 = i1p_no_modes; /* Go through all the modes */
} else {
- sx1 = m->mmode; sx2 = sx1 + 1; /* Just current mode */
+ /* Special case - doing reflective cal. to fix emiss hires */
+ if ((cs->emiss || cs->trans) /* We're in an emissive mode */
+ && (*calt & inst_calt_ref_white)) { /* but we're asked for a ref white cal */
+ sx1 = m->mmode; sx2 = sx1 + 1; /* Just current mode */
+ sx3 = i1p_refl_spot; /* no extra mode */
+ } else {
+ sx1 = m->mmode; sx2 = sx1 + 1; /* Just current mode */
+ sx3 = i1p_no_modes; /* no extra mode */
+ }
}
/* Go through the modes we are going to cover */
- for (sx = sx1; sx < sx2; sx++) {
+ for (sx = sx1; sx < sx2; (++sx >= sx2 && sx3 != i1p_no_modes) ? sx = sx3, sx2 = sx+1, sx3 = i1p_no_modes : 0) {
i1pro_state *s = &m->ms[sx];
m->mmode = sx; /* A lot of functions we call rely on this */
@@ -1459,15 +1551,15 @@ i1pro_code i1pro_imp_calibrate(
free_dvector(wlraw, -1, m->nraw-1);
- /* Compute normal res. reflective wavelength corrected filters */
- if ((ev = i1pro2_compute_wav_filters(p, 1)) != I1PRO_OK) {
- a1logd(p->log,2,"i1pro2_compute_wav_filters() failed\n");
+ /* Compute normal res. emissive/transmissive wavelength corrected filters */
+ if ((ev = i1pro_compute_wav_filters(p, 0, 0)) != I1PRO_OK) {
+ a1logd(p->log,2,"i1pro_compute_wav_filters() failed\n");
return ev;
}
- /* Compute normal res. emissive/transmissive wavelength corrected filters */
- if ((ev = i1pro2_compute_wav_filters(p, 0)) != I1PRO_OK) {
- a1logd(p->log,2,"i1pro2_compute_wav_filters() failed\n");
+ /* Compute normal res. reflective wavelength corrected filters */
+ if ((ev = i1pro_compute_wav_filters(p, 0, 1)) != I1PRO_OK) {
+ a1logd(p->log,2,"i1pro_compute_wav_filters() failed\n");
return ev;
}
@@ -2112,13 +2204,28 @@ i1pro_code i1pro_imp_calibrate(
return ev;
}
/* Compute a calibration factor given the reading of the white reference. */
- i1pro_compute_white_cal(p, s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
- s->cal_factor[1], m->white_ref[1], s->cal_factor[1]);
+ ev = i1pro_compute_white_cal(p,
+ s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
+ s->cal_factor[1], m->white_ref[1], s->cal_factor[1],
+ !s->scan); /* Use this for emis hires fine tune if not scan */
+
+ if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ m->mmode = mmode; /* Restore actual mode */
+ return ev;
+ }
- } else {
+ } else { /* transmissive */
/* Compute a calibration factor given the reading of the white reference. */
- m->transwarn |= i1pro_compute_white_cal(p, s->cal_factor[0], NULL, s->cal_factor[0],
- s->cal_factor[1], NULL, s->cal_factor[1]);
+ ev = i1pro_compute_white_cal(p, s->cal_factor[0], NULL, s->cal_factor[0],
+ s->cal_factor[1], NULL, s->cal_factor[1], 0);
+ if (ev == I1PRO_RD_TRANSWHITEWARN) {
+ m->transwarn |= 1;
+ ev = I1PRO_OK;
+ }
+ if (ev != I1PRO_OK) {
+ m->mmode = mmode; /* Restore actual mode */
+ return ev;
+ }
}
s->cal_valid = 1;
s->cfdate = cdate;
@@ -2195,8 +2302,16 @@ i1pro_code i1pro_imp_calibrate(
} /* Look at next mode */
m->mmode = mmode; /* Restore actual mode */
- /* Make sure there's the right condition for any remaining calibrations */
- if (*calt & inst_calt_wavelength) { /* Wavelength calibration */
+ /* Make sure there's the right condition for any remaining calibrations. */
+ /* Do ref_white first in case we are doing a high res fine tune. */
+
+ if (*calt & (inst_calt_ref_dark | inst_calt_ref_white)) {
+ sprintf(id, "Serial no. %d",m->serno);
+ if (*calc != inst_calc_man_ref_white) {
+ *calc = inst_calc_man_ref_white; /* Calibrate using white tile */
+ return I1PRO_CAL_SETUP;
+ }
+ } else if (*calt & inst_calt_wavelength) { /* Wavelength calibration */
if (cs->emiss && cs->ambient) {
id[0] = '\000';
if (*calc != inst_calc_man_am_dark) {
@@ -2210,12 +2325,6 @@ i1pro_code i1pro_imp_calibrate(
return I1PRO_CAL_SETUP;
}
}
- } else if (*calt & (inst_calt_ref_dark | inst_calt_ref_white)) {
- sprintf(id, "Serial no. %d",m->serno);
- if (*calc != inst_calc_man_ref_white) {
- *calc = inst_calc_man_ref_white; /* Calibrate using white tile */
- return I1PRO_CAL_SETUP;
- }
} else if (*calt & inst_calt_em_dark) { /* Emissive Dark calib */
id[0] = '\000';
if (*calc != inst_calc_man_em_dark) {
@@ -2286,6 +2395,154 @@ int icoms2i1pro_err(int se) {
}
/* - - - - - - - - - - - - - - - - */
+/* Measure a display update delay. It is assumed that a */
+/* white to black change has been made to the displayed color, */
+/* and this will measure the time it took for the update to */
+/* be noticed by the instrument, up to 0.6 seconds. */
+/* inst_misread will be returned on failure to find a transition to black. */
+#define NDMXTIME 0.7 /* Maximum time to take */
+#define NDSAMPS 500 /* Debug samples */
+
+typedef struct {
+ double sec;
+ double rgb[3];
+ double tot;
+} i1rgbdsamp;
+
+i1pro_code i1pro_imp_meas_delay(
+i1pro *p,
+int *msecdelay) { /* Return the number of msec */
+ i1pro_code ev = I1PRO_OK;
+ i1proimp *m = (i1proimp *)p->m;
+ i1pro_state *s = &m->ms[m->mmode];
+ int i, j, k, mm;
+ double **multimeas; /* Spectral measurements */
+ int nummeas;
+ double rgbw[3] = { 610.0, 520.0, 460.0 };
+ double ucalf = 1.0; /* usec_time calibration factor */
+ double inttime;
+ i1rgbdsamp *samp;
+ double stot, etot, del, thr;
+ double etime;
+ int isdeb;
+
+ /* Read the samples */
+ inttime = m->min_int_time;
+ nummeas = (int)(NDMXTIME/inttime + 0.5);
+ multimeas = dmatrix(0, nummeas-1, -1, m->nwav[m->highres]-1);
+ if ((samp = (i1rgbdsamp *)calloc(sizeof(i1rgbdsamp), nummeas)) == NULL) {
+ a1logd(p->log, 1, "i1pro_meas_delay: malloc failed\n");
+ return I1PRO_INT_MALLOC;
+ }
+
+//printf("~1 %d samples at %f int\n",nummeas,inttime);
+ if ((ev = i1pro_read_patches_all(p, multimeas, nummeas, &inttime, 0)) != inst_ok) {
+ free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav[m->highres]-1);
+ free(samp);
+ return ev;
+ }
+
+ /* Convert the samples to RGB */
+ for (i = 0; i < nummeas; i++) {
+ samp[i].sec = i * inttime;
+ samp[i].rgb[0] = samp[i].rgb[1] = samp[i].rgb[2] = 0.0;
+ for (j = 0; j < m->nwav[m->highres]; j++) {
+ double wl = XSPECT_WL(m->wl_short[m->highres], m->wl_long[m->highres], m->nwav[m->highres], j);
+
+//printf("~1 multimeas %d %d = %f\n",i, j, multimeas[i][j]);
+ for (k = 0; k < 3; k++) {
+ double tt = (double)(wl - rgbw[k]);
+ tt = (50.0 - fabs(tt))/50.0;
+ if (tt < 0.0)
+ tt = 0.0;
+ samp[i].rgb[k] += sqrt(tt) * multimeas[i][j];
+ }
+ }
+ samp[i].tot = samp[i].rgb[0] + samp[i].rgb[1] + samp[i].rgb[2];
+ }
+ free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav[m->highres]-1);
+
+ a1logd(p->log, 3, "i1pro_measure_refresh: Read %d samples for refresh calibration\n",nummeas);
+
+#ifdef PLOT_UPDELAY
+ /* Plot the raw sensor values */
+ {
+ double xx[NDSAMPS];
+ double y1[NDSAMPS];
+ double y2[NDSAMPS];
+ double y3[NDSAMPS];
+ double y4[NDSAMPS];
+
+ for (i = 0; i < nummeas && i < NDSAMPS; i++) {
+ xx[i] = samp[i].sec;
+ y1[i] = samp[i].rgb[0];
+ y2[i] = samp[i].rgb[1];
+ y3[i] = samp[i].rgb[2];
+ y4[i] = samp[i].tot;
+//printf("%d: %f -> %f\n",i,samp[i].sec, samp[i].tot);
+ }
+ printf("Display update delay measure sensor values and time (sec)\n");
+ do_plot6(xx, y1, y2, y3, y4, NULL, NULL, nummeas);
+ }
+#endif
+
+ /* Over the first 100msec, locate the maximum value */
+ etime = samp[nummeas-1].sec;
+ stot = -1e9;
+ for (i = 0; i < nummeas; i++) {
+ if (samp[i].tot > stot)
+ stot = samp[i].tot;
+ if (samp[i].sec > 0.1)
+ break;
+ }
+
+ /* Over the last 100msec, locate the maximum value */
+ etime = samp[nummeas-1].sec;
+ etot = -1e9;
+ for (i = nummeas-1; i >= 0; i--) {
+ if (samp[i].tot > etot)
+ etot = samp[i].tot;
+ if ((etime - samp[i].sec) > 0.1)
+ break;
+ }
+
+ del = stot - etot;
+ thr = etot + 0.30 * del; /* 30% of transition threshold */
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1pro_meas_delay: start tot %f end tot %f del %f, thr %f\n", stot, etot, del, thr);
+#endif
+
+ /* Check that there has been a transition */
+ if (del < 5.0) {
+ free(samp);
+ a1logd(p->log, 1, "i1pro_meas_delay: can't detect change from white to black\n");
+ return I1PRO_RD_NOTRANS_FOUND;
+ }
+
+ /* Locate the time at which the values are above the end values */
+ for (i = nummeas-1; i >= 0; i--) {
+ if (samp[i].tot > thr)
+ break;
+ }
+ if (i < 0) /* Assume the update was so fast that we missed it */
+ i = 0;
+
+ a1logd(p->log, 2, "i1pro_meas_delay: stoped at sample %d time %f\n",i,samp[i].sec);
+
+ *msecdelay = (int)(samp[i].sec * 1000.0 + 0.5);
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "i1pro_meas_delay: returning %d msec\n",*msecdelay);
+#endif
+ free(samp);
+
+ return I1PRO_OK;
+}
+#undef NDSAMPS
+#undef NDMXTIME
+
+/* - - - - - - - - - - - - - - - - */
/* Measure a patch or strip in the current mode. */
/* To try and speed up the reaction time between */
/* triggering a scan measurement and being able to */
@@ -2799,10 +3056,11 @@ i1pro_code i1pro_imp_meas_refrate(
tt = (40.0 - fabs(tt))/40.0;
if (tt < 0.0)
tt = 0.0;
- samp[i].rgb[k] += tt * multimeas[i][j];
+ samp[i].rgb[k] += sqrt(tt) * multimeas[i][j];
}
}
}
+ free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav[m->highres]-1);
nfsamps = i;
a1logd(p->log, 3, "i1pro_measure_refresh: Read %d samples for refresh calibration\n",nfsamps);
@@ -3325,6 +3583,7 @@ i1pro_code i1pro_imp_meas_refrate(
if (brange > 0.05) {
a1logd(p->log, 3, "Readings are too inconsistent (brange %.1f%%) - should retry ?\n",brange * 100.0);
} else {
+
if (ref_rate != NULL)
*ref_rate = brate;
@@ -3399,7 +3658,7 @@ i1pro_code i1pro_restore_refspot_cal(i1pro *p) {
} else
s->gainmode = 0;
- /* Get the calibration integrattion time */
+ /* Get the calibration integration time */
if ((dp = m->data->get_doubles(m->data, &count, key_inttime + offst)) == NULL || count < 1) {
a1logd(p->log,2,"Failed to read calibration integration time from EEPRom\n");
return I1PRO_OK;
@@ -3470,8 +3729,12 @@ i1pro_code i1pro_restore_refspot_cal(i1pro *p) {
return I1PRO_OK;
}
/* Compute a calibration factor given the reading of the white reference. */
- i1pro_compute_white_cal(p, s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
- s->cal_factor[1], m->white_ref[1], s->cal_factor[1]);
+ ev = i1pro_compute_white_cal(p, s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
+ s->cal_factor[1], m->white_ref[1], s->cal_factor[1], 1);
+ if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ a1logd(p->log,2,"i1pro_compute_white_cal failed to convert EEProm data to calibration\n");
+ return I1PRO_OK;
+ }
/* We've sucessfully restored the calibration */
s->cal_valid = 1;
@@ -4300,6 +4563,7 @@ i1pro_code i1pro_dark_measure_2(
/* absolute linearised sensor values. */
if ((ev = i1pro_sens_to_absraw(p, multimes, buf, nummeas, inttime, gainmode, &darkthresh))
!= I1PRO_OK) {
+ free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
return ev;
}
@@ -5459,6 +5723,7 @@ i1pro_trigger_one_measure(
}
/* Trigger a measurement */
+ usb_reinit_cancel(&m->rd_sync); /* Prepare to sync rd and trigger */
if (p->itype != instI1Pro2) {
if ((ev = i1pro_triggermeasure(p, TRIG_DELAY)) != I1PRO_OK)
return ev;
@@ -6819,14 +7084,21 @@ void i1pro_sub_absraw(
a1logd(p->log,2,"Black shielded value = %f, Reading shielded value = %f\n",sub[-1], avgscell);
/* Compute the adjusted black */
+ /* [ Unlike the ColorMunki, using the black drift comp. for reflective */
+ /* seems to be OK and even beneficial. ] */
for (j = 0; j < m->nraw; j++) {
-#ifdef NEVER
+#ifdef ENABLE_BKDRIFTC
+# ifdef HEURISTIC_BKDRIFTC
+ /* heuristic scaled correction */
+ asub[j] = zero - (zero - sub[j]) * (zero - avgscell)/(zero - sub[-1]);
+# else
/* simple additive correction */
-# pragma message("######### i1pro2 Simple shielded cell temperature correction! ########")
+# pragma message("######### i1pro2 Simple shielded cell temperature correction! ########")
asub[j] = sub[j] + avgscell - sub[-1];
+# endif
#else
- /* heuristic scaled correction */
- asub[j] = zero - (zero - sub[j]) * (zero - avgscell)/(zero - sub[-1]);
+# pragma message("######### i1pro2 No shielded cell temperature correction! ########")
+ asub[j] = sub[j]; /* Just use the calibration dark data */
#endif
}
@@ -7448,9 +7720,11 @@ i1pro_code i1pro2_match_wl_meas(i1pro *p, double *pled_off, double *wlraw) {
return ev;
}
-/* Compute standard res. downsampling filters for the given mode */
-/* given the current wl_led_off, and set them as current. */
-i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
+/* Compute standard/high res. downsampling filters for the given mode */
+/* given the current wl_led_off, and set them as current, */
+/* using triangular filters of the lagrange interpolation of the */
+/* CCD values. */
+i1pro_code i1pro_compute_wav_filters(i1pro *p, int hr, int refl) {
i1proimp *m = (i1proimp *)p->m;
i1pro_state *s = &m->ms[m->mmode];
i1pro_code ev = I1PRO_OK;
@@ -7461,28 +7735,28 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
double trh, trx; /* Triangle height and triangle equation x weighting */
int i, j, k;
- a1logd(p->log,2,"i1pro2_compute_wav_filters called with correction %f raw\n",s->wl_led_off - m->wl_led_ref_off);
+ a1logd(p->log,2,"i1pro_compute_wav_filters called with correction %f raw\n",s->wl_led_off - m->wl_led_ref_off);
- twidth = (m->wl_long[0] - m->wl_short[0])/(m->nwav[0] - 1.0); /* Filter width */
+ twidth = (m->wl_long[hr] - m->wl_short[hr])/(m->nwav[hr] - 1.0); /* Filter width */
trh = 1.0/twidth; /* Triangle height */
trx = trh/twidth; /* Triangle equation x weighting */
/* Allocate separate space for the calibrated versions, so that the */
/* original eeprom values are preserved */
- if (m->mtx_c[0][refl].index == NULL) {
+ if (m->mtx_c[hr][refl].index == NULL) {
- if ((m->mtx_c[0][refl].index = (int *)calloc(m->nwav[0], sizeof(int))) == NULL) {
+ if ((m->mtx_c[hr][refl].index = (int *)calloc(m->nwav[hr], sizeof(int))) == NULL) {
a1logd(p->log,1,"i1pro: malloc ndex1 failed!\n");
return I1PRO_INT_MALLOC;
}
- if ((m->mtx_c[0][refl].nocoef = (int *)calloc(m->nwav[0], sizeof(int))) == NULL) {
+ if ((m->mtx_c[hr][refl].nocoef = (int *)calloc(m->nwav[hr], sizeof(int))) == NULL) {
a1logd(p->log,1,"i1pro: malloc nocoef failed!\n");
return I1PRO_INT_MALLOC;
}
- if ((m->mtx_c[0][refl].coef = (double *)calloc(16 * m->nwav[0], sizeof(double)))
+ if ((m->mtx_c[hr][refl].coef = (double *)calloc(16 * m->nwav[hr], sizeof(double)))
== NULL) {
a1logd(p->log,1,"i1pro: malloc coef failed!\n");
return I1PRO_INT_MALLOC;
@@ -7490,9 +7764,9 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
}
/* For each output wavelength */
- wlcop = m->mtx_c[0][refl].coef;
- for (wlix = 0; wlix < m->nwav[0]; wlix++) {
- double owl = wlix/(m->nwav[0]-1.0) * (m->wl_long[0] - m->wl_short[0]) + m->wl_short[0];
+ wlcop = m->mtx_c[hr][refl].coef;
+ for (wlix = 0; wlix < m->nwav[hr]; wlix++) {
+ double owl = wlix/(m->nwav[hr]-1.0) * (m->wl_long[hr] - m->wl_short[hr]) + m->wl_short[hr];
int lip; /* Lagrange interpolation position */
// printf("Generating filter for %.1f nm width %.1f nm\n",owl, twidth);
@@ -7503,11 +7777,14 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
/* Do a dumb search from high to low nm */
for (six = 0; six < m->nraw; six++) {
+//printf("~1 (raw2wav (six %d) %f <? (owl %f + twidth %f) %f\n",six,i1pro_raw2wav(p, refl, (double)six),owl,twidth,owl + twidth);
+
if (i1pro_raw2wav(p, refl, (double)six) < (owl + twidth))
break;
}
+
if (six < 2 || six >= m->nraw) {
- a1loge(p->log,1,"i1pro: compute_wav_filters() six %d out of raw range to cover output filter %.1f nm width %.1f nm\n",six, owl, twidth);
+ a1loge(p->log,1,"i1pro: compute_wav_filters() six %d, exceeds raw range to cover output filter %.1f nm width %.1f nm\n",six, owl, twidth);
return I1PRO_INT_ASSERT;
}
eix = six;
@@ -7518,30 +7795,30 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
break;
}
if (eix > (m->nraw - 2) ) {
- a1loge(p->log,1,"i1pro: compute_wav_filters() eix %d out of raw range to cover output filter %.1f nm width %.1f nm\n",eix, owl, twidth);
+ a1loge(p->log,1,"i1pro: compute_wav_filters() eix %d, exceeds raw range to cover output filter %.1f nm width %.1f nm\n",eix, owl, twidth);
return I1PRO_INT_ASSERT;
}
- eix += 2;
+ eix += 2; /* Outside */
// for (j = six; j < eix; j++)
// printf("Using raw %d @ %.1f nm\n",j, i1pro_raw2wav(p, refl, (double)j));
/* Set start index for this wavelength */
- m->mtx_c[0][refl].index[wlix] = six;
+ m->mtx_c[hr][refl].index[wlix] = six;
/* Set number of filter coefficients */
- m->mtx_c[0][refl].nocoef[wlix] = eix - six;
+ m->mtx_c[hr][refl].nocoef[wlix] = eix - six;
- if (m->mtx_c[0][refl].nocoef[wlix] > 16) {
- a1loge(p->log,1,"i1pro: compute_wav_filters() too many filter %d\n",m->mtx_c[0][refl].nocoef[wlix]);
+ if (m->mtx_c[hr][refl].nocoef[wlix] > 16) {
+ a1loge(p->log,1,"i1pro: compute_wav_filters() too many filter %d\n",m->mtx_c[hr][refl].nocoef[wlix]);
return I1PRO_INT_ASSERT;
}
/* Start with zero filter weightings */
- for (i = 0; i < m->mtx_c[0][refl].nocoef[wlix]; i++)
+ for (i = 0; i < m->mtx_c[hr][refl].nocoef[wlix]; i++)
wlcop[i] = 0.0;
- /* for each Lagrange interpolation position */
+ /* for each Lagrange interpolation position (adjacent CCD locations) */
for (lip = six; (lip + 3) < eix; lip++) {
double rwav[4]; /* Relative wavelength of these Lagrange points */
double den[4]; /* Denominator values for points */
@@ -7656,14 +7933,14 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
}
}
// printf("~1 Weightings for for %.1f nm are:\n",owl);
-// for (i = 0; i < m->mtx_c[0][refl].nocoef[wlix]; i++)
+// for (i = 0; i < m->mtx_c[hr][refl].nocoef[wlix]; i++)
// printf("~1 comp %d weight %e\n",i,wlcop[i]);
- wlcop += m->mtx_c[0][refl].nocoef[wlix]; /* Next group of weightings */
+ wlcop += m->mtx_c[hr][refl].nocoef[wlix]; /* Next group of weightings */
}
#ifdef DEBUG
/* Check against orginal filters */
- {
+ if (!hr) {
int ix1, ix1c;
double aerr = 0.0;
@@ -7712,7 +7989,7 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
#endif /* DEBUG */
/* Switch normal res. to use wavelength calibrated version */
- m->mtx[0][refl] = m->mtx_c[0][refl];
+ m->mtx[hr][refl] = m->mtx_c[hr][refl];
return ev;
}
@@ -7721,16 +7998,34 @@ i1pro_code i1pro2_compute_wav_filters(i1pro *p, int refl) {
/* =============================================== */
#ifdef HIGH_RES
-#undef ANALIZE_EXISTING /* Analize the manufacturers existing filter shape */
+/*
+ It turns out that using the sharpest possible resampling filter
+ may make accuracy worse (particularly on the RevE), because it
+ enhances bumps in the raw response that mightn't be there
+ after calibrating for the instrument spectral sensitivity.
+ A better scheme (which we could sythesise using the hi-res
+ emissive calibration logic) would be to calibrate the raw CCD
+ values and then resample with possible sharpening.
+ Another approach would be to sharpen after filtering with
+ non-sharpening resampling filters.
+ The bottom line is that it's best to use a gausian hi-res
+ filter to avoid sharpening in non calibrated spectral space.
+ */
/* High res congiguration */
/* Pick one of these: */
-#define USE_LANCZOS2 /* [def] Use lanczos2 filter shape */
+#undef USE_TRI_LAGRANGE /* [und] Use normal res filter shape */
+#undef USE_LANCZOS2 /* [und] Use lanczos2 filter shape */
+#undef USE_LANCZOS3 /* [und] Use lanczos3 filter shape */
#undef USE_DECONV /* [und] Use deconvolution curve */
-#undef USE_GAUSSIAN /* [und] Use gaussian filter shape*/
#undef USE_BLACKMAN /* [und] Use Blackman windowed sinc shape */
+#define USE_GAUSSIAN /* [def] Use gaussian filter shape*/
#undef USE_CUBIC /* [und] Use cubic spline filter */
+#define DO_CCDNORM /* [def] Normalise CCD values to original */
+#define DO_CCDNORMAVG /* [und] Normalise averages rather than per CCD bin */
+ /* (We relly on fine cal & white cal to fix it) */
+
#undef COMPUTE_DISPERSION /* Compute slit & optics dispersion from red laser data */
#ifdef NEVER
@@ -7766,7 +8061,7 @@ static void i1pro_debug_plot_mtx_coef(i1pro *p) {
free_dvector(xx, -1, m->nraw-1);
free_dmatrix(yy, 0, 2, -1, m->nraw-1);
}
-#endif
+#endif /* NEVER */
#ifdef COMPUTE_DISPERSION
@@ -7876,7 +8171,7 @@ static double lin_fshape(i1pro_fs *fsh, int n, double x) {
/* Generate a sample from a lanczos2 filter shape */
/* wi is the width of the filter */
static double lanczos2(double wi, double x) {
- double y;
+ double y = 0.0;
#ifdef USE_DECONV
/* For 3.333, created by i1deconv.c */
@@ -7948,11 +8243,21 @@ static double lanczos2(double wi, double x) {
x = fabs(1.0 * x/wi);
if (x >= 2.0)
return 0.0;
- if (x < 1e-5)
+ if (x < 1e-6)
return 1.0;
y = sin(DBL_PI * x)/(DBL_PI * x) * sin(DBL_PI * x/2.0)/(DBL_PI * x/2.0);
#endif
+#ifdef USE_LANCZOS3
+ /* lanczos3 */
+ x = fabs(1.0 * x/wi);
+ if (x >= 3.0)
+ return 0.0;
+ if (x < 1e-6)
+ return 1.0;
+ y = sin(DBL_PI * x)/(DBL_PI * x) * sin(DBL_PI * x/3.0)/(DBL_PI * x/3.0);
+#endif
+
#ifdef USE_BLACKMAN /* Use Blackman windowed sinc shape */
double xx = x, w;
double a0, a1, a2, a3;
@@ -8034,16 +8339,126 @@ static int gcc_bug_fix(int i) {
}
#endif /* APPLE */
+/* Re-create calibration factors for hi-res */
+/* Set emisonly to only recompute emissive factors */
+i1pro_code i1pro_create_hr_calfactors(i1pro *p, int eonly) {
+ i1proimp *m = (i1proimp *)p->m;
+ i1pro_code ev = I1PRO_OK;
+ int i, j;
+
+ /* Generate high res. per mode calibration factors. */
+ if (m->hr_inited) {
+
+ for (i = 0; i < i1p_no_modes; i++) {
+ i1pro_state *s = &m->ms[i];
+
+ if (s->cal_factor[1] == NULL)
+ s->cal_factor[1] = dvectorz(0, m->nwav[1]-1);
+
+ switch(i) {
+ case i1p_refl_spot:
+ case i1p_refl_scan:
+ if (eonly)
+ continue;
+ if (s->cal_valid) {
+ /* (Using cal_factor[] as temp. for i1pro_absraw_to_abswav()) */
+#ifdef NEVER
+ printf("~1 regenerating calibration for reflection\n");
+ printf("~1 raw white data:\n");
+ plot_raw(s->white_data);
+#endif /* NEVER */
+ i1pro_absraw_to_abswav(p, 0, s->reflective, 1, &s->cal_factor[0], &s->white_data);
+#ifdef NEVER
+ printf("~1 Std res intmd. cal_factor:\n");
+ plot_wav(m, 0, s->cal_factor[0]);
+#endif /* NEVER */
+ i1pro_absraw_to_abswav(p, 1, s->reflective, 1, &s->cal_factor[1], &s->white_data);
+#ifdef NEVER
+ printf("~1 High intmd. cal_factor:\n");
+ plot_wav(m, 1, s->cal_factor[1]);
+ printf("~1 Std res white ref:\n");
+ plot_wav(m, 0, m->white_ref[0]);
+ printf("~1 High res white ref:\n");
+ plot_wav(m, 1, m->white_ref[1]);
+#endif /* NEVER */
+ ev = i1pro_compute_white_cal(p,
+ s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
+ s->cal_factor[1], m->white_ref[1], s->cal_factor[1],
+ i == i1p_refl_spot);
+ if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ return ev;
+ }
+#ifdef NEVER
+ printf("~1 Std res final cal_factor:\n");
+ plot_wav(m, 0, s->cal_factor[0]);
+ printf("~1 High final cal_factor:\n");
+ plot_wav(m, 1, s->cal_factor[1]);
+#endif /* NEVER */
+ }
+ break;
+
+ case i1p_emiss_spot_na:
+ case i1p_emiss_spot:
+ case i1p_emiss_scan:
+ for (j = 0; j < m->nwav[1]; j++)
+ s->cal_factor[1][j] = EMIS_SCALE_FACTOR * m->emis_coef[1][j];
+ break;
+
+ case i1p_amb_spot:
+ case i1p_amb_flash:
+#ifdef FAKE_AMBIENT
+ for (j = 0; j < m->nwav[1]; j++)
+ s->cal_factor[1][j] = EMIS_SCALE_FACTOR * m->emis_coef[1][j];
+ s->cal_valid = 1;
+#else
+
+ if (m->amb_coef[0] != NULL) {
+ for (j = 0; j < m->nwav[1]; j++)
+ s->cal_factor[1][j] = AMB_SCALE_FACTOR * m->emis_coef[1][j] * m->amb_coef[1][j];
+ s->cal_valid = 1;
+ }
+#endif
+ break;
+ case i1p_trans_spot:
+ case i1p_trans_scan:
+ if (eonly)
+ continue;
+ if (s->cal_valid) {
+ /* (Using cal_factor[] as temp. for i1pro_absraw_to_abswav()) */
+ i1pro_absraw_to_abswav(p, 0, s->reflective, 1, &s->cal_factor[0], &s->white_data);
+ i1pro_absraw_to_abswav(p, 1, s->reflective, 1, &s->cal_factor[1], &s->white_data);
+ ev = i1pro_compute_white_cal(p, s->cal_factor[0], NULL, s->cal_factor[0],
+ s->cal_factor[1], NULL, s->cal_factor[1], 0);
+ if (ev != I1PRO_RD_TRANSWHITEWARN && ev != I1PRO_OK) {
+ return ev;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return ev;
+}
+
+#ifdef SALONEINSTLIB
+# define ONEDSTRAYLIGHTUS
+#endif
+
/* Create or re-create high resolution mode references */
i1pro_code i1pro_create_hr(i1pro *p) {
i1proimp *m = (i1proimp *)p->m;
i1pro_code ev = I1PRO_OK;
int refl;
+ double twidth = HIGHRES_WIDTH;
int i, j, k, cx, sx;
/* If we don't have any way of converting raw2wav (ie. RevE polinomial equations), */
/* use the orginal filters to figure this out. */
- if (p->itype != instI1Pro2 && m->raw2wav == NULL) {
+ if (m->raw2wav == NULL
+#ifndef ANALIZE_EXISTING
+ && p->itype != instI1Pro2
+#endif
+ ) {
i1pro_fc coeff[100][16]; /* Existing filter cooefficients */
i1pro_xp xp[101]; /* Crossover points each side of filter */
i1pro_fs fshape[100 * 16]; /* Existing filter shape */
@@ -8101,51 +8516,55 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
#endif /* HIGH_RES_PLOT */
+// a1logd(p->log,3,"computing crossover points\n");
/* Compute the crossover points between each filter */
for (i = 0; i < (m->nwav[0]-1); i++) {
double den, y1, y2, y3, y4, yn, xn; /* Location of intersection */
+ double eps = 1e-6; /* Numerical tollerance */
+ double besty = -1e6;
/* between filter i and i+1, we want to find the two */
/* raw indexes where the weighting values cross over */
/* Do a brute force search to avoid making assumptions */
- /* about the raw order */
+ /* about the raw order. */
for (j = 0; j < (m->mtx_o.nocoef[i]-1); j++) {
for (k = 0; k < (m->mtx_o.nocoef[i+1]-1); k++) {
-// printf("~1 checking %d, %d: %d = %d, %d = %d\n",j,k, coeff[i][j].ix, coeff[i+1][k].ix, coeff[i][j+1].ix, coeff[i+1][k+1].ix);
if (coeff[i][j].ix == coeff[i+1][k].ix
- && coeff[i][j+1].ix == coeff[i+1][k+1].ix
- && coeff[i][j].we > 0.0 && coeff[i][j+1].we > 0.0
- && coeff[i][k].we > 0.0 && coeff[i][k+1].we > 0.0
- && (( coeff[i][j].we >= coeff[i+1][k].we
- && coeff[i][j+1].we <= coeff[i+1][k+1].we)
- || ( coeff[i][j].we <= coeff[i+1][k].we
- && coeff[i][j+1].we >= coeff[i+1][k+1].we))) {
-// printf("~1 got it at %d, %d: %d = %d, %d = %d\n",j,k, coeff[i][j].ix, coeff[i+1][k].ix, coeff[i][j+1].ix, coeff[i+1][k+1].ix);
- goto gotit;
+ && coeff[i][j+1].ix == coeff[i+1][k+1].ix) {
+
+// a1logd(p->log,3,"got it at %d, %d: %d = %d, %d = %d\n",j,k, coeff[i][j].ix, coeff[i+1][k].ix, coeff[i][j+1].ix, coeff[i+1][k+1].ix);
+
+ /* Compute the intersection of the two line segments */
+ y1 = coeff[i][j].we;
+ y2 = coeff[i][j+1].we;
+ y3 = coeff[i+1][k].we;
+ y4 = coeff[i+1][k+1].we;
+// a1logd(p->log,3,"y1 %f, y2 %f, y3 %f, y4 %f\n",y1, y2, y3, y4);
+ den = -y4 + y3 + y2 - y1;
+ if (fabs(den) < eps)
+ continue;
+ yn = (y2 * y3 - y1 * y4)/den;
+ xn = (y3 - y1)/den;
+ if (xn < -eps || xn > (1.0 + eps))
+ continue;
+// a1logd(p->log,3,"den = %f, yn = %f, xn = %f\n",den,yn,xn);
+ if (yn > besty) {
+ xp[i+1].wav = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i + 0.5);
+ xp[i+1].raw = (1.0 - xn) * coeff[i][j].ix + xn * coeff[i][j+1].ix;
+ xp[i+1].wei = yn;
+ besty = yn;
+// a1logd(p->log,3,"Intersection %d: wav %f, raw %f, wei %f\n",i+1,xp[i+1].wav,xp[i+1].raw,xp[i+1].wei);
+// a1logd(p->log,3,"Found new best y %f\n",yn);
+ }
+// a1logd(p->log,3,"\n");
}
}
}
- gotit:;
- if (j >= m->mtx_o.nocoef[i]) { /* Assert */
- a1loge(p->log,1,"i1pro: failed to locate crossover between resampling filters\n");
+ if (besty < 0.0) { /* Assert */
+ a1logw(p->log,"i1pro: failed to locate crossover between resampling filters\n");
return I1PRO_INT_ASSERT;
}
-// printf("~1 %d: overlap at %d, %d: %f : %f, %f : %f\n",i, j,k, coeff[i][j].we, coeff[i+1][k].we, coeff[i][j+1].we, coeff[i+1][k+1].we);
-
- /* Compute the intersection of the two line segments */
- y1 = coeff[i][j].we;
- y2 = coeff[i][j+1].we;
- y3 = coeff[i+1][k].we;
- y4 = coeff[i+1][k+1].we;
- den = -y4 + y3 + y2 - y1;
- yn = (y2 * y3 - y1 * y4)/den;
- xn = (y3 - y1)/den;
-// printf("~1 den = %f, yn = %f, xn = %f\n",den,yn,xn);
- xp[i+1].wav = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i + 0.5);
- xp[i+1].raw = (1.0 - xn) * coeff[i][j].ix + xn * coeff[i][j+1].ix;
- xp[i+1].wei = yn;
-// printf("Intersection %d: wav %f, raw %f, wei %f\n",i+1,xp[i+1].wav,xp[i+1].raw,xp[i+1].wei);
-// printf("\n");
+// a1logd(p->log,3,"\n");
}
/* Add the two points for the end filters */
@@ -8177,7 +8596,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
}
if (j >= m->mtx_o.nocoef[0]) { /* Assert */
- a1loge(p->log,1,"i1pro: failed to end crossover\n");
+ a1loge(p->log,1,"i1pro: failed to find end crossover\n");
return I1PRO_INT_ASSERT;
}
@@ -8216,7 +8635,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
}
if (j >= m->mtx_o.nocoef[m->nwav[0]-1]) { /* Assert */
- a1loge(p->log,1,"i1pro: failed to end crossover\n");
+ a1loge(p->log,1,"i1pro: failed to find end crossover\n");
return I1PRO_INT_ASSERT;
}
den = -y4 + y3 + y2 - y1;
@@ -8277,6 +8696,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
avgdev[0] = 0.0;
m->raw2wav->fit_rspl(m->raw2wav, 0, sd, m->nwav[0]+1, glow, ghigh, gres, vlow, vhigh, 0.5, avgdev, NULL);
+ }
#ifdef HIGH_RES_PLOT
/* Plot raw to wav lookup */
@@ -8299,99 +8719,98 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
printf("CCD bin to wavelength mapping of original filters + rspl:\n");
- do_plot6(xx, yy, y2, NULL, NULL, NULL, NULL, m->nwav+1);
+ do_plot6(xx, yy, y2, NULL, NULL, NULL, NULL, m->nwav[0]+1);
free_dvector(xx, 0, m->nwav[0]+1);
free_dvector(yy, 0, m->nwav[0]+1);
free_dvector(y2, 0, m->nwav[0]+1);
}
#endif /* HIGH_RES_PLOT */
- }
- }
#ifdef ANALIZE_EXISTING
- /* Convert each weighting curves values into normalized values and */
- /* accumulate into a single curve. */
- if (!m->hr_inited) {
- for (i = 0; i < m->nwav[0]; i++) {
- double cwl; /* center wavelegth */
- double weight = 0.0;
+ /* Convert each weighting curves values into normalized values and */
+ /* accumulate into a single curve. */
+ if (!m->hr_inited) {
+ for (i = 0; i < m->nwav[0]; i++) {
+ double cwl; /* center wavelegth */
+ double weight = 0.0;
- for (j = 0; j < (m->mtx_o.nocoef[i]); j++) {
- double w1, w2, cellw;
+ for (j = 0; j < (m->mtx_o.nocoef[i]); j++) {
+ double w1, w2, cellw;
- /* Translate CCD cell boundaries index to wavelength */
- w1 = i1pro_raw2wav_uncal(p, (double)coeff[i][j].ix - 0.5);
+ /* Translate CCD cell boundaries index to wavelength */
+ w1 = i1pro_raw2wav_uncal(p, (double)coeff[i][j].ix - 0.5);
- w2 = i1pro_raw2wav_uncal(p, (double)coeff[i][j].ix + 0.5);
+ w2 = i1pro_raw2wav_uncal(p, (double)coeff[i][j].ix + 0.5);
- cellw = fabs(w2 - w1);
+ cellw = fabs(w2 - w1);
- cwl = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i);
+ cwl = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i);
- /* Translate CCD index to wavelength */
- fshape[ncp].wl = i1pro_raw2wav_uncal(p, (double)coeff[i][j].ix) - cwl;
- fshape[ncp].we = coeff[i][j].we / (0.09 * cellw);
- ncp++;
+ /* Translate CCD index to wavelength */
+ fshape[ncp].wl = i1pro_raw2wav_uncal(p, (double)coeff[i][j].ix) - cwl;
+ fshape[ncp].we = coeff[i][j].we / (0.09 * cellw);
+ ncp++;
+ }
}
- }
- /* Now sort by wavelength */
+ /* Now sort by wavelength */
#define HEAP_COMPARE(A,B) (A.wl < B.wl)
- HEAPSORT(i1pro_fs, fshape, ncp)
+ HEAPSORT(i1pro_fs, fshape, ncp)
#undef HEAP_COMPARE
- /* Strip out leading zero's */
- for (i = 0; i < ncp; i++) {
- if (fshape[i].we != 0.0)
- break;
- }
- if (i > 1 && i < ncp) {
- memmove(&fshape[0], &fshape[i-1], sizeof(i1pro_fs) * (ncp - i + 1));
- ncp = ncp - i + 1;
+ /* Strip out leading zero's */
for (i = 0; i < ncp; i++) {
if (fshape[i].we != 0.0)
break;
}
- }
+ if (i > 1 && i < ncp) {
+ memmove(&fshape[0], &fshape[i-1], sizeof(i1pro_fs) * (ncp - i + 1));
+ ncp = ncp - i + 1;
+ for (i = 0; i < ncp; i++) {
+ if (fshape[i].we != 0.0)
+ break;
+ }
+ }
#ifdef HIGH_RES_PLOT
- /* Plot the shape of the accumulated curve */
- {
- double *x1 = dvectorz(0, ncp-1);
- double *y1 = dvectorz(0, ncp-1);
+ /* Plot the shape of the accumulated curve */
+ {
+ double *x1 = dvectorz(0, ncp-1);
+ double *y1 = dvectorz(0, ncp-1);
- for (i = 0; i < ncp; i++) {
- double x;
- x1[i] = fshape[i].wl;
- y1[i] = fshape[i].we;
- }
- printf("Accumulated curve:\n");
- do_plot(x1, y1, NULL, NULL, ncp);
+ for (i = 0; i < ncp; i++) {
+ double x;
+ x1[i] = fshape[i].wl;
+ y1[i] = fshape[i].we;
+ }
+ printf("Original accumulated curve:\n");
+ do_plot(x1, y1, NULL, NULL, ncp);
- free_dvector(x1, 0, ncp-1);
- free_dvector(y1, 0, ncp-1);
- }
+ free_dvector(x1, 0, ncp-1);
+ free_dvector(y1, 0, ncp-1);
+ }
#endif /* HIGH_RES_PLOT */
#ifdef HIGH_RES_DEBUG
- /* Check that the orginal filter sums to a constant */
- {
- double x, sum;
-
- for (x = 0.0; x < 10.0; x += 0.2) {
- sum = 0;
- sum += lin_fshape(fshape, ncp, x - 30.0);
- sum += lin_fshape(fshape, ncp, x - 20.0);
- sum += lin_fshape(fshape, ncp, x - 10.0);
- sum += lin_fshape(fshape, ncp, x - 0.0);
- sum += lin_fshape(fshape, ncp, x + 10.0);
- sum += lin_fshape(fshape, ncp, x + 20.0);
- printf("Offset %f, sum %f\n",x, sum);
+ /* Check that the orginal filter sums to a constant */
+ {
+ double x, sum;
+
+ for (x = 0.0; x < 10.0; x += 0.2) {
+ sum = 0;
+ sum += lin_fshape(fshape, ncp, x - 30.0);
+ sum += lin_fshape(fshape, ncp, x - 20.0);
+ sum += lin_fshape(fshape, ncp, x - 10.0);
+ sum += lin_fshape(fshape, ncp, x - 0.0);
+ sum += lin_fshape(fshape, ncp, x + 10.0);
+ sum += lin_fshape(fshape, ncp, x + 20.0);
+ printf("Offset %f, sum %f\n",x, sum);
+ }
}
- }
#endif /* HIGH_RES_DEBUG */
- }
+ }
#endif /* ANALIZE_EXISTING */
+ } /* End of compute wavelength cal from existing filters */
#ifdef COMPUTE_DISPERSION
if (!m->hr_inited) {
@@ -8498,7 +8917,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
datao vlow, vhigh;
int gres[2];
double avgdev[2];
- int ii;
+ int ix, ii;
co pp;
if ((trspl = new_rspl(RSPL_NOFLAGS, 1, 1)) == NULL) {
@@ -8506,6 +8925,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
return I1PRO_INT_NEW_RSPL_FAILED;
}
+ /* For ref, emis, ambient */
for (ii = 0; ii < 3; ii++) {
double **ref2, *ref1;
double smooth = 1.0;
@@ -8513,17 +8933,26 @@ i1pro_code i1pro_create_hr(i1pro *p) {
if (ii == 0) {
ref1 = m->white_ref[0];
ref2 = &m->white_ref[1];
- smooth = 0.5;
+// smooth = 0.5;
+ smooth = 1.5;
} else if (ii == 1) {
+ /* Don't create high res. from low res., if there is */
+ /* a better, calibrated cal read from .cal file */
+ if (m->emis_coef[1] != NULL) {
+ if (m->emis_hr_cal)
+ continue;
+ free(m->emis_coef[1]); /* Regenerate it anyway */
+ }
ref1 = m->emis_coef[0];
ref2 = &m->emis_coef[1];
- smooth = 500.0; /* Hmm. Lagrange may work better ?? */
+ m->emis_hr_cal = 0;
+ smooth = 10.0;
} else {
if (m->amb_coef[0] == NULL)
break;
ref1 = m->amb_coef[0];
ref2 = &m->amb_coef[1];
- smooth = 0.2;
+ smooth = 1.0;
}
if (ref1 == NULL)
@@ -8531,46 +8960,58 @@ i1pro_code i1pro_create_hr(i1pro *p) {
vlow[0] = 1e6;
vhigh[0] = -1e6;
- for (i = 0; i < m->nwav[0]; i++) {
+ for (ix = i = 0; i < m->nwav[0]; i++) {
- sd[i].p[0] = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i);
- sd[i].v[0] = ref1[i];
- sd[i].w = 1.0;
+ sd[ix].p[0] = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i);
+ sd[ix].v[0] = ref1[i];
+ sd[ix].w = 1.0;
- if (sd[i].v[0] < vlow[0])
- vlow[0] = sd[i].v[0];
- if (sd[i].v[0] > vhigh[0])
- vhigh[0] = sd[i].v[0];
+ if (sd[ix].v[0] < vlow[0])
+ vlow[0] = sd[ix].v[0];
+ if (sd[ix].v[0] > vhigh[0])
+ vhigh[0] = sd[ix].v[0];
+ ix++;
}
- if (ii == 1) { /* fudge factors */
+ /* Our upsampling is OK for reflective and ambient cal's, */
+ /* but isn't so good for the emissive cal., especially */
+ /* on the i1pro2. We'll get an opportunity to fix it */
+ /* when we do a reflective calibration, by using the */
+ /* smoothness of the lamp as a reference. */
-#ifdef NEVER /* Doesn't help */
- /* Increase boost at short wavelegths */
- if (m->wl_short[1] < 380.0) {
- sd[i].p[0] = m->wl_short[1];
- sd[i].v[0] = sd[0].v[0] * (1.0 + (380.0 - m->wl_short[1])/20.0);
- sd[i++].w = 0.6;
- }
-#endif
+ /* Add inbetween points to restrain dips and peaks in interp. */
+ for (i = 0; i < (m->nwav[0]-1); i++) {
-#ifdef NEVER /* Doesn't help */
- /* Reduces boost at long wavelegths */
- if (m->wl_long[1] > 730.0) {
- sd[i].p[0] = m->wl_long[1];
- sd[i].v[0] = sd[m->nwav[0]-1].v[0] * (1.0 + (m->wl_long[1] - 730.0)/100.0);
- sd[i++].w = 0.3;
- }
-#endif
+ /* Use linear interp extra points */
+ double wt = 0.05;
+
+ sd[ix].p[0] = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i + 0.3333);
+ sd[ix].v[0] = (2.0 * ref1[i] + ref1[i+1])/3.0;
+ sd[ix].w = wt;
+
+ if (sd[ix].v[0] < vlow[0])
+ vlow[0] = sd[ix].v[0];
+ if (sd[ix].v[0] > vhigh[0])
+ vhigh[0] = sd[ix].v[0];
+ ix++;
+
+ sd[ix].p[0] = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i + 0.66667);
+ sd[ix].v[0] = (ref1[i] + 2.0 * ref1[i+1])/3.0;
+ sd[ix].w = wt;
+
+ if (sd[ix].v[0] < vlow[0])
+ vlow[0] = sd[ix].v[0];
+ if (sd[ix].v[0] > vhigh[0])
+ vhigh[0] = sd[ix].v[0];
+ ix++;
}
-
+
glow[0] = m->wl_short[1];
ghigh[0] = m->wl_long[1];
- gres[0] = m->nwav[1];
+ gres[0] = 3 * m->nwav[1];
avgdev[0] = 0.0;
- trspl->fit_rspl_w(trspl, 0, sd, i, glow, ghigh, gres, vlow, vhigh, smooth, avgdev, NULL);
-
+ trspl->fit_rspl_w(trspl, 0, sd, ix, glow, ghigh, gres, vlow, vhigh, smooth, avgdev, NULL);
if ((*ref2 = (double *)calloc(m->nwav[1], sizeof(double))) == NULL) {
trspl->del(trspl);
a1logw(p->log, "i1pro: malloc ref2 failed!\n");
@@ -8583,6 +9024,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
trspl->interp(trspl, &pp);
(*ref2)[i] = pp.v[0];
}
+
#ifdef HIGH_RES_PLOT
/* Plot original and upsampled reference */
{
@@ -8593,27 +9035,13 @@ i1pro_code i1pro_create_hr(i1pro *p) {
for (i = 0; i < m->nwav[1]; i++) {
double wl = m->wl_short[1] + (double)i * (m->wl_long[1] - m->wl_short[1])/(m->nwav[1]-1.0);
x1[i] = wl;
- y1[i] = (*ref2)[i];
- if (wl < m->wl_short[0] || wl > m->wl_long[0]) {
- y2[i] = 0.0;
- } else {
- double x, wl1, wl2;
- for (j = 0; j < (m->nwav[0]-1); j++) {
- wl1 = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], j);
- wl2 = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], j+1);
- if (wl >= wl1 && wl <= wl2)
- break;
- }
- x = (wl - wl1)/(wl2 - wl1);
- y2[i] = ref1[j] + (ref1[j+1] - ref1[j]) * x;
- }
+ y1[i] = wav_lerp_cv(m, 0, ref1, wl, 0.0);
+ y2[i] = (*ref2)[i];
}
printf("Original and up-sampled ");
if (ii == 0) {
printf("Reflective cal. curve:\n");
} else if (ii == 1) {
- ref1 = m->emis_coef[0];
- ref2 = &m->emis_coef[1];
printf("Emission cal. curve:\n");
} else {
printf("Ambient cal. curve:\n");
@@ -8630,7 +9058,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
/* Upsample stray light */
if (p->itype == instI1Pro2) {
-#ifdef SALONEINSTLIB
+#ifdef ONEDSTRAYLIGHTUS
double **slp; /* 2D Array of stray light values */
/* Then the 2D stray light using linear interpolation */
@@ -8676,7 +9104,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
}
}
-#else /* !SALONEINSTLIB */
+#else /* !ONEDSTRAYLIGHTUS */
/* Then setup 2D stray light using rspl */
if ((trspl = new_rspl(RSPL_NOFLAGS, 2, 1)) == NULL) {
a1logd(p->log,1,"i1pro: creating rspl for high res conversion failed\n");
@@ -8707,7 +9135,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
avgdev[1] = 0.0;
trspl->fit_rspl_w(trspl, 0, sd, m->nwav[0] * m->nwav[0], glow, ghigh, gres, NULL, NULL, 0.5, avgdev, NULL);
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
m->straylight[1] = dmatrixz(0, m->nwav[1]-1, 0, m->nwav[1]-1);
@@ -8717,7 +9145,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
double p0, p1;
p0 = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], i);
p1 = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], j);
-#ifdef SALONEINSTLIB
+#ifdef ONEDSTRAYLIGHTUS
/* Do linear interp with clipping at ends */
{
int x0, x1, y0, y1;
@@ -8748,11 +9176,11 @@ i1pro_code i1pro_create_hr(i1pro *p) {
+ w1 * v0 * slp[x1][y0]
+ w1 * v1 * slp[x1][y1];
}
-#else /* !SALONEINSTLIB */
+#else /* !ONEDSTRAYLIGHTUS */
pp.p[0] = p0;
pp.p[1] = p1;
trspl->interp(trspl, &pp);
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
m->straylight[1][i][j] = pp.v[0] * HIGHRES_WIDTH/10.0;
if (m->straylight[1][i][j] > 0.0)
m->straylight[1][i][j] = 0.0;
@@ -8823,39 +9251,48 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
#endif /* HIGH_RES_PLOT */
-#ifdef SALONEINSTLIB
+#ifdef ONEDSTRAYLIGHTUS
free_dmatrix(slp, 0, m->nwav[0]-1, 0, m->nwav[0]-1);
-#else /* !SALONEINSTLIB */
+#else /* !ONEDSTRAYLIGHTUS */
trspl->del(trspl);
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
}
}
/* Create or re-create the high resolution filters */
for (refl = 0; refl < 2; refl++) { /* for emis/trans and reflective */
+#define MXNOWL 500 /* Max hires bands */
+#define MXNOFC 64 /* Max hires coeffs */
+
+#ifndef USE_TRI_LAGRANGE /* Use decimation filter */
+ int super = 0; /* nz if we're super sampling */
double fshmax; /* filter shape max wavelength from center */
-#define MXNOFC 64
- i1pro_fc coeff2[500][MXNOFC]; /* New filter cooefficients */
- double twidth;
+ i1pro_fc coeff2[MXNOWL][MXNOFC]; /* New filter cooefficients */
/* Construct a set of filters that uses more CCD values */
- twidth = HIGHRES_WIDTH;
- if (m->nwav[1] > 500) { /* Assert */
+ if (twidth < 3.0)
+ super = 1;
+
+ if (m->nwav[1] > MXNOWL) { /* Assert */
a1loge(p->log,1,"High res filter has too many bands\n");
return I1PRO_INT_ASSERT;
}
- /* Use a simple means of determining width */
- for (fshmax = 50.0; fshmax >= 0.0; fshmax -= 0.1) {
- if (fabs(lanczos2(twidth, fshmax)) > 0.0001) {
- fshmax += 0.1;
- break;
+ if (super) {
+ fshmax = 5.0;
+ } else {
+ /* Use a simple means of determining width */
+ for (fshmax = 50.0; fshmax >= 0.0; fshmax -= 0.1) {
+ if (fabs(lanczos2(twidth, fshmax)) > 0.0001) {
+ fshmax += 0.1;
+ break;
+ }
+ }
+ if (fshmax <= 0.0) {
+ a1logw(p->log, "i1pro: fshmax search failed\n");
+ return I1PRO_INT_ASSERT;
}
- }
- if (fshmax <= 0.0) {
- a1logw(p->log, "i1pro: fshmax search failed\n");
- return I1PRO_INT_ASSERT;
}
// printf("~1 fshmax = %f\n",fshmax);
@@ -8886,164 +9323,108 @@ i1pro_code i1pro_create_hr(i1pro *p) {
return I1PRO_INT_MALLOC;
}
- /* For all the useful CCD bands */
- for (i = 1; i < 127; i++) {
- double w1, wl, w2;
+ if (super) { /* Use linear interpolation */
- /* Translate CCD center and boundaries to calibrated wavelength */
- wl = i1pro_raw2wav(p, refl, (double)i);
- w1 = i1pro_raw2wav(p, refl, (double)i - 0.5);
- w2 = i1pro_raw2wav(p, refl, (double)i + 0.5);
+ /* For all the useful CCD bands */
+ for (i = 1; i < (127-1); i++) {
+ double wl, wh;
-// printf("~1 CCD %d, w1 %f, wl %f, w2 %f\n",i,w1,wl,w2);
-
- /* For each filter */
- for (j = 0; j < m->nwav[1]; j++) {
- double cwl, rwl; /* center, relative wavelegth */
- double we;
-
- cwl = m->wl_short[1] + (double)j * (m->wl_long[1] - m->wl_short[1])/(m->nwav[1]-1.0);
- rwl = wl - cwl; /* relative wavelength to filter */
-
- if (fabs(w1 - cwl) > fshmax && fabs(w2 - cwl) > fshmax)
- continue; /* Doesn't fall into this filter */
+ /* Translate CCD centers to calibrated wavelength */
+ wh = i1pro_raw2wav(p, refl, (double)(i+0));
+ wl = i1pro_raw2wav(p, refl, (double)(i+1));
- /* Integrate in 0.05 nm increments from filter shape */
- /* using triangular integration. */
- {
- int nn;
- double lw, ll;
-
- nn = (int)(fabs(w2 - w1)/0.05 + 0.5); /* Number to integrate over */
-
- lw = w1; /* start at lower boundary of CCD cell */
- ll = lanczos2(twidth, w1- cwl);
- we = 0.0;
- for (k = 0; k < nn; k++) {
- double cw, cl;
-
-#if defined(__APPLE__) && defined(__POWERPC__)
- gcc_bug_fix(k);
-#endif
- cw = w1 + (k+1.0)/(nn +1.0) * (w2 - w1); /* wl to sample */
- cl = lanczos2(twidth, cw- cwl);
- we += 0.5 * (cl + ll) * (lw - cw); /* Area under triangle */
- ll = cl;
- lw = cw;
+ /* For each filter */
+ for (j = 0; j < m->nwav[1]; j++) {
+ double cwl; /* Center wavelength */
+ double we; /* Weighting */
+ double wwwe = 1.0;
+
+ cwl = m->wl_short[1] + (double)j * (m->wl_long[1] - m->wl_short[1])
+ /(m->nwav[1]-1.0);
+//printf("~1 wl %f, wh %f, cwl %f\n",wl,wh,cwl);
+ if (cwl < (wl - 1e-6) || cwl > (wh + 1e-6))
+ continue; /* Doesn't fall into this filter */
+
+ if ((m->mtx_c[1][refl].nocoef[j]+1) >= MXNOFC) {
+ a1logw(p->log, "i1pro: run out of high res filter space\n");
+ return I1PRO_INT_ASSERT;
}
- }
-
- if (m->mtx_c[1][refl].nocoef[j] >= MXNOFC) {
- a1logw(p->log, "i1pro: run out of high res filter space\n");
- return I1PRO_INT_ASSERT;
- }
-
- coeff2[j][m->mtx_c[1][refl].nocoef[j]].ix = i;
- coeff2[j][m->mtx_c[1][refl].nocoef[j]++].we = we;
-// printf("~1 filter %d, cwl %f, rwl %f, ix %d, we %f, nocoefs %d\n",j,cwl,rwl,i,we,m->mtx_c[1][refl].nocoef[j]-1);
- }
- }
-
-#ifdef HIGH_RES_PLOT
- /* Plot resampled curves */
- {
- double *xx, *ss;
- double **yy;
-
- xx = dvectorz(-1, m->nraw-1); /* X index */
- yy = dmatrixz(0, 5, -1, m->nraw-1); /* Curves distributed amongst 5 graphs */
-
- for (i = 0; i < m->nraw; i++)
- xx[i] = i;
- /* For each output wavelength */
- for (j = 0; j < m->nwav[1]; j++) {
- i = j % 5;
+ we = (cwl - wl)/(wh - wl);
+// wwwe = 3.3/(wh - wl);
- /* For each matrix value */
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++) {
- yy[5][coeff2[j][k].ix] += 0.5 * coeff2[j][k].we;
- yy[i][coeff2[j][k].ix] = coeff2[j][k].we;
+ coeff2[j][m->mtx_c[1][refl].nocoef[j]].ix = i;
+ coeff2[j][m->mtx_c[1][refl].nocoef[j]++].we = wwwe * we;
+//printf("~1 filter %d, cwl %f, ix %d, we %f, nocoefs %d\n",j,cwl,i,we,m->mtx_c[1][refl].nocoef[j]);
+ coeff2[j][m->mtx_c[1][refl].nocoef[j]].ix = i+1;
+ coeff2[j][m->mtx_c[1][refl].nocoef[j]++].we = wwwe * (1.0 - we);
+//printf("~1 filter %d, cwl %f, ix %d, we %f, nocoefs %d\n",j,cwl,i+1,1.0-we,m->mtx_c[1][refl].nocoef[j]);
}
}
- printf("Hi-Res wavelength sampling curves:\n");
- do_plot6(xx, yy[0], yy[1], yy[2], yy[3], yy[4], yy[5], m->nraw);
- free_dvector(xx, -1, m->nraw-1);
- free_dmatrix(yy, 0, 2, -1, m->nraw-1);
- }
-#endif /* HIGH_RES_PLOT */
-
- /* Normalise the filters area in CCD space, while maintaining the */
- /* total contribution of each CCD at the target too. */
- {
- int ii;
- double tot = 0.0;
- double ccdweight[128], avgw; /* Weighting determined by cell widths */
- double ccdsum[128];
-
- /* Normalize the overall filter weightings */
- for (j = 0; j < m->nwav[1]; j++)
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
- tot += coeff2[j][k].we;
- tot /= (double)m->nwav[1];
- for (j = 0; j < m->nwav[1]; j++)
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
- coeff2[j][k].we /= tot;
-
- /* Determine the relative weights for each CCD */
- avgw = 0.0;
+ } else {
+ /* For all the useful CCD bands */
for (i = 1; i < 127; i++) {
+ double w1, wl, w2;
- ccdweight[i] = i1pro_raw2wav(p, refl, (double)i - 0.5)
- - i1pro_raw2wav(p, refl, (double)i + 0.5);
- ccdweight[i] = fabs(ccdweight[i]);
- avgw += ccdweight[i];
- }
- avgw /= 126.0;
- // ~~this isn't right because not all CCD's get used!!
+ /* Translate CCD center and boundaries to calibrated wavelength */
+ wl = i1pro_raw2wav(p, refl, (double)i);
+ w1 = i1pro_raw2wav(p, refl, (double)i - 0.5);
+ w2 = i1pro_raw2wav(p, refl, (double)i + 0.5);
-#ifdef NEVER
- /* Itterate */
- for (ii = 0; ; ii++) {
+// printf("~1 CCD %d, w1 %f, wl %f, w2 %f\n",i,w1,wl,w2);
- /* Normalize the individual filter weightings */
+ /* For each filter */
for (j = 0; j < m->nwav[1]; j++) {
- double err;
- tot = 0.0;
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
- tot += coeff2[j][k].we;
- err = 1.0 - tot;
-
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
- coeff2[j][k].we += err/m->mtx_c[1][refl].nocoef[j];
-// for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
-// coeff2[j][k].we *= 1.0/tot;
- }
+ double cwl, rwl; /* center, relative wavelegth */
+ double we;
- /* Check CCD sums */
- for (i = 1; i < 127; i++)
- ccdsum[i] = 0.0;
+ cwl = m->wl_short[1] + (double)j * (m->wl_long[1] - m->wl_short[1])
+ /(m->nwav[1]-1.0);
+ rwl = wl - cwl; /* relative wavelength to filter */
- for (j = 0; j < m->nwav[1]; j++) {
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
- ccdsum[coeff2[j][k].ix] += coeff2[j][k].we;
- }
+ if (fabs(w1 - cwl) > fshmax && fabs(w2 - cwl) > fshmax)
+ continue; /* Doesn't fall into this filter */
- if (ii >= 6)
- break;
+ /* Integrate in 0.05 nm increments from filter shape */
+ /* using triangular integration. */
+ {
+ int nn;
+ double lw, ll;
+#ifdef FAST_HIGH_RES_SETUP
+# define FINC 0.2
+#else
+# define FINC 0.05
+#endif
+ nn = (int)(fabs(w2 - w1)/0.2 + 0.5); /* Number to integrate over */
+
+ lw = w1; /* start at lower boundary of CCD cell */
+ ll = lanczos2(twidth, w1- cwl);
+ we = 0.0;
+ for (k = 0; k < nn; k++) {
+ double cw, cl;
- /* Readjust CCD sum */
- for (i = 1; i < 127; i++) {
- ccdsum[i] = ccdtsum[i]/ccdsum[i]; /* Amount to adjust */
- }
+#if defined(__APPLE__) && defined(__POWERPC__)
+ gcc_bug_fix(k);
+#endif
+ cw = w1 + (k+1.0)/(nn +1.0) * (w2 - w1); /* wl to sample */
+ cl = lanczos2(twidth, cw- cwl);
+ we += 0.5 * (cl + ll) * (lw - cw); /* Area under triangle */
+ ll = cl;
+ lw = cw;
+ }
+ }
- for (j = 0; j < m->nwav[1]; j++) {
- for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++)
- coeff2[j][k].we *= ccdsum[coeff2[j][k].ix];
+ if (m->mtx_c[1][refl].nocoef[j] >= MXNOFC) {
+ a1logw(p->log, "i1pro: run out of high res filter space\n");
+ return I1PRO_INT_ASSERT;
+ }
+
+ coeff2[j][m->mtx_c[1][refl].nocoef[j]].ix = i;
+ coeff2[j][m->mtx_c[1][refl].nocoef[j]++].we = we;
+// printf("~1 filter %d, cwl %f, rwl %f, ix %d, we %f, nocoefs %d\n",j,cwl,rwl,i,we,m->mtx_c[1][refl].nocoef[j]);
}
}
-#endif /* NEVER */
}
#ifdef HIGH_RES_PLOT
@@ -9069,7 +9450,7 @@ i1pro_code i1pro_create_hr(i1pro *p) {
}
}
- printf("Normalized Hi-Res wavelength sampling curves:\n");
+ printf("Hi-Res wavelength sampling curves %s:\n",refl ? "refl" : "emis");
do_plot6(xx, yy[0], yy[1], yy[2], yy[3], yy[4], yy[5], m->nraw);
free_dvector(xx, -1, m->nraw-1);
free_dmatrix(yy, 0, 2, -1, m->nraw-1);
@@ -9109,93 +9490,229 @@ i1pro_code i1pro_create_hr(i1pro *p) {
/* Set high res tables to new allocations */
m->mtx[1][refl] = m->mtx_c[1][refl];
}
- }
- /* Generate high res. per mode calibration factors. */
- if (!m->hr_inited) {
+#else /* USE_TRI_LAGRANGE, use triangle over lagrange interp */
- m->hr_inited = 1; /* Set so that i1pro_compute_white_cal() etc. does right thing */
+ /* Compute high res. reflective wavelength corrected filters */
+ if ((ev = i1pro_compute_wav_filters(p, 1, refl)) != I1PRO_OK) {
+ a1logd(p->log,2,"i1pro_compute_wav_filters() failed\n");
+ return ev;
+ }
+#endif /* USE_TRI_LAGRANGE */
- for (i = 0; i < i1p_no_modes; i++) {
- i1pro_state *s = &m->ms[i];
+ /* Normalise the filters area in CCD space, while maintaining the */
+ /* total contribution of each CCD at the target too. */
+ /* Hmm. This will wreck super-sample. We should fix it */
+#ifdef DO_CCDNORM /* Normalise CCD values to original */
+ {
+ double x[4], y[4];
+ double avg[2], max[2];
+ double ccdsum[2][128]; /* Target weight/actual for each CCD */
+ double dth[2];
- if (s->cal_factor[1] == NULL)
- s->cal_factor[1] = dvectorz(0, m->nwav[1]-1);
+ avg[0] = avg[1] = 0.0;
+ max[0] = max[1] = 0.0;
+ for (j = 0; j < 128; j++) {
+ ccdsum[0][j] = 0.0;
+ ccdsum[1][j] = 0.0;
+ }
- switch(i) {
- case i1p_refl_spot:
- case i1p_refl_scan:
- if (s->cal_valid) {
- /* (Using cal_factor[] as temp. for i1pro_absraw_to_abswav()) */
-#ifdef NEVER
- printf("~1 regenerating calibration for reflection\n");
- printf("~1 raw white data:\n");
- plot_raw(s->white_data);
-#endif /* NEVER */
- i1pro_absraw_to_abswav(p, 0, s->reflective, 1, &s->cal_factor[0], &s->white_data);
-#ifdef NEVER
- printf("~1 Std res intmd. cal_factor:\n");
- plot_wav(m, 0, s->cal_factor[0]);
-#endif /* NEVER */
- i1pro_absraw_to_abswav(p, 1, s->reflective, 1, &s->cal_factor[1], &s->white_data);
-#ifdef NEVER
- printf("~1 High intmd. cal_factor:\n");
- plot_wav(m, 1, s->cal_factor[1]);
- printf("~1 Std res white ref:\n");
- plot_wav(m, 0, m->white_ref[0]);
- printf("~1 High res white ref:\n");
- plot_wav(m, 1, m->white_ref[1]);
-#endif /* NEVER */
- i1pro_compute_white_cal(p, s->cal_factor[0], m->white_ref[0], s->cal_factor[0],
- s->cal_factor[1], m->white_ref[1], s->cal_factor[1]);
-#ifdef NEVER
- printf("~1 Std res final cal_factor:\n");
- plot_wav(m, 0, s->cal_factor[0]);
- printf("~1 High final cal_factor:\n");
- plot_wav(m, 1, s->cal_factor[1]);
-#endif /* NEVER */
+ /* Compute the weighting of each CCD value in the normal output */
+ for (cx = j = 0; j < m->nwav[0]; j++) { /* For each wavelength */
+
+ /* For each matrix value */
+ sx = m->mtx_o.index[j]; /* Starting index */
+ for (k = 0; k < m->mtx_o.nocoef[j]; k++, cx++, sx++) {
+ ccdsum[0][sx] += m->mtx_o.coef[cx];
+//printf("~1 Norm CCD [%d] %f += [%d] %f\n",sx,ccdsum[0][sx],cx, m->mtx_o.coef[cx]);
+ }
+ }
+
+ /* Compute the weighting of each CCD value in the hires output */
+ for (cx = j = 0; j < m->nwav[1]; j++) { /* For each wavelength */
+
+ /* For each matrix value */
+ sx = m->mtx_c[1][refl].index[j]; /* Starting index */
+ for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++, cx++, sx++) {
+ ccdsum[1][sx] += m->mtx_c[1][refl].coef[cx];
+//printf("~1 HiRes CCD [%d] %f += [%d] %f\n",sx,ccdsum[1][sx],cx, m->mtx_c[1][refl].coef[cx]);
+ }
+ }
+
+ /* Figure valid range and extrapolate to edges */
+ dth[0] = 0.0; /* ref */
+// dth[1] = 0.007; /* hires */
+ dth[1] = 0.004; /* hires */
+
+ for (k = 0; k < 2; k++) {
+
+ for (i = 0; i < 128; i++) {
+ if (ccdsum[k][i] > max[k])
+ max[k] = ccdsum[k][i];
+ }
+
+//printf("~1 max[%d] = %f\n",k, max[k]);
+ /* Figure out the valid range */
+ for (i = 64; i >= 0; i--) {
+ if (ccdsum[k][i] > (0.8 * max[k])) {
+ x[0] = (double)i;
+ } else {
+ break;
}
- break;
+ }
+ for (i = 64; i < 128; i++) {
+ if (ccdsum[k][i] > (0.8 * max[k])) {
+ x[3] = (double)i;
+ } else {
+ break;
+ }
+ }
+ /* Space off the last couple of entries */
+ x[0] += (3.0 + 3.0);
+ x[3] -= (3.0 + 3.0);
+ x[1] = floor((2 * x[0] + x[3])/3.0);
+ x[2] = floor((x[0] + 2 * x[3])/3.0);
+
+ for (i = 0; i < 4; i++) {
+ y[i] = 0.0;
+ for (j = -3; j < 4; j++) {
+ y[i] += ccdsum[k][(int)x[i]+j];
+ }
+ y[i] /= 7.0;
+ }
- case i1p_emiss_spot_na:
- case i1p_emiss_spot:
- case i1p_emiss_scan:
- for (j = 0; j < m->nwav[1]; j++)
- s->cal_factor[1][j] = EMIS_SCALE_FACTOR * m->emis_coef[1][j];
- break;
+//printf("~1 extrap nodes %f, %f, %f, %f\n",x[0],x[1],x[2],x[3]);
+//printf("~1 extrap value %f, %f, %f, %f\n",y[0],y[1],y[2],y[3]);
- case i1p_amb_spot:
- case i1p_amb_flash:
-#ifdef FAKE_AMBIENT
- for (j = 0; j < m->nwav[1]; j++)
- s->cal_factor[1][j] = EMIS_SCALE_FACTOR * m->emis_coef[1][j];
- s->cal_valid = 1;
-#else
+ for (i = 0; i < 128; i++) {
+ double xw, yw;
- if (m->amb_coef[0] != NULL) {
- for (j = 0; j < m->nwav[1]; j++)
- s->cal_factor[1][j] = AMB_SCALE_FACTOR * m->emis_coef[1][j] * m->amb_coef[1][j];
- s->cal_valid = 1;
+ xw = (double)i;
+
+ /* Compute interpolated value using Lagrange: */
+ yw = y[0] * (xw-x[1]) * (xw-x[2]) * (xw-x[3])
+ /((x[0]-x[1]) * (x[0]-x[2]) * (x[0]-x[3]))
+ + y[1] * (xw-x[0]) * (xw-x[2]) * (xw-x[3])
+ /((x[1]-x[0]) * (x[1]-x[2]) * (x[1]-x[3]))
+ + y[2] * (xw-x[0]) * (xw-x[1]) * (xw-x[3])
+ /((x[2]-x[0]) * (x[2]-x[1]) * (x[2]-x[3]))
+ + y[3] * (xw-x[0]) * (xw-x[1]) * (xw-x[2])
+ /((x[3]-x[0]) * (x[3]-x[1]) * (x[3]-x[2]));
+
+ if ((xw < x[0] || xw > x[3])
+ && fabs(ccdsum[k][i] - yw)/yw > dth[k]) {
+ ccdsum[k][i] = yw;
}
+ avg[k] += ccdsum[k][i];
+ }
+ avg[k] /= 128.0;
+ }
+
+#ifdef HIGH_RES_PLOT
+ /* Plot target CCD values */
+ {
+ double xx[128], y1[128], y2[128];
+
+ for (i = 0; i < 128; i++) {
+ xx[i] = i;
+ y1[i] = ccdsum[0][i]/avg[0];
+ y2[i] = ccdsum[1][i]/avg[1];
+ }
+
+ printf("Target and actual CCD weight sums:\n");
+ do_plot(xx, y1, y2, NULL, 128);
+ }
#endif
- break;
- case i1p_trans_spot:
- case i1p_trans_scan:
- if (s->cal_valid) {
- /* (Using cal_factor[] as temp. for i1pro_absraw_to_abswav()) */
- i1pro_absraw_to_abswav(p, 0, s->reflective, 1, &s->cal_factor[0], &s->white_data);
- i1pro_absraw_to_abswav(p, 1, s->reflective, 1, &s->cal_factor[1], &s->white_data);
- i1pro_compute_white_cal(p, s->cal_factor[0], NULL, s->cal_factor[0],
- s->cal_factor[1], NULL, s->cal_factor[1]);
+
+#ifdef DO_CCDNORMAVG /* Just correct by average */
+ for (cx = j = 0; j < m->nwav[1]; j++) { /* For each wavelength */
+
+ /* For each matrix value */
+ sx = m->mtx_c[1][refl].index[j]; /* Starting index */
+ for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++, cx++, sx++) {
+ m->mtx_c[1][refl].coef[cx] *= 10.0/twidth * avg[0]/avg[1];
+ }
+ }
+
+#else /* Correct by CCD bin */
+
+ /* Correct the weighting of each CCD value in the hires output */
+ for (i = 0; i < 128; i++) {
+ ccdsum[1][i] = 10.0/twidth * ccdsum[0][i]/ccdsum[1][i]; /* Correction factor */
+ }
+ for (cx = j = 0; j < m->nwav[1]; j++) { /* For each wavelength */
+
+ /* For each matrix value */
+ sx = m->mtx_c[1][refl].index[j]; /* Starting index */
+ for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++, cx++, sx++) {
+ m->mtx_c[1][refl].coef[cx] *= ccdsum[1][sx];
+ }
+ }
+#endif
+ }
+#endif /* DO_CCDNORM */
+
+#ifdef HIGH_RES_PLOT
+ {
+ static i1pro_fc coeff2[MXNOWL][MXNOFC];
+ double *xx, *ss;
+ double **yy;
+
+ /* Convert the native filter cooeficient representation to */
+ /* a 2D array we can randomly index. */
+ for (cx = j = 0; j < m->nwav[1]; j++) { /* For each output wavelength */
+ if (j >= MXNOWL) { /* Assert */
+ a1loge(p->log,1,"i1pro: number of hires output wavelenths is > %d\n",MXNOWL);
+ return I1PRO_INT_ASSERT;
+ }
+
+ /* For each matrix value */
+ sx = m->mtx[1][refl].index[j]; /* Starting index */
+ for (k = 0; k < m->mtx[1][refl].nocoef[j]; k++, cx++, sx++) {
+ if (k >= MXNOFC) { /* Assert */
+ a1loge(p->log,1,"i1pro: number of hires filter coeefs is > %d\n",MXNOFC);
+ return I1PRO_INT_ASSERT;
}
- break;
+ coeff2[j][k].ix = sx;
+ coeff2[j][k].we = m->mtx[1][refl].coef[cx];
+// printf("Output %d, filter %d weight = %e\n",j,k,coeff2[j][k].we);
+ }
+ }
+
+ xx = dvectorz(-1, m->nraw-1); /* X index */
+ yy = dmatrixz(0, 5, -1, m->nraw-1); /* Curves distributed amongst 5 graphs */
+
+ for (i = 0; i < m->nraw; i++)
+ xx[i] = i;
+
+ /* For each output wavelength */
+ for (j = 0; j < m->nwav[1]; j++) {
+ i = j % 5;
+
+ /* For each matrix value */
+ for (k = 0; k < m->mtx_c[1][refl].nocoef[j]; k++) {
+ yy[5][coeff2[j][k].ix] += 0.5 * coeff2[j][k].we;
+ yy[i][coeff2[j][k].ix] = coeff2[j][k].we;
+ }
}
+
+ printf("Normalized Hi-Res wavelength sampling curves: %s\n",refl ? "refl" : "emis");
+ do_plot6(xx, yy[0], yy[1], yy[2], yy[3], yy[4], yy[5], m->nraw);
+ free_dvector(xx, -1, m->nraw-1);
+ free_dmatrix(yy, 0, 2, -1, m->nraw-1);
}
- }
+#endif /* HIGH_RES_PLOT */
+#undef MXNOWL
+#undef MXNOFC
+ } /* Do next filter */
/* Hires has been initialised */
m->hr_inited = 1;
+ /* Generate high res. per mode calibration factors. */
+ if ((ev = i1pro_create_hr_calfactors(p, 0)) != I1PRO_OK)
+ return ev;
+
return ev;
}
@@ -9373,6 +9890,7 @@ i1pro_code i1pro_conv2XYZ(
if (!m->spec_en) {
vals[i].sp.spec_n = 0;
}
+
}
conv->del(conv);
@@ -9447,20 +9965,280 @@ i1pro_code i1pro_check_white_reference1(
}
/* Compute a mode calibration factor given the reading of the white reference. */
-/* Return 1 if any of the transmission wavelengths are low. */
-int i1pro_compute_white_cal(
+/* We will also calibrate & smooth hi-res emis_coef[1] if they are present. */
+/* Return I1PRO_RD_TRANSWHITEWARN if any of the transmission wavelengths are low. */
+/* May return some other error (malloc) */
+i1pro_code i1pro_compute_white_cal(
i1pro *p,
double *cal_factor0, /* [nwav[0]] Calibration factor to compute */
double *white_ref0, /* [nwav[0]] White reference to aim for, NULL for 1.0 */
double *white_read0, /* [nwav[0]] The white that was read */
double *cal_factor1, /* [nwav[1]] Calibration factor to compute */
double *white_ref1, /* [nwav[1]] White reference to aim for, NULL for 1.0 */
- double *white_read1 /* [nwav[1]] The white that was read */
+ double *white_read1, /* [nwav[1]] The white that was read */
+ int do_emis_ft /* Do emission hires fine tune with this info. */
) {
i1proimp *m = (i1proimp *)p->m;
i1pro_state *s = &m->ms[m->mmode];
- int j, warn = 0;;
+ int j, warn = I1PRO_OK;;
+
+#ifdef HIGH_RES
+ /* If we need to, fine calibrate the emission */
+ /* calibration coefficients, using the reflectance cal. */
+ /* illuminant as an (assumed) smooth light source reference. */
+ /* (Do this first, befor white_read0/cal_factor0 is overwritten by white cal.) */
+ if (do_emis_ft && m->hr_inited != 0 && white_ref1 != NULL) {
+ i1pro_code ev = I1PRO_OK;
+ int i;
+ double *lincal;
+ double *fudge;
+ xspect illA;
+#ifdef HIGH_RES_PLOT
+ double *targ_smth; /* Hires target in smooth space */
+ double *old_emis;
+ double avgl;
+
+ if ((targ_smth = (double *)calloc(m->nwav[1], sizeof(double))) == NULL) {
+ return I1PRO_INT_MALLOC;
+ }
+ if ((old_emis = (double *)calloc(m->nwav[1], sizeof(double))) == NULL) {
+ return I1PRO_INT_MALLOC;
+ }
+ for (i = 0; i < m->nwav[1]; i++)
+ old_emis[i] = m->emis_coef[1][i];
+#endif
+
+ if ((lincal = (double *)calloc(m->nwav[0], sizeof(double))) == NULL) {
+ return I1PRO_INT_MALLOC;
+ }
+ if ((fudge = (double *)calloc(m->nwav[0], sizeof(double))) == NULL) {
+ return I1PRO_INT_MALLOC;
+ }
+
+ /* Fill in an xpsect with a standard illuminant spectrum */
+ if (standardIlluminant(&illA, icxIT_Ptemp, 2990.0)) {
+ a1loge(p->log,1,"i1pro_compute_white_cal: standardIlluminant() failed");
+ return I1PRO_INT_ASSERT;
+ }
+
+ for (j = 0; j < m->nwav[0]; j++) {
+ double wl = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], j);
+
+ lincal[j] = white_read0[j] * m->emis_coef[0][j]
+ / (white_ref0[j] * value_xspect(&illA, wl));
+ }
+
+#ifndef NEVER
+ /* Generate the hires emis_coef by interpolating lincal */
+ /* using rspl, and reversing computation through hi-res readings */
+ {
+ rspl *trspl; /* Upsample rspl */
+ cow sd[40]; /* Scattered data points of existing references */
+ datai glow, ghigh;
+ datao vlow, vhigh;
+ int gres[1];
+ double avgdev[1];
+ int ix;
+ co pp;
+
+ if ((trspl = new_rspl(RSPL_NOFLAGS, 1, 1)) == NULL) {
+ a1logd(p->log,1,"i1pro: creating rspl for high res conversion failed\n");
+ return I1PRO_INT_NEW_RSPL_FAILED;
+ }
+
+ vlow[0] = 1e6;
+ vhigh[0] = -1e6;
+ for (ix = i = 0; i < m->nwav[0]; i++) {
+
+ sd[ix].p[0] = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], i);
+ sd[ix].v[0] = lincal[i];
+ sd[ix].w = 1.0;
+
+ if (sd[ix].v[0] < vlow[0])
+ vlow[0] = sd[ix].v[0];
+ if (sd[ix].v[0] > vhigh[0])
+ vhigh[0] = sd[ix].v[0];
+ ix++;
+ }
+
+ glow[0] = m->wl_short[1];
+ ghigh[0] = m->wl_long[1];
+ gres[0] = 6 * m->nwav[1];
+ avgdev[0] = 0.0;
+
+ /* The smoothness factor of 0.02 seems critical in tuning the RevE */
+ /* hires accuracy, as measured on an LCD display */
+ trspl->fit_rspl_w(trspl, 0, sd, ix, glow, ghigh, gres, vlow, vhigh, 0.05, avgdev, NULL);
+
+ /* Create a linear interp fudge factor to place interp at low */
+ /* res. exactly on lowres linear curve. This compensates */
+ /* if the rspl moves the target at the lowres points */
+ for (j = 0; j < m->nwav[0]; j++) {
+ double wl = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], j);
+ pp.p[0] = wl;
+ trspl->interp(trspl, &pp);
+
+ fudge[j] = lincal[j] / pp.v[0];
+ }
+
+ /* Compute hires emis_coef */
+ for (i = 0; i < m->nwav[1]; i++) {
+ double wl = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], i);
+ double ff;
+
+ pp.p[0] = wl;
+ trspl->interp(trspl, &pp);
+
+#ifdef HIGH_RES_PLOT
+ targ_smth[i] = pp.v[0];
+#endif
+ /* Invert lincal at high res */
+ ff = wav_lerp(m, 0, fudge, wl);
+ m->emis_coef[1][i] = (ff * pp.v[0] * white_ref1[i] * value_xspect(&illA, wl))
+ /white_read1[i];
+ }
+ trspl->del(trspl);
+ }
+
+#else
+ /* Generate the hires emis_coef by interpolating lincal */
+ /* using lagrange, and reversing computation through hi-res readings */
+ for (i = 0; i < m->nwav[1]; i++) {
+ int k;
+ double x[4], xw;
+ double y[4], yw;
+
+ xw = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], i);
+
+ /* Locate lowres index below it */
+ j = (int)floor(XSPECT_DIX(m->wl_short[0], m->wl_long[0], m->nwav[0], xw)) -1;
+ if (j < 0)
+ j = 0;
+ if (j > (m->nwav[0]-4))
+ j = (m->nwav[0]-4);
+
+ /* Setup the surrounding point values */
+ for (k = 0; k < 4; k++) {
+ x[k] = XSPECT_WL(m->wl_short[0], m->wl_long[0], m->nwav[0], j+k);
+ y[k] = lincal[j+k];
+ }
+
+ /* Compute interpolated value using Lagrange: */
+ yw = y[0] * (xw-x[1]) * (xw-x[2]) * (xw-x[3])
+ /((x[0]-x[1]) * (x[0]-x[2]) * (x[0]-x[3]))
+ + y[1] * (xw-x[0]) * (xw-x[2]) * (xw-x[3])
+ /((x[1]-x[0]) * (x[1]-x[2]) * (x[1]-x[3]))
+ + y[2] * (xw-x[0]) * (xw-x[1]) * (xw-x[3])
+ /((x[2]-x[0]) * (x[2]-x[1]) * (x[2]-x[3]))
+ + y[3] * (xw-x[0]) * (xw-x[1]) * (xw-x[2])
+ /((x[3]-x[0]) * (x[3]-x[1]) * (x[3]-x[2]));
+
+ targ_smth[i] = yw;
+
+ /* Invert lincal at high res */
+ m->emis_coef[1][i] = (yw * white_ref1[i] * value_xspect(&illA, xw))/white_read1[i];
+ }
+#endif /* NEVER */
+
+#ifdef HIGH_RES_PLOT
+ /* Plot linear target curve and measured curve */
+ {
+ double *xx, *y1, *y2, *y3, *y4;
+
+ xx = dvector(0, m->nwav[1]); /* X wl */
+ y1 = dvector(0, m->nwav[1]);
+ y2 = dvector(0, m->nwav[1]);
+ y3 = dvector(0, m->nwav[1]);
+ y4 = dvector(0, m->nwav[1]);
+
+ for (j = 0; j < (m->nwav[1]); j++) {
+ xx[j] = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], j);
+ y1[j] = wav_lerp_cv(m, 0, lincal, xx[j], 0.0);
+ y2[j] = targ_smth[j];
+ y3[j] = white_read1[j] * wav_lerp(m, 0, m->emis_coef[0], xx[j])
+ /(white_ref1[j] * value_xspect(&illA, xx[j]));
+ y4[j] = white_read1[j] * old_emis[j]
+ /(white_ref1[j] * value_xspect(&illA, xx[j]));
+ }
+
+ printf("stdres interp targ (bk), smoothed targ (rd), measured hires resp. (gn), previous cal resp.(bu):\n");
+ do_plot6(xx, y1, y2, y3, y4, NULL, NULL, m->nwav[1]);
+ free_dvector(xx, 0, m->nwav[1]);
+ free_dvector(y1, 0, m->nwav[1]);
+ free_dvector(y2, 0, m->nwav[1]);
+ free_dvector(y4, 0, m->nwav[1]);
+ }
+ /* Plot target and achieved smooth space responses */
+ {
+ double *xx, *y2;
+
+ xx = dvector(0, m->nwav[1]);
+ y2 = dvector(0, m->nwav[1]);
+
+ for (j = 0; j < (m->nwav[1]); j++) {
+ xx[j] = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], j);
+ y2[j] = white_read1[j] * m->emis_coef[1][j]
+ /(white_ref1[j] * value_xspect(&illA, xx[j]));
+ }
+
+ printf("target smooth curve, achived smooth curve:\n");
+ do_plot6(xx, targ_smth, y2, NULL, NULL, NULL, NULL, m->nwav[1]);
+
+ free_dvector(xx, 0, m->nwav[1]);
+ free_dvector(y2, 0, m->nwav[1]);
+ }
+ /* Plot lowres and hires lamp response */
+ {
+ double *xx, *y1, *y2;
+
+ xx = dvector(0, m->nwav[1]);
+ y1 = dvector(0, m->nwav[1]);
+ y2 = dvector(0, m->nwav[1]);
+
+ for (j = 0; j < (m->nwav[1]); j++) {
+ xx[j] = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], j);
+ y1[j] = wav_lerp(m, 0, white_read0, xx[j]) * wav_lerp(m, 0, m->emis_coef[0], xx[j])
+ /wav_lerp(m, 0, white_ref0, xx[j]);
+ y2[j] = white_read1[j] * m->emis_coef[1][j]
+ /white_ref1[j];
+ }
+
+ printf("lowres, high res lamp response:\n");
+ do_plot6(xx, y1, y2, NULL, NULL, NULL, NULL, m->nwav[1]);
+
+ free_dvector(xx, 0, m->nwav[1]);
+ free_dvector(y1, 0, m->nwav[1]);
+ free_dvector(y2, 0, m->nwav[1]);
+ }
+ /* Plot hires emis calibration */
+ {
+ double *xx;
+
+ xx = dvector(0, m->nwav[1]); /* X wl */
+
+ for (j = 0; j < (m->nwav[1]); j++) {
+ xx[j] = XSPECT_WL(m->wl_short[1], m->wl_long[1], m->nwav[1], j);
+ }
+
+ printf("orig upsampled + smoothed hires emis_coef:\n");
+ do_plot6(xx, old_emis, m->emis_coef[1], NULL, NULL, NULL, NULL, m->nwav[1]);
+ free_dvector(xx, 0, m->nwav[1]);
+ }
+ free(old_emis);
+ free(targ_smth);
+#endif /* HIGH_RES_PLOT */
+ free(fudge);
+ free(lincal);
+
+ m->emis_hr_cal = 1; /* We don't have to do a reflective calibration */
+
+ /* Make sure these are updated */
+ if ((ev = i1pro_create_hr_calfactors(p, 1)) != I1PRO_OK)
+ return ev;
+ }
+#endif /* HIGH_RES */
+
if (white_ref0 == NULL) { /* transmission white reference */
double avgwh = 0.0;
@@ -9474,7 +10252,7 @@ int i1pro_compute_white_cal(
/* If reference is < 0.4% of average */
if (white_read0[j]/avgwh < 0.004) {
cal_factor0[j] = 1.0/(0.004 * avgwh);
- warn = 1;
+ warn = I1PRO_RD_TRANSWHITEWARN;
} else {
cal_factor0[j] = 1.0/white_read0[j];
}
@@ -9508,7 +10286,7 @@ int i1pro_compute_white_cal(
/* If reference is < 0.4% of average */
if (white_read1[j]/avgwh < 0.004) {
cal_factor1[j] = 1.0/(0.004 * avgwh);
- warn = 1;
+ warn = I1PRO_RD_TRANSWHITEWARN;
} else {
cal_factor1[j] = 1.0/white_read1[j];
}
@@ -9523,8 +10301,8 @@ int i1pro_compute_white_cal(
else
cal_factor1[j] = white_ref1[j]/white_read1[j];
}
- }
#endif /* HIGH_RES */
+ }
return warn;
}
@@ -10136,8 +10914,12 @@ i1pro_delayed_trigger(void *pp) {
a1logd(p->log,2,"i1pro_delayed_trigger: start sleep @ %d msec\n", msec_time() - m->msec);
+#ifdef USE_RD_SYNC
+ p->icom->usb_wait_io(p->icom, &m->rd_sync); /* Wait for read to start */
+#else
/* Delay the trigger */
msec_sleep(m->trig_delay);
+#endif
m->tr_t1 = msec_time(); /* Diagnostic */
@@ -10197,7 +10979,7 @@ i1pro_triggermeasure(i1pro *p, int delay) {
/* A buffer full of bytes is returned. */
/* (This will fail on a Rev. A if there is more than about a 40 msec delay */
/* between triggering the measurement and starting this read. */
-/* It appears though that the read can be pending before triggering though. */
+/* It appears that the read can be pending before triggering though. */
/* Scan reads will also terminate if there is too great a delay beteween each read.) */
i1pro_code
i1pro_readmeasurement(
@@ -10268,7 +11050,7 @@ i1pro_readmeasurement(
m->tr_t6 = msec_time(); /* Diagnostic, start of subsequent reads */
if (m->tr_t3 == 0) m->tr_t3 = m->tr_t6; /* Diagnostic, start of first read */
- se = p->icom->usb_read(p->icom, NULL, 0x82, buf, size, &rwbytes, top);
+ se = p->icom->usb_read(p->icom, &m->rd_sync, 0x82, buf, size, &rwbytes, top);
m->tr_t5 = m->tr_t7;
m->tr_t7 = msec_time(); /* Diagnostic, end of subsequent reads */
@@ -10538,7 +11320,7 @@ i1pro_code i1pro_waitfor_switch_th(i1pro *p, double top) {
(stime = msec_time()) - m->msec);
/* Now read 1 byte */
- se = p->icom->usb_read(p->icom, &m->cancelt, 0x84, buf, 1, &rwbytes, top);
+ se = p->icom->usb_read(p->icom, &m->sw_cancel, 0x84, buf, 1, &rwbytes, top);
if (se & ICOM_TO) {
a1logd(p->log,2,"i1pro_waitfor_switch_th: read 0x%x bytes, timed out (%d msec)\n",
@@ -10596,7 +11378,7 @@ i1pro_terminate_switch(
msec_sleep(50);
if (m->th_termed == 0) {
a1logd(p->log,3,"i1pro terminate switch thread failed, canceling I/O\n");
- p->icom->usb_cancel_io(p->icom, &m->cancelt);
+ p->icom->usb_cancel_io(p->icom, &m->sw_cancel);
}
return rv;
@@ -10731,9 +11513,12 @@ i1pro2_delayed_trigger(void *pp) {
a1logd(p->log,2,"i1pro2_delayed_trigger: Rev E start sleep @ %d msec\n",
msec_time() - m->msec);
-
+#ifdef USE_RD_SYNC
+ p->icom->usb_wait_io(p->icom, &m->rd_sync); /* Wait for read to start */
+#else
/* Delay the trigger */
msec_sleep(m->trig_delay);
+#endif
m->tr_t1 = msec_time(); /* Diagnostic */
diff --git a/spectro/i1pro_imp.h b/spectro/i1pro_imp.h
index 64296b2..c0d0708 100644
--- a/spectro/i1pro_imp.h
+++ b/spectro/i1pro_imp.h
@@ -114,7 +114,6 @@ struct _i1pro_state {
double *cal_factor[2]; /* [low res, high res][nwav] calibration scale factor for this mode */
double *white_data; /* [-1 nraw] linear absolute dark subtracted white data */
/* used to compute cal_factor */
-// double *cal_factor1, *cal_factor2; /* (Underlying tables for two resolutions) */
/* Adaptive emission/transparency black data */
int idark_valid; /* idark calibration factors valid */
@@ -163,9 +162,10 @@ struct _i1proimp {
athread *th; /* Switch monitoring thread (NULL if not used) */
volatile int switch_count; /* Incremented in thread */
volatile int hide_switch; /* Set to supress switch event during read */
- usb_cancelt cancelt; /* Token to allow cancelling an outstanding I/O */
+ usb_cancelt sw_cancel; /* Token to allow cancelling switch I/O */
volatile int th_term; /* Terminate thread on next return */
volatile int th_termed; /* Thread has terminated */
+ usb_cancelt rd_sync; /* Token to allow meas. read to be synchronized */
inst_opt_type trig; /* Reading trigger mode */
int noinitcalib; /* Disable initial calibration if not essential */
int highres; /* High resolution mode */
@@ -268,6 +268,7 @@ struct _i1proimp {
double *emis_coef[2]; /* [low res, high res][nwav] Emission cal coefficients */
double *amb_coef[2]; /* [low res, high res][nwav] Ambient light cal values */
/* (compound with Emission), NULL if ambient not supported */
+ int emis_hr_cal; /* NZ if emis_coef[1] has been fine calibrated using reflective cal. */
double **straylight[2]; /* [nwav][nwav] Stray light convolution matrix (Rev E) */
@@ -392,6 +393,11 @@ void del_i1proimp(i1pro *p);
#define I1PRO_RD_NOFLASHES 0x3E /* No flashes recognized */
#define I1PRO_RD_NOAMBB4FLASHES 0x3F /* No ambient before flashes found */
#define I1PRO_RD_NOREFR_FOUND 0x40 /* Unable to measure refresh rate */
+#define I1PRO_RD_NOTRANS_FOUND 0x41 /* Unable to measure delay transition */
+
+#define I1PRO_CAL_SETUP 0x7A /* Cal. retry with correct setup is needed */
+#define I1PRO_RD_TRANSWHITEWARN 0x7B /* Transmission white ref wl are low */
+
/* Internal errors */
#define I1PRO_INT_NO_COMS 0x50
@@ -471,14 +477,20 @@ i1pro_code i1pro_imp_meas_refrate(
double *ref_rate
);
+/* Measure the display update delay */
+i1pro_code i1pro_imp_meas_delay(
+ i1pro *p,
+ int *msecdelay
+);
+
/* Given a raw measurement of the wavelength LED, */
/* Compute the base offset that best fits it to the reference */
i1pro_code i1pro2_match_wl_meas(i1pro *p, double *pled_off, double *wlraw);
-/* Compute standard res downsampling filters */
+/* Compute downsampling filters using the default filters. */
/* mtx_index1, mtx_nocoef1, mtx_coef1 given the */
/* current wl_led_off */
-i1pro_code i1pro2_compute_wav_filters(i1pro *p, int reflective);
+i1pro_code i1pro_compute_wav_filters(i1pro *p, int hires, int reflective);
/* return nz if high res is supported */
int i1pro_imp_highres(i1pro *p);
@@ -603,6 +615,18 @@ i1pro_code i1pro2_wl_measure(
double targoscale /* Optimal reading scale factor */
);
+/* Take a measurement reading using the current mode (combined parts 1 & 2a) */
+/* Converts to completely processed output readings, without averaging or extracting */
+/* sample patches. */
+/* (NOTE:- this can't be used for calibration, as it implements uv mode) */
+i1pro_code i1pro_read_patches_all(
+ i1pro *p,
+ double **specrd, /* Return array [numpatches][nwav] of spectral reading values */
+ int numpatches, /* Number of sample to measure */
+ double *inttime, /* Integration time to use/used */
+ int gainmode /* Gain mode to use, 0 = normal, 1 = high */
+);
+
/* Take a measurement reading using the current mode, part 1 */
/* Converts to completely processed output readings. */
i1pro_code i1pro_read_patches_1(
@@ -811,15 +835,16 @@ i1pro_code i1pro_check_white_reference1(
);
/* Compute a calibration factor given the reading of the white reference. */
-/* Return nz if any of the transmission wavelengths are low */
-int i1pro_compute_white_cal(
+/* Return I1PRO_RD_TRANSWHITEWARN if any of the transmission wavelengths are low */
+i1pro_code i1pro_compute_white_cal(
i1pro *p,
double *cal_factor0, /* [nwav0] Calibration factor to compute */
double *white_ref0, /* [nwav0] White reference to aim for, NULL for 1.0 */
double *white_read0, /* [nwav0] The white that was read */
double *cal_factor1, /* [nwav1] Calibration factor to compute */
double *white_ref1, /* [nwav1] White reference to aim for, NULL for 1.0 */
- double *white_read1 /* [nwav1] The white that was read */
+ double *white_read1, /* [nwav1] The white that was read */
+ int do_emis_ft /* Do emission hires fine tune with this info. */
);
/* For adaptive mode, compute a new integration time and gain mode */
diff --git a/spectro/icoms.c b/spectro/icoms.c
index 0dc815c..0166e21 100644
--- a/spectro/icoms.c
+++ b/spectro/icoms.c
@@ -43,17 +43,64 @@
/* ----------------------------------------------------- */
-/* Fake device */
-icompath icomFakeDevice = { "Fake Display Device" };
+/* Fake display & instrument device */
+icompath icomFakeDevice = { instFakeDisp, "Fake Display Device" };
+
+
+/* Free an icompath */
+static
+void icompath_del_contents(icompath *p) {
+
+ if (p->name != NULL)
+ free(p->name);
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+ if (p->spath != NULL)
+ free(p->spath);
+#endif /* ENABLE_SERIAL */
+#ifdef ENABLE_USB
+ usb_del_usb_idevice(p->usbd);
+ hid_del_hid_idevice(p->hidd);
+#endif /* ENABLE_USB */
+}
+
+/* Free an icompath */
+static void icompath_del(icompath *p) {
+
+ icompath_del_contents(p);
+ free(p);
+}
+
+/* Delete the last path */
+static void icompaths_del_last_path(
+ icompaths *p
+) {
+ if (p->npaths == 0)
+ return;
+
+ icompath_del(p->paths[p->npaths-1]);
+ p->paths[p->npaths-1] = NULL;
+ p->npaths--;
+}
+
+/* Return the last path */
+static icompath *icompaths_get_last_path(
+ icompaths *p
+) {
+ if (p->npaths == 0)
+ return NULL;
+
+ return p->paths[p->npaths-1];
+}
/* Return the path corresponding to the port number, or NULL if out of range */
static icompath *icompaths_get_path(
icompaths *p,
int port /* Enumerated port number, 1..n */
) {
- if (port == -99)
+ if (port == FAKE_DEVICE_PORT)
return &icomFakeDevice;
+
if (port <= 0 || port > p->npaths)
return NULL;
@@ -63,20 +110,10 @@ static icompath *icompaths_get_path(
static void icompaths_clear(icompaths *p) {
/* Free any old list */
- if (p->paths != NULL) {
+ if (p != NULL && p->paths != NULL) {
int i;
for (i = 0; i < p->npaths; i++) {
- if (p->paths[i]->name != NULL)
- free(p->paths[i]->name);
-#ifdef ENABLE_SERIAL
- if (p->paths[i]->spath != NULL)
- free(p->paths[i]->spath);
-#endif /* ENABLE_SERIAL */
-#ifdef ENABLE_USB
- usb_del_usb_idevice(p->paths[i]->usbd);
- hid_del_hid_idevice(p->paths[i]->hidd);
-#endif /* ENABLE_USB */
- free(p->paths[i]);
+ icompath_del(p->paths[i]);
}
free(p->paths);
p->npaths = 0;
@@ -111,11 +148,11 @@ static int icompaths_add_path(icompaths *p) {
return ICOM_OK;
}
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
/* Add a serial path */
/* return icom error */
-static int icompaths_add_serial(icompaths *p, char *name, char *spath) {
+static int icompaths_add_serial(icompaths *p, char *name, char *spath, int fast) {
int rv;
if ((rv = icompaths_add_path(p)) != ICOM_OK)
@@ -129,6 +166,28 @@ static int icompaths_add_serial(icompaths *p, char *name, char *spath) {
a1loge(p->log, ICOM_SYS, "icompaths: strdup failed!\n");
return ICOM_SYS;
}
+ p->paths[p->npaths-1]->fast = fast;
+
+ return ICOM_OK;
+}
+
+/* Modify a serial path to add the instrument type */
+int icompaths_set_serial_itype(icompath *p, instType itype) {
+ char pname[400], *cp;
+
+ p->itype = itype;
+
+ /* Strip any existing description in brackets */
+ if ((cp = strchr(p->name, '(')) != NULL && cp > p->name)
+ cp[-1] = '\000';
+ sprintf(pname,"%s (%s)", p->name, inst_name(itype));
+ cp = p->name;
+ if ((p->name = strdup(pname)) == NULL) {
+ p->name = cp;
+ a1loge(g_log, ICOM_SYS, "icompaths_set_serial_itype: strdup path failed!\n");
+ return ICOM_SYS;
+ }
+ free(cp);
return ICOM_OK;
}
@@ -138,6 +197,7 @@ static int icompaths_add_serial(icompaths *p, char *name, char *spath) {
/* Set an icompath details */
/* return icom error */
+static
int icompath_set_usb(a1log *log, icompath *p, char *name, unsigned int vid, unsigned int pid,
int nep, struct usb_idevice *usbd, instType itype) {
int rv;
@@ -195,10 +255,12 @@ static int icompaths_add_hid(icompaths *p, char *name, unsigned int vid, unsigne
#endif /* ENABLE_USB */
static void icompaths_del(icompaths *p) {
- icompaths_clear(p);
-
- p->log = del_a1log(p->log); /* Unreference it */
- free(p);
+ if (p != NULL) {
+ icompaths_clear(p);
+
+ p->log = del_a1log(p->log); /* Unreference it and set to NULL */
+ free(p);
+ }
}
int icompaths_refresh_paths(icompaths *p); /* Defined in platform specific */
@@ -216,8 +278,10 @@ icompaths *new_icompaths(a1log *log) {
p->clear = icompaths_clear;
p->refresh = icompaths_refresh_paths;
+ p->del_last_path = icompaths_del_last_path;
+ p->get_last_path = icompaths_get_last_path;
p->get_path = icompaths_get_path;
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
p->add_serial = icompaths_add_serial;
#endif /* ENABLE_SERIAL */
#ifdef ENABLE_USB
@@ -228,6 +292,7 @@ icompaths *new_icompaths(a1log *log) {
if (icompaths_refresh_paths(p)) {
a1loge(log, ICOM_SYS, "new_icompaths: icompaths_refresh_paths failed!\n");
+ free(p);
return NULL;
}
@@ -242,16 +307,19 @@ icompaths *new_icompaths(a1log *log) {
static int icom_copy_path_to_icom(icoms *p, icompath *pp) {
int rv;
+ if (p->name != NULL)
+ free(p->name);
if ((p->name = strdup(pp->name)) == NULL) {
a1loge(p->log, ICOM_SYS, "copy_path_to_icom: malloc name failed\n");
return ICOM_SYS;
}
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
if (pp->spath != NULL) {
if ((p->spath = strdup(pp->spath)) == NULL) {
a1loge(p->log, ICOM_SYS, "copy_path_to_icom: malloc spath failed\n");
return ICOM_SYS;
}
+ p->fast = pp->fast;
} else {
p->spath = NULL;
}
@@ -274,12 +342,14 @@ static int icom_copy_path_to_icom(icoms *p, icompath *pp) {
static icom_type icoms_port_type(
icoms *p
) {
+
#ifdef ENABLE_USB
if (p->hidd != NULL)
return icomt_hid;
if (p->usbd != NULL)
return icomt_usb;
#endif
+
return icomt_serial;
}
@@ -301,8 +371,8 @@ icoms *p,
char *wbuf, /* Write puffer */
char *rbuf, /* Read buffer */
int bsize, /* Buffer size */
-char tc, /* Terminating characer */
-int ntc, /* Number of terminating characters */
+char *tc, /* Terminating characers, NULL for none */
+int ntc, /* Number of terminating characters needed to terminate */
double tout
) {
int rv = ICOM_OK;
@@ -314,10 +384,11 @@ double tout
return ICOM_NOTS;
}
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
/* Flush any stray chars if serial */
if (p->usbd == NULL && p->hidd == NULL) {
int debug = p->log->debug;
+
if (debug < 8)
p->log->debug = 0;
for (; rv == ICOM_OK;) /* Until we get a timeout */
@@ -364,11 +435,12 @@ icoms *new_icoms(
/* Copy ipath info to this icoms */
if (icom_copy_path_to_icom(p, ipath)) {
+ free(p->name);
free(p);
return NULL;
}
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
#ifdef NT
p->phandle = NULL;
#endif
@@ -383,7 +455,7 @@ icoms *new_icoms(
#endif /* ENABLE_SERIAL */
p->lserr = 0;
- p->tc = -1;
+// p->tc = -1;
p->log = new_a1log_d(log);
p->debug = p->log->debug; /* Legacy code */
@@ -391,7 +463,7 @@ icoms *new_icoms(
p->close_port = icoms_close_port;
p->port_type = icoms_port_type;
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
p->set_ser_port = icoms_set_ser_port;
#endif /* ENABLE_SERIAL */
@@ -442,6 +514,10 @@ icoms_fix(char *ss) {
unsigned char *s = (unsigned char *)ss;
if (++ix >= 5)
ix = 0;
+ if (ss == NULL) {
+ strcpy((char *)buf[ix],"(null)");
+ return (char *)buf[ix];
+ }
for(d = buf[ix]; (d - buf[ix]) < 1000;) {
if (*s < ' ' && *s > '\000') {
*d++ = '^';
diff --git a/spectro/icoms.h b/spectro/icoms.h
index aac351a..f219312 100644
--- a/spectro/icoms.h
+++ b/spectro/icoms.h
@@ -18,26 +18,6 @@
* Derived from serio.h
*/
-/*
-
- Notes: The user keyboard/interrupt handling is really broken.
- It's not noticed most of the time because mostly keys are only
- hit at the expected times. Serial instruments (X-Rite) are more
- forgiving in interrupting coms to/from the instrument, as well
- as being long winded and needing abort. For USB insruments it's
- not necessarily robust to interrupt or terminate after a give
- USB transaction. The handling of user commands and aborts
- is not consistent either, possibly leaving some instruments
- suseptable to bodgy results due to an unrecognised aborted
- command. Really, the instrument driver should deterimine
- at what points an operation can be aborted, and how to recover.
-
- Because the instrument itself can be a source of commands,
- some way of waiting for instrument or user input is needed.
- Could a threaded approach with instrument abort work ?
-
-*/
-
/* Some MSWin specific stuff is in icoms, and used by usbio & hidio */
#if defined (NT)
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0501
@@ -76,7 +56,12 @@ typedef struct {
int packetsize; /* The max packet size */
int type; /* 2 = bulk, 3 = interrupt */
int interface; /* interface number */
+#if defined(__APPLE__)
int pipe; /* pipe number (1..N, OS X only) */
+#endif
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+ int fd; /* ep file descriptor */
+#endif
} usb_ep;
#define ICOM_EP_TYPE_BULK 2
@@ -92,9 +77,11 @@ typedef struct {
/* Store information about a possible instrument communication path */
/* (Note a path doesn't have a reference to icompaths or its' log) */
struct _icompath{
+ instType itype; /* Type of instrument if known */
char *name; /* instance description */
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
char *spath; /* Serial device path */
+ int fast; /* Virtual serial port that can be identified quickly */
#endif
#ifdef ENABLE_USB
int nep; /* Number of end points */
@@ -102,7 +89,6 @@ struct _icompath{
struct usb_idevice *usbd; /* USB port, NULL if not USB */
struct hid_idevice *hidd; /* HID port, NULL if not HID */
#endif /* ENABLE_USB */
- instType itype; /* Type of instrument if known */
};
extern icompath icomFakeDevice; /* Declare fake device */
@@ -117,9 +103,9 @@ struct _icompaths {
/* return icom error */
int (*refresh)(struct _icompaths *p);
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
/* Add a serial path. path is copied. Return icom error */
- int (*add_serial)(struct _icompaths *p, char *name, char *spath);
+ int (*add_serial)(struct _icompaths *p, char *name, char *spath, int fast);
#endif /* ENABLE_SERIAL */
#ifdef ENABLE_USB
@@ -132,10 +118,18 @@ struct _icompaths {
int nep, struct hid_idevice *hidd, instType itype);
#endif /* ENABLE_USB */
+ /* Delete the last path */
+ void (*del_last_path)(struct _icompaths *p);
+
+ /* Return the last path */
+ icompath *(*get_last_path)(struct _icompaths *p);
+
/* Return the path corresponding to the port number, or NULL if out of range */
icompath *(*get_path)(
struct _icompaths *p,
int port); /* Enumerated port number, 1..n */
+#define FAKE_DEVICE_PORT -98 /* Fake display & instrument */
+#define DEMO_DEVICE_PORT -99 /* Fake Demo instrument */
/* Clear all the paths */
void (*clear)(struct _icompaths *p);
@@ -175,7 +169,8 @@ typedef enum {
baud_19200 = 9,
baud_38400 = 10,
baud_57600 = 11,
- baud_115200 = 12
+ baud_115200 = 12,
+ baud_921600 = 13
} baud_rate;
/* Possible parity */
@@ -214,6 +209,7 @@ typedef enum {
/* Type of port */
typedef enum {
icomt_serial, /* Serial port */
+ icomt_usbserial, /* USB Serial port */
icomt_usb, /* USB port */
icomt_hid /* HID (USB) port */
} icom_type;
@@ -223,8 +219,8 @@ typedef enum {
#define ICOM_NOTS 0x001000 /* Not supported */
#define ICOM_SIZE 0x002000 /* Request/response size exceeded limits */
-#define ICOM_TO 0x004000 /* Timed out */
-#define ICOM_SHORT 0x008000 /* Number of bytes wasn't read/written */
+#define ICOM_TO 0x004000 /* Timed out, but there may be bytes read/written */
+#define ICOM_SHORT 0x008000 /* No timeout but number of bytes wasn't read/written */
#define ICOM_CANC 0x010000 /* Was cancelled */
#define ICOM_SYS 0x020000 /* System error (ie. malloc, system call fail) */
#define ICOM_VER 0x040000 /* Version error - need up to date kernel driver */
@@ -250,7 +246,7 @@ typedef struct _usb_cancelt usb_cancelt;
#ifdef ENABLE_USB
void usb_init_cancel(usb_cancelt *p);
void usb_uninit_cancel(usb_cancelt *p);
-
+void usb_reinit_cancel(usb_cancelt *p);
#endif
struct _icoms {
@@ -262,7 +258,7 @@ struct _icoms {
int is_open; /* Flag, NZ if this port is open */
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
/* Serial port parameters */
char *spath; /* Serial port path */
@@ -275,6 +271,8 @@ struct _icoms {
#if defined (UNIX) || defined(__APPLE__)
int fd; /* Unix file descriptor */
#endif
+ int fast; /* Virtual serial port that can be identified quickly */
+
flow_control fc;
baud_rate br;
parity py;
@@ -287,13 +285,6 @@ struct _icoms {
/* USB port parameters */
struct usb_idevice *usbd; /* USB port - copy of ppath->usbd */
-#ifndef NATIVE_USB /* Hmm. could put all this within usb_idevice if not #defined ? */
-# ifdef USE_LIBUSB1
- libusb_device_handle *usbh;
-# else
- struct usb_dev_handle *usbh;
-# endif
-#endif
icomuflags uflags; /* Bug workaround flags */
unsigned int vid, pid; /* USB vendor and product id's, used to distiguish instruments */
@@ -304,6 +295,8 @@ struct _icoms {
int nep; /* Number of end points */
int wr_ep, rd_ep; /* Default end points to use for "serial" read/write */
int rd_qa; /* Read quanta size */
+ int ms_bytes; /* No. Modem status bytes to strip from each read */
+ int latmsec; /* Latency timeout in msec for modem status bytes */
usb_ep ep[32]; /* Information about each end point for general usb i/o */
@@ -317,7 +310,6 @@ struct _icoms {
/* General parameters */
int lserr; /* Last serial communication error code */
- int tc; /* Current serial parser termination character (-1 if not set) */
a1log *log; /* Debug & Error log */
int debug; /* legacy - Flag, nz to print instrument io info to stderr */
@@ -329,7 +321,7 @@ struct _icoms {
/* Return the port type */
icom_type (*port_type)(struct _icoms *p);
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
/* Select the serial communications port and characteristics */
/* return icom error */
int (*set_ser_port)(
@@ -382,8 +374,8 @@ struct _icoms {
struct _icoms *p,
char *buf, /* Buffer to store characters read */
int bsize, /* Buffer size */
- char tc, /* Terminating character */
- int ntc, /* Number of terminating characters */
+ char *tc, /* Terminating characters */
+ int ntc, /* Number of terminating characters seen */
double tout); /* Timeout in seconds */
/* "Serial" write and read */
@@ -393,8 +385,8 @@ struct _icoms {
char *wbuf, /* Write puffer */
char *rbuf, /* Read buffer */
int bsize, /* Buffer size */
- char tc, /* Terminating characer */
- int ntc, /* Number of terminating characters */
+ char *tc, /* Terminating characers */
+ int ntc, /* Number of terminating characters seen */
double tout); /* Timeout in seconds */
/* For a USB device, do a control message */
@@ -428,6 +420,11 @@ struct _icoms {
int *bwritten, /* Bytes written */
double tout); /* Timeout in seconds */
+ /* Wait until a read/write in another thread has started. */
+ /* return icom error */
+ int (*usb_wait_io)(struct _icoms *p,
+ usb_cancelt *cantelt); /* Cancel handle */
+
/* Cancel a read/write in another thread */
/* return icom error */
int (*usb_cancel_io)(struct _icoms *p,
diff --git a/spectro/icoms_nt.c b/spectro/icoms_nt.c
index ef364c4..3caa8e0 100644
--- a/spectro/icoms_nt.c
+++ b/spectro/icoms_nt.c
@@ -16,6 +16,16 @@
#include <conio.h>
+/* Link list element to hold fast_serial port names */
+typedef struct fast_com_name {
+ char name[100];
+ struct fast_com_name *next;
+} fast_com_name;
+
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+instType fast_ser_inst_type(icoms *p, int tryhard, void *, void *);
+#endif /* ENABLE_SERIAL */
+
/* Create and return a list of available serial ports or USB instruments for this system. */
/* We look at the registry key "HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM" */
/* to determine serial ports, and use libusb to discover USB instruments. */
@@ -23,9 +33,10 @@
/* return icom error */
int icompaths_refresh_paths(icompaths *p) {
int rv, usbend = 0;
- int i,j;
+ int i, j;
LONG stat;
HKEY sch; /* Serial coms handle */
+ fast_com_name *fastlist = NULL, *fn, *fn2;
a1logd(p->log, 8, "icoms_get_paths: called\n");
@@ -42,7 +53,131 @@ int icompaths_refresh_paths(icompaths *p) {
a1logd(p->log, 6, "icoms_get_paths: got %d paths, looking up the registry for serial ports\n",p->npaths);
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+ // (Beware KEY_WOW64_64KEY ?)
+
+ /* See if there are and FTDI fast_serial ports, and make a list of them */
+ if ((stat = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum\\FTDIBUS",
+ 0, KEY_READ, &sch)) != ERROR_SUCCESS) {
+ a1logd(p->log, 1, "icoms_get_paths: There don't appear to be any FTDI serial ports\n");
+ } else {
+
+#define MXKSIZE 500
+#define MXVSIZE 300
+
+ a1logd(p->log, 6, "icoms_get_paths: looking through FTDI ports\n");
+ for (i = 0; ; i++) {
+ char ftdiname[MXKSIZE];
+ DWORD ftdisize = MXKSIZE;
+ HKEY devkey;
+
+ stat = RegEnumKeyEx(
+ sch, /* handle to key to enumerate */
+ i, /* index of subkey to enumerate */
+ ftdiname, /* address of buffer for value name */
+ &ftdisize, /* address for size of value name buffer */
+ NULL, /* reserved */
+ NULL, /* Address of value type */
+ NULL, /* Address of value buffer */
+ NULL /* Address of value buffer size */
+ );
+ if (stat == ERROR_NO_MORE_ITEMS) {
+ a1logd(p->log, 9, "icoms_get_paths: got ERROR_NO_MORE_ITEMS\n");
+ break;
+ }
+ if (stat == ERROR_MORE_DATA /* Hmm. Should expand buffer size */
+ || stat != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: RegEnumValue failed with %d\n",stat);
+ break;
+ }
+ ftdiname[MXKSIZE-1] = '\000';
+
+ /* Enumerate subkeys, looking for Device Parameters/PortName */
+ if ((stat = RegOpenKeyEx(sch, ftdiname, 0, KEY_READ, &devkey)) != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: OpenKey '%s' failed with %d\n",ftdiname,stat);
+ continue;
+ }
+
+ a1logd(p->log, 6, "icoms_get_paths: looking through '%s'\n",ftdiname);
+
+ for (j = 0; ; j++) {
+ char skname[MXKSIZE + 50]; /* Allow for cat of "\Device Parameters" */
+ DWORD sksize = MXKSIZE;
+ HKEY skkey;
+ DWORD vtype;
+ char value[MXVSIZE];
+ DWORD vsize = MXVSIZE;
+
+ stat = RegEnumKeyEx(
+ devkey, /* handle to key to enumerate */
+ j, /* index of subkey to enumerate */
+ skname, /* address of buffer for value name */
+ &sksize, /* address for size of value name buffer */
+ NULL, /* reserved */
+ NULL, /* Address of value type */
+ NULL, /* Address of value buffer */
+ NULL /* Address of value buffer size */
+ );
+ if (stat == ERROR_NO_MORE_ITEMS) {
+ a1logd(p->log, 9, "icoms_get_paths: got ERROR_NO_MORE_ITEMS\n");
+ break;
+ }
+ if (stat == ERROR_MORE_DATA /* Hmm. Should expand buffer size */
+ || stat != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: RegEnumValue failed with %d\n",stat);
+ break;
+ }
+ skname[MXKSIZE-1] = '\000';
+
+ /* See if there is a Device Parameters\PortName */
+ strcat(skname, "\\Device Parameters");
+
+ if ((stat = RegOpenKeyEx(devkey, skname, 0, KEY_READ, &skkey)) != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: OpenKey '%s' failed with %d\n",skname,stat);
+ continue;
+ }
+ stat = RegQueryValueEx(
+ skkey, /* handle to key to enumerate */
+ "PortName", /* address of buffer for value name */
+ NULL, /* reserved */
+ &vtype, /* Address of value type */
+ value, /* Address of value buffer */
+ &vsize /* Address of value buffer size */
+ );
+ RegCloseKey(skkey);
+
+ if (stat == ERROR_MORE_DATA /* Hmm. Should expand buffer size */
+ || stat != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: RegQueryValueEx '%s' failed with %d\n",skname,stat);
+ break;
+ }
+ if (vtype != REG_SZ) {
+ a1logw(p->log, "icoms_get_paths: RegEnumValue '%s' didn't return stringz type\n",skname);
+ continue;
+ }
+ value[MXVSIZE-1] = '\000';
+
+ if ((fn = malloc(sizeof(fast_com_name))) == NULL) {
+ a1loge(p->log, 1, "icoms_get_paths: malloc failed\n");
+ continue;
+ }
+ strcpy(fn->name, value);
+ fn->next = fastlist;
+ fastlist = fn;
+ a1logd(p->log, 2, "icoms_get_paths: got FTDI port '%s'\n",value);
+
+ }
+ if ((stat = RegCloseKey(devkey)) != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: RegCloseKey failed with %d\n",stat);
+ }
+
+ }
+ if ((stat = RegCloseKey(sch)) != ERROR_SUCCESS) {
+ a1logw(p->log, "icoms_get_paths: RegCloseKey failed with %d\n",stat);
+ }
+ }
+
+
/* Look in the registry for serial ports */
if ((stat = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM",
0, KEY_READ, &sch)) != ERROR_SUCCESS) {
@@ -52,13 +187,14 @@ int icompaths_refresh_paths(icompaths *p) {
/* Look at all the values in this key */
a1logd(p->log, 8, "icoms_get_paths: looking through all the values in the SERIALCOMM key\n");
-
+
for (i = 0; ; i++) {
- char valname[500];
- DWORD vnsize = 500;
+ char valname[MXKSIZE];
+ DWORD vnsize = MXKSIZE;
DWORD vtype;
- char value[500];
- DWORD vsize = 500;
+ char value[MXVSIZE];
+ DWORD vsize = MXVSIZE;
+ int fast = 0;
stat = RegEnumValue(
sch, /* handle to key to enumerate */
@@ -79,17 +215,36 @@ int icompaths_refresh_paths(icompaths *p) {
a1logw(p->log, "icoms_get_paths: RegEnumValue failed with %d\n",stat);
break;
}
- valname[500-1] = '\000';
- value[500-1] = '\000';
+ valname[MXKSIZE-1] = '\000';
+ value[MXVSIZE-1] = '\000';
if (vtype != REG_SZ) {
a1logw(p->log, "icoms_get_paths: RegEnumValue didn't return stringz type\n");
continue;
}
+ /* Check if it's a fast serial port */
+ for (fn = fastlist; fn != NULL; fn = fn->next) {
+ if (strcmp(fn->name, value) == 0)
+ fast = 1;
+ }
+
/* Add the port to the list */
- p->add_serial(p, value, value);
- a1logd(p->log, 8, "icoms_get_paths: Added path '%s'\n",value);
+ p->add_serial(p, value, value, fast);
+ a1logd(p->log, 8, "icoms_get_paths: Added path '%s' fast %d\n",value,fast);
+
+ /* If fast, try and identify it */
+ if (fast) {
+ icompath *path;
+ icoms *icom;
+ if ((path = p->get_last_path(p)) != NULL
+ && (icom = new_icoms(path, p->log)) != NULL) {
+ instType itype = fast_ser_inst_type(icom, 0, NULL, NULL);
+ if (itype != instUnknown)
+ icompaths_set_serial_itype(path, itype);
+ icom->del(icom);
+ }
+ }
}
if ((stat = RegCloseKey(sch)) != ERROR_SUCCESS) {
a1logw(p->log, "icoms_get_paths: RegCloseKey failed with %d\n",stat);
@@ -97,10 +252,14 @@ int icompaths_refresh_paths(icompaths *p) {
#endif /* ENABLE_SERIAL */
/* Sort the COM keys so people don't get confused... */
+ /* Sort identified instruments ahead of unknown serial ports */
a1logd(p->log, 6, "icoms_get_paths: we now have %d entries and are about to sort them\n",p->npaths);
for (i = usbend; i < (p->npaths-1); i++) {
for (j = i+1; j < p->npaths; j++) {
- if (strcmp(p->paths[i]->name, p->paths[j]->name) > 0) {
+ if ((p->paths[i]->itype == instUnknown && p->paths[j]->itype != instUnknown)
+ || (((p->paths[i]->itype == instUnknown && p->paths[j]->itype == instUnknown)
+ || (p->paths[i]->itype != instUnknown && p->paths[j]->itype != instUnknown))
+ && strcmp(p->paths[i]->name, p->paths[j]->name) > 0)) {
icompath *tt = p->paths[i];
p->paths[i] = p->paths[j];
p->paths[j] = tt;
@@ -110,6 +269,12 @@ int icompaths_refresh_paths(icompaths *p) {
a1logd(p->log, 8, "icoms_get_paths: returning %d paths and ICOM_OK\n",p->npaths);
+ /* Free fast list */
+ for (fn = fastlist; fn != NULL; fn = fn2) {
+ fn2 = fn->next;
+ free(fn);
+ }
+
return ICOM_OK;
}
@@ -124,7 +289,7 @@ static void icoms_close_port(icoms *p) {
hid_close_port(p);
}
#endif
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
if (p->phandle != NULL) {
CloseHandle(p->phandle);
}
@@ -133,10 +298,14 @@ static void icoms_close_port(icoms *p) {
}
}
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
static int icoms_ser_write(icoms *p, char *wbuf, double tout);
-static int icoms_ser_read(icoms *p, char *rbuf, int bsize, char tc, int ntc, double tout);
+static int icoms_ser_read(icoms *p, char *rbuf, int bsize, char *tc, int ntc, double tout);
+
+#ifndef CBR_921600
+# define CBR_921600 921600
+#endif
/* Set the serial port characteristics */
/* This always re-opens the port */
@@ -150,6 +319,7 @@ parity parity,
stop_bits stop,
word_length word)
{
+
a1logd(p->log, 8, "icoms_set_ser_port: About to set port characteristics:\n"
" Port name = %s\n"
" Flow control = %d\n"
@@ -180,10 +350,15 @@ word_length word)
/* Make sure the port is open */
if (!p->is_open) {
+ char buf[50]; /* Temporary for COM device path */
+
a1logd(p->log, 8, "icoms_set_ser_port: about to open serial port '%s'\n",p->spath);
+ /* Workaround bug of ports > COM9 */
+ sprintf(buf, "\\\\.\\%s", p->spath);
+
if ((p->phandle = CreateFile(
- p->spath,
+ buf,
GENERIC_READ|GENERIC_WRITE,
0, /* Exclusive access */
NULL, /* No security */
@@ -191,7 +366,7 @@ word_length word)
0, /* No overlapped I/O */
NULL) /* NULL template */
) == INVALID_HANDLE_VALUE) {
- a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: open port '%s' failed with LastError %d\n",p->spath,GetLastError());
+ a1logd(p->log, 1, "icoms_set_ser_port: open port '%s' failed with LastError %d\n",buf,GetLastError());
return ICOM_SYS;
}
p->is_open = 1;
@@ -215,7 +390,8 @@ word_length word)
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;
dcb.fRtsControl = RTS_CONTROL_ENABLE; /* Turn RTS on during connection */
- dcb.fAbortOnError = TRUE;
+// dcb.fAbortOnError = TRUE; // Hmm. Stuffs up FTDI. Is it needed ?
+ dcb.fAbortOnError = FALSE;
switch (p->fc) {
case fc_nc:
@@ -329,6 +505,9 @@ word_length word)
case baud_115200:
dcb.BaudRate = CBR_115200;
break;
+ case baud_921600:
+ dcb.BaudRate = CBR_921600;
+ break;
default:
CloseHandle(p->phandle);
a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal baud rate! (0x%x)\n",p->br);
@@ -370,7 +549,7 @@ double tout)
{
COMMTIMEOUTS tmo;
DWORD wbytes;
- int c, len;
+ int len;
long toc, i, top; /* Timout count, counter, timeout period */
int rv = ICOM_OK;
@@ -384,7 +563,7 @@ double tout)
len = strlen(wbuf);
tout *= 1000.0; /* Timout in msec */
- top = 100; /* Timeout period in msecs */
+ top = 20; /* Timeout period in msecs */
toc = (int)(tout/top + 0.5); /* Number of timout periods in timeout */
if (toc < 1)
toc = 1;
@@ -393,8 +572,8 @@ double tout)
tmo.ReadIntervalTimeout = top;
tmo.ReadTotalTimeoutMultiplier = 0;
tmo.ReadTotalTimeoutConstant = top;
- tmo.WriteTotalTimeoutMultiplier = top;
- tmo.WriteTotalTimeoutConstant = 0;
+ tmo.WriteTotalTimeoutMultiplier = 0;
+ tmo.WriteTotalTimeoutConstant = top;
if (!SetCommTimeouts(p->phandle, &tmo)) {
a1loge(p->log, ICOM_SYS, "icoms_ser_write: SetCommTimeouts failed with %d\n",GetLastError());
p->lserr = rv = ICOM_SYS;
@@ -441,13 +620,13 @@ icoms_ser_read(
icoms *p,
char *rbuf, /* Buffer to store characters read */
int bsize, /* Buffer size */
-char tc, /* Terminating characer */
-int ntc, /* Number of terminating characters */
+char *tc, /* Terminating characers, NULL for none */
+int ntc, /* Number of terminating characters seen */
double tout /* Time out in seconds */
) {
COMMTIMEOUTS tmo;
DWORD rbytes;
- int c, j;
+ int j;
long toc, i, top; /* Timout count, counter, timeout period */
char *rrbuf = rbuf; /* Start of return buffer */
DCB dcb;
@@ -460,35 +639,15 @@ double tout /* Time out in seconds */
}
if (bsize < 3) {
- a1loge(p->log, ICOM_SYS, "icoms_read: given too small a buffer\n");
+ a1loge(p->log, ICOM_SYS, "icoms_read: given too small a bufferi (%d)\n",bsize);
p->lserr = rv = ICOM_SYS;
return rv;
}
-#ifdef NEVER
- /* The Prolific 2303 USB<->serial seems to choke on this, */
- /* so we just put up with a 100msec delay at the end of each */
- /* reply. */
- if (GetCommState(p->phandle, &dcb) == FALSE) {
- a1loge(p->log, ICOM_SYS, "icoms_ser_read: GetCommState failed with %d\n",GetLastError());
- p->lserr = rv = ICOM_SYS;
- return rv;
- }
-
- dcb.EofChar = tc;
-
- if (!SetCommState(p->phandle, &dcb)) {
- a1loge(p->log, ICOM_SYS, "icoms_ser_read: SetCommState failed %d\n",GetLastError());
- p->lserr = rv = ICOM_SYS;
- return rv;
- }
-#endif
- p->tc = tc;
-
tout *= 1000.0; /* Timout in msec */
bsize--; /* Allow space for null */
- top = 100; /* Timeout period in msecs */
+ top = 20; /* Timeout period in msecs */
toc = (int)(tout/top + 0.5); /* Number of timout periods in timeout */
if (toc < 1)
toc = 1;
@@ -497,8 +656,8 @@ double tout /* Time out in seconds */
tmo.ReadIntervalTimeout = top;
tmo.ReadTotalTimeoutMultiplier = 0;
tmo.ReadTotalTimeoutConstant = top;
- tmo.WriteTotalTimeoutMultiplier = top;
- tmo.WriteTotalTimeoutConstant = 0;
+ tmo.WriteTotalTimeoutMultiplier = 0;
+ tmo.WriteTotalTimeoutConstant = top;
if (!SetCommTimeouts(p->phandle, &tmo)) {
a1loge(p->log, ICOM_SYS, "icoms_ser_read: SetCommTimeouts failed with %d\n",GetLastError());
p->lserr = rv = ICOM_SYS;
@@ -525,10 +684,18 @@ double tout /* Time out in seconds */
} else if (rbytes > 0) { /* Account for bytes done */
i = toc;
bsize -= rbytes;
- while(rbytes--) { /* Count termination characters */
- if (*rbuf++ == tc)
- j++;
- }
+ if (tc != NULL) {
+ while(rbytes--) { /* Count termination characters */
+ char ch = *rbuf++, *tcp = tc;
+
+ while(*tcp != '\000') {
+ if (ch == *tcp)
+ j++;
+ tcp++;
+ }
+ }
+ } else
+ rbuf += rbytes;
}
}
if (i <= 0) { /* timed out */
@@ -557,6 +724,13 @@ icoms_del(icoms *p) {
usb_del_usb(p);
hid_del_hid(p);
#endif
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+ if (p->spath != NULL)
+ free(p->spath);
+#endif
+ p->log = del_a1log(p->log);
+ if (p->name != NULL)
+ free(p->name);
p->log = del_a1log(p->log); /* unref */
free (p);
}
diff --git a/spectro/icoms_ux.c b/spectro/icoms_ux.c
index 722492e..3e49f3e 100644
--- a/spectro/icoms_ux.c
+++ b/spectro/icoms_ux.c
@@ -46,6 +46,10 @@
#include <mach/task_policy.h>
#endif /* __APPLE__ */
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+instType fast_ser_inst_type(icoms *p, int tryhard, void *, void *);
+#endif /* ENABLE_SERIAL */
+
/* Create and return a list of available serial ports or USB instruments for this system */
/* return icom error */
int icompaths_refresh_paths(icompaths *p) {
@@ -65,7 +69,7 @@ int icompaths_refresh_paths(icompaths *p) {
#endif /* ENABLE_USB */
usbend = p->npaths;
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
#ifdef __APPLE__
/* Search the OSX registry for serial ports */
{
@@ -93,7 +97,8 @@ int icompaths_refresh_paths(icompaths *p) {
/* Find all the matching serial ports */
for (;;) {
- char pname[100];
+ char pname[200];
+ int fast = 0;
CFTypeRef dfp; /* Device file path */
@@ -115,10 +120,26 @@ int icompaths_refresh_paths(icompaths *p) {
|| strstr(pname, "Bluetooth") != NULL)
goto continue2;
- /* Add the port to the list */
- p->add_serial(p, pname, pname);
- a1logd(p->log, 8, "icoms_get_paths: Added path '%s'\n",pname);
+ /* Would be nice to identify FTDI serial ports more specifically ? */
+ if (strstr(pname, "usbserial") != NULL)
+ fast = 1;
+ /* Add the port to the list */
+ p->add_serial(p, pname, pname, fast);
+ a1logd(p->log, 8, "icoms_get_paths: Added path '%s' fast %d\n",pname, fast);
+
+ /* If fast, try and identify it */
+ if (fast) {
+ icompath *path;
+ icoms *icom;
+ if ((path = p->get_last_path(p)) != NULL
+ && (icom = new_icoms(path, p->log)) != NULL) {
+ instType itype = fast_ser_inst_type(icom, 0, NULL, NULL);
+ if (itype != instUnknown)
+ icompaths_set_serial_itype(path, itype);
+ icom->del(icom);
+ }
+ }
continue2:
CFRelease(dfp);
continue1:
@@ -177,6 +198,7 @@ int icompaths_refresh_paths(icompaths *p) {
*/
/* Search for devices that match the pattern /dev/ttyS[0-9]* and /dev/ttyUSB* */
+ /* We will assume that ttyUSB* ports includes FTDI ports */
{
DIR *dd;
struct dirent *de;
@@ -190,6 +212,7 @@ int icompaths_refresh_paths(icompaths *p) {
for (;;) {
int fd;
char *dpath;
+ int fast = 0;
if ((de = readdir(dd)) == NULL)
break;
@@ -242,9 +265,26 @@ int icompaths_refresh_paths(icompaths *p) {
}
a1logd(p->log, 8, "icoms_get_paths: open'd serial \"%s\" - assume real\n",dpath);
+ if (strncmp(de->d_name, "ttyUSB", 5) == 0)
+ fast = 1;
+
/* Add the path to the list */
- p->add_serial(p, dpath, dpath);
- a1logd(p->log, 8, "icoms_get_paths: Added path '%s'\n",dpath);
+ p->add_serial(p, dpath, dpath, 0);
+ a1logd(p->log, 8, "icoms_get_paths: Added path '%s' fast %d\n",dpath,fast);
+ free(dpath);
+
+ /* If fast, try and identify it */
+ if (fast) {
+ icompath *path;
+ icoms *icom;
+ if ((path = p->get_last_path(p)) != NULL
+ && (icom = new_icoms(path, p->log)) != NULL) {
+ instType itype = fast_ser_inst_type(icom, 0, NULL, NULL);
+ if (itype != instUnknown)
+ icompaths_set_serial_itype(path, itype);
+ icom->del(icom);
+ }
+ }
}
closedir(dd);
}
@@ -252,12 +292,13 @@ int icompaths_refresh_paths(icompaths *p) {
#endif /* ENABLE_SERIAL */
/* Sort the serial /dev keys so people don't get confused... */
- /* Sort USB serial ports ahead of normal serial ports. */
+ /* Sort identified instruments ahead of unknown serial ports */
for (i = usbend; i < (p->npaths-1); i++) {
for (j = i+1; j < p->npaths; j++) {
- if ((strncmp(p->paths[i]->name, "/dev/ttyUSB", 11) ||
- strncmp(p->paths[j]->name, "/dev/ttyS", 9)) &&
- strcmp(p->paths[i]->name, p->paths[j]->name) > 0) {
+ if ((p->paths[i]->itype == instUnknown && p->paths[j]->itype != instUnknown)
+ || (((p->paths[i]->itype == instUnknown && p->paths[j]->itype == instUnknown)
+ || (p->paths[i]->itype != instUnknown && p->paths[j]->itype != instUnknown))
+ && strcmp(p->paths[i]->name, p->paths[j]->name) > 0)) {
icompath *tt = p->paths[i];
p->paths[i] = p->paths[j];
p->paths[j] = tt;
@@ -279,7 +320,7 @@ static void icoms_close_port(icoms *p) {
hid_close_port(p);
}
#endif
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
if (p->fd != -1) {
close(p->fd);
p->fd = -1;
@@ -289,10 +330,20 @@ static void icoms_close_port(icoms *p) {
}
}
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
static int icoms_ser_write(icoms *p, char *wbuf, double tout);
-static int icoms_ser_read(icoms *p, char *rbuf, int bsize, char tc, int ntc, double tout);
+static int icoms_ser_read(icoms *p, char *rbuf, int bsize, char *tc, int ntc, double tout);
+
+
+#ifdef __APPLE__
+# ifndef IOSSIOSPEED
+# define IOSSIOSPEED _IOW('T', 2, speed_t)
+# endif
+# ifndef B921600
+# define B921600 921600
+# endif
+#endif
/* Set the serial port number and characteristics */
/* This always re-opens the port */
@@ -344,7 +395,7 @@ word_length word
a1logd(p->log, 8, "icoms_set_ser_port: about to open serial port '%s'\n",p->spath);
if ((p->fd = open(p->spath, O_RDWR | O_NOCTTY )) < 0) {
- a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: open port '%s' failed with %d (%s)\n",p->spath,p->fd,strerror(errno));
+ a1logd(p->log, 1, "icoms_set_ser_port: open port '%s' failed with %d (%s)\n",p->spath,p->fd,strerror(errno));
return ICOM_SYS;
}
/* O_NONBLOCK O_SYNC */
@@ -490,6 +541,9 @@ word_length word
case baud_115200:
speed = B115200;
break;
+ case baud_921600:
+ speed = B921600;
+ break;
default:
close(p->fd);
a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: illegal baud rate! (0x%x)\n",p->br);
@@ -498,6 +552,15 @@ word_length word
tcflush(p->fd, TCIOFLUSH); /* Discard any current in/out data */
+#ifdef NEVER
+ // for osx >= 10.4 ? or >= 10.3 ??
+ // Doesn't actually seem to be needed... ??
+ if (speed > B115200) {
+ if (ioctl(p->fd, IOSSIOSPEED, &speed ) == -1)
+ printf( "Error %d calling ioctl( ..., IOSSIOSPEED, ... )\n", errno );
+
+ }
+#endif
if ((rv = cfsetispeed(&tio, speed)) < 0) {
close(p->fd);
a1loge(p->log, ICOM_SYS, "icoms_set_ser_port: cfsetispeed failed with '%s'\n", strerror(errno));
@@ -611,7 +674,7 @@ icoms_ser_read(
icoms *p,
char *rbuf, /* Buffer to store characters read */
int bsize, /* Buffer size */
-char tc, /* Terminating characer */
+char *tc, /* Terminating characers, NULL for none */
int ntc, /* Number of terminating characters */
double tout /* Time out in seconds */
) {
@@ -635,34 +698,6 @@ double tout /* Time out in seconds */
return rv;
}
-#ifdef NEVER
- /* The Prolific 2303 USB<->serial seems to choke on this, */
- /* so we just put up with the 100msec delay at the end of each reply. */
- if (tc != p->tc) { /* Set the termination char */
- struct termios tio;
-
- if (tcgetattr(p->fd, &tio) < 0) {
- a1loge(p->log, ICOM_SYS, "icoms_ser_read: tcgetattr failed with '%s' on '%s'\n",
- strerror(errno),p->spath);
- p->lserr = rv = ICOM_SYS;
- return rv;
- }
-
- tio.c_cc[VEOL] = tc;
-
- /* Make change immediately */
- tcflush(p->fd, TCIFLUSH);
- if (tcsetattr(p->fd, TCSANOW, &tio) < 0) {
- a1loge(p->log, ICOM_SYS, "icoms_ser_read: tcsetattr failed with '%s' on '%s'\n",
- strerror(errno),p->spath);
- p->lserr = rv = ICOM_SYS;
- return rv;
- }
-
- p->tc = tc;
- }
-#endif
-
/* Wait for serial input to have data */
pa[0].fd = p->fd;
pa[0].events = POLLIN | POLLPRI;
@@ -695,10 +730,18 @@ double tout /* Time out in seconds */
} else if (rbytes > 0) {
i = toc; /* Reset time */
bsize -= rbytes;
- while(rbytes--) { /* Count termination characters */
- if (*rbuf++ == tc)
- j++;
- }
+ if (tc != NULL) {
+ while(rbytes--) { /* Count termination characters */
+ char ch = *rbuf++, *tcp = tc;
+
+ while(*tcp != '\000') {
+ if (ch == *tcp)
+ j++;
+ tcp++;
+ }
+ }
+ } else
+ rbuf += rbytes;
}
}
} else {
@@ -733,6 +776,13 @@ icoms_del(icoms *p) {
usb_del_usb(p);
hid_del_hid(p);
#endif
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+ if (p->spath != NULL)
+ free(p->spath);
+#endif
+ p->log = del_a1log(p->log);
+ if (p->name != NULL)
+ free(p->name);
p->log = del_a1log(p->log);
free (p);
}
diff --git a/spectro/ifiles b/spectro/ifiles
index 6e73997..717fcca 100644
--- a/spectro/ifiles
+++ b/spectro/ifiles
@@ -8,7 +8,11 @@ huey.c
i1d3.c
spyd2.c
ss.c
+ss_imp.c
i1pro.c
+i1pro_imp.c
munki.c
+munki_imp.c
hcfr.c
colorhug.c
+specbos.c
diff --git a/spectro/illumread.c b/spectro/illumread.c
index 282ec2f..7cc7eae 100644
--- a/spectro/illumread.c
+++ b/spectro/illumread.c
@@ -30,7 +30,7 @@
*/
-#undef DEBUG /* Save measurements and restore them to outname_X.sp */
+#define DEBUG /* Save measurements and restore them to outname_X.sp */
/*
outname_i.sp Illuminant spectrum
@@ -41,7 +41,7 @@
*/
-#define SHOWDXX /* Plot the best matched daylight as well */
+#undef SHOWDXX /* Plot the best matched daylight as well */
#include <stdio.h>
#include <stdlib.h>
@@ -109,7 +109,7 @@ typedef struct {
xsp2cie *pap; /* Estimated illuminant + UV on paper lookup inc FWA */
xsp2cie *ref; /* Measured illuminant on paper lookup */
- xspect ill; /* Illuminant with UV added */
+ xspect ill; /* Illuminant with UV added - set by bfindfunc() */
xspect cpsp; /* FWA corrected calculated paper reflectance */
xspect srop; /* Scaled measured paper reflectance */
@@ -124,7 +124,7 @@ static double bfindfunc(void *adata, double pv[]) {
/* Add UV level to illuminant */
b->ill = *b->i_sp;
- xsp_setUV(&b->ill, b->i_sp, pv[0]);
+ xsp_setUV(&b->ill, b->i_sp, pv[0]); /* Extends ill range into UV */
/* Update the conversion */
if (b->pap->update_fwa_custillum(b->pap, NULL, &b->ill) != 0)
@@ -212,12 +212,20 @@ static double cfindfunc(void *adata, double pv[]) {
/* ============================================================== */
void
-usage() {
+usage(char *diag, ...) {
icompaths *icmps;
fprintf(stderr,"Measure an illuminant, Version %s\n",ARGYLL_VERSION_STR);
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
if (setup_spyd2() == 2)
fprintf(stderr,"WARNING: This file contains a proprietary firmware image, and may not be freely distributed !\n");
+ if (diag != NULL) {
+ va_list args;
+ fprintf(stderr,"Diagnostic: ");
+ va_start(args, diag);
+ vfprintf(stderr, diag, args);
+ va_end(args);
+ fprintf(stderr,"\n");
+ }
fprintf(stderr,"usage: illumread [-options] output.sp\n");
fprintf(stderr," -v Verbose mode\n");
fprintf(stderr," -S Plot spectrum for each reading\n");
@@ -239,6 +247,8 @@ usage() {
}
fprintf(stderr," -N Disable initial calibration of instrument if possible\n");
fprintf(stderr," -H Use high resolution spectrum mode (if available)\n");
+ fprintf(stderr," -Y r Set refresh measurement mode\n");
+ fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
fprintf(stderr," -D [level] Print debug diagnostics to stderr\n");
fprintf(stderr," illuminant.sp File to save measurement to\n");
@@ -257,6 +267,8 @@ int main(int argc, char *argv[])
int nocal = 0; /* Disable initial calibration */
int pspec = 0; /* 2 = Plot out the spectrum for each reading */
int highres = 0; /* Use high res mode if available */
+ int refrmode = -1; /* -1 = default, = non-refresh mode, 1 = non-refresh mode */
+ double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */
char outname[MAXNAMEL+1] = "\000"; /* Spectral output file name */
#ifdef DEBUG
char tname[MAXNAMEL+11] = "\000", *tnp;
@@ -316,7 +328,7 @@ int main(int argc, char *argv[])
}
if (argv[fa][1] == '?') {
- usage();
+ usage(NULL);
} else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
verb = 1;
@@ -328,9 +340,9 @@ int main(int argc, char *argv[])
/* COM port */
} else if (argv[fa][1] == 'c') {
fa = nfa;
- if (na == NULL) usage();
+ if (na == NULL) usage(NULL);
comno = atoi(na);
- if (comno < 1 || comno > 99) usage();
+ if (comno < 1 || comno > 99) usage(NULL);
/* No initial calibration */
} else if (argv[fa][1] == 'N') {
@@ -340,18 +352,36 @@ int main(int argc, char *argv[])
} else if (argv[fa][1] == 'H') {
highres = 1;
+ /* Extra flags */
+ } else if (argv[fa][1] == 'Y') {
+ if (na == NULL)
+ usage(NULL);
+
+ if (na[0] == 'R') {
+ if (na[1] != ':')
+ usage("-Y R:rate syntax incorrect");
+ refrate = atof(na+2);
+ if (refrate < 5.0 || refrate > 150.0)
+ usage("-Y R:rate %f Hz not in valid range",refrate);
+ } else if (na[0] == 'r')
+ refrmode = 1;
+ else
+ usage(NULL);
+ fa = nfa;
+
/* Serial port flow control */
} else if (argv[fa][1] == 'W') {
fa = nfa;
- if (na == NULL) usage();
- if (na[0] == 'n' || na[0] == 'N')
- fc = fc_none;
- else if (na[0] == 'h' || na[0] == 'H')
- fc = fc_Hardware;
- else if (na[0] == 'x' || na[0] == 'X')
- fc = fc_XonXOff;
- else
- usage();
+ if (na == NULL) usage(NULL);
+
+ if (na[0] == 'n' || na[0] == 'N')
+ fc = fc_none;
+ else if (na[0] == 'h' || na[0] == 'H')
+ fc = fc_Hardware;
+ else if (na[0] == 'x' || na[0] == 'X')
+ fc = fc_XonXOff;
+ else
+ usage(NULL);
} else if (argv[fa][1] == 'D') {
debug = 1;
@@ -361,7 +391,7 @@ int main(int argc, char *argv[])
}
g_log->debug = debug;
} else
- usage();
+ usage(NULL);
}
else
break;
@@ -369,7 +399,7 @@ int main(int argc, char *argv[])
/* Get the output spectrum file name argument */
if (fa >= argc)
- usage();
+ usage(NULL);
strncpy(outname,argv[fa++],MAXNAMEL-1); outname[MAXNAMEL-1] = '\000';
@@ -495,25 +525,22 @@ int main(int argc, char *argv[])
printf("Instrument lacks spectral measurement capability");
}
+ if (refrmode >= 0 && !IMODETST(cap, inst_mode_emis_refresh_ovd)
+ && !IMODETST(cap, inst_mode_emis_norefresh_ovd)) {
+ if (verb) {
+ printf("Requested refresh mode override and instrument doesn't support it (ignored)\n");
+ refrmode = -1;
+ }
+ }
+
/* Disable iniial calibration of machine if selected */
- if (nocal != 0){
+ if (nocal != 0) {
if ((rv = it->get_set_opt(it,inst_opt_noinitcalib, 0)) != inst_ok) {
printf("Setting no-initial calibrate failed failed with '%s' (%s) !!!\n",
it->inst_interp_error(it, rv), it->interp_error(it, rv));
printf("Disable initial-calibrate not supported\n");
}
}
- if (highres) {
- if (IMODETST(cap, inst_mode_highres)) {
- inst_code ev;
- if ((ev = it->get_set_opt(it, inst_opt_highres)) != inst_ok) {
- printf("!!! Setting high res mode failed with error :'%s' (%s) !!!\n",
- it->inst_interp_error(it, ev), it->interp_error(it, ev));
- }
- } else if (verb) {
- printf("!!! High resolution ignored - instrument doesn't support it !!!\n");
- }
- }
}
/* Check the instrument has the necessary capabilities for this measurement */
@@ -558,6 +585,19 @@ int main(int argc, char *argv[])
}
mode |= inst_mode_spectral;
+ if (refrmode == 0)
+ mode |= inst_mode_emis_norefresh_ovd;
+ else if (refrmode == 1)
+ mode |= inst_mode_emis_refresh_ovd;
+
+ if (highres) {
+ if (IMODETST(cap, inst_mode_highres)) {
+ mode |= inst_mode_highres;
+ } else if (verb) {
+ printf("!!! High resolution ignored - instrument doesn't support it !!!\n");
+ }
+ }
+
if ((rv = it->set_mode(it, mode)) != inst_ok) {
printf("!!! Setting instrument mode failed with error :'%s' (%s) !!!\n",
it->inst_interp_error(it, rv), it->interp_error(it, rv));
@@ -565,6 +605,19 @@ int main(int argc, char *argv[])
}
it->capabilities(it, &cap, &cap2, &cap3);
+ if (refrate > 0.0) {
+ if (!(cap2 & inst2_set_refresh_rate)) {
+ if (verb)
+ printf("Attempted to set refresh rate and instrument doesn't support setting it (ignored)\n");
+ refrate = 0.0;
+ } else {
+ if ((rv = it->set_refr_rate(it, refrate)) != inst_ok) {
+ error("Setting instrument refresh rate to %f Hz failed with error :'%s' (%s)",
+ refrate, it->inst_interp_error(it, rv), it->interp_error(it, rv));
+ }
+ }
+ }
+
/* If it batter powered, show the status of the battery */
if ((cap2 & inst2_has_battery)) {
double batstat = 0.0;
diff --git a/spectro/inst.c b/spectro/inst.c
index d57a84a..2d3adc3 100644
--- a/spectro/inst.c
+++ b/spectro/inst.c
@@ -49,18 +49,21 @@
#include "ccmx.h"
#include "ccss.h"
#include "conv.h"
-#include "insttypes.h"
+#include "insttypes.h"
#include "icoms.h"
#include "inst.h"
#include "insttypeinst.h"
-
#include "sort.h"
-#ifdef ENABLE_SERIAL
+#if defined(ENABLE_FAST_SERIAL)
+instType fast_ser_inst_type(icoms *p, int tryhard,
+ inst_code (*uicallback)(void *cntx, inst_ui_purp purp), void *cntx);
+# if defined(ENABLE_SERIAL)
static instType ser_inst_type(icoms *p,
-inst_code (*uicallback)(void *cntx, inst_ui_purp purp), void *cntx);
-#endif /* ENABLE_SERIAL */
+ inst_code (*uicallback)(void *cntx, inst_ui_purp purp), void *cntx);
+# endif /* ENABLE_SERIAL */
+#endif /* ENABLE_FAST_SERIAL */
/* ------------------------------------ */
/* Default methods for instrument class */
@@ -336,10 +339,10 @@ inst_cal_type *n_cals,
inst_cal_type *a_cals) {
if (n_cals != NULL)
- *n_cals = inst_calc_none;
+ *n_cals = inst_calt_none;
if (a_cals != NULL)
- *a_cals = inst_mode_none;
+ *a_cals = inst_calt_none;
return inst_ok;
}
@@ -521,13 +524,23 @@ void *cntx /* Context for callback */
icoms *icom;
inst *p = NULL;
+ a1logd(log, 2, "new_inst: called with path '%s'\n",path->name);
+
if ((icom = new_icoms(path, log)) == NULL) {
+ a1logd(log, 2, "new_inst: new_icoms failed to open it\n");
return NULL;
}
+
/* Set instrument type from USB port, if not specified */
itype = icom->itype; /* Instrument type if its known from usb/hid */
-#ifdef ENABLE_SERIAL
+
+#if defined(ENABLE_FAST_SERIAL)
+ if (itype == instUnknown && !nocoms && icom->fast)
+ itype = fast_ser_inst_type(icom, 1, uicallback, cntx); /* Else type from serial */
+#endif /* ENABLE_FAST_SERIAL */
+
+#if defined(ENABLE_SERIAL)
if (itype == instUnknown && !nocoms)
itype = ser_inst_type(icom, uicallback, cntx); /* Else type from serial */
#endif /* ENABLE_SERIAL */
@@ -552,6 +565,12 @@ void *cntx /* Context for callback */
*/
#endif /* ENABLE_SERIAL */
+#ifdef ENABLE_FAST_SERIAL
+ if (itype == instSpecbos1201
+ || itype == instSpecbos)
+ p = (inst *)new_specbos(icom, itype);
+#endif /* ENABLE_SERIAL */
+
#ifdef ENABLE_USB
if (itype == instDTP94)
p = (inst *)new_dtp92(icom, itype);
@@ -585,9 +604,14 @@ void *cntx /* Context for callback */
p = (inst *)new_colorhug(icom, itype);
#endif /* ENABLE_USB */
+
+
/* Nothing matched */
- if (p == NULL)
+ if (p == NULL) {
+ a1logd(log, 2, "new_inst: instrument type not recognised\n");
+ icom->del(icom);
return NULL;
+ }
/* Add default methods if constructor did not supply them */
if (p->init_coms == NULL)
@@ -696,6 +720,35 @@ void *cntx /* Context for callback */
R Raw sensor values
*/
+/* Default display technology strings:
+
+ "Color Matching Function"
+ "Custom"
+ "CRT"
+ "LCD CCFL IPS"
+ "LCD CCFL VPA"
+ "LCD CCFL TFT"
+ "LCD CCFL Wide Gamut IPS"
+ "LCD CCFL Wide Gamut VPA"
+ "LCD CCFL Wide Gamut TFT"
+ "LCD White LED IPS"
+ "LCD White LED VPA"
+ "LCD White LED TFT"
+ "LCD RGB LED IPS"
+ "LCD RGB LED VPA"
+ "LCD RGB LED TFT"
+ "LED OLED"
+ "LED AMOLED"
+ "Plasma"
+ "LCD RG Phosphor"
+ "Projector RGB Filter Wheel"
+ "Projector RGBW Filter Wheel"
+ "Projector RGBCMY Filter Wheel"
+ "Projector"
+ "Unknown"
+
+ */
+
/* Free a display type list */
void inst_del_disptype_list(inst_disptypesel *list, int no) {
@@ -751,17 +804,31 @@ static inst_disptypesel *expand_dlist(inst_disptypesel *list, int nlist, int *na
if no selector remain,
allocate a free one.
mark all used selectors
+
+ We treat the first selector as more important
+ than any aliases that come after it, so we need
+ to do two passes to resolve what gets used.
*/
/* Set the selection characters */
/* return NZ if we have run out */
-static int set_sel(char *sel, char *usels, int *k, char *asels) {
- char *d, *s;
+/* If flag == 0, deal with all selectors */
+/* If flag == 1, deal with just primary selectors */
+/* If flag == 2, deal with just secondary selectors */
+static int set_sel(int flag, char *sel, char *usels, int *k, char *asels) {
+ char *d, *s, i;
/* First remove any used chars from selector */
- for (d = s = sel; *s != '\000'; s++) {
- if (usels[*s] == 0)
+ for (i = 0, d = s = sel; *s != '\000'; s++, i++) {
+ if ((flag == 2 && i == 0) /* Ignore and keep primary selector */
+ || (flag == 1 && i == 1)) { /* Ignore and keep secondary selectors */
*d++ = *s;
+ continue;
+ }
+ if (usels[*s] == 0) { /* If selector is not currently used */
+ *d++ = *s;
+ usels[*s] = 1;
+ }
}
*d = '\000';
@@ -805,9 +872,9 @@ int doccmx /* Add matching installed ccmx files */
for (i = 0; i < 256; i++)
usels[i] = 0;
- k = 0;
+ k = 0; /* Next selector index */
- /* Add entries from the static list */
+ /* Add entries from the static list and their primary selectors */
/* Count the number in the static list */
for (i = 0; !(sdtlist[i].flags & inst_dtflags_end); i++) {
@@ -816,14 +883,12 @@ int doccmx /* Add matching installed ccmx files */
list[nlist-1] = sdtlist[i]; /* Struct copy */
- if (set_sel(list[nlist-1].sel, usels, &k, asels)) {
+ if (set_sel(1, list[nlist-1].sel, usels, &k, asels)) {
a1loge(p->log, 1, "inst_creat_disptype_list run out of selectors\n");
break;
}
}
- k = 0; /* Next selector index */
-
/* Add any ccss's */
if (doccss) {
iccss *ss_list;
@@ -843,7 +908,7 @@ int doccmx /* Add matching installed ccmx files */
strncpy(list[nlist-1].sel, ss_list[i].sel, INST_DTYPE_SEL_LEN);
list[nlist-1].sel[INST_DTYPE_SEL_LEN-1] = '\000';
}
- if (set_sel(list[nlist-1].sel, usels, &k, asels)) {
+ if (set_sel(1, list[nlist-1].sel, usels, &k, asels)) {
a1loge(p->log, 1, "inst_creat_disptype_list run out of selectors\n");
break;
}
@@ -889,7 +954,7 @@ int doccmx /* Add matching installed ccmx files */
strncpy(list[nlist-1].sel, ss_list[i].sel, INST_DTYPE_SEL_LEN);
list[nlist-1].sel[INST_DTYPE_SEL_LEN-1] = '\000';
}
- if (set_sel(list[nlist-1].sel, usels, &k, asels)) {
+ if (set_sel(1, list[nlist-1].sel, usels, &k, asels)) {
a1loge(p->log, 1, "inst_creat_disptype_list run out of selectors\n");
break;
}
@@ -902,6 +967,11 @@ int doccmx /* Add matching installed ccmx files */
}
}
+ /* Verify or delete any secondary selectors from the list */
+ for (i = 0; i < nlist; i++) {
+ set_sel(2, list[i].sel, usels, &k, asels);
+ }
+
if (pndtlist != NULL)
*pndtlist = nlist;
if (pdtlist != NULL)
@@ -963,6 +1033,7 @@ iccmx *list_iccmx(char *inst, int *no) {
if (inst != NULL && cs->inst != NULL && strcmp(inst, cs->inst) != 0)
continue;
+ a1logd(g_log, 5, "Reading '%s'\n",paths[i]);
if ((tech = cs->tech) == NULL)
tech = "";
if ((disp = cs->disp) == NULL)
@@ -1089,6 +1160,7 @@ iccss *list_iccss(int *no) {
continue; /* Skip any unreadable ccss's */
}
+ a1logd(g_log, 5, "Reading '%s'\n",paths[i]);
if ((tech = cs->tech) == NULL)
tech = "";
if ((disp = cs->disp) == NULL)
@@ -1170,6 +1242,102 @@ void free_iccss(iccss *list) {
}
/* ============================================================= */
+/* Detect fast serial instruments */
+
+#ifdef ENABLE_FAST_SERIAL
+static void hex2bin(char *buf, int len);
+
+/* Heuristicly determine the instrument type for */
+/* a fast serial connection, and instUnknown if not serial. */
+/* Set it in icoms and also return it. */
+instType fast_ser_inst_type(
+ icoms *p,
+ int tryhard,
+ inst_code (*uicallback)(void *cntx, inst_ui_purp purp), /* optional uicallback */
+ void *cntx /* Context for callback */
+) {
+ instType rv = instUnknown;
+ char buf[100];
+ baud_rate brt[] = { baud_921600, baud_115200, baud_38400, baud_nc };
+ unsigned int etime;
+ unsigned int i;
+ int se, len;
+
+ if (p->port_type(p) != icomt_serial
+ && p->port_type(p) != icomt_usbserial)
+ return p->itype;
+
+ /* The tick to give up on */
+ etime = msec_time() + (long)(2000.0 + 0.5);
+
+ a1logd(p->log, 1, "fser_inst_type: Trying different baud rates (%u msec to go)\n",etime - msec_time());
+
+ /* Until we time out, find the correct baud rate */
+ for (i = 0; msec_time() < etime; i++) {
+ if (brt[i] == baud_nc) {
+ i = 0;
+ if (!tryhard)
+ break; /* try only once */
+ }
+ if ((se = p->set_ser_port(p, fc_none, brt[i], parity_none,
+ stop_1, length_8)) != ICOM_OK) {
+ a1logd(p->log, 5, "fser_inst_type: set_ser_port failed with 0x%x\n",se);
+ return instUnknown; /* Give up */
+ }
+
+// a1logd(p->log, 5, "brt = %d\n",brt[i]);
+
+ /* See if it's a JETI specbos */
+ if ((se = p->write_read(p, "*idn?\r", buf, 100, "\r", 1, 0.050)) != inst_ok) {
+ /* Check for user abort */
+ if (uicallback != NULL) {
+ inst_code ev;
+ if ((ev = uicallback(cntx, inst_negcoms)) == inst_user_abort) {
+ a1logd(p->log, 5, "fser_inst_type: User aborted\n");
+ return instUnknown;
+ }
+ }
+ continue;
+ }
+ len = strlen(buf);
+
+ a1logd(p->log, 5, "len = %d\n",len);
+
+ /* JETI specbos returns "JETI_SBXXXX", where XXXX is the instrument type, */
+ /* except for the 1201 which returns "SB05" */
+
+ /* Is this a JETI specbos 1201 response ? */
+ if (strncmp(buf, "SB05", 4) == 0) {
+// a1logd(p->log, 5, "specbos1201\n");
+ rv = instSpecbos1201;
+ break;
+ }
+ /* Is this a JETI specbos XXXX response ? */
+ if (len >= 11 && strncmp(buf, "JETI_SB", 7) == 0) {
+// a1logd(p->log, 5, "specbos\n");
+ rv = instSpecbos;
+ break;
+ }
+ }
+
+ if (rv == instUnknown
+ && msec_time() >= etime) { /* We haven't established comms */
+ a1logd(p->log, 5, "fser_inst_type: Failed to establish coms\n");
+ p->itype = rv;
+ return instUnknown;
+ }
+
+ a1logd(p->log, 5, "fser_inst_type: Instrument type is '%s'\n", inst_name(rv));
+
+ p->itype = rv;
+
+ return rv;
+}
+
+#endif /* ENABLE_FAST_SERIAL */
+
+/* ============================================================= */
+/* Detect serial instruments */
#ifdef ENABLE_SERIAL
static void hex2bin(char *buf, int len);
@@ -1217,7 +1385,7 @@ static instType ser_inst_type(
}
// a1logd(p->log, 5, "brt = %d\n",brt[i]);
- if ((se = p->write_read(p, ";D024\r\n", buf, 100, '\r', 1, 0.5)) != inst_ok) {
+ if ((se = p->write_read(p, ";D024\r\n", buf, 100, "\r", 1, 0.5)) != inst_ok) {
/* Check for user abort */
if (uicallback != NULL) {
inst_code ev;
@@ -1226,6 +1394,7 @@ static instType ser_inst_type(
return instUnknown;
}
}
+ continue;
}
len = strlen(buf);
@@ -1254,7 +1423,8 @@ static instType ser_inst_type(
}
}
- if (msec_time() >= etime) { /* We haven't established comms */
+ if (rv == instUnknown
+ && msec_time() >= etime) { /* We haven't established comms */
a1logd(p->log, 5, "ser_inst_type: Failed to establish coms\n");
return instUnknown;
}
@@ -1269,7 +1439,7 @@ static instType ser_inst_type(
/* SpectroScan */
if (ss) {
rv = instSpectroScan;
- if ((se = p->write_read(p, ";D030\r\n", buf, 100, '\n', 1, 1.5)) == 0) {
+ if ((se = p->write_read(p, ";D030\r\n", buf, 100, "\n", 1, 1.5)) == 0) {
if (strlen(buf) >= 41) {
hex2bin(&buf[5], 12);
// a1logd(p->log, 5, "spectroscan type = '%s'\n",buf);
@@ -1281,7 +1451,7 @@ static instType ser_inst_type(
if (xrite) {
/* Get the X-Rite model and version number */
- if ((se = p->write_read(p, "SV\r\n", buf, 100, '>', 1, 2.5)) != 0)
+ if ((se = p->write_read(p, "SV\r\n", buf, 100, ">", 1, 2.5)) != 0)
return instUnknown;
if (strlen(buf) >= 12) {
@@ -1311,6 +1481,10 @@ static instType ser_inst_type(
return rv;
}
+#endif /* ENABLE_SERIAL */
+
+#if defined(ENABLE_SERIAL) || defined(ENABLE_FAST_SERIAL)
+
/* Convert an ASCII Hex character to an integer. */
static int h2b(char c) {
if (c >= '0' && c <= '9')
diff --git a/spectro/inst.h b/spectro/inst.h
index 5b5d710..d69a37f 100644
--- a/spectro/inst.h
+++ b/spectro/inst.h
@@ -66,14 +66,15 @@
#define ICOM_MAX_LOC_LEN 10
/* Type of measurement result */
-typedef enum { /* XYZ units, spectral units */
+typedef enum { /* XYZ units, Spectral units */
inst_mrt_none = 0, /* Not set */
- inst_mrt_emission = 1, /* cd/m^2, mW/m^2/nm */
- inst_mrt_ambient = 2, /* Lux/3.1415926 ?? */
- inst_mrt_emission_flash = 3, /* cd/m^2.s, mW/m^2/nm.s*/
- inst_mrt_ambient_flash = 4, /* Lux/3.1415926/s ?? */
+ inst_mrt_emission = 1, /* cd/m^2, mW/(m^2.sr.nm) */
+ inst_mrt_ambient = 2, /* Lux mW/(m^2.nm) */
+ inst_mrt_emission_flash = 3, /* cd/(m^2.s), mW/(m^2.sr.nm.s) */
+ inst_mrt_ambient_flash = 4, /* Lux/s mW/(m^2.nm.s) */
inst_mrt_reflective = 5, /* %, %/nm */
- inst_mrt_transmissive = 6 /* %, %/nm */
+ inst_mrt_transmissive = 6, /* %, %/nm */
+ inst_mrt_frequency = 7 /* Hz */
} inst_meas_type;
struct _ipatch {
@@ -101,31 +102,31 @@ struct _ipatch {
/* Note :- update inst_interp_error() in inst.c if anything here is changed. */
/* and also check all the instrument specific XXX_interp_code() routines too. */
typedef enum {
- inst_ok = 0x0000,
- inst_notify = 0x0100, /* A Notification */
- inst_warning = 0x0200, /* A Warning */
- inst_no_coms = 0x0300, /* init_coms() hasn't been called yet */
- inst_no_init = 0x0400, /* init_inst() hasn't been called yet */
- inst_unsupported = 0x0500, /* Unsupported function */
- inst_internal_error = 0x0600, /* Internal software error */
- inst_coms_fail = 0x0700, /* Communication failure */
- inst_unknown_model = 0x0800, /* Not the expected instrument */
- inst_protocol_error = 0x0900, /* Read or Write protocol error */
- inst_user_abort = 0x0A00, /* User hit escape */
- inst_user_trig = 0x0C00, /* User hit trigger key */
- inst_misread = 0x0E00, /* Bad reading, or strip misread */
- inst_nonesaved = 0x0F00, /* No saved data to read */
- inst_nochmatch = 0x1000, /* Chart doesn't match */
- inst_needs_cal = 0x1100, /* Instrument needs calibration, and read retried */
- inst_cal_setup = 0x1200, /* Calibration retry with correct setup is needed */
- inst_wrong_config = 0x1300, /* Retry with correct inst. config./sensor posn. needed */
- inst_unexpected_reply = 0x1400, /* Unexpected Reply */
- inst_wrong_setup = 0x1500, /* Setup is wrong or conflicting */
- inst_hardware_fail = 0x1600, /* Hardware failure */
- inst_bad_parameter = 0x1700, /* Bad parameter value */
- inst_other_error = 0x1800, /* Some other error */
- inst_mask = 0xff00, /* inst_code mask value */
- inst_imask = 0x00ff /* instrument specific mask value */
+ inst_ok = 0x000000,
+ inst_notify = 0x010000, /* A Notification */
+ inst_warning = 0x020000, /* A Warning */
+ inst_no_coms = 0x030000, /* init_coms() hasn't been called yet */
+ inst_no_init = 0x040000, /* init_inst() hasn't been called yet */
+ inst_unsupported = 0x050000, /* Unsupported function */
+ inst_internal_error = 0x060000, /* Internal software error */
+ inst_coms_fail = 0x070000, /* Communication failure */
+ inst_unknown_model = 0x080000, /* Not the expected instrument */
+ inst_protocol_error = 0x090000, /* Read or Write protocol error */
+ inst_user_abort = 0x0A0000, /* User hit escape */
+ inst_user_trig = 0x0C0000, /* User hit trigger key */
+ inst_misread = 0x0E0000, /* Bad reading, or strip misread */
+ inst_nonesaved = 0x0F0000, /* No saved data to read */
+ inst_nochmatch = 0x100000, /* Chart doesn't match */
+ inst_needs_cal = 0x110000, /* Instrument needs calibration, and read retried */
+ inst_cal_setup = 0x120000, /* Calibration retry with correct setup is needed */
+ inst_wrong_config = 0x130000, /* Retry with correct inst. config./sensor posn. needed */
+ inst_unexpected_reply = 0x140000, /* Unexpected Reply */
+ inst_wrong_setup = 0x150000, /* Setup is wrong or conflicting */
+ inst_hardware_fail = 0x160000, /* Hardware failure */
+ inst_bad_parameter = 0x170000, /* Bad parameter value */
+ inst_other_error = 0x180000, /* Some other error */
+ inst_mask = 0xff0000, /* inst_code mask value */
+ inst_imask = 0x00ffff /* instrument specific mask value */
} inst_code;
/* Instrument capabilities & modes */
@@ -257,7 +258,11 @@ typedef enum {
inst2_xy_position = 0x00000004, /* Can be positioned at a given location */
inst2_meas_disp_update = 0x00000010, /* Is able to measure display update delay */
- inst2_refresh_rate = 0x00000020, /* Is able to retrieve the calibrated refresh rate */
+
+ inst2_get_refresh_rate = 0x00000020, /* Is able to get the calibrated refresh rate */
+ inst2_set_refresh_rate = 0x00000040, /* Is able to set the calibrated refresh rate */
+
+ inst2_emis_refr_meas = 0x00000080, /* Has an emissive refresh rate measurement func. */
inst2_prog_trig = 0x00000100, /* Progromatic trigger measure capability */
inst2_user_trig = 0x00000200, /* User trigger measure capability */
@@ -270,17 +275,21 @@ typedef enum {
inst2_no_feedback = 0x00008000, /* Instrument doesn't give any user feedback */
inst2_has_leds = 0x00200000, /* Instrument has some user viewable indicator LEDs */
- inst2_has_sensmode = 0x00400000, /* Instrument can report it's sensors mode */
+ inst2_has_target = 0x00400000, /* Instrument has aiming target */
+ inst2_has_sensmode = 0x00800000, /* Instrument can report it's sensors mode */
+
+ inst2_has_battery = 0x01000000, /* Instrument is battery powered */
- inst2_has_battery = 0x00800000, /* Instrument is battery powered */
+ inst2_disptype = 0x02000000, /* Has a display type selector */
+ inst2_ccmx = 0x04000000, /* Colorimeter Correction Matrix capability */
+ inst2_ccss = 0x08000000, /* Colorimeter Cal. Spectral Set capability */
- inst2_disptype = 0x01000000, /* Has a display type selector */
- inst2_ccmx = 0x02000000, /* Colorimeter Correction Matrix capability */
- inst2_ccss = 0x04000000, /* Colorimeter Cal. Spectral Set capability */
+ inst2_ambient_mono = 0x10000000, /* The ambient measurement is monochrome */
- inst2_ambient_mono = 0x08000000, /* The ambient measurement is monochrome */
+ inst2_ambient_cardioid = 0x20000000, /* The ambient measurement has a cardioid response */
- inst2_emis_refr_meas = 0x10000000, /* Has an emissive refresh rate measurement func. */
+ inst2_get_min_int_time = 0x40000000, /* Is able to get the minimum integration time */
+ inst2_set_min_int_time = 0x80000000 /* Is able to set the minimum integration time */
} inst2_capability;
@@ -297,7 +306,6 @@ typedef enum {
inst_dtflags_ccss = 0x0002, /* ccss */
inst_dtflags_ccmx = 0x0004, /* ccmx */
inst_dtflags_end = 0x8000 /* end marker */
-
} inst_dtflags;
#define INST_DTYPE_SEL_LEN 10
@@ -310,7 +318,7 @@ typedef struct _inst_disptypesel {
inst_dtflags flags; /* Attribute flags */
int cbid; /* Calibration base ID. NZ if valid ccmx calibration base. */
/* Should remain constant between releases */
- char sel[INST_DTYPE_SEL_LEN]; /* String of selector characters */
+ char sel[INST_DTYPE_SEL_LEN]; /* String of selector character aliases */
char desc[INST_DTYPE_DESC_LEN]; /* Textural description */
int refr; /* Refresh mode flag */
@@ -353,9 +361,8 @@ typedef enum {
inst_opt_initcalib = 0x0008, /* Enable initial calibration (default) [No args] */
inst_opt_noinitcalib = 0x0009, /* Disable initial calibration if < losecs since last */ /* opened, or losecs == 0 [int losecs] */
- inst_opt_set_ccss_obs = 0x000A, /* Set the observer used with ccss device types */
- /* Only takes effect after inst_opt_set_disp_type */
- /* or col_cal_spec_set() */
+ inst_opt_set_ccss_obs = 0x000A, /* Set the observer used with ccss device types - */
+ /* Not applicable to any other type of instrument. */
/* [args: icxObserverType obType,*/
/* xspect custObserver[3] */
@@ -371,7 +378,7 @@ typedef enum {
inst_opt_trig_switch = 0x0010, /* Trigger using instrument switch [No args] */
inst_opt_trig_user_switch = 0x0011, /* Trigger from user via uicallback or switch (def) [No args] */
- inst_opt_highres = 0x0012, /* Enable high resolution spectral mode */
+ inst_opt_highres = 0x0012, /* Enable high res spectral mode indep. of set_mode() */
inst_opt_stdres = 0x0013, /* Revert to standard resolution spectral mode */
inst_opt_scan_toll = 0x0014, /* Modify the patch scan recognition tollnce [double] */
@@ -383,7 +390,11 @@ typedef enum {
inst_opt_get_pulse_ledmask = 0x0018, /* Get the bitmask for pulseable ind. LEDs [*int] */
inst_opt_set_led_pulse_state= 0x0019, /* Set the current LED state. [double period_in_secs, */
/* double on_time_prop, double trans_time_prop] */
- inst_opt_get_led_pulse_state= 0x001A /* Get the current pulse LED state. [*double period, */
+ inst_opt_get_led_pulse_state= 0x001A, /* Get the current pulse LED state. [*double period] */
+ inst_opt_set_target_state = 0x001B, /* Set the aiming target state 0 = off, 1 == on, 2 = toggle [int] */
+
+ inst_opt_get_min_int_time = 0x001C, /* Get the minimum integration time [*double time] */
+ inst_opt_set_min_int_time = 0x001D /* Set the minimum integration time [double time] */
} inst_opt_type;
@@ -480,9 +491,11 @@ typedef enum {
inst_calc_man_man_mask = 0x000000F0, /* user configured calibration mask */
inst_calc_emis_white = 0x00000100, /* Provide a white test patch */
- inst_calc_emis_grey = 0x00000200, /* Provide a grey test patch */
- inst_calc_emis_grey_darker = 0x00000300, /* Provide a darker grey test patch */
- inst_calc_emis_grey_ligher = 0x00000400, /* Provide a darker grey test patch */
+ inst_calc_emis_80pc = 0x00000200, /* Provide an 80% white test patch */
+ inst_calc_emis_grey = 0x00000300, /* Provide a grey test patch */
+ inst_calc_emis_grey_darker = 0x00000400, /* Provide a darker grey test patch */
+ inst_calc_emis_grey_ligher = 0x00000500, /* Provide a darker grey test patch */
+
inst_calc_emis_mask = 0x00000F00, /* Emmissive/display provided reference patch */
inst_calc_change_filter = 0x00010000, /* Filter needs changing on device - see id[] */
@@ -803,6 +816,7 @@ typedef enum {
int *msecdelay); /* Return the number of msec */ \
\
/* Return the last calibrated refresh rate in Hz. Returns: */ \
+ /* (Available if cap2 & inst2_get_refresh_rate) */ \
/* inst_unsupported - if this instrument doesn't suport a refresh mode */ \
/* or is unable to retrieve the refresh rate */ \
/* inst_needs_cal - if the refresh rate value is not valid */ \
@@ -813,6 +827,7 @@ typedef enum {
double *ref_rate); /* Return the Hz */ \
\
/* Set the calibrated refresh rate in Hz. */ \
+ /* (Available if cap2 & inst2_set_refresh_rate) */ \
/* Set refresh rate to 0.0 to mark it as invalid */ \
/* Rates outside the range 5.0 to 150.0 Hz will return an error */ \
/* Note that not all instruments that can return a refresh rate, */ \
@@ -824,6 +839,7 @@ typedef enum {
/* Insert a compensation filter in the instrument readings */ \
/* This is typically needed if an adapter is being used, that alters */ \
/* the spectrum of the light reaching the instrument */ \
+ /* Not fully implemented across all instrument types (spectrolino only ?) */ \
/* To remove the filter, pass NULL for the filter filename */ \
inst_code (*comp_filter)( \
struct _inst *p, \
diff --git a/spectro/instappsup.c b/spectro/instappsup.c
index 67849c7..c83c953 100644
--- a/spectro/instappsup.c
+++ b/spectro/instappsup.c
@@ -317,6 +317,19 @@ inst_code inst_handle_calibrate(
}
break;
+ case inst_calc_emis_80pc:
+ if (disp_setup == NULL || dwi == NULL) { /* No way of creating a test window */
+ printf("Place the instrument on a 80%% white test patch,\n");
+ printf(" and then hit any key to continue,\n");
+ printf(" or hit Esc or Q to abort: ");
+ } else {
+ /* We need to display a 80% white patch to proceed with this */
+ /* type of calibration */
+ if ((rv = disp_setup(p, calc, dwi)) != inst_ok)
+ return rv;
+ }
+ break;
+
case inst_calc_emis_grey:
case inst_calc_emis_grey_darker:
case inst_calc_emis_grey_ligher:
diff --git a/spectro/instlib.ksh b/spectro/instlib.ksh
index 88fcba5..e112b3c 100644
--- a/spectro/instlib.ksh
+++ b/spectro/instlib.ksh
@@ -97,6 +97,8 @@ SPECTRO_FILES="
spyd2.h
spyd2setup.h
spyd2PLD.h
+ specbos.h
+ specbos.c
oemarch.c
oemarch.h
oeminst.c
@@ -111,10 +113,10 @@ SPECTRO_FILES="
iusb.h
usbio.h
usbio.c
- usbio_lusb.c
usbio_nt.c
usbio_ox.c
usbio_lx.c
+ usbio_bsd.c
xdg_bds.c
xdg_bds.h
spotread.c
diff --git a/spectro/insttypeinst.h b/spectro/insttypeinst.h
index c61a5c4..8ed93d8 100644
--- a/spectro/insttypeinst.h
+++ b/spectro/insttypeinst.h
@@ -22,4 +22,5 @@
#include "hcfr.h"
#include "spyd2.h"
#include "huey.h"
+#include "specbos.h"
#include "colorhug.h"
diff --git a/spectro/insttypes.c b/spectro/insttypes.c
index e0863d0..d70bc71 100644
--- a/spectro/insttypes.c
+++ b/spectro/insttypes.c
@@ -86,6 +86,10 @@ char *inst_sname(instType itype) {
return "Huey";
case instSmile:
return "Smile";
+ case instSpecbos1201:
+ return "specbos 1201";
+ case instSpecbos:
+ return "specbos";
case instColorHug:
return "ColorHug";
default:
@@ -143,6 +147,10 @@ char *inst_name(instType itype) {
return "GretagMacbeth Huey";
case instSmile:
return "ColorMunki Smile";
+ case instSpecbos1201:
+ return "JETI specbos 1201";
+ case instSpecbos:
+ return "JETI specbos";
case instColorHug:
return "Hughski ColorHug";
default:
@@ -205,9 +213,14 @@ instType inst_enum(char *name) {
return instHuey;
else if (strcmp(name, "ColorMunki Smile") == 0)
return instSmile;
+ else if (strcmp(name, "JETI specbos 1201") == 0)
+ return instSpecbos1201;
+ else if (strcmp(name, "JETI specbos") == 0)
+ return instSpecbos;
else if (strcmp(name, "Hughski ColorHug") == 0)
return instColorHug;
+
return instUnknown;
}
@@ -286,6 +299,8 @@ int nep) { /* Number of end points */
}
/* Add other instruments here */
+
+
return instUnknown;
}
@@ -371,6 +386,10 @@ int inst_illuminant(xspect *sp, instType itype) {
case instSmile:
return 1; /* Not applicable */
+ case instSpecbos1201:
+ case instSpecbos:
+ return 1; /* Not applicable */
+
case instColorHug:
return 1; /* Not applicable */
diff --git a/spectro/insttypes.h b/spectro/insttypes.h
index 88e800b..ff86cc5 100644
--- a/spectro/insttypes.h
+++ b/spectro/insttypes.h
@@ -21,6 +21,7 @@
extern "C" {
#endif
+
/* ----------------------------- */
/* Possible types of instruments */
typedef enum {
@@ -48,8 +49,13 @@ typedef enum {
instSpyder4, /* Datacolor Spyder4 */
instHuey, /* GretagMacbeth Huey */
instSmile, /* X-rite Colormunki Smile */
+ instSpecbos1201, /* JETI specbos 1201 */
+ instSpecbos, /* JETI specbos XXXX */
instColorHug, /* Hughski ColorHug */
+
+ instFakeDisp = 9998, /* Fake display & instrument device id */
+
} instType;
struct _icoms; /* Forward declaration */
diff --git a/spectro/linear.cal b/spectro/linear.cal
index 30da145..5b494f9 100644
--- a/spectro/linear.cal
+++ b/spectro/linear.cal
@@ -2,7 +2,7 @@ CAL
DESCRIPTOR "Argyll Device Calibration Curves"
ORIGINATOR "Argyll synthcal"
-CREATED "Sat Mar 09 18:33:22 2013"
+CREATED "Fri Jan 31 13:50:43 2014"
KEYWORD "DEVICE_CLASS"
DEVICE_CLASS "DISPLAY"
KEYWORD "COLOR_REP"
@@ -16,260 +16,260 @@ END_DATA_FORMAT
NUMBER_OF_SETS 256
BEGIN_DATA
-0.0000 0.0000 0.0000 0.0000
-3.9216e-003 3.9216e-003 3.9216e-003 3.9216e-003
-7.8431e-003 7.8431e-003 7.8431e-003 7.8431e-003
-0.011765 0.011765 0.011765 0.011765
-0.015686 0.015686 0.015686 0.015686
-0.019608 0.019608 0.019608 0.019608
-0.023529 0.023529 0.023529 0.023529
-0.027451 0.027451 0.027451 0.027451
-0.031373 0.031373 0.031373 0.031373
-0.035294 0.035294 0.035294 0.035294
-0.039216 0.039216 0.039216 0.039216
-0.043137 0.043137 0.043137 0.043137
-0.047059 0.047059 0.047059 0.047059
-0.050980 0.050980 0.050980 0.050980
-0.054902 0.054902 0.054902 0.054902
-0.058824 0.058824 0.058824 0.058824
-0.062745 0.062745 0.062745 0.062745
-0.066667 0.066667 0.066667 0.066667
-0.070588 0.070588 0.070588 0.070588
-0.074510 0.074510 0.074510 0.074510
-0.078431 0.078431 0.078431 0.078431
-0.082353 0.082353 0.082353 0.082353
-0.086275 0.086275 0.086275 0.086275
-0.090196 0.090196 0.090196 0.090196
-0.094118 0.094118 0.094118 0.094118
-0.098039 0.098039 0.098039 0.098039
-0.10196 0.10196 0.10196 0.10196
-0.10588 0.10588 0.10588 0.10588
-0.10980 0.10980 0.10980 0.10980
-0.11373 0.11373 0.11373 0.11373
-0.11765 0.11765 0.11765 0.11765
-0.12157 0.12157 0.12157 0.12157
-0.12549 0.12549 0.12549 0.12549
-0.12941 0.12941 0.12941 0.12941
-0.13333 0.13333 0.13333 0.13333
-0.13725 0.13725 0.13725 0.13725
-0.14118 0.14118 0.14118 0.14118
-0.14510 0.14510 0.14510 0.14510
-0.14902 0.14902 0.14902 0.14902
-0.15294 0.15294 0.15294 0.15294
-0.15686 0.15686 0.15686 0.15686
-0.16078 0.16078 0.16078 0.16078
-0.16471 0.16471 0.16471 0.16471
-0.16863 0.16863 0.16863 0.16863
-0.17255 0.17255 0.17255 0.17255
-0.17647 0.17647 0.17647 0.17647
-0.18039 0.18039 0.18039 0.18039
-0.18431 0.18431 0.18431 0.18431
-0.18824 0.18824 0.18824 0.18824
-0.19216 0.19216 0.19216 0.19216
-0.19608 0.19608 0.19608 0.19608
-0.20000 0.20000 0.20000 0.20000
-0.20392 0.20392 0.20392 0.20392
-0.20784 0.20784 0.20784 0.20784
-0.21176 0.21176 0.21176 0.21176
-0.21569 0.21569 0.21569 0.21569
-0.21961 0.21961 0.21961 0.21961
-0.22353 0.22353 0.22353 0.22353
-0.22745 0.22745 0.22745 0.22745
-0.23137 0.23137 0.23137 0.23137
-0.23529 0.23529 0.23529 0.23529
-0.23922 0.23922 0.23922 0.23922
-0.24314 0.24314 0.24314 0.24314
-0.24706 0.24706 0.24706 0.24706
-0.25098 0.25098 0.25098 0.25098
-0.25490 0.25490 0.25490 0.25490
-0.25882 0.25882 0.25882 0.25882
-0.26275 0.26275 0.26275 0.26275
-0.26667 0.26667 0.26667 0.26667
-0.27059 0.27059 0.27059 0.27059
-0.27451 0.27451 0.27451 0.27451
-0.27843 0.27843 0.27843 0.27843
-0.28235 0.28235 0.28235 0.28235
-0.28627 0.28627 0.28627 0.28627
-0.29020 0.29020 0.29020 0.29020
-0.29412 0.29412 0.29412 0.29412
-0.29804 0.29804 0.29804 0.29804
-0.30196 0.30196 0.30196 0.30196
-0.30588 0.30588 0.30588 0.30588
-0.30980 0.30980 0.30980 0.30980
-0.31373 0.31373 0.31373 0.31373
-0.31765 0.31765 0.31765 0.31765
-0.32157 0.32157 0.32157 0.32157
-0.32549 0.32549 0.32549 0.32549
-0.32941 0.32941 0.32941 0.32941
-0.33333 0.33333 0.33333 0.33333
-0.33725 0.33725 0.33725 0.33725
-0.34118 0.34118 0.34118 0.34118
-0.34510 0.34510 0.34510 0.34510
-0.34902 0.34902 0.34902 0.34902
-0.35294 0.35294 0.35294 0.35294
-0.35686 0.35686 0.35686 0.35686
-0.36078 0.36078 0.36078 0.36078
-0.36471 0.36471 0.36471 0.36471
-0.36863 0.36863 0.36863 0.36863
-0.37255 0.37255 0.37255 0.37255
-0.37647 0.37647 0.37647 0.37647
-0.38039 0.38039 0.38039 0.38039
-0.38431 0.38431 0.38431 0.38431
-0.38824 0.38824 0.38824 0.38824
-0.39216 0.39216 0.39216 0.39216
-0.39608 0.39608 0.39608 0.39608
-0.40000 0.40000 0.40000 0.40000
-0.40392 0.40392 0.40392 0.40392
-0.40784 0.40784 0.40784 0.40784
-0.41176 0.41176 0.41176 0.41176
-0.41569 0.41569 0.41569 0.41569
-0.41961 0.41961 0.41961 0.41961
-0.42353 0.42353 0.42353 0.42353
-0.42745 0.42745 0.42745 0.42745
-0.43137 0.43137 0.43137 0.43137
-0.43529 0.43529 0.43529 0.43529
-0.43922 0.43922 0.43922 0.43922
-0.44314 0.44314 0.44314 0.44314
-0.44706 0.44706 0.44706 0.44706
-0.45098 0.45098 0.45098 0.45098
-0.45490 0.45490 0.45490 0.45490
-0.45882 0.45882 0.45882 0.45882
-0.46275 0.46275 0.46275 0.46275
-0.46667 0.46667 0.46667 0.46667
-0.47059 0.47059 0.47059 0.47059
-0.47451 0.47451 0.47451 0.47451
-0.47843 0.47843 0.47843 0.47843
-0.48235 0.48235 0.48235 0.48235
-0.48627 0.48627 0.48627 0.48627
-0.49020 0.49020 0.49020 0.49020
-0.49412 0.49412 0.49412 0.49412
-0.49804 0.49804 0.49804 0.49804
-0.50196 0.50196 0.50196 0.50196
-0.50588 0.50588 0.50588 0.50588
-0.50980 0.50980 0.50980 0.50980
-0.51373 0.51373 0.51373 0.51373
-0.51765 0.51765 0.51765 0.51765
-0.52157 0.52157 0.52157 0.52157
-0.52549 0.52549 0.52549 0.52549
-0.52941 0.52941 0.52941 0.52941
-0.53333 0.53333 0.53333 0.53333
-0.53725 0.53725 0.53725 0.53725
-0.54118 0.54118 0.54118 0.54118
-0.54510 0.54510 0.54510 0.54510
-0.54902 0.54902 0.54902 0.54902
-0.55294 0.55294 0.55294 0.55294
-0.55686 0.55686 0.55686 0.55686
-0.56078 0.56078 0.56078 0.56078
-0.56471 0.56471 0.56471 0.56471
-0.56863 0.56863 0.56863 0.56863
-0.57255 0.57255 0.57255 0.57255
-0.57647 0.57647 0.57647 0.57647
-0.58039 0.58039 0.58039 0.58039
-0.58431 0.58431 0.58431 0.58431
-0.58824 0.58824 0.58824 0.58824
-0.59216 0.59216 0.59216 0.59216
-0.59608 0.59608 0.59608 0.59608
-0.60000 0.60000 0.60000 0.60000
-0.60392 0.60392 0.60392 0.60392
-0.60784 0.60784 0.60784 0.60784
-0.61176 0.61176 0.61176 0.61176
-0.61569 0.61569 0.61569 0.61569
-0.61961 0.61961 0.61961 0.61961
-0.62353 0.62353 0.62353 0.62353
-0.62745 0.62745 0.62745 0.62745
-0.63137 0.63137 0.63137 0.63137
-0.63529 0.63529 0.63529 0.63529
-0.63922 0.63922 0.63922 0.63922
-0.64314 0.64314 0.64314 0.64314
-0.64706 0.64706 0.64706 0.64706
-0.65098 0.65098 0.65098 0.65098
-0.65490 0.65490 0.65490 0.65490
-0.65882 0.65882 0.65882 0.65882
-0.66275 0.66275 0.66275 0.66275
-0.66667 0.66667 0.66667 0.66667
-0.67059 0.67059 0.67059 0.67059
-0.67451 0.67451 0.67451 0.67451
-0.67843 0.67843 0.67843 0.67843
-0.68235 0.68235 0.68235 0.68235
-0.68627 0.68627 0.68627 0.68627
-0.69020 0.69020 0.69020 0.69020
-0.69412 0.69412 0.69412 0.69412
-0.69804 0.69804 0.69804 0.69804
-0.70196 0.70196 0.70196 0.70196
-0.70588 0.70588 0.70588 0.70588
-0.70980 0.70980 0.70980 0.70980
-0.71373 0.71373 0.71373 0.71373
-0.71765 0.71765 0.71765 0.71765
-0.72157 0.72157 0.72157 0.72157
-0.72549 0.72549 0.72549 0.72549
-0.72941 0.72941 0.72941 0.72941
-0.73333 0.73333 0.73333 0.73333
-0.73725 0.73725 0.73725 0.73725
-0.74118 0.74118 0.74118 0.74118
-0.74510 0.74510 0.74510 0.74510
-0.74902 0.74902 0.74902 0.74902
-0.75294 0.75294 0.75294 0.75294
-0.75686 0.75686 0.75686 0.75686
-0.76078 0.76078 0.76078 0.76078
-0.76471 0.76471 0.76471 0.76471
-0.76863 0.76863 0.76863 0.76863
-0.77255 0.77255 0.77255 0.77255
-0.77647 0.77647 0.77647 0.77647
-0.78039 0.78039 0.78039 0.78039
-0.78431 0.78431 0.78431 0.78431
-0.78824 0.78824 0.78824 0.78824
-0.79216 0.79216 0.79216 0.79216
-0.79608 0.79608 0.79608 0.79608
-0.80000 0.80000 0.80000 0.80000
-0.80392 0.80392 0.80392 0.80392
-0.80784 0.80784 0.80784 0.80784
-0.81176 0.81176 0.81176 0.81176
-0.81569 0.81569 0.81569 0.81569
-0.81961 0.81961 0.81961 0.81961
-0.82353 0.82353 0.82353 0.82353
-0.82745 0.82745 0.82745 0.82745
-0.83137 0.83137 0.83137 0.83137
-0.83529 0.83529 0.83529 0.83529
-0.83922 0.83922 0.83922 0.83922
-0.84314 0.84314 0.84314 0.84314
-0.84706 0.84706 0.84706 0.84706
-0.85098 0.85098 0.85098 0.85098
-0.85490 0.85490 0.85490 0.85490
-0.85882 0.85882 0.85882 0.85882
-0.86275 0.86275 0.86275 0.86275
-0.86667 0.86667 0.86667 0.86667
-0.87059 0.87059 0.87059 0.87059
-0.87451 0.87451 0.87451 0.87451
-0.87843 0.87843 0.87843 0.87843
-0.88235 0.88235 0.88235 0.88235
-0.88627 0.88627 0.88627 0.88627
-0.89020 0.89020 0.89020 0.89020
-0.89412 0.89412 0.89412 0.89412
-0.89804 0.89804 0.89804 0.89804
-0.90196 0.90196 0.90196 0.90196
-0.90588 0.90588 0.90588 0.90588
-0.90980 0.90980 0.90980 0.90980
-0.91373 0.91373 0.91373 0.91373
-0.91765 0.91765 0.91765 0.91765
-0.92157 0.92157 0.92157 0.92157
-0.92549 0.92549 0.92549 0.92549
-0.92941 0.92941 0.92941 0.92941
-0.93333 0.93333 0.93333 0.93333
-0.93725 0.93725 0.93725 0.93725
-0.94118 0.94118 0.94118 0.94118
-0.94510 0.94510 0.94510 0.94510
-0.94902 0.94902 0.94902 0.94902
-0.95294 0.95294 0.95294 0.95294
-0.95686 0.95686 0.95686 0.95686
-0.96078 0.96078 0.96078 0.96078
-0.96471 0.96471 0.96471 0.96471
-0.96863 0.96863 0.96863 0.96863
-0.97255 0.97255 0.97255 0.97255
-0.97647 0.97647 0.97647 0.97647
-0.98039 0.98039 0.98039 0.98039
-0.98431 0.98431 0.98431 0.98431
-0.98824 0.98824 0.98824 0.98824
-0.99216 0.99216 0.99216 0.99216
-0.99608 0.99608 0.99608 0.99608
-1.0000 1.0000 1.0000 1.0000
+0.00000 0.00000 0.00000 0.00000
+3.92157e-003 3.92157e-003 3.92157e-003 3.92157e-003
+7.84314e-003 7.84314e-003 7.84314e-003 7.84314e-003
+0.0117647 0.0117647 0.0117647 0.0117647
+0.0156863 0.0156863 0.0156863 0.0156863
+0.0196078 0.0196078 0.0196078 0.0196078
+0.0235294 0.0235294 0.0235294 0.0235294
+0.0274510 0.0274510 0.0274510 0.0274510
+0.0313725 0.0313725 0.0313725 0.0313725
+0.0352941 0.0352941 0.0352941 0.0352941
+0.0392157 0.0392157 0.0392157 0.0392157
+0.0431373 0.0431373 0.0431373 0.0431373
+0.0470588 0.0470588 0.0470588 0.0470588
+0.0509804 0.0509804 0.0509804 0.0509804
+0.0549020 0.0549020 0.0549020 0.0549020
+0.0588235 0.0588235 0.0588235 0.0588235
+0.0627451 0.0627451 0.0627451 0.0627451
+0.0666667 0.0666667 0.0666667 0.0666667
+0.0705882 0.0705882 0.0705882 0.0705882
+0.0745098 0.0745098 0.0745098 0.0745098
+0.0784314 0.0784314 0.0784314 0.0784314
+0.0823529 0.0823529 0.0823529 0.0823529
+0.0862745 0.0862745 0.0862745 0.0862745
+0.0901961 0.0901961 0.0901961 0.0901961
+0.0941176 0.0941176 0.0941176 0.0941176
+0.0980392 0.0980392 0.0980392 0.0980392
+0.101961 0.101961 0.101961 0.101961
+0.105882 0.105882 0.105882 0.105882
+0.109804 0.109804 0.109804 0.109804
+0.113725 0.113725 0.113725 0.113725
+0.117647 0.117647 0.117647 0.117647
+0.121569 0.121569 0.121569 0.121569
+0.125490 0.125490 0.125490 0.125490
+0.129412 0.129412 0.129412 0.129412
+0.133333 0.133333 0.133333 0.133333
+0.137255 0.137255 0.137255 0.137255
+0.141176 0.141176 0.141176 0.141176
+0.145098 0.145098 0.145098 0.145098
+0.149020 0.149020 0.149020 0.149020
+0.152941 0.152941 0.152941 0.152941
+0.156863 0.156863 0.156863 0.156863
+0.160784 0.160784 0.160784 0.160784
+0.164706 0.164706 0.164706 0.164706
+0.168627 0.168627 0.168627 0.168627
+0.172549 0.172549 0.172549 0.172549
+0.176471 0.176471 0.176471 0.176471
+0.180392 0.180392 0.180392 0.180392
+0.184314 0.184314 0.184314 0.184314
+0.188235 0.188235 0.188235 0.188235
+0.192157 0.192157 0.192157 0.192157
+0.196078 0.196078 0.196078 0.196078
+0.200000 0.200000 0.200000 0.200000
+0.203922 0.203922 0.203922 0.203922
+0.207843 0.207843 0.207843 0.207843
+0.211765 0.211765 0.211765 0.211765
+0.215686 0.215686 0.215686 0.215686
+0.219608 0.219608 0.219608 0.219608
+0.223529 0.223529 0.223529 0.223529
+0.227451 0.227451 0.227451 0.227451
+0.231373 0.231373 0.231373 0.231373
+0.235294 0.235294 0.235294 0.235294
+0.239216 0.239216 0.239216 0.239216
+0.243137 0.243137 0.243137 0.243137
+0.247059 0.247059 0.247059 0.247059
+0.250980 0.250980 0.250980 0.250980
+0.254902 0.254902 0.254902 0.254902
+0.258824 0.258824 0.258824 0.258824
+0.262745 0.262745 0.262745 0.262745
+0.266667 0.266667 0.266667 0.266667
+0.270588 0.270588 0.270588 0.270588
+0.274510 0.274510 0.274510 0.274510
+0.278431 0.278431 0.278431 0.278431
+0.282353 0.282353 0.282353 0.282353
+0.286275 0.286275 0.286275 0.286275
+0.290196 0.290196 0.290196 0.290196
+0.294118 0.294118 0.294118 0.294118
+0.298039 0.298039 0.298039 0.298039
+0.301961 0.301961 0.301961 0.301961
+0.305882 0.305882 0.305882 0.305882
+0.309804 0.309804 0.309804 0.309804
+0.313725 0.313725 0.313725 0.313725
+0.317647 0.317647 0.317647 0.317647
+0.321569 0.321569 0.321569 0.321569
+0.325490 0.325490 0.325490 0.325490
+0.329412 0.329412 0.329412 0.329412
+0.333333 0.333333 0.333333 0.333333
+0.337255 0.337255 0.337255 0.337255
+0.341176 0.341176 0.341176 0.341176
+0.345098 0.345098 0.345098 0.345098
+0.349020 0.349020 0.349020 0.349020
+0.352941 0.352941 0.352941 0.352941
+0.356863 0.356863 0.356863 0.356863
+0.360784 0.360784 0.360784 0.360784
+0.364706 0.364706 0.364706 0.364706
+0.368627 0.368627 0.368627 0.368627
+0.372549 0.372549 0.372549 0.372549
+0.376471 0.376471 0.376471 0.376471
+0.380392 0.380392 0.380392 0.380392
+0.384314 0.384314 0.384314 0.384314
+0.388235 0.388235 0.388235 0.388235
+0.392157 0.392157 0.392157 0.392157
+0.396078 0.396078 0.396078 0.396078
+0.400000 0.400000 0.400000 0.400000
+0.403922 0.403922 0.403922 0.403922
+0.407843 0.407843 0.407843 0.407843
+0.411765 0.411765 0.411765 0.411765
+0.415686 0.415686 0.415686 0.415686
+0.419608 0.419608 0.419608 0.419608
+0.423529 0.423529 0.423529 0.423529
+0.427451 0.427451 0.427451 0.427451
+0.431373 0.431373 0.431373 0.431373
+0.435294 0.435294 0.435294 0.435294
+0.439216 0.439216 0.439216 0.439216
+0.443137 0.443137 0.443137 0.443137
+0.447059 0.447059 0.447059 0.447059
+0.450980 0.450980 0.450980 0.450980
+0.454902 0.454902 0.454902 0.454902
+0.458824 0.458824 0.458824 0.458824
+0.462745 0.462745 0.462745 0.462745
+0.466667 0.466667 0.466667 0.466667
+0.470588 0.470588 0.470588 0.470588
+0.474510 0.474510 0.474510 0.474510
+0.478431 0.478431 0.478431 0.478431
+0.482353 0.482353 0.482353 0.482353
+0.486275 0.486275 0.486275 0.486275
+0.490196 0.490196 0.490196 0.490196
+0.494118 0.494118 0.494118 0.494118
+0.498039 0.498039 0.498039 0.498039
+0.501961 0.501961 0.501961 0.501961
+0.505882 0.505882 0.505882 0.505882
+0.509804 0.509804 0.509804 0.509804
+0.513725 0.513725 0.513725 0.513725
+0.517647 0.517647 0.517647 0.517647
+0.521569 0.521569 0.521569 0.521569
+0.525490 0.525490 0.525490 0.525490
+0.529412 0.529412 0.529412 0.529412
+0.533333 0.533333 0.533333 0.533333
+0.537255 0.537255 0.537255 0.537255
+0.541176 0.541176 0.541176 0.541176
+0.545098 0.545098 0.545098 0.545098
+0.549020 0.549020 0.549020 0.549020
+0.552941 0.552941 0.552941 0.552941
+0.556863 0.556863 0.556863 0.556863
+0.560784 0.560784 0.560784 0.560784
+0.564706 0.564706 0.564706 0.564706
+0.568627 0.568627 0.568627 0.568627
+0.572549 0.572549 0.572549 0.572549
+0.576471 0.576471 0.576471 0.576471
+0.580392 0.580392 0.580392 0.580392
+0.584314 0.584314 0.584314 0.584314
+0.588235 0.588235 0.588235 0.588235
+0.592157 0.592157 0.592157 0.592157
+0.596078 0.596078 0.596078 0.596078
+0.600000 0.600000 0.600000 0.600000
+0.603922 0.603922 0.603922 0.603922
+0.607843 0.607843 0.607843 0.607843
+0.611765 0.611765 0.611765 0.611765
+0.615686 0.615686 0.615686 0.615686
+0.619608 0.619608 0.619608 0.619608
+0.623529 0.623529 0.623529 0.623529
+0.627451 0.627451 0.627451 0.627451
+0.631373 0.631373 0.631373 0.631373
+0.635294 0.635294 0.635294 0.635294
+0.639216 0.639216 0.639216 0.639216
+0.643137 0.643137 0.643137 0.643137
+0.647059 0.647059 0.647059 0.647059
+0.650980 0.650980 0.650980 0.650980
+0.654902 0.654902 0.654902 0.654902
+0.658824 0.658824 0.658824 0.658824
+0.662745 0.662745 0.662745 0.662745
+0.666667 0.666667 0.666667 0.666667
+0.670588 0.670588 0.670588 0.670588
+0.674510 0.674510 0.674510 0.674510
+0.678431 0.678431 0.678431 0.678431
+0.682353 0.682353 0.682353 0.682353
+0.686275 0.686275 0.686275 0.686275
+0.690196 0.690196 0.690196 0.690196
+0.694118 0.694118 0.694118 0.694118
+0.698039 0.698039 0.698039 0.698039
+0.701961 0.701961 0.701961 0.701961
+0.705882 0.705882 0.705882 0.705882
+0.709804 0.709804 0.709804 0.709804
+0.713725 0.713725 0.713725 0.713725
+0.717647 0.717647 0.717647 0.717647
+0.721569 0.721569 0.721569 0.721569
+0.725490 0.725490 0.725490 0.725490
+0.729412 0.729412 0.729412 0.729412
+0.733333 0.733333 0.733333 0.733333
+0.737255 0.737255 0.737255 0.737255
+0.741176 0.741176 0.741176 0.741176
+0.745098 0.745098 0.745098 0.745098
+0.749020 0.749020 0.749020 0.749020
+0.752941 0.752941 0.752941 0.752941
+0.756863 0.756863 0.756863 0.756863
+0.760784 0.760784 0.760784 0.760784
+0.764706 0.764706 0.764706 0.764706
+0.768627 0.768627 0.768627 0.768627
+0.772549 0.772549 0.772549 0.772549
+0.776471 0.776471 0.776471 0.776471
+0.780392 0.780392 0.780392 0.780392
+0.784314 0.784314 0.784314 0.784314
+0.788235 0.788235 0.788235 0.788235
+0.792157 0.792157 0.792157 0.792157
+0.796078 0.796078 0.796078 0.796078
+0.800000 0.800000 0.800000 0.800000
+0.803922 0.803922 0.803922 0.803922
+0.807843 0.807843 0.807843 0.807843
+0.811765 0.811765 0.811765 0.811765
+0.815686 0.815686 0.815686 0.815686
+0.819608 0.819608 0.819608 0.819608
+0.823529 0.823529 0.823529 0.823529
+0.827451 0.827451 0.827451 0.827451
+0.831373 0.831373 0.831373 0.831373
+0.835294 0.835294 0.835294 0.835294
+0.839216 0.839216 0.839216 0.839216
+0.843137 0.843137 0.843137 0.843137
+0.847059 0.847059 0.847059 0.847059
+0.850980 0.850980 0.850980 0.850980
+0.854902 0.854902 0.854902 0.854902
+0.858824 0.858824 0.858824 0.858824
+0.862745 0.862745 0.862745 0.862745
+0.866667 0.866667 0.866667 0.866667
+0.870588 0.870588 0.870588 0.870588
+0.874510 0.874510 0.874510 0.874510
+0.878431 0.878431 0.878431 0.878431
+0.882353 0.882353 0.882353 0.882353
+0.886275 0.886275 0.886275 0.886275
+0.890196 0.890196 0.890196 0.890196
+0.894118 0.894118 0.894118 0.894118
+0.898039 0.898039 0.898039 0.898039
+0.901961 0.901961 0.901961 0.901961
+0.905882 0.905882 0.905882 0.905882
+0.909804 0.909804 0.909804 0.909804
+0.913725 0.913725 0.913725 0.913725
+0.917647 0.917647 0.917647 0.917647
+0.921569 0.921569 0.921569 0.921569
+0.925490 0.925490 0.925490 0.925490
+0.929412 0.929412 0.929412 0.929412
+0.933333 0.933333 0.933333 0.933333
+0.937255 0.937255 0.937255 0.937255
+0.941176 0.941176 0.941176 0.941176
+0.945098 0.945098 0.945098 0.945098
+0.949020 0.949020 0.949020 0.949020
+0.952941 0.952941 0.952941 0.952941
+0.956863 0.956863 0.956863 0.956863
+0.960784 0.960784 0.960784 0.960784
+0.964706 0.964706 0.964706 0.964706
+0.968627 0.968627 0.968627 0.968627
+0.972549 0.972549 0.972549 0.972549
+0.976471 0.976471 0.976471 0.976471
+0.980392 0.980392 0.980392 0.980392
+0.984314 0.984314 0.984314 0.984314
+0.988235 0.988235 0.988235 0.988235
+0.992157 0.992157 0.992157 0.992157
+0.996078 0.996078 0.996078 0.996078
+1.00000 1.00000 1.00000 1.00000
END_DATA
diff --git a/spectro/madvrwin.c b/spectro/madvrwin.c
new file mode 100644
index 0000000..9769b71
--- /dev/null
+++ b/spectro/madvrwin.c
@@ -0,0 +1,589 @@
+
+
+/*
+ * Argyll Color Correction System
+ * Web Display target patch window
+ *
+ * Author: Graeme W. Gill
+ * Date: 3/4/12
+ *
+ * Copyright 2013 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#ifdef NT
+# include <winsock2.h>
+#endif
+#ifdef UNIX
+# include <sys/types.h>
+# include <ifaddrs.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# ifdef __FreeBSD__
+# include <sys/socket.h>
+# endif /* __FreeBSD__ */
+#endif
+#include "copyright.h"
+#include "aconfig.h"
+#include "icc.h"
+#include "numsup.h"
+#include "cgats.h"
+#include "conv.h"
+#include "dispwin.h"
+#include "madvrwin.h"
+#include "conv.h"
+#include "mongoose.h"
+
+#define ENABLE_RAMDAC
+
+#undef DEBUG
+//#define STANDALONE_TEST
+
+#ifdef DEBUG
+#define errout stderr
+# define debug(xx) fprintf(errout, xx )
+# define debug2(xx) fprintf xx
+# define debugr(xx) fprintf(errout, xx )
+# define debugr2(xx) fprintf xx
+# define debugrr(xx) fprintf(errout, xx )
+# define debugrr2(xx) fprintf xx
+# define debugrr2l(lev, xx) fprintf xx
+#else
+#define errout stderr
+# define debug(xx)
+# define debug2(xx)
+# define debugr(xx) if (p->ddebug) fprintf(errout, xx )
+# define debugr2(xx) if (p->ddebug) fprintf xx
+# define debugrr(xx) if (callback_ddebug) fprintf(errout, xx )
+# define debugrr2(xx) if (callback_ddebug) fprintf xx
+# define debugrr2l(lev, xx) if (callback_ddebug >= lev) fprintf xx
+#endif
+
+/* ----------------------------------------------- */
+/* MadVR functions */
+
+#ifndef KEY_WOW64_32KEY
+# define KEY_WOW64_32KEY (0x0200)
+#endif
+
+HMODULE HcNetDll = NULL;
+BOOL (WINAPI *madVR_BlindConnect)(BOOL searchLan, DWORD timeOut) = NULL;
+BOOL (WINAPI *madVR_SetOsdText)(LPCWSTR text);
+BOOL (WINAPI *madVR_Disable3dlut)() = NULL;
+BOOL (WINAPI *madVR_GetDeviceGammaRamp)(LPVOID ramp) = NULL;
+BOOL (WINAPI *madVR_SetDeviceGammaRamp)(LPVOID ramp) = NULL;
+BOOL (WINAPI *madVR_SetBackground)(int patternAreaInPercent, COLORREF backgroundColor) = NULL;
+BOOL (WINAPI *madVR_ShowRGB)(double r, double g, double b) = NULL;
+BOOL (WINAPI *madVR_SetProgressBarPos)(int currentPos, int maxPos);
+BOOL (WINAPI *madVR_Disconnect)() = NULL;
+
+/* Locate and populate the MadVR functions */
+/* Return NZ on failure */
+static int initMadVR(dispwin *p) {
+ wchar_t *dllname;
+
+ if (sizeof(dllname) > 4) /* Compiled as 64 bit */
+ dllname = L"madHcNet64.dll";
+ else
+ dllname = L"madHcNet32.dll";
+
+ if ((HcNetDll = LoadLibraryW(dllname)) == NULL) {
+ HKEY hk1;
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID\\{E1A8B82A-32CE-4B0D-BE0D-AA68C772E423}\\InprocServer32", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hk1) == ERROR_SUCCESS) {
+ DWORD size;
+ LPWSTR us1;
+ int i1;
+ size = MAX_PATH * 2 + 2;
+ us1 = (LPWSTR) LocalAlloc(LPTR, size + 20);
+ i1 = RegQueryValueExW(hk1, NULL, NULL, NULL, (LPBYTE) us1, &size);
+ if (i1 == ERROR_MORE_DATA) {
+ LocalFree(us1);
+ us1 = (LPWSTR) LocalAlloc(LPTR, size + 20);
+ i1 = RegQueryValueExW(hk1, NULL, NULL, NULL, (LPBYTE) us1, &size);
+ }
+ if (i1 == ERROR_SUCCESS) {
+ for (i1 = lstrlenW(us1) - 2; i1 > 0; i1--)
+ if (us1[i1] == L'\\') {
+ us1[i1 + 1] = 0;
+ break;
+ }
+ wcscat(us1, dllname);
+ HcNetDll = LoadLibraryW(us1);
+ }
+ LocalFree(us1);
+ RegCloseKey(hk1);
+ }
+ }
+ if (HcNetDll != NULL) {
+ *(FARPROC*)&madVR_BlindConnect = GetProcAddress(HcNetDll, "madVR_BlindConnect");
+ *(FARPROC*)&madVR_SetOsdText = GetProcAddress(HcNetDll, "madVR_SetOsdText");
+ *(FARPROC*)&madVR_Disable3dlut = GetProcAddress(HcNetDll, "madVR_Disable3dlut");
+ *(FARPROC*)&madVR_GetDeviceGammaRamp = GetProcAddress(HcNetDll, "madVR_GetDeviceGammaRamp");
+ *(FARPROC*)&madVR_SetDeviceGammaRamp = GetProcAddress(HcNetDll, "madVR_SetDeviceGammaRamp");
+ *(FARPROC*)&madVR_SetBackground = GetProcAddress(HcNetDll, "madVR_SetBackground");
+ *(FARPROC*)&madVR_ShowRGB = GetProcAddress(HcNetDll, "madVR_ShowRGB");
+ *(FARPROC*)&madVR_SetProgressBarPos = GetProcAddress(HcNetDll, "madVR_SetProgressBarPos");
+ *(FARPROC*)&madVR_Disconnect = GetProcAddress(HcNetDll, "madVR_Disconnect");
+
+ if (madVR_BlindConnect
+ && madVR_SetOsdText
+ && madVR_Disable3dlut
+ && madVR_GetDeviceGammaRamp
+ && madVR_SetDeviceGammaRamp
+ && madVR_SetBackground
+ && madVR_ShowRGB
+ && madVR_SetProgressBarPos
+ && madVR_Disconnect) {
+ return 0;
+ }
+ debugr2((errout,"Failed to locate function in %ls\n",dllname));
+ FreeLibrary(HcNetDll);
+ } else {
+ debugr2((errout,"Failed to load %ls\n",dllname));
+ }
+ return 1;
+}
+
+static void deinitMadVR(dispwin *p) {
+ if (HcNetDll != NULL) {
+ FreeLibrary(HcNetDll);
+ HcNetDll = NULL;
+ }
+}
+
+/* ----------------------------------------------- */
+
+/* Get RAMDAC values. ->del() when finished. */
+/* Return NULL if not possible */
+static ramdac *madvrwin_get_ramdac(dispwin *p) {
+ ramdac *r = NULL;
+
+#ifdef ENABLE_RAMDAC
+ WORD vals[3][256]; /* 256 x 16 bit elements (Quantize) */
+ int i, j;
+
+ debugr("madvrwin_get_ramdac called\n");
+
+ /* Allocate a ramdac */
+ if ((r = (ramdac *)calloc(sizeof(ramdac), 1)) == NULL) {
+ debugr("madvrwin_get_ramdac failed on malloc()\n");
+ return NULL;
+ }
+ r->pdepth = p->pdepth;
+ r->nent = (1 << p->pdepth);
+ r->clone = dispwin_clone_ramdac;
+ r->setlin = dispwin_setlin_ramdac;
+ r->del = dispwin_del_ramdac;
+
+ for (j = 0; j < 3; j++) {
+
+ if ((r->v[j] = (double *)calloc(sizeof(double), r->nent)) == NULL) {
+ for (j--; j >= 0; j--)
+ free(r->v[j]);
+ free(r);
+ debugr("madvrwin_get_ramdac failed on malloc()\n");
+ return NULL;
+ }
+ }
+
+ /* GetDeviceGammaRamp() is hard coded for 3 x 256 entries (Quantize) */
+ if (r->nent != 256) {
+ free(r);
+ debugr2((errout,"GetDeviceGammaRamp() is hard coded for nent == 256, and we've got nent = %d!\n",r->nent));
+ return NULL;
+ }
+
+ if (madVR_GetDeviceGammaRamp(vals) == 0) {
+ free(r);
+ debugr2((errout,"madvrwin_get_ramdac failed on madVR_GetDeviceGammaRamp()\n"));
+ return NULL;
+ }
+
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < r->nent; i++) {
+ r->v[j][i] = vals[j][i]/65535.0;
+ }
+ }
+#endif // ENABLE_RAMDAC
+ debugr2((errout,"madvrwin_get_ramdac returning 0x%x\n",r));
+
+ return r;
+}
+
+/* Set the RAMDAC values. */
+/* Return nz if not possible */
+static int madvrwin_set_ramdac(dispwin *p, ramdac *r, int persist) {
+ int rv = 1;
+
+#ifdef ENABLE_RAMDAC
+ int i, j;
+ WORD vals[3][256]; /* 16 bit elements */
+
+ debugr("madvrwin_set_ramdac called\n");
+
+ for (j = 0; j < 3; j++) {
+ for (i = 0; i < r->nent; i++) {
+ double vv = r->v[j][i];
+ if (vv < 0.0)
+ vv = 0.0;
+ else if (vv > 1.0)
+ vv = 1.0;
+ vals[j][i] = (int)(65535.0 * vv + 0.5);
+ }
+ }
+
+ if (madVR_SetDeviceGammaRamp(vals) == 0) {
+ debugr2((errout,"madvrwin_set_ramdac failed on madVR_SetDeviceGammaRamp()\n"));
+ rv = 1;
+ } else {
+ debugr("madvrwin_set_ramdac set\n");
+ rv = 0;
+ }
+#endif // ENABLE_RAMDAC
+ return rv;
+}
+
+/* ----------------------------------------------- */
+/* Install a display profile and make */
+/* it the default for this display. */
+/* Return nz if failed */
+int madvrwin_install_profile(dispwin *p, char *fname, ramdac *r, p_scope scope) {
+ debugr("madVRdisp doesn't support installing profiles\n");
+ return 1;
+}
+
+/* Un-Install a display profile */
+/* Return nz if failed, */
+int madvrwin_uninstall_profile(dispwin *p, char *fname, p_scope scope) {
+ debugr("madVRdisp doesn't support uninstalling profiles\n");
+ return 1;
+}
+
+/* Get the currently installed display profile. */
+/* Return NULL if failed. */
+icmFile *madvrwin_get_profile(dispwin *p, char *name, int mxlen) {
+ debugr("madVRdisp doesn't support getting the current profile\n");
+ return NULL;
+}
+
+/* ----------------------------------------------- */
+
+/* Change the window color. */
+/* Return 1 on error, 2 on window being closed */
+static int madvrwin_set_color(
+dispwin *p,
+double r, double g, double b /* Color values 0.0 - 1.0 */
+) {
+ int j;
+ double orgb[3]; /* Previous RGB value */
+ double kr, kf;
+ int update_delay = p->update_delay;
+ double xdelay = 0.0; /* Extra delay for response time */
+
+ debugr("madvrwin_set_color called\n");
+
+ if (p->nowin)
+ return 1;
+
+ orgb[0] = p->rgb[0]; p->rgb[0] = r;
+ orgb[1] = p->rgb[1]; p->rgb[1] = g;
+ orgb[2] = p->rgb[2]; p->rgb[2] = b;
+
+ if (!madVR_ShowRGB(p->rgb[0], p->rgb[1], p->rgb[2])) {
+ debugr2((errout,"madVR_ShowRGB failed\n"));
+ return 1;
+ }
+
+ /* Don't want extra delay if we're measuring update delay */
+ if (update_delay != 0 && p->do_resp_time_del) {
+ /* Compute am expected response time for the change in level */
+ kr = DISPLAY_RISE_TIME/log(1 - 0.9); /* Exponent constant */
+ kf = DISPLAY_FALL_TIME/log(1 - 0.9); /* Exponent constant */
+//printf("~1 k2 = %f\n",k2);
+ for (j = 0; j < 3; j++) {
+ double el, dl, n, t;
+
+ el = pow(p->rgb[j], 2.2);
+ dl = el - pow(orgb[j], 2.2); /* Change in level */
+ if (fabs(dl) > 0.01) { /* More than 1% change in level */
+ n = DISPLAY_SETTLE_AIM * el;
+ if (n < DISPLAY_ABS_AIM)
+ n = DISPLAY_ABS_AIM;
+//printf("~1 sl %f, el %f, log (%f / %f)\n",sl,el,n,fabs(sl - el));
+ if (dl > 0.0)
+ t = kr * log(n/dl);
+ else
+ t = kf * log(n/-dl);
+
+ if (t > xdelay)
+ xdelay = t;
+ }
+ }
+//printf("~1 xdelay = %f secs\n",xdelay);
+ xdelay *= 1000.0; /* To msec */
+ /* This is kind of a fudge since update delay is after latency, */
+ /* but displays with long delay (ie. CRT) have short latency, and visa versa */
+ if ((int)xdelay > update_delay)
+ update_delay = (int)xdelay;
+ }
+
+ /* Allow some time for the display to update before */
+ /* a measurement can take place. This allows for CRT */
+ /* refresh, or LCD processing/update time, + */
+ /* display settling time (quite long for smaller LCD changes). */
+ msec_sleep(update_delay);
+
+ return 0;
+}
+
+/* ----------------------------------------------- */
+/* set patch info */
+/* Return nz on error */
+static int madvrwin_set_pinfo(dispwin *p, int pno, int tno) {
+
+ if (!madVR_SetProgressBarPos(pno, tno))
+ return 1;
+
+ return 0;
+}
+
+/* ----------------------------------------------- */
+/* Set an update delay, and return the previous value */
+/* Value can be set to zero, but othewise will be forced */
+/* to be >= min_update_delay */
+static int madvrwin_set_update_delay(
+dispwin *p,
+int update_delay) {
+ int cval = p->update_delay;
+ p->update_delay = update_delay;
+ if (update_delay != 0 && p->update_delay < p->min_update_delay)
+ p->update_delay = p->min_update_delay;
+ return cval;
+}
+
+/* ----------------------------------------------- */
+/* Set the shell set color callout */
+void madvrwin_set_callout(
+dispwin *p,
+char *callout
+) {
+ debugr2((errout,"madvrwin_set_callout called with '%s'\n",callout));
+
+ p->callout = strdup(callout);
+}
+
+/* ----------------------------------------------- */
+/* Destroy ourselves */
+static void madvrwin_del(
+dispwin *p
+) {
+
+ debugr("madvrwin_del called\n");
+
+ if (p == NULL)
+ return;
+
+ deinitMadVR(p);
+
+ if (p->name != NULL)
+ free(p->name);
+ if (p->description != NULL)
+ free(p->description);
+ if (p->callout != NULL)
+ free(p->callout);
+
+ /* Since we don't restore the display, delete these here */
+ if (p->oor != NULL) {
+ p->oor->del(p->oor);
+ p->oor = NULL;
+ }
+ if (p->or != NULL) {
+ p->or->del(p->or);
+ p->or = NULL;
+ }
+ if (p->r != NULL) {
+ p->r->del(p->r);
+ p->r = NULL;
+ }
+
+ free(p);
+}
+
+/* ----------------------------------------------- */
+
+/* Create a web display test window, default grey */
+dispwin *new_madvrwin(
+double width, double height, /* Width and height in mm - turned into % of screen */
+double hoff, double voff, /* Offset from center in fraction of screen - ignored */
+int nowin, /* NZ if no window should be created - RAMDAC access only */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
+int blackbg, /* NZ if whole screen should be filled with black */
+int verb, /* NZ for verbose prompts */
+int ddebug /* >0 to print debug statements to stderr */
+) {
+ dispwin *p = NULL;
+ char *cp;
+ struct mg_context *mg;
+ const char *options[3];
+ char port[50];
+
+ debug("new_madvrwin called with native = %d\n");
+
+ if (out_tvenc)
+ return NULL;
+
+ if ((p = (dispwin *)calloc(sizeof(dispwin), 1)) == NULL) {
+ if (ddebug) fprintf(stderr,"new_madvrwin failed because malloc failed\n");
+ return NULL;
+ }
+
+ /* !!!! Make changes in dispwin.c & webwin.c as well !!!! */
+ p->name = strdup("Web Window");
+ p->nowin = nowin;
+ p->native = native;
+ p->out_tvenc = 0;
+ p->blackbg = blackbg;
+ p->ddebug = ddebug;
+ p->get_ramdac = madvrwin_get_ramdac;
+ p->set_ramdac = madvrwin_set_ramdac;
+ p->install_profile = madvrwin_install_profile;
+ p->uninstall_profile = madvrwin_uninstall_profile;
+ p->get_profile = madvrwin_get_profile;
+ p->set_color = madvrwin_set_color;
+ p->set_pinfo = madvrwin_set_pinfo;
+ p->set_update_delay = madvrwin_set_update_delay;
+ p->set_callout = madvrwin_set_callout;
+ p->del = madvrwin_del;
+
+ debugr2((errout, "new_madvrwin got native = %d\n",native));
+
+#ifndef ENABLE_RAMDAC
+ if (noramdac != NULL)
+ *noramdac = 1;
+ p->native &= ~1;
+#endif
+
+ p->rgb[0] = p->rgb[1] = p->rgb[2] = 0.5; /* Set Grey as the initial test color */
+
+ p->min_update_delay = 20;
+
+ if ((cp = getenv("ARGYLL_MIN_DISPLAY_UPDATE_DELAY_MS")) != NULL) {
+ p->min_update_delay = atoi(cp);
+ if (p->min_update_delay < 20)
+ p->min_update_delay = 20;
+ if (p->min_update_delay > 60000)
+ p->min_update_delay = 60000;
+ debugr2((errout, "new_madvrwin: Minimum display update delay set to %d msec\n",p->min_update_delay));
+ }
+
+ p->update_delay = DISPLAY_UPDATE_DELAY; /* Default update delay */
+ if (p->update_delay < p->min_update_delay)
+ p->update_delay = p->min_update_delay;
+
+ p->pdepth = 8; /* Assume this */
+ p->edepth = 16;
+
+ if (initMadVR(p)) {
+ free(p);
+ return NULL;
+ }
+
+ if (!madVR_BlindConnect(0, 1000)) {
+ debugr2((errout,"Failed to locate MadVR\n"));
+ free(p);
+ return NULL;
+ }
+
+ if (p->native & 2) {
+ debugr2((errout,"new_madvrwin: disbling 3dLuts\n"));
+ madVR_Disable3dlut();
+ }
+
+ if (blackbg) {
+ int perc;
+
+ perc = (int)(width * height * 100 + 0.5);
+ madVR_SetBackground(perc, 0x0000);
+ }
+
+ /* Create a suitable description */
+ {
+ char buf[1000];
+
+ sprintf(buf,"ArgyllCMS Patches");
+ p->description = strdup(buf);
+
+ if (verb)
+ printf("Created MadVR window\n");
+
+ madVR_SetOsdText(L"ArgyllCMS Patches");
+ }
+
+#ifdef ENABLE_RAMDAC
+
+ /* Save the original ramdac, which gets restored on exit */
+ if ((p->or = p->get_ramdac(p)) != NULL) {
+
+ debugr("Saved original VideoLUT\n");
+
+ if (noramdac != NULL)
+ *noramdac = 0;
+
+ /* Copy original ramdac that never gets altered */
+ if ((p->oor = p->or->clone(p->or)) == NULL) {
+ madvrwin_del(p);
+ debugr("ramdac clone failed - memory ?\n");
+ return NULL;
+ }
+
+ /* Create a working ramdac for native or other use */
+ if ((p->r = p->or->clone(p->or)) == NULL) {
+ madvrwin_del(p);
+ debugr("ramdac clone failed - memory ?\n");
+ return NULL;
+ }
+
+ /* Setup for native mode == linear RAMDAC */
+ if ((p->native & 1) == 1) {
+int ii = 0;
+ debug("About to setup native mode\n");
+
+ /* Since we MadVR does dithering, we don't need to use the VideoLUTs */
+ /* to emulate higher precision, so simply set it to linear here. */
+ if ((ii = madVR_SetDeviceGammaRamp(NULL)) == 0) {
+ madvrwin_del(p);
+ debugr("Clear gamma ramp failed\n");
+ return NULL;
+ }
+ }
+
+ } else {
+ debugr2((errout,"Unable to access VideoLUT\n"));
+ if (noramdac != NULL)
+ *noramdac = 1;
+ p->oor = p->or = p->r = NULL;
+ }
+
+ if (!p->nowin) {
+
+ /* Make sure initial test color is displayed */
+ madvrwin_set_color(p, p->rgb[0], p->rgb[1], p->rgb[2]);
+ }
+#endif
+
+ debugr("new_madvrwin: return sucessfully\n");
+
+ return p;
+}
+
diff --git a/spectro/madvrwin.h b/spectro/madvrwin.h
new file mode 100644
index 0000000..74c8f4f
--- /dev/null
+++ b/spectro/madvrwin.h
@@ -0,0 +1,37 @@
+
+#ifndef MADVRWIN_H
+
+/*
+ * Argyll Color Correction System
+ * MadVR target patch window
+ *
+ * Author: Graeme W. Gill
+ * Date: 26/6/13
+ *
+ * Copyright 2013 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.
+ */
+
+
+/* Create a MadVR display test window, default grey */
+dispwin *new_madvrwin(
+double width, double height, /* Width and height in mm - turned into % of screen */
+double hoff, double voff, /* Offset from center in fraction of screen - ignored */
+int nowin, /* NZ if no window should be created - RAMDAC access only */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+int out_tvenc, /* 1 = use RGB Video Level encoding - will error */
+int blackbg, /* NZ if whole screen should be filled with black */
+int verb, /* NZ for verbose prompts */
+int ddebug /* >0 to print debug statements to stderr */
+);
+
+#define MADVRWIN_H
+#endif /* MADVRWIN_H */
diff --git a/spectro/munki.c b/spectro/munki.c
index 6fa898e..5d4de2d 100644
--- a/spectro/munki.c
+++ b/spectro/munki.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 12/1/2009
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -90,8 +90,8 @@ munki_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
a1logd(p->log, 2, "munki_init_coms: called\n");
if (p->icom->port_type(p->icom) != icomt_usb) {
- a1logd(p->log, 1, "munki_init_coms: wrong sort of coms!\n");
- return munki_interp_code(p, MUNKI_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "munki_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
a1logd(p->log, 2, "munki_init_coms: about to init USB\n");
@@ -145,8 +145,10 @@ munki_determine_capabilities(munki *p) {
if (p->m != NULL) {
munkiimp *m = (munkiimp *)p->m;
munki_state *s = &m->ms[m->mmode];
- if (s->emiss)
+ if (s->emiss) {
p->cap2 |= inst2_emis_refr_meas;
+ p->cap2 |= inst2_meas_disp_update;
+ }
}
p->cap3 = inst3_none;
@@ -314,6 +316,25 @@ double *ref_rate) {
rv = munki_imp_meas_refrate(p, ref_rate);
+
+ return munki_interp_code(p, rv);
+}
+
+/* Read the display update delay */
+static inst_code
+munki_meas_delay(
+inst *pp,
+int *msecdelay) {
+ munki *p = (munki *)pp;
+ munki_code rv;
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ rv = munki_imp_meas_delay(p, msecdelay);
+
return munki_interp_code(p, rv);
}
@@ -425,6 +446,8 @@ munki_interp_error(inst *pp, munki_code ec) {
return "No ambient found before first flash";
case MUNKI_RD_NOREFR_FOUND:
return "No refresh rate detected or failed to measure it";
+ case MUNKI_RD_NOTRANS_FOUND:
+ return "No delay calibration transition found";
case MUNKI_SPOS_PROJ:
return "Sensor should be in projector position";
@@ -557,6 +580,7 @@ munki_interp_code(munki *p, munki_code ec) {
case MUNKI_RD_NOFLASHES:
case MUNKI_RD_NOAMBB4FLASHES:
case MUNKI_RD_NOREFR_FOUND:
+ case MUNKI_RD_NOTRANS_FOUND:
return inst_misread | ec;
case MUNKI_INTERNAL_ERROR:
@@ -700,8 +724,7 @@ inst_code munki_set_mode(inst *pp, inst_mode m) {
if ((mmode = munki_convert_mode(p, m)) == mk_no_modes)
return inst_unsupported;
- if ((rv = munki_interp_code(p, munki_imp_set_mode(p, mmode, m & inst_mode_spectral)))
- != inst_ok)
+ if ((rv = munki_interp_code(p, munki_imp_set_mode(p, mmode, m))) != inst_ok)
return rv;
munki_determine_capabilities(p);
@@ -920,6 +943,7 @@ extern munki *new_munki(icoms *icom, instType itype) {
p->read_refrate = munki_read_refrate;
p->get_n_a_cals = munki_get_n_a_cals;
p->calibrate = munki_calibrate;
+ p->meas_delay = munki_meas_delay;
p->interp_error = munki_interp_error;
p->config_enum = munki_config_enum;
p->del = munki_del;
diff --git a/spectro/munki_imp.c b/spectro/munki_imp.c
index c76e9bc..9f431cc 100644
--- a/spectro/munki_imp.c
+++ b/spectro/munki_imp.c
@@ -5,7 +5,7 @@
* Author: Graeme W. Gill
* Date: 12/1/2009
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
@@ -67,14 +67,22 @@
#include "sort.h"
/* Configuration */
-#undef USE_HIGH_GAIN_MODE /* [Und] Make use of high gain mode */
+#undef USE_HIGH_GAIN_MODE /* [Und] Make use of high gain mode in emissive measurements */
#define USE_THREAD /* [Def] Need to use thread, or there are 1.5 second internal */
/* instrument delays ! */
-#define ENABLE_NONVCAL /* [Def] Enable saving calibration state between program runs in a file */
+#define ENABLE_NONVCAL /* [Def] Enable saving calibration state between program runs to a file */
#define ENABLE_NONLINCOR /* [Def] Enable non-linear correction */
/* NOTE :- high gain scaling will be stuffed if disabled! */
#define ENABLE_LEDTEMPC /* [Def] Enable LED temperature compensation */
-#define ENABLE_SPOS_CHECK /* [Def] Chech the sensor position is reasonable for measurement */
+#define ENABLE_BKDRIFTC /* [Def] Enable Emis. Black drift compensation using sheilded cell values */
+#define HEURISTIC_BKDRIFTC /* [Def] Use heusristic black drift correction version */
+#undef ENABLE_REFSTRAYC /* [Und] Enable Reflective stray light compensation */
+#define REFSTRAYC_FACTOR 0.000086 /* [0.00043] Compensation factor */
+#undef ENABLE_REFLEDINTER /* [Und] Enable Reflective LED interference correction */
+
+#define ENABLE_SPOS_CHECK /* [Def] Check the sensor position is reasonable for measurement */
+#define FILTER_SPOS_EVENTS /* [Def] Use a thread to filter SPOS event changes */
+#define FILTER_TIME 500 /* [500] Filter time in msec */
#define DCALTOUT (1 * 60 * 60) /* [1 Hrs] Dark Calibration timeout in seconds */
#define WCALTOUT (24 * 60 * 60) /* [24 Hrs] White Calibration timeout in seconds */
#define MAXSCANTIME 20.0 /* [20 Sec] Maximum scan time in seconds */
@@ -83,24 +91,27 @@
#define SINGLE_READ /* [Def] Use a single USB read for scan to eliminate latency issues. */
#define HIGH_RES /* [Def] Enable high resolution spectral mode code. Disable */
/* to break dependency on rspl library. */
+# undef FAST_HIGH_RES_SETUP /* Slightly better accuracy ? */
/* Debug [Und] */
#undef DEBUG /* Turn on extra messages & plots */
#undef PLOT_DEBUG /* Use plot to show readings & processing */
#undef PLOT_REFRESH /* Plot refresh rate measurement info */
+#undef PLOT_UPDELAY /* Plot data used to determine display update delay */
#undef RAWR_DEBUG /* Print out raw reading processing values */
#undef DUMP_SCANV /* Dump scan readings to a file "mkdump.txt" */
#undef DUMP_DARKM /* Append raw dark readings to file "mkddump.txt" */
+#undef DUMP_BKLED /* Save REFSTRAYC & REFLEDNOISE comp plot to "refbk1.txt" & "refbk2.txt" */
#undef APPEND_MEAN_EMMIS_VAL /* Append averaged uncalibrated reading to file "mkdump.txt" */
#undef IGNORE_WHITE_INCONS /* Ignore define reference reading inconsistency */
#undef TEST_DARK_INTERP /* Test out the dark interpolation (need DEBUG for plot) */
#undef PLOT_RCALCURVE /* Plot the reflection reference curve */
#undef PLOT_ECALCURVES /* Plot the emission reference curves */
-#undef PLOT_TEMPCOMP /* Plot before and after temp. compensation */
-#undef PATREC_DEBUG /* Print & Plot patch/flash recognition information */
+#undef PLOT_TEMPCOMP /* Plot before and after LED temp. compensation */
+#undef PLOT_PATREC /* Print & Plot patch/flash recognition information */
#undef HIGH_RES_DEBUG
#undef HIGH_RES_PLOT
-#undef HIGH_RES_PLOT_STRAYL /* Plot strat light upsample */
+#undef HIGH_RES_PLOT_STRAYL /* Plot stray light upsample */
#define DISP_INTT 0.7 /* Seconds per reading in display spot mode */
@@ -116,24 +127,22 @@
#define ADARKINT_MAX 2.0 /* Max cal time for adaptive dark cal with high gain mode */
#define ADARKINT_MAX2 4.0 /* Max cal time for adaptive dark for no high gain */
-#define SCAN_OP_LEV 0.10 /* Degree of optimimum sensor value to aim for */
- /* Make it scan as fast as possible */
-
#define RDEAD_TIME 0.004432 /* Fudge figure to make reflecting intn. time scale linearly */
#define EMIS_SCALE_FACTOR 1.0 /* Emission mode scale factor */
-#define AMB_SCALE_FACTOR (1.0/3.141592654) /* Ambient mode scale factor - convert */
- /* from Lux to Lux/PI */
- /* These factors get the same behaviour as the GMB drivers. */
+#define AMB_SCALE_FACTOR 1.0 /* Ambient mode scale factor for Lux */
#define NSEN_MAX 140 /* Maximum nsen/raw value we can cope with */
+/* Wavelength to start duplicating values below, because it is too noisy */
+#define WL_REF_MIN 420.0
+#define WL_EMIS_MIN 400.0
+
/* High res mode settings */
-#define HIGHRES_SHORT 360 /* Wavelength to calculate */
-#define HIGHRES_LONG 740
+#define HIGHRES_SHORT 380 /* Wavelength to calculate. Too noisy to try expanding range. */
+#define HIGHRES_LONG 730
#define HIGHRES_WIDTH (10.0/3.0) /* (The 3.3333 spacing and lanczos2 seems a good combination) */
-#define HIGHRES_REF_MIN 410.0 /* Too much stray light below this in reflective mode */
-#define HIGHRES_TRANS_MIN 380.0 /* Too much stray light below this in reflective mode */
+
#include "munki.h"
#include "munki_imp.h"
@@ -177,7 +186,7 @@ static void dump_bytes(a1log *log, char *pfx, unsigned char *buf, int base, int
bp += sprintf(bp,".");
}
bp += sprintf(bp,"\n");
- a1logd(log,0,oline);
+ a1logd(log,0,"%s",oline);
bp = oline;
}
}
@@ -186,7 +195,7 @@ static void dump_bytes(a1log *log, char *pfx, unsigned char *buf, int base, int
/* ============================================================ */
/* Debugging plot support */
-#if defined(DEBUG) || defined(PLOT_DEBUG) || defined(PATREC_DEBUG) || defined(HIGH_RES_PLOT) || defined(HIGH_RES_PLOT_STRAYL)
+#if defined(DEBUG) || defined(PLOT_DEBUG) || defined(PLOT_PATREC) || defined(HIGH_RES_PLOT) || defined(HIGH_RES_PLOT_STRAYL)
# include <plot.h>
@@ -322,6 +331,11 @@ void del_munkiimp(munki *p) {
munkiimp *m = (munkiimp *)p->m;
munki_state *s;
+#ifdef FILTER_SPOS_EVENTS
+ if (m->spos_th != NULL)
+ m->spos_th_term = 1;
+#endif
+
if (m->th != NULL) { /* Terminate switch monitor thread by simulating an event */
m->th_term = 1; /* Tell thread to exit on error */
munki_simulate_event(p, mk_eve_spos_change, 0);
@@ -331,9 +345,20 @@ void del_munkiimp(munki *p) {
a1logd(p->log,3,"Munki switch thread termination failed\n");
}
m->th->del(m->th);
- usb_uninit_cancel(&m->cancelt); /* Don't need cancel token now */
+ usb_uninit_cancel(&m->sw_cancel); /* Don't need cancel token now */
}
+#ifdef FILTER_SPOS_EVENTS
+ if (m->spos_th != NULL) {
+ for (i = 0; m->spos_th_termed == 0 && i < 5; i++)
+ msec_sleep(50); /* Wait for thread to terminate */
+ if (i >= 5) {
+ a1logd(p->log,3,"Munki spos thread termination failed\n");
+ }
+ m->spos_th->del(m->spos_th);
+ }
+#endif
+
/* Free any per mode data */
for (i = 0; i < mk_no_modes; i++) {
s = &m->ms[i];
@@ -568,11 +593,17 @@ munki_code munki_imp_init(munki *p) {
#ifdef USE_THREAD
/* Setup the switch monitoring thread */
- usb_init_cancel(&m->cancelt); /* Get cancel token ready */
+ usb_init_cancel(&m->sw_cancel); /* Get cancel token ready */
if ((m->th = new_athread(munki_switch_thread, (void *)p)) == NULL)
return MUNKI_INT_THREADFAILED;
#endif
+#ifdef FILTER_SPOS_EVENTS
+ /* Setup the sensor position filter thread */
+ if ((m->spos_th = new_athread(munki_spos_thread, (void *)p)) == NULL)
+ return MUNKI_INT_THREADFAILED;
+#endif
+
/* Set up the current state of each mode */
{
int i, j;
@@ -589,6 +620,11 @@ munki_code munki_imp_init(munki *p) {
s->targmaxitime = 2.0; /* Maximum integration time to aim for */
s->targoscale2 = 0.15; /* Proportion of targoscale to meed targmaxitime */
+#ifdef USE_HIGH_GAIN_MODE
+ s->auto_gain = 1; /* No high gain by default */
+#else
+ s->auto_gain = 0; /* No high gain by default */
+#endif
s->gainmode = 0; /* Normal gain mode */
s->inttime = 0.5; /* Initial integration time */
@@ -608,18 +644,14 @@ munki_code munki_imp_init(munki *p) {
s->idark_valid = 0; /* Interpolatable Dark cal invalid */
s->idark_data = dmatrixz(0, 3, -1, m->nraw-1);
- s->min_wl = 0.0; /* Default minimum to report */
-
s->dark_int_time = DISP_INTT; /* 0.7 */
s->dark_int_time2 = DISP_INTT2; /* 0.3 */
s->dark_int_time3 = DISP_INTT3; /* 0.1 */
s->idark_int_time[0] = s->idark_int_time[2] = m->min_int_time;
-#ifdef USE_HIGH_GAIN_MODE
- s->idark_int_time[1] = s->idark_int_time[3] = ADARKINT_MAX; /* 2.0 */
-#else
- s->idark_int_time[1] = s->idark_int_time[3] = ADARKINT_MAX2; /* 4.0 */
-#endif
+ s->idark_int_time[1] = ADARKINT_MAX; /* 2.0 */
+ s->idark_int_time[3] = ADARKINT_MAX2; /* 4.0 */
+
s->want_calib = 1; /* By default want an initial calibration */
s->want_dcalib = 1;
}
@@ -629,7 +661,8 @@ munki_code munki_imp_init(munki *p) {
s = &m->ms[i];
switch(i) {
case mk_refl_spot:
- s->targoscale = 1.0; /* Optimised sensor scaling to full */
+ s->auto_gain = 0; /* Don't automatically set gain */
+ s->targoscale = 1.0; /* Optimised sensor scaling to full */
s->reflective = 1;
s->adaptive = 0;
s->inttime = s->targoscale * m->cal_int_time;
@@ -642,17 +675,19 @@ munki_code munki_imp_init(munki *p) {
s->dreadtime = 0.5; /* same as reading */
s->wreadtime = 0.5;
s->maxscantime = 0.0;
- s->min_wl = HIGHRES_REF_MIN; /* Not enogh illumination to go below this */
break;
case mk_refl_scan:
- s->targoscale = SCAN_OP_LEV; /* Maximize scan rate */
+ s->auto_gain = 0; /* Don't automatically set gain */
+ s->targoscale = 1.0; /* Maximize level */
s->reflective = 1;
s->scan = 1;
s->adaptive = 0;
- s->inttime = (s->targoscale * m->cal_int_time - RDEAD_TIME) + RDEAD_TIME;
- if (s->inttime < m->min_int_time)
- s->inttime = m->min_int_time;
+// s->inttime = (s->targoscale * m->cal_int_time - RDEAD_TIME) + RDEAD_TIME;
+// if (s->inttime < m->min_int_time)
+// s->inttime = m->min_int_time;
+// s->dark_int_time = s->inttime;
+ s->inttime = s->targoscale * m->cal_int_time;
s->dark_int_time = s->inttime;
s->dpretime = 0.20; /* Pre-measure time */
@@ -662,7 +697,6 @@ munki_code munki_imp_init(munki *p) {
s->dreadtime = 0.10;
s->wreadtime = 0.10;
s->maxscantime = MAXSCANTIME;
- s->min_wl = HIGHRES_REF_MIN; /* Not enogh illumination to go below this */
break;
case mk_emiss_spot_na: /* Emissive spot not adaptive */
@@ -767,14 +801,13 @@ munki_code munki_imp_init(munki *p) {
s->dreadtime = 0.0;
s->wreadtime = 1.0;
s->maxscantime = 0.0;
- s->min_wl = HIGHRES_TRANS_MIN; /* Too much stray light below this ? */
break;
case mk_trans_scan:
- s->targoscale = 0.90; /* Allow extra 10% margine */
+ // ~~99 should we use high gain mode ??
+ s->targoscale = 0.10; /* Scan as fast as possible */
s->trans = 1;
s->scan = 1;
- s->targoscale = SCAN_OP_LEV;
s->inttime = s->targoscale * m->cal_int_time;
if (s->inttime < m->min_int_time)
s->inttime = m->min_int_time;
@@ -788,7 +821,6 @@ munki_code munki_imp_init(munki *p) {
s->dreadtime = 0.00;
s->wreadtime = 0.10;
s->maxscantime = MAXSCANTIME;
- s->min_wl = HIGHRES_TRANS_MIN; /* Too much stray light below this ? */
break;
}
}
@@ -837,12 +869,12 @@ char *munki_imp_get_serial_no(munki *p) {
/* Set the measurement mode. It may need calibrating */
munki_code munki_imp_set_mode(
munki *p,
- mk_mode mmode,
- int spec_en /* nz to enable reporting spectral */
+ mk_mode mmode, /* Operating mode */
+ inst_mode mode /* Full mode mask for options */
) {
munkiimp *m = (munkiimp *)p->m;
- a1logd(p->log,3,"munki_imp_set_mode called with %d\n",mmode);
+ a1logd(p->log,2,"munki_imp_set_mode called with mode no. %d and mask 0x%x\n",mmode,m);
switch(mmode) {
case mk_refl_spot:
case mk_refl_scan:
@@ -856,12 +888,21 @@ munki_code munki_imp_set_mode(
case mk_trans_spot:
case mk_trans_scan:
m->mmode = mmode;
- m->spec_en = spec_en ? 1 : 0;
- return MUNKI_OK;
- default:
break;
+ default:
+ return MUNKI_INT_ILLEGALMODE;
}
- return MUNKI_INT_ILLEGALMODE;
+ m->spec_en = (mode & inst_mode_spectral) != 0;
+
+ if ((mode & inst_mode_highres) != 0) {
+ munki_code rv;
+ if ((rv = munki_set_highres(p)) != MUNKI_OK)
+ return rv;
+ } else {
+ munki_set_stdres(p); /* Ignore any error */
+ }
+
+ return MUNKI_OK;
}
/* Return needed and available inst_cal_type's */
@@ -875,7 +916,7 @@ munki_code munki_imp_get_n_a_cals(munki *p, inst_cal_type *pn_cals, inst_cal_typ
a1logd(p->log,3,"munki_imp_get_n_a_cals: checking mode %d\n",m->mmode);
/* Timout calibrations that are too old */
- a1logd(p->log,4,"curtime = %u, iddate = %u\n",curtime,cs->iddate);
+ a1logd(p->log,4,"curtime %u, iddate %u, ddate %u, cfdate %u\n",curtime,cs->iddate,cs->ddate,cs->cfdate);
if ((curtime - cs->iddate) > DCALTOUT) {
a1logd(p->log,3,"Invalidating adaptive dark cal as %d secs from last cal\n",curtime - cs->iddate);
cs->idark_valid = 0;
@@ -972,7 +1013,7 @@ munki_code munki_imp_calibrate(
else if (*calt == inst_calt_available)
*calt = available & inst_calt_n_dfrble_mask;
- a1logd(p->log,4,"munki_imp_calibrate: doing calt 0x%x\n",calt);
+ a1logd(p->log,4,"munki_imp_calibrate: doing calt 0x%x\n",*calt);
if ((*calt & inst_calt_n_dfrble_mask) == 0) /* Nothing todo */
return MUNKI_OK;
@@ -989,6 +1030,16 @@ munki_code munki_imp_calibrate(
}
a1logd(p->log,4,"munki sensor position = 0x%x\n",spos);
+#ifdef NEVER
+ /* We can set the *calc to the actual conditions, in which case */
+ /* the calibration will commence immediately. */
+ if (!m->nosposcheck && spos == mk_spos_calib) {
+ *calc = inst_calc_man_cal_smode;
+ a1logd(p->log,4,"munki set calc to cal conditions\n",spos);
+
+ }
+#endif
+
/* Make sure that the instrument configuration matches the */
/* conditions */
if (*calc == inst_calc_man_cal_smode) {
@@ -1001,13 +1052,6 @@ munki_code munki_imp_calibrate(
}
}
- /* If the instrument is in the calibration position, */
- /* we know what the conditions are. */
- if (!m->nosposcheck && spos == mk_spos_calib) {
- *calc = inst_calc_man_cal_smode;
- a1logd(p->log,4,"munki set calc to cal conditions\n",spos);
- }
-
a1logd(p->log,4,"munki_imp_calibrate has right conditions\n");
if (*calt & inst_calt_ap_flag) {
@@ -1025,9 +1069,9 @@ munki_code munki_imp_calibrate(
/* Sanity check scan mode settings, in case something strange */
/* has been restored from the persistence file. */
- if (s->scan && s->inttime > (2.1 * m->min_int_time)) {
- s->inttime = m->min_int_time; /* Maximize scan rate */
- }
+// if (s->scan && s->inttime > (2.1 * m->min_int_time)) {
+// s->inttime = m->min_int_time; /* Maximize scan rate */
+// }
/* We are now either in inst_calc_man_cal_smode, */
/* inst_calc_man_trans_white, inst_calc_disp_white or inst_calc_proj_white */
@@ -1053,7 +1097,7 @@ munki_code munki_imp_calibrate(
nummeas = munki_comp_nummeas(p, s->dcaltime, s->inttime);
- a1logd(p->log,3,"\nDoing initial display black calibration with dcaltime %f, int_time %f, nummeas %d, gainmode %d\n", s->dcaltime, s->inttime, nummeas, s->gainmode);
+ a1logd(p->log,3,"\nDoing initial black calibration with dcaltime %f, int_time %f, nummeas %d, gainmode %d\n", s->dcaltime, s->inttime, nummeas, s->gainmode);
stm = msec_time();
if ((ev = munki_dark_measure(p, s->dark_data, nummeas, &s->inttime, s->gainmode))
!= MUNKI_OK) {
@@ -1207,25 +1251,25 @@ if (ss->dark_int_time2 != s->dark_int_time2
return ev;
}
-#ifdef USE_HIGH_GAIN_MODE
- s->idark_int_time[2] = m->min_int_time; /* 0.01 */
- nummeas = munki_comp_nummeas(p, s->dcaltime, s->idark_int_time[2]);
- a1logd(p->log,3,"Doing adaptive interpolated black calibration, dcaltime %f, idark_int_time[2] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[2], nummeas, 1);
- if ((ev = munki_dark_measure(p, s->idark_data[2], nummeas, &s->idark_int_time[2], 1))
- != MUNKI_OK) {
- m->mmode = mmode; /* Restore actual mode */
- return ev;
- }
-
- s->idark_int_time[3] = ADARKINT_MAX; /* 2.0 */
- a1logd(p->log,3,"Doing adaptive interpolated black calibration, dcaltime %f, idark_int_time[3] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[3], nummeas, 1);
- nummeas = munki_comp_nummeas(p, s->dcaltime, s->idark_int_time[3]);
- if ((ev = munki_dark_measure(p, s->idark_data[3], nummeas, &s->idark_int_time[3], 1))
- != MUNKI_OK) {
- m->mmode = mmode; /* Restore actual mode */
- return ev;
+ if (s->auto_gain) { /* If high gain is permitted */
+ s->idark_int_time[2] = m->min_int_time; /* 0.01 */
+ nummeas = munki_comp_nummeas(p, s->dcaltime, s->idark_int_time[2]);
+ a1logd(p->log,3,"Doing adaptive interpolated black calibration, dcaltime %f, idark_int_time[2] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[2], nummeas, 1);
+ if ((ev = munki_dark_measure(p, s->idark_data[2], nummeas, &s->idark_int_time[2], 1))
+ != MUNKI_OK) {
+ m->mmode = mmode; /* Restore actual mode */
+ return ev;
+ }
+
+ s->idark_int_time[3] = ADARKINT_MAX; /* 2.0 */
+ a1logd(p->log,3,"Doing adaptive interpolated black calibration, dcaltime %f, idark_int_time[3] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[3], nummeas, 1);
+ nummeas = munki_comp_nummeas(p, s->dcaltime, s->idark_int_time[3]);
+ if ((ev = munki_dark_measure(p, s->idark_data[3], nummeas, &s->idark_int_time[3], 1))
+ != MUNKI_OK) {
+ m->mmode = mmode; /* Restore actual mode */
+ return ev;
+ }
}
-#endif /* USE_HIGH_GAIN_MODE */
munki_prepare_idark(p);
@@ -1263,12 +1307,7 @@ if (ss->dark_int_time != s->dark_int_time
|| ss->dark_gain_mode != s->dark_gain_mode)
a1logd(p->log,1,"copying cal to mode with different cal/gain mode: %d -> %d\n",s->mode, ss->mode);
#endif
-#ifdef USE_HIGH_GAIN_MODE
- for (j = 0; j < 4; j++)
-#else
- for (j = 0; j < 2; j++)
-#endif
- {
+ for (j = 0; j < (s->auto_gain ? 4 : 2); j++) {
ss->idark_int_time[j] = s->idark_int_time[j];
#ifndef NEVER // ~~99
if (ss->idark_int_time[j] != s->idark_int_time[j])
@@ -1318,30 +1357,30 @@ if (ss->idark_int_time[j] != s->idark_int_time[j])
ddumpdarkm = 0;
#endif
-#ifdef USE_HIGH_GAIN_MODE
- // fprintf(stderr,"High gain offsets, base:\n");
- // plot_raw(s->idark_data[2]);
- // fprintf(stderr,"High gain offsets, multiplier:\n");
- // plot_raw(s->idark_data[3]);
+ if (s->auto_gain) {
+// fprintf(stderr,"High gain offsets, base:\n");
+// plot_raw(s->idark_data[2]);
+// fprintf(stderr,"High gain offsets, multiplier:\n");
+// plot_raw(s->idark_data[3]);
- for (tinttime = m->min_int_time; ; tinttime *= 2.0) {
- if (tinttime >= m->max_int_time)
- tinttime = m->max_int_time;
-
- nummeas = munki_comp_nummeas(p, s->dcaltime, tinttime);
- if ((ev = munki_dark_measure(p, ref, nummeas, &tinttime, 1)) != MUNKI_OK) {
- m->mmode = mmode; /* Restore actual mode */
- return ev;
- }
- munki_interp_dark(p, interp, tinttime, 1);
+ for (tinttime = m->min_int_time; ; tinttime *= 2.0) {
+ if (tinttime >= m->max_int_time)
+ tinttime = m->max_int_time;
+
+ nummeas = munki_comp_nummeas(p, s->dcaltime, tinttime);
+ if ((ev = munki_dark_measure(p, ref, nummeas, &tinttime, 1)) != MUNKI_OK) {
+ m->mmode = mmode; /* Restore actual mode */
+ return ev;
+ }
+ munki_interp_dark(p, interp, tinttime, 1);
#ifdef DEBUG
- printf("High gain, int time %f:\n",tinttime);
- plot_raw2(ref, interp);
+ printf("High gain, int time %f:\n",tinttime);
+ plot_raw2(ref, interp);
#endif
- if ((tinttime * 1.1) > m->max_int_time)
- break;
- }
-#endif /* USE_HIGH_GAIN_MODE */
+ if ((tinttime * 1.1) > m->max_int_time)
+ break;
+ }
+ }
}
#endif /* TEST_DARK_INTERP */
@@ -1370,27 +1409,24 @@ if (ss->idark_int_time[j] != s->idark_int_time[j])
return ev;
}
-#ifdef USE_HIGH_GAIN_MODE
- s->idark_int_time[2] = s->inttime;
- nummeas = munki_comp_nummeas(p, s->dcaltime, s->idark_int_time[2]);
- a1logd(p->log,3,"Doing adaptive scan black calibration, dcaltime %f, idark_int_time[2] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[2], nummeas, s->gainmode);
- if ((ev = munki_dark_measure(p, s->idark_data[2], nummeas, &s->idark_int_time[2], 1))
- != MUNKI_OK) {
- m->mmode = mmode; /* Restore actual mode */
- return ev;
+ if (s->auto_gain) {
+ s->idark_int_time[2] = s->inttime;
+ nummeas = munki_comp_nummeas(p, s->dcaltime, s->idark_int_time[2]);
+ a1logd(p->log,3,"Doing adaptive scan black calibration, dcaltime %f, idark_int_time[2] %f, nummeas %d, gainmode %d\n", s->dcaltime, s->idark_int_time[2], nummeas, s->gainmode);
+ if ((ev = munki_dark_measure(p, s->idark_data[2], nummeas, &s->idark_int_time[2], 1))
+ != MUNKI_OK) {
+ m->mmode = mmode; /* Restore actual mode */
+ return ev;
+ }
}
-#endif
s->idark_valid = 1;
s->iddate = cdate;
-#ifdef USE_HIGH_GAIN_MODE
- if (s->gainmode) {
+ if (s->auto_gain && s->gainmode) {
for (j = -1; j < m->nraw; j++)
s->dark_data[j] = s->idark_data[2][j];
- } else
-#endif
- {
+ } else {
for (j = -1; j < m->nraw; j++)
s->dark_data[j] = s->idark_data[0][j];
}
@@ -1418,12 +1454,8 @@ if (ss->idark_int_time[j] != s->idark_int_time[j])
ss->iddate = s->iddate;
ss->dark_int_time = s->dark_int_time;
ss->dark_gain_mode = s->dark_gain_mode;
-#ifdef USE_HIGH_GAIN_MODE
- for (j = 0; j < 4; j += 2)
-#else
- for (j = 0; j < 2; j += 2)
-#endif
- {
+
+ for (j = 0; j < (s->auto_gain ? 4 : 2); j += 2) {
ss->idark_int_time[j] = s->idark_int_time[j];
for (k = -1; k < m->nraw; k++)
ss->idark_data[j][k] = s->idark_data[j][k];
@@ -1724,6 +1756,154 @@ int icoms2munki_err(int se) {
return MUNKI_OK;
}
+/* - - - - - - - - - - - - - - - - */
+/* Measure a display update delay. It is assumed that a */
+/* white to black change has been made to the displayed color, */
+/* and this will measure the time it took for the update to */
+/* be noticed by the instrument, up to 0.6 seconds. */
+/* inst_misread will be returned on failure to find a transition to black. */
+#define NDMXTIME 0.7 /* Maximum time to take */
+#define NDSAMPS 500 /* Debug samples */
+
+typedef struct {
+ double sec;
+ double rgb[3];
+ double tot;
+} i1rgbdsamp;
+
+munki_code munki_imp_meas_delay(
+munki *p,
+int *msecdelay) { /* Return the number of msec */
+ munki_code ev = MUNKI_OK;
+ munkiimp *m = (munkiimp *)p->m;
+ munki_state *s = &m->ms[m->mmode];
+ int i, j, k, mm;
+ double **multimeas; /* Spectral measurements */
+ int nummeas;
+ double rgbw[3] = { 610.0, 520.0, 460.0 };
+ double ucalf = 1.0; /* usec_time calibration factor */
+ double inttime;
+ i1rgbdsamp *samp;
+ double stot, etot, del, thr;
+ double etime;
+ int isdeb;
+
+ /* Read the samples */
+ inttime = m->min_int_time;
+ nummeas = (int)(NDMXTIME/inttime + 0.5);
+ multimeas = dmatrix(0, nummeas-1, -1, m->nwav-1);
+ if ((samp = (i1rgbdsamp *)calloc(sizeof(i1rgbdsamp), nummeas)) == NULL) {
+ a1logd(p->log, 1, "munki_meas_delay: malloc failed\n");
+ return MUNKI_INT_MALLOC;
+ }
+
+//printf("~1 %d samples at %f int\n",nummeas,inttime);
+ if ((ev = munki_read_patches_all(p, multimeas, nummeas, &inttime, 0)) != inst_ok) {
+ free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav-1);
+ free(samp);
+ return ev;
+ }
+
+ /* Convert the samples to RGB */
+ for (i = 0; i < nummeas; i++) {
+ samp[i].sec = i * inttime;
+ samp[i].rgb[0] = samp[i].rgb[1] = samp[i].rgb[2] = 0.0;
+ for (j = 0; j < m->nwav; j++) {
+ double wl = XSPECT_WL(m->wl_short, m->wl_long, m->nwav, j);
+
+//printf("~1 multimeas %d %d = %f\n",i, j, multimeas[i][j]);
+ for (k = 0; k < 3; k++) {
+ double tt = (double)(wl - rgbw[k]);
+ tt = (50.0 - fabs(tt))/50.0;
+ if (tt < 0.0)
+ tt = 0.0;
+ samp[i].rgb[k] += sqrt(tt) * multimeas[i][j];
+ }
+ }
+ samp[i].tot = samp[i].rgb[0] + samp[i].rgb[1] + samp[i].rgb[2];
+ }
+ free_dmatrix(multimeas, 0, nummeas-1, 0, m->nwav-1);
+
+ a1logd(p->log, 3, "munki_measure_refresh: Read %d samples for refresh calibration\n",nummeas);
+
+#ifdef PLOT_UPDELAY
+ /* Plot the raw sensor values */
+ {
+ double xx[NDSAMPS];
+ double y1[NDSAMPS];
+ double y2[NDSAMPS];
+ double y3[NDSAMPS];
+ double y4[NDSAMPS];
+
+ for (i = 0; i < nummeas && i < NDSAMPS; i++) {
+ xx[i] = samp[i].sec;
+ y1[i] = samp[i].rgb[0];
+ y2[i] = samp[i].rgb[1];
+ y3[i] = samp[i].rgb[2];
+ y4[i] = samp[i].tot;
+//printf("%d: %f -> %f\n",i,samp[i].sec, samp[i].tot);
+ }
+ printf("Display update delay measure sensor values and time (sec)\n");
+ do_plot6(xx, y1, y2, y3, y4, NULL, NULL, nummeas);
+ }
+#endif
+
+ /* Over the first 100msec, locate the maximum value */
+ etime = samp[nummeas-1].sec;
+ stot = -1e9;
+ for (i = 0; i < nummeas; i++) {
+ if (samp[i].tot > stot)
+ stot = samp[i].tot;
+ if (samp[i].sec > 0.1)
+ break;
+ }
+
+ /* Over the last 100msec, locate the maximum value */
+ etime = samp[nummeas-1].sec;
+ etot = -1e9;
+ for (i = nummeas-1; i >= 0; i--) {
+ if (samp[i].tot > etot)
+ etot = samp[i].tot;
+ if ((etime - samp[i].sec) > 0.1)
+ break;
+ }
+
+ del = stot - etot;
+ thr = etot + 0.30 * del; /* 30% of transition threshold */
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "munki_meas_delay: start tot %f end tot %f del %f, thr %f\n", stot, etot, del, thr);
+#endif
+
+ /* Check that there has been a transition */
+ if (del < 5.0) {
+ free(samp);
+ a1logd(p->log, 1, "munki_meas_delay: can't detect change from white to black\n");
+ return MUNKI_RD_NOTRANS_FOUND;
+ }
+
+ /* Locate the time at which the values are above the end values */
+ for (i = nummeas-1; i >= 0; i--) {
+ if (samp[i].tot > thr)
+ break;
+ }
+ if (i < 0) /* Assume the update was so fast that we missed it */
+ i = 0;
+
+ a1logd(p->log, 2, "munki_meas_delay: stoped at sample %d time %f\n",i,samp[i].sec);
+
+ *msecdelay = (int)(samp[i].sec * 1000.0 + 0.5);
+
+#ifdef PLOT_UPDELAY
+ a1logd(p->log, 0, "munki_meas_delay: returning %d msec\n",*msecdelay);
+#endif
+ free(samp);
+
+ return MUNKI_OK;
+}
+#undef NDSAMPS
+#undef NDMXTIME
+
/* - - - - - - - - - - - - - - - - */
/* Measure a patch or strip or flash in the current mode. */
@@ -2276,7 +2456,7 @@ munki_code munki_imp_meas_refrate(
tt = (40.0 - fabs(tt))/40.0;
if (tt < 0.0)
tt = 0.0;
- samp[i].rgb[k] += tt * multimeas[i][j];
+ samp[i].rgb[k] += sqrt(tt) * multimeas[i][j];
}
}
}
@@ -3461,7 +3641,8 @@ munki_code munki_dark_measure_2(
free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
#ifdef PLOT_DEBUG
- printf("Average absolute sensor readings, average = %f, darkthresh %f\n",sensavg,darkthresh);
+ a1logd(p->log,4,"dark_measure_2: Avg abs. sensor readings = %f, sh/darkthresh %f\n",sensavg,darkthresh);
+ printf("sens data:\n");
plot_raw(sens);
#endif
@@ -3681,6 +3862,7 @@ munki_code munki_whitemeasure(
a1logd(p->log,3,"Average absolute sensor readings, avg %f, max %f, darkth %f satth %f\n",
sensavg,maxval,darkthresh,trackmax[2]);
#ifdef PLOT_DEBUG
+ printf("absraw whitemeas:\n");
plot_raw(absraw);
#endif
}
@@ -3720,7 +3902,7 @@ munki_code munki_compute_wav_whitemeas(
munki_absraw_to_abswav1(p, 1, &abswav1, &absraw);
#ifdef PLOT_DEBUG
- printf("Converted to wavelengths std res:\n");
+ printf("White meas converted to wavelengths std res:\n");
plot_wav1(m, abswav1);
#endif
}
@@ -3810,7 +3992,7 @@ munki_code munki_ledtemp_whitemeasure(
*reftemp = 0.5 * (ledtemp[0] + ledtemp[nummeas-1]);
#ifdef PLOT_DEBUG
- printf("Dark data:\n");
+ printf("Ledtemp Dark data:\n");
plot_raw(s->dark_data);
#endif
@@ -3961,8 +4143,7 @@ munki_code munki_ledtemp_comp(
return MUNKI_OK;
}
-/* Take a measurement reading using the current mode, part 1 */
-/* Converts to completely processed output readings. */
+/* Trigger measure and gather raw readings using the current mode. */
munki_code munki_read_patches_1(
munki *p,
int ninvmeas, /* Number of extra invalid measurements at start */
@@ -3972,7 +4153,7 @@ munki_code munki_read_patches_1(
int gainmode, /* Gain mode to use, 0 = normal, 1 = high */
int *nmeasuered, /* Number actually measured (excluding ninvmeas) */
unsigned char *buf, /* Raw USB reading buffer */
- unsigned int bsize
+ unsigned int bsize /* Raw USB readings buffer size in bytes */
) {
munki_code ev = MUNKI_OK;
munkiimp *m = (munkiimp *)p->m;
@@ -4002,8 +4183,8 @@ munki_code munki_read_patches_1(
return ev;
}
-/* Take a measurement reading using the current mode, part 2 */
-/* Converts to completely processed output readings. */
+/* Given a buffer full of raw USB values, process them into */
+/* completely processed spectral output patch readings. */
munki_code munki_read_patches_2(
munki *p,
double *duration, /* Return flash duration in seconds */
@@ -4014,7 +4195,7 @@ munki_code munki_read_patches_2(
int ninvmeas, /* Number of extra invalid measurements at start */
int nummeas, /* Number of actual measurements */
unsigned char *buf, /* Raw USB reading buffer */
- unsigned int bsize
+ unsigned int bsize /* Raw USB reading buffer size */
) {
munki_code ev = MUNKI_OK;
munkiimp *m = (munkiimp *)p->m;
@@ -4049,32 +4230,6 @@ munki_code munki_read_patches_2(
munki_sub_raw_to_absraw(p, nummeas, inttime, gainmode, multimes, s->dark_data,
&darkthresh, 1, NULL);
-#ifdef PLOT_TEMPCOMP
- /* Plot the raw spectra, 6 at a time */
- if (s->reflective) {
- int i, j, k;
- double *indx;
- double **mod;
- indx = dvectorz(0, nummeas-1);
- mod = dmatrix(0, 5, 0, nummeas-1);
- for (i = 0; i < nummeas; i++)
- indx[i] = (double)i;
-
-// for (j = 0; (j+5) < m->nraw; j += 6) {
- for (j = 50; (j+5) < 56; j += 6) {
- for (i = 0; i < nummeas; i++) {
- for (k = j; k < (j + 6); k++) {
- mod[k-j][i] = multimes[i][k];
- }
- }
-
- printf("Before temp comp, bands %d - %d\n",j, j+5);
- do_plot6(indx, mod[0], mod[1], mod[2], mod[3], mod[4], mod[5], nummeas);
- }
- free_dvector(indx, 0, nummeas-1);
- free_dmatrix(mod, 0, 5, 0, nummeas-1);
- }
-#endif
#ifdef DUMP_SCANV
/* Dump raw scan readings to a file "mkdump.txt" */
{
@@ -4097,8 +4252,38 @@ munki_code munki_read_patches_2(
#endif
#ifdef ENABLE_LEDTEMPC
+
+
/* Do LED temperature compensation of absraw values */
if (s->reflective) {
+
+#ifdef PLOT_TEMPCOMP
+ /* Plot the raw spectra, 6 at a time */
+ {
+ int i, j, k;
+ double *indx;
+ double **mod;
+ indx = dvectorz(0, nummeas-1);
+ mod = dmatrix(0, 5, 0, nummeas-1);
+ for (i = 0; i < nummeas; i++)
+ indx[i] = (double)i;
+
+// for (j = 0; (j+5) < m->nraw; j += 6) {
+ for (j = 50; (j+5) < 56; j += 6) {
+ for (i = 0; i < nummeas; i++) {
+ for (k = j; k < (j + 6); k++) {
+ mod[k-j][i] = multimes[i][k];
+ }
+ }
+
+ printf("Before temp comp, bands %d - %d\n",j, j+5);
+ do_plot6(indx, mod[0], mod[1], mod[2], mod[3], mod[4], mod[5], nummeas);
+ }
+ free_dvector(indx, 0, nummeas-1);
+ free_dmatrix(mod, 0, 5, 0, nummeas-1);
+ }
+#endif
+ /* Do the LED temperature compensation */
if ((ev = munki_ledtemp_comp(p, multimes, ledtemp, nummeas, s->reftemp, s->iwhite_data))
!= MUNKI_OK) {
free_dvector(ledtemp, 0, nummeas-1);
@@ -4177,7 +4362,7 @@ munki_code munki_read_patches_2(
/* Recognise the required number of ref/trans patch locations, */
/* and average the measurements within each patch. */
if ((ev = munki_extract_patches_multimeas(p, &rv, absraw, numpatches, multimes,
- nummeas, inttime)) != MUNKI_OK) {
+ nummeas, inttime)) != MUNKI_OK) {
free_dvector(ledtemp, 0, nummeas-1);
free_dmatrix(multimes, 0, nummeas-1, -1, m->nraw-1);
free_dmatrix(absraw, 0, numpatches-1, -1, m->nraw-1);
@@ -4195,6 +4380,52 @@ munki_code munki_read_patches_2(
return MUNKI_RD_READINCONS;
}
+#ifdef ENABLE_REFSTRAYC /* Enable Reflective stray light compensation */
+ if (s->reflective) {
+ int i, j;
+# if defined(PLOT_DEBUG) || defined(DUMP_BKLED)
+ double xx[140];
+ double yy[3][140];
+# endif
+
+ double fact = REFSTRAYC_FACTOR; /* Slightly conservative */
+
+ for (i = 0; i < numpatches; i++) {
+
+ for (j = 0; j < m->nraw; j++) {
+# if defined(PLOT_DEBUG) || defined(DUMP_BKLED)
+ yy[0][j] = absraw[i][j];
+# endif
+ absraw[i][j] -= fact * s->white_data[j];
+# if defined(PLOT_DEBUG) || defined(DUMP_BKLED)
+ xx[j] = j;
+ yy[1][j] = fact * s->white_data[j];
+ yy[2][j] = absraw[i][j];
+# endif
+ }
+# ifdef PLOT_DEBUG
+ printf("Before/After subtracting stray ref. light %d:\n",i);
+ do_plot6(xx, yy[0], yy[1], yy[2], NULL, NULL, NULL, m->nraw);
+# endif
+# ifdef DUMP_BKLED /* Save REFSTRAYC & REFLEDNOISE comp plot to "refbk1.txt" & "refbk2.txt" */
+ {
+ xspect sp[3];
+ for (i = 0; i < 3; i++) {
+ sp[i].spec_n = 128;
+ sp[i].spec_wl_short = 0.0;
+ sp[i].spec_wl_long = 127.0;
+ sp[i].norm = 1.0;
+ for (j = 0; j < 128; j++)
+ sp[i].spec[j] = yy[i][j];
+ }
+ write_nxspect("refbk2.txt", sp, 3, 0);
+# pragma message("######### munki DUMP_BKLED enabled! ########")
+ }
+# endif /* DUMP_BKLED */
+ }
+ }
+#endif /* ENABLE_REFSTRAYC */
+
/* Convert an absraw array from raw wavelengths to output wavelenths */
munki_absraw_to_abswav(p, numpatches, specrd, absraw);
free_dmatrix(absraw, 0, numpatches-1, -1, m->nraw-1);
@@ -4243,9 +4474,11 @@ munki_code munki_read_patches_2(
return ev;
}
-/* Take a measurement reading using the current mode, part 2a */
-/* Converts to completely processed output readings, */
+/* Given a buffer full of raw USB values, process them into */
+/* completely processed spectral output readings, */
/* but don't average together or extract patches or flash. */
+/* This is used for delay & refresh rate measurement. */
+/* !! Doesn't do LED temperature compensation for reflective !! */
/* (! Note that we aren't currently detecting saturation here!) */
munki_code munki_read_patches_2a(
munki *p,
@@ -4309,7 +4542,8 @@ munki_code munki_read_patches_2a(
/* Take a measurement reading using the current mode (combined parts 1 & 2a) */
/* Converts to completely processed output readings, without averaging or extracting */
-/* sample patches. */
+/* sample patches, for emissive measurement mode. */
+/* This is used for delay & refresh rate measurement. */
munki_code munki_read_patches_all(
munki *p,
double **specrd, /* Return array [numpatches][nwav] of spectral reading values */
@@ -4535,7 +4769,7 @@ munki_code munki_sens_to_raw(
int ninvalid, /* Number of initial invalid readings to skip */
int nummeas, /* Number of readings measured */
double satthresh, /* Saturation threshold to trigger error in raw units (if > 0.0) */
- double *pdarkthresh /* Return a dark threshold value */
+ double *pdarkthresh /* Return a dark threshold value = sheilded cell values */
) {
munkiimp *m = (munkiimp *)p->m;
int i, j, k;
@@ -4551,11 +4785,6 @@ munki_code munki_sens_to_raw(
return MUNKI_INT_ASSERT;
}
- if (ninvalid >= nummeas) {
- a1logw(p->log,"ninvalid %d is >= nummeas %d!\n",ninvalid,nummeas);
- return MUNKI_INT_ASSERT;
- }
-
if (ninvalid > 0)
a1logd(p->log, 4, "munki_sens_to_raw: Skipping %d invalid readings\n",ninvalid);
@@ -4624,12 +4853,13 @@ void munki_sub_raw_to_absraw(
double inttime, /* Integration time used */
int gainmode, /* Gain mode, 0 = normal, 1 = high */
double **absraw, /* Source/Desination array [-1 nraw] */
- double *sub, /* Value to subtract [-1 nraw] */
+ double *sub, /* Value to subtract [-1 nraw] (ie. cal dark data) */
double *trackmax, /* absraw values that should be offset the same as max */
int ntrackmax, /* Number of trackmax values */
double *maxv /* If not NULL, return the maximum value */
) {
munkiimp *m = (munkiimp *)p->m;
+ munki_state *s = &m->ms[m->mmode];
int npoly; /* Number of linearisation coefficients */
double *polys; /* the coeficients */
double scale; /* Absolute scale value */
@@ -4639,6 +4869,11 @@ void munki_sub_raw_to_absraw(
double rawmax, maxval = -1e38;
double maxzero = 0.0;
int i, j, k;
+
+ /* Heusristic correction for LED interference bump for 0.018 secs int_time */
+ int pos[] = { 0, 20, 56, 62, 75, 127 };
+// double off[] = { 0.7, 0.0, 0.6, -0.9, -1.2, -0.7 };
+ double off[] = { 0.7, 0.0, 0.6, -0.9, -0.8, -0.5 };
if (gainmode) { /* High gain */
npoly = m->nlin1; /* Encodes gain too */
@@ -4681,18 +4916,129 @@ void munki_sub_raw_to_absraw(
a1logd(p->log,4,"Black shielded value = %f, Reading shielded value = %f\n",sub[-1], avgscell);
- /* Compute the adjusted black */
- for (j = 0; j < m->nraw; j++) {
-#ifdef NEVER
- /* simple additive correction */
-# pragma message("######### munki Simple shielded cell temperature correction! ########")
- asub[j] = sub[j] + avgscell - sub[-1];
+ /* Compute the adjusted black for each band */
+ if (s->reflective) {
+
+ /* It seems that having the LED on shifts the shielded cell values */
+ /* by about 2.5, and this stuffs up the reflective measurement. */
+ /* This seems to be from the LED PWM driver, which perhaps */
+ /* is synchronous to the sensor clock, and so switches */
+ /* at a certain point in the transfer of data from the sensor. */
+ /* The result is a step up from 0-60, and then down from 61-128. */
+ /* Perhaps altering the LED PWM setting and seeing if this point */
+ /* shifts would be a way of confirming this ? */
+ /* There is also some stray light reflected into the sensor */
+ /* from the LED, but due to the LED step, the sensor reading is */
+ /* less than the dark data at some wavelengths. */
+ /* The details of the LED step seem to be integration time dependent, */
+ /* but decresing the scanning rate therebye increasing integration */
+ /* time and light level reduces the impact of this error. */
+
+ /* Since we do an on the fly black measurement before each */
+ /* reflective measurement, ignoring the shielded cell values */
+ /* shouldn't affect accuracy so much. */
+
+#ifdef ENABLE_REFLEDINTER
+ /* A heuristic to correct for the LED noise. */
+ /* This is only valid for int_time of 0.0182 secs, */
+ /* and it's not clear how well it works across different */
+ /* temperatures or examples of the ColorMunki. */
+ /* in another revision ?? */
+ for (j = 0; j < m->nraw; j++) {
+ int ix;
+ double bl, val;
+
+ for (ix = 0; ; ix++) {
+ if (j >= pos[ix] && j <= pos[ix+1])
+ break;
+ }
+ bl = (j - pos[ix])/((double)pos[ix+1] - pos[ix]);
+ val = (1.0 - bl) * off[ix] + bl * off[ix+1];
+ asub[j] = sub[j] + val;
+ }
+#else
+ for (j = 0; j < m->nraw; j++)
+ asub[j] = sub[j]; /* Just use the calibration dark data */
+#endif
+
+ } else {
+ /* No LED on operation - use sheilded cell values */
+ for (j = 0; j < m->nraw; j++) {
+#ifdef ENABLE_BKDRIFTC
+
+# ifdef HEURISTIC_BKDRIFTC
+ /* heuristic scaled correction */
+ asub[j] = zero - (zero - sub[j]) * (zero - avgscell)/(zero - sub[-1]);
+# else
+ /* simple additive correction */
+# pragma message("######### munki Simple shielded cell temperature correction! ########")
+ asub[j] = sub[j] + (avgscell - sub[-1]);
+# endif
#else
- /* heuristic scaled correction */
- asub[j] = zero - (zero - sub[j]) * (zero - avgscell)/(zero - sub[-1]);
+# pragma message("######### munki No shielded cell temperature correction! ########")
+ asub[j] = sub[j]; /* Just use the calibration dark data */
#endif
+ }
}
-
+
+#if defined(PLOT_DEBUG) || defined(DUMP_BKLED)
+ {
+ double xx[130];
+ double yy[3][130];
+
+ for (j = -1; j < m->nraw+1; j++)
+ yy[0][j+1] = 0.0;
+
+ for (i = 0; i < nummeas; i++) {
+ for (j = -1; j < m->nraw; j++)
+ yy[0][j+1] += absraw[i][j];
+ }
+ for (j = -1; j < m->nraw; j++)
+ yy[0][j+1] /= (double)nummeas;
+
+ for (j = -1; j < m->nraw; j++)
+ yy[1][j+1]= sub[j];
+
+ /* Show what ENABLE_REFLEDINTER would do */
+ for (j = 0; j < m->nraw; j++) {
+ int ix;
+ double bl, val;
+
+ for (ix = 0; ; ix++) {
+ if (j >= pos[ix] && j <= pos[ix+1])
+ break;
+ }
+ bl = (j - pos[ix])/((double)pos[ix+1] - pos[ix]);
+ val = (1.0 - bl) * off[ix] + bl * off[ix+1];
+ yy[2][j+1] = yy[0][j+1] - val;
+ }
+ yy[2][0] = yy[0][0];
+
+ for (j = -1; j < m->nraw; j++)
+ xx[j+1] = (double)j;
+
+ xx[0]= -10.0;
+
+# ifdef PLOT_DEBUG
+ printf("sub_raw_to_absraw %d samp avg - dark ref:\n",nummeas);
+ do_plot(xx, yy[0], yy[1], yy[2], 129);
+# endif
+# ifdef DUMP_BKLED
+ {
+ xspect sp[3];
+ for (i = 0; i < 3; i++) {
+ sp[i].spec_n = 128;
+ sp[i].spec_wl_short = 0.0;
+ sp[i].spec_wl_long = 127.0;
+ sp[i].norm = 1.0;
+ for (j = 0; j < 128; j++)
+ sp[i].spec[j] = yy[i][j+1];
+ }
+ write_nxspect("refbk1.txt", sp, 3, 0);
+ }
+# endif /* DUMP_BKLED */
+ }
+#endif /* PLOT_DEBUG || DUMP_BKLED */
/* For each measurement */
for (i = 0; i < nummeas; i++) {
@@ -4701,6 +5047,7 @@ void munki_sub_raw_to_absraw(
for (j = 0; j < m->nraw; j++) {
rval = absraw[i][j];
+
sval = rval - asub[j]; /* Make zero based */
#ifdef ENABLE_NONLINCOR
@@ -4825,7 +5172,7 @@ int munki_average_multimeas(
#define BH 105 /* End */
#define BW 5 /* Width */
-/* Record of possible patch */
+/* Record of possible patch within a reading buffer */
typedef struct {
int ss; /* Start sample index */
int no; /* Number of samples */
@@ -4866,7 +5213,7 @@ munki_code munki_extract_patches_multimeas(
double white_avg; /* Average of (aproximate) white data */
int rv = 0;
double patch_cons_thr = PATCH_CONS_THR * m->scan_toll_ratio;
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
double **plot;
#endif
@@ -4888,7 +5235,7 @@ munki_code munki_extract_patches_multimeas(
maxval[j] = 1.0;
}
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
/* Plot out 6 lots of 6 values each */
plot = dmatrixz(0, 6, 0, nummeas-1);
// for (j = 1; j < (m->nraw-6); j += 6) /* Plot all the bands */
@@ -4906,6 +5253,16 @@ munki_code munki_extract_patches_multimeas(
}
#endif
+#ifdef NEVER
+ /* Plot the shielded cell value */
+ for (i = 0; i < nummeas; i++) {
+ plot[0][i] = multimeas[i][-1];
+ plot[6][i] = (double)i;
+ }
+ printf("Sheilded values\n");
+ do_plot6(plot[6], plot[0], NULL, NULL, NULL, NULL, NULL, nummeas);
+#endif
+
sslope = dmatrixz(0, nummeas-1, -1, m->nraw-1);
slope = dvectorz(0, nummeas-1);
fslope = dvectorz(0, nummeas-1);
@@ -5144,7 +5501,7 @@ munki_code munki_extract_patches_multimeas(
}
#endif
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
printf("Slope filter output\n");
for (i = 0; i < nummeas; i++) {
int jj;
@@ -5196,7 +5553,8 @@ munki_code munki_extract_patches_multimeas(
}
a1logd(p->log,7,"Number of patches = %d\n",npat);
- /* We don't count the first and last patches, as we assume they are white leader */
+ /* We don't count the first and last patches, as we assume they are white leader. */
+ /* (They are marked !use in list anyway) */
if (npat < (tnpatch + 2)) {
free_ivector(sizepop, 0, nummeas-1);
free_dvector(slope, 0, nummeas-1);
@@ -5214,7 +5572,7 @@ munki_code munki_extract_patches_multimeas(
}
avglegth /= (double)npat;
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
for (i = 0; i < npat; i++) {
printf("Raw patch %d, start %d, length %d\n",i, pat[i].ss, pat[i].no);
}
@@ -5227,7 +5585,7 @@ munki_code munki_extract_patches_multimeas(
/* Locate the median potential patch width */
for (j = 0, i = 0; i < nummeas; i++) {
j += sizepop[i];
- if (j >= ((npat-2)/2))
+ if (j > ((npat-2)/2))
break;
}
median = (double)i;
@@ -5308,7 +5666,7 @@ munki_code munki_extract_patches_multimeas(
return MUNKI_RD_NOTENOUGHPATCHES;
}
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
printf("Got %d patches out of potentional %d:\n",tnpatch, npat);
printf("Average patch legth %f\n",avglegth);
for (i = 1; i < (npat-1); i++) {
@@ -5325,15 +5683,15 @@ munki_code munki_extract_patches_multimeas(
if (pat[k].use == 0)
continue;
-
nno = (pat[k].no * 3)/4;
+// nno = (pat[k].no * 2)/3; // experimental tighter trim
trim = (pat[k].no - nno)/2;
pat[k].ss += trim;
pat[k].no = nno;
}
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
printf("After trimming got:\n");
for (i = 1; i < (npat-1); i++) {
if (pat[i].use == 0)
@@ -5351,7 +5709,8 @@ munki_code munki_extract_patches_multimeas(
slope[i] = 0.0;
}
- printf("Trimmed output:\n");
+ printf("Trimmed output - averaged bands:\n");
+ /* Plot box averaged bands */
for (i = 0; i < nummeas; i++) {
int jj;
for (jj = 0, j = BL; jj < 6 && j < BH; jj++, j += ((BH-BL)/6)) {
@@ -5364,8 +5723,27 @@ munki_code munki_extract_patches_multimeas(
for (i = 0; i < nummeas; i++)
plot[6][i] = (double)i;
do_plot6(plot[6], slope, plot[0], plot[1], plot[2], plot[3], plot[4], nummeas);
+
+#ifdef NEVER
+ /* Plot all the bands */
+ printf("Trimmed output - all bands:\n");
+ for (j = 0; j < (m->nraw-5); j += 5) {
+ for (k = 0; k < 5; k ++) {
+ for (i = 0; i < nummeas; i++) {
+ plot[k][i] = multimeas[i][j+k]/maxval[j+k];
+ }
+ }
+ for (i = 0; i < nummeas; i++)
+ plot[6][i] = (double)i;
+ printf("Bands %d - %d\n",j,j+5);
+ do_plot6(plot[6], slope, plot[0], plot[1], plot[2], plot[3], plot[4], nummeas);
+ }
+#endif
+
#endif
+ /* Now compute averaged patch values */
+
/* Compute average of (aproximate) white */
white_avg = 0.0;
for (j = 1; j < (m->nraw-1); j++)
@@ -5429,14 +5807,14 @@ munki_code munki_extract_patches_multimeas(
if (flags != NULL)
*flags = rv;
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
free_dmatrix(plot, 0, 6, 0, nummeas-1);
#endif
free_dvector(slope, 0, nummeas-1);
free_ivector(sizepop, 0, nummeas-1);
free_dvector(maxval, -1, m->nraw-1);
- free(pat);
+ free(pat); /* Otherwise caller will have to do it */
a1logd(p->log,3,"munki_extract_patches_multimeas done, sat = %s, inconsist = %s\n",
rv & 2 ? "true" : "false", rv & 1 ? "true" : "false");
@@ -5475,7 +5853,7 @@ munki_code munki_extract_patches_flash(
double *aavg; /* ambient average [-1 nraw] */
double finttime; /* Flash integration time */
int rv = 0;
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
double **plot;
#endif
@@ -5511,7 +5889,7 @@ munki_code munki_extract_patches_flash(
thresh = (3.0 * mean + maxval)/4.0;
a1logd(p->log,7,"munki_extract_patches_flash band %d minval %f maxval %f, mean = %f, thresh = %f\n",maxband,minval,maxval,mean, thresh);
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
/* Plot out 6 lots of 6 values each */
plot = dmatrixz(0, 6, 0, nummeas-1);
for (j = maxband -3; j>= 0 && j < (m->nraw-6); j += 100) /* Do one set around max */
@@ -5529,7 +5907,7 @@ munki_code munki_extract_patches_flash(
free_dmatrix(plot,0,6,0,nummeas-1);
#endif
-#ifdef PATREC_DEBUG
+#ifdef PLOT_PATREC
/* Plot just the pulses */
{
int start, end;
@@ -5841,8 +6219,11 @@ void munki_scale_specrd(
#ifdef HIGH_RES
/* High res congiguration */
-#undef EXISTING_SHAPE /* Else generate filter shape */
-#undef USE_GAUSSIAN /* Use gaussian filter shape, else lanczos2 */
+#undef EXISTING_SHAPE /* [und] Else generate filter shape */
+#define USE_GAUSSIAN /* [def] Use gaussian filter shape, else lanczos2 */
+
+#define DO_CCDNORM /* [def] Normalise CCD values to original */
+#define DO_CCDNORMAVG /* [unde] Normalise averages rather than per CCD bin */
#ifdef NEVER
/* Plot the matrix coefficients */
@@ -5940,7 +6321,8 @@ static double lanczos2(double wi, double x) {
/* gausian */
wi = wi/(2.0 * sqrt(2.0 * log(2.0))); /* Convert width at half max to std. dev. */
x = x/(sqrt(2.0) * wi);
- y = 1.0/(wi * sqrt(2.0 * DBL_PI)) * exp(-(x * x));
+// y = 1.0/(wi * sqrt(2.0 * DBL_PI)) * exp(-(x * x)); /* Unity area */
+ y = exp(-(x * x)); /* Center at 1.0 */
#else
/* lanczos2 */
@@ -5964,6 +6346,10 @@ static int gcc_bug_fix(int i) {
}
#endif /* APPLE */
+#ifdef SALONEINSTLIB
+# define ONEDSTRAYLIGHTUS
+#endif
+
/* Create high resolution mode references, */
/* Create Reflective if ref nz, else create Emissive */
/* We expect this to be called twice, once for each. */
@@ -5982,6 +6368,8 @@ munki_code munki_create_hr(munki *p, int ref) {
int *mtx_index1, **pmtx_index2, *mtx_index2;
int *mtx_nocoef1, **pmtx_nocoef2, *mtx_nocoef2;
double *mtx_coef1, **pmtx_coef2, *mtx_coef2;
+
+ double min_wl = ref ? WL_REF_MIN : WL_EMIS_MIN;
/* Start with nominal values. May alter these if filters are not unique */
nwav1 = m->nwav1;
@@ -5993,7 +6381,8 @@ munki_code munki_create_hr(munki *p, int ref) {
mtx_index1 = m->rmtx_index1;
mtx_nocoef1 = m->rmtx_nocoef1;
mtx_coef1 = m->rmtx_coef1;
- mtx_index2 = mtx_nocoef2 = NULL;
+ mtx_index2 = NULL;
+ mtx_nocoef2 = NULL;
mtx_coef2 = NULL;
pmtx_index2 = &m->rmtx_index2;
pmtx_nocoef2 = &m->rmtx_nocoef2;
@@ -6002,7 +6391,8 @@ munki_code munki_create_hr(munki *p, int ref) {
mtx_index1 = m->emtx_index1;
mtx_nocoef1 = m->emtx_nocoef1;
mtx_coef1 = m->emtx_coef1;
- mtx_index2 = mtx_nocoef2 = NULL;
+ mtx_index2 = NULL;
+ mtx_nocoef2 = NULL;
mtx_coef2 = NULL;
pmtx_index2 = &m->emtx_index2;
pmtx_nocoef2 = &m->emtx_nocoef2;
@@ -6020,7 +6410,7 @@ munki_code munki_create_hr(munki *p, int ref) {
/* For each matrix value */
sx = mtx_index1[j]; /* Starting index */
- if (jj == 0 && (j+1) < m->nwav1 && sx == mtx_index1[j+1]) { /* Same index */
+ if (j < (m->nwav1-1) && sx == mtx_index1[j+1]) { /* Skip duplicates + last */
// printf("~1 skipping %d\n",j);
wl_short1 += wl_step1;
nwav1--;
@@ -6076,6 +6466,7 @@ munki_code munki_create_hr(munki *p, int ref) {
/* Compute the crossover points between each filter */
for (i = 0; i < (nwav1-1); i++) {
double den, y1, y2, y3, y4, yn, xn; /* Location of intersection */
+ double eps = 1e-6; /* Numerical tollerance */
double besty = -1e6;
/* between filter i and i+1, we want to find the two */
@@ -6085,13 +6476,8 @@ munki_code munki_create_hr(munki *p, int ref) {
for (j = 0; j < (mtx_nocoef1[i]-1); j++) {
for (k = 0; k < (mtx_nocoef1[i+1]-1); k++) {
if (coeff[i][j].ix == coeff[i+1][k].ix
- && coeff[i][j+1].ix == coeff[i+1][k+1].ix
- && coeff[i][j].we > 0.0 && coeff[i][j+1].we > 0.0
- && coeff[i+1][k].we > 0.0 && coeff[i+1][k+1].we > 0.0
- && (( coeff[i][j].we >= coeff[i+1][k].we
- && coeff[i][j+1].we <= coeff[i+1][k+1].we)
- || ( coeff[i][j].we <= coeff[i+1][k].we
- && coeff[i][j+1].we >= coeff[i+1][k+1].we))) {
+ && coeff[i][j+1].ix == coeff[i+1][k+1].ix) {
+
// a1logd(p->log,3,"got it at %d, %d: %d = %d, %d = %d\n",j,k, coeff[i][j].ix, coeff[i+1][k].ix, coeff[i][j+1].ix, coeff[i+1][k+1].ix);
/* Compute the intersection of the two line segments */
@@ -6099,17 +6485,22 @@ munki_code munki_create_hr(munki *p, int ref) {
y2 = coeff[i][j+1].we;
y3 = coeff[i+1][k].we;
y4 = coeff[i+1][k+1].we;
+// a1logd(p->log,3,"y1 %f, y2 %f, y3 %f, y4 %f\n",y1, y2, y3, y4);
den = -y4 + y3 + y2 - y1;
+ if (fabs(den) < eps)
+ continue;
yn = (y2 * y3 - y1 * y4)/den;
xn = (y3 - y1)/den;
+ if (xn < -eps || xn > (1.0 + eps))
+ continue;
// a1logd(p->log,3,"den = %f, yn = %f, xn = %f\n",den,yn,xn);
-// a1logd(p->log,3,"Intersection %d: wav %f, raw %f, wei %f\n",i+1,xp[i+1].wav,xp[i+1].raw,xp[i+1].wei);
if (yn > besty) {
xp[i+1].wav = XSPECT_WL(wl_short1, wl_long1, nwav1, i + 0.5);
xp[i+1].raw = (1.0 - xn) * coeff[i][j].ix + xn * coeff[i][j+1].ix;
xp[i+1].wei = yn;
besty = yn;
-// a1logd(p->log,3,"Found new best y\n");
+// a1logd(p->log,3,"Intersection %d: wav %f, raw %f, wei %f\n",i+1,xp[i+1].wav,xp[i+1].raw,xp[i+1].wei);
+// a1logd(p->log,3,"Found new best y %f\n",yn);
}
// a1logd(p->log,3,"\n");
}
@@ -6151,7 +6542,7 @@ munki_code munki_create_hr(munki *p, int ref) {
}
}
if (j >= mtx_nocoef1[0]) { /* Assert */
- a1logw(p->log,"munki: failed to end crossover\n");
+ a1logw(p->log,"munki: failed to find end crossover\n");
return MUNKI_INT_ASSERT;
}
den = -y4 + y3 + y2 - y1;
@@ -6189,7 +6580,7 @@ munki_code munki_create_hr(munki *p, int ref) {
}
}
if (j >= mtx_nocoef1[nwav1-1]) { /* Assert */
- a1logw(p->log, "munki: failed to end crossover\n");
+ a1logw(p->log, "munki: failed to find end crossover\n");
return MUNKI_INT_ASSERT;
}
den = -y4 + y3 + y2 - y1;
@@ -6397,14 +6788,15 @@ munki_code munki_create_hr(munki *p, int ref) {
{
double fshmax; /* filter shape max wavelength from center */
+#define MXNOWL 500 /* Max hires bands */
#define MXNOFC 64
- munki_fc coeff2[500][MXNOFC]; /* New filter cooefficients */
+ munki_fc coeff2[MXNOWL][MXNOFC]; /* New filter cooefficients */
double twidth;
/* Construct a set of filters that uses more CCD values */
twidth = HIGHRES_WIDTH;
- if (m->nwav2 > 500) { /* Assert */
+ if (m->nwav2 > MXNOWL) { /* Assert */
a1logw(p->log,"High res filter has too many bands\n");
return MUNKI_INT_ASSERT;
}
@@ -6474,7 +6866,7 @@ munki_code munki_create_hr(munki *p, int ref) {
raw2wav->interp(raw2wav, &pp);
w2 = pp.v[0];
-// a1logd(p->log,1,"CCD %d, wl %f\n",i,wl);
+ a1logd(p->log,1,"CCD %d, wl %f - %f\n",i,w1,w2);
/* For each filter */
for (j = 0; j < m->nwav2; j++) {
@@ -6482,6 +6874,10 @@ munki_code munki_create_hr(munki *p, int ref) {
double we;
cwl = m->wl_short2 + (double)j * (m->wl_long2 - m->wl_short2)/(m->nwav2-1.0);
+
+ if (cwl < min_wl) /* Duplicate below this wl */
+ cwl = min_wl;
+
rwl = wl - cwl; /* relative wavelgth to filter */
if (fabs(w1 - cwl) > fshmax && fabs(w2 - cwl) > fshmax)
@@ -6492,8 +6888,12 @@ munki_code munki_create_hr(munki *p, int ref) {
{
int nn;
double lw, ll;
-
- nn = (int)(fabs(w2 - w1)/0.05 + 0.5);
+#ifdef FAST_HIGH_RES_SETUP
+# define FINC 0.2
+#else
+# define FINC 0.05
+#endif
+ nn = (int)(fabs(w2 - w1)/FINC + 0.5);
lw = w1;
#ifdef EXISTING_SHAPE
@@ -6538,7 +6938,21 @@ munki_code munki_create_hr(munki *p, int ref) {
coeff2[j][mtx_nocoef2[j]].ix = i;
coeff2[j][mtx_nocoef2[j]++].we = we;
-// a1logd(p->log,1,"filter %d, cwl %f, rwl %f, ix %d, we %f\n",j,cwl,rwl,i,we);
+ a1logd(p->log,1,"filter %d, cwl %f, rwl %f, ix %d, we %f\n",j,cwl,rwl,i,we);
+ }
+ }
+
+ /* Dump the filter coefficients */
+ if (p->log->debug >= 1) {
+
+ /* For each output wavelength */
+ for (j = 0; j < m->nwav2; j++) {
+
+ a1logd(p->log,1,"filter %d, cwl %f\n",j,XSPECT_WL(m->wl_short2, m->wl_long2, m->nwav2, j));
+ /* For each matrix value */
+ for (k = 0; k < mtx_nocoef2[j]; k++) {
+ a1logd(p->log,1," CCD %d, we %f\n",coeff2[j][k].ix,coeff2[j][k].we);
+ }
}
}
@@ -6575,89 +6989,230 @@ munki_code munki_create_hr(munki *p, int ref) {
}
#endif /* HIGH_RES_PLOT */
+ /* Convert into runtime format */
+ {
+ int xcount;
+
+ if ((*pmtx_index2 = mtx_index2 = (int *)calloc(m->nwav2, sizeof(int))) == NULL) {
+ a1logd(p->log,1,"munki: malloc mtx_index2 failed!\n");
+ return MUNKI_INT_MALLOC;
+ }
+
+ xcount = 0;
+ for (j = 0; j < m->nwav2; j++) {
+ mtx_index2[j] = coeff2[j][0].ix;
+ xcount += mtx_nocoef2[j];
+ }
+
+ if ((*pmtx_coef2 = mtx_coef2 = (double *)calloc(xcount, sizeof(double))) == NULL) {
+ a1logd(p->log,1,"munki: malloc mtx_coef2 failed!\n");
+ return MUNKI_INT_MALLOC;
+ }
+
+ for (i = j = 0; j < m->nwav2; j++)
+ for (k = 0; k < mtx_nocoef2[j]; k++, i++)
+ mtx_coef2[i] = coeff2[j][k].we;
+ }
+
/* Normalise the filters area in CCD space, while maintaining the */
/* total contribution of each CCD at the target too. */
+ /* Hmm. This will wreck super-sample. We should fix it */
+#ifdef DO_CCDNORM /* Normalise CCD values to original */
{
- int ii;
- double tot = 0.0;
- double ccdweight[NSEN_MAX], avgw; /* Weighting determined by cell widths */
- double ccdsum[NSEN_MAX];
+ double x[4], y[4];
+ double avg[2], max[2];
+ double ccdsum[2][128]; /* Target weight/actual for each CCD */
+ double dth[2];
+
+ avg[0] = avg[1] = 0.0;
+ max[0] = max[1] = 0.0;
+ for (j = 0; j < 128; j++) {
+ ccdsum[0][j] = 0.0;
+ ccdsum[1][j] = 0.0;
+ }
- /* Normalize the overall filter weightings */
- for (j = 0; j < m->nwav2; j++)
- for (k = 0; k < mtx_nocoef2[j]; k++)
- tot += coeff2[j][k].we;
- tot /= (double)m->nwav2;
- for (j = 0; j < m->nwav2; j++)
- for (k = 0; k < mtx_nocoef2[j]; k++)
- coeff2[j][k].we /= tot;
+ /* Compute the weighting of each CCD value in the normal output */
+ for (cx = j = 0; j < m->nwav1; j++) { /* For each wavelength */
- /* Determine the relative weights for each CCD */
- avgw = 0.0;
- for (i = 0; i < m->nraw; i++) {
- co pp;
+ /* For each matrix value */
+ sx = mtx_index1[j]; /* Starting index */
+ if (j < (m->nwav1-2) && sx == mtx_index1[j+1]) {
+ cx += mtx_nocoef1[j];
+ continue; /* Skip all duplicate filters */
+ }
+ for (k = 0; k < mtx_nocoef1[j]; k++, cx++, sx++) {
+ ccdsum[0][sx] += mtx_coef1[cx];
+//printf("~1 Norm CCD [%d] %f += [%d] %f\n",sx,ccdsum[0][sx],cx, mtx_coef1[cx]);
+ }
+ }
- pp.p[0] = i - 0.5;
- raw2wav->interp(raw2wav, &pp);
- ccdweight[i] = pp.v[0];
+ /* Compute the weighting of each CCD value in the hires output */
+ for (cx = j = 0; j < m->nwav2; j++) { /* For each wavelength */
- pp.p[0] = i + 0.5;
- raw2wav->interp(raw2wav, &pp);
- ccdweight[i] = fabs(ccdweight[i] - pp.v[0]);
- avgw += ccdweight[i];
+ /* For each matrix value */
+ sx = mtx_index2[j]; /* Starting index */
+ if (j < (m->nwav2-2) && sx == mtx_index2[j+1]) {
+ cx += mtx_nocoef2[j];
+ continue; /* Skip all duplicate filters */
+ }
+ for (k = 0; k < mtx_nocoef2[j]; k++, cx++, sx++) {
+ ccdsum[1][sx] += mtx_coef2[cx];
+//printf("~1 HiRes CCD [%d] %f += [%d] %f\n",sx,ccdsum[1][sx],cx, mtx_coef2[cx]);
+ }
}
- avgw /= 126.0;
- // ~~this isn't right because not all CCD's get used!!
-#ifdef NEVER
- /* Itterate */
- for (ii = 0; ; ii++) {
-
- /* Normalize the individual filter weightings */
- for (j = 0; j < m->nwav2; j++) {
- double err;
- tot = 0.0;
- for (k = 0; k < mtx_nocoef2[j]; k++)
- tot += coeff2[j][k].we;
- err = 1.0 - tot;
+#ifdef HIGH_RES_PLOT
+ /* Plot target CCD values */
+ {
+ double xx[128], y1[128], y2[128];
+
+ for (i = 0; i < 128; i++) {
+ xx[i] = i;
+ y1[i] = ccdsum[0][i];
+ y2[i] = ccdsum[1][i];
+ }
- for (k = 0; k < mtx_nocoef2[j]; k++)
- coeff2[j][k].we += err/mtx_nocoef2[j];
-// for (k = 0; k < mtx_nocoef2[j]; k++)
-// coeff2[j][k].we *= 1.0/tot;
+ printf("Raw target and actual CCD weight sums:\n");
+ do_plot(xx, y1, y2, NULL, 128);
+ }
+#endif
+
+ /* Figure valid range and extrapolate to edges */
+ dth[0] = 0.0; /* ref */
+ dth[1] = 0.007; /* hires */
+
+ for (k = 0; k < 2; k++) {
+
+ for (i = 0; i < 128; i++) {
+ if (ccdsum[k][i] > max[k])
+ max[k] = ccdsum[k][i];
}
- /* Check CCD sums */
- for (i = 0; i < nraw; i++)
- ccdsum[i] = 0.0;
+//printf("~1 max[%d] = %f\n",k, max[k]);
+ /* Figure out the valid range */
+ for (i = 64; i >= 0; i--) {
+ if (ccdsum[k][i] > (0.8 * max[k])) {
+ x[0] = (double)i;
+ } else {
+ break;
+ }
+ }
+ for (i = 64; i < 128; i++) {
+ if (ccdsum[k][i] > (0.8 * max[k])) {
+ x[3] = (double)i;
+ } else {
+ break;
+ }
+ }
+ /* Space off the last couple of entries */
+ x[0] += 2.0;
+ x[3] -= 6.0;
+ x[1] = floor((2 * x[0] + x[3])/3.0);
+ x[2] = floor((x[0] + 2 * x[3])/3.0);
+
+ for (i = 0; i < 4; i++)
+ y[i] = ccdsum[k][(int)x[i]];
+
+//printf("~1 extrap nodes %f, %f, %f, %f\n",x[0],x[1],x[2],x[3]);
+//printf("~1 extrap value %f, %f, %f, %f\n",y[0],y[1],y[2],y[3]);
- for (j = 0; j < m->nwav2; j++) {
- for (k = 0; k < mtx_nocoef2[j]; k++)
- ccdsum[coeff2[j][k].ix] += coeff2[j][k].we;
+ for (i = 0; i < 128; i++) {
+ double xw, yw;
+
+ xw = (double)i;
+
+ /* Compute interpolated value using Lagrange: */
+ yw = y[0] * (xw-x[1]) * (xw-x[2]) * (xw-x[3])
+ /((x[0]-x[1]) * (x[0]-x[2]) * (x[0]-x[3]))
+ + y[1] * (xw-x[0]) * (xw-x[2]) * (xw-x[3])
+ /((x[1]-x[0]) * (x[1]-x[2]) * (x[1]-x[3]))
+ + y[2] * (xw-x[0]) * (xw-x[1]) * (xw-x[3])
+ /((x[2]-x[0]) * (x[2]-x[1]) * (x[2]-x[3]))
+ + y[3] * (xw-x[0]) * (xw-x[1]) * (xw-x[2])
+ /((x[3]-x[0]) * (x[3]-x[1]) * (x[3]-x[2]));
+
+ if ((xw < x[0] || xw > x[3])
+ && fabs(ccdsum[k][i] - yw)/yw > dth[k]) {
+ ccdsum[k][i] = yw;
+ }
+ avg[k] += ccdsum[k][i];
}
+ avg[k] /= 128.0;
+ }
- if (ii >= 6)
- break;
+#ifdef HIGH_RES_PLOT
+ /* Plot target CCD values */
+ {
+ double xx[129], y1[129], y2[129];
+
+ for (i = 0; i < 128; i++) {
+ xx[i] = i;
+ y1[i] = ccdsum[0][i]/avg[0];
+ y2[i] = ccdsum[1][i]/avg[1];
+ }
+ xx[i] = i;
+ y1[i] = 0.0;
+ y2[i] = 0.0;
+
+ printf("Extrap. target and actual CCD weight sums:\n");
+ do_plot(xx, y1, y2, NULL, 129);
+ }
+#endif
+
+#ifdef DO_CCDNORMAVG /* Just correct by average */
+ for (cx = j = 0; j < m->nwav2; j++) { /* For each wavelength */
- /* Readjust CCD sum */
- for (i = 0; i < nraw; i++) {
- ccdsum[i] = ccdtsum[i]/ccdsum[i]; /* Amount to adjust */
+ /* For each matrix value */
+ sx = mtx_index2[j]; /* Starting index */
+ for (k = 0; k < mtx_nocoef2[j]; k++, cx++, sx++) {
+ mtx_coef2[cx] *= 10.0/twidth * avg[0]/avg[1];
}
+ }
+
+#else /* Correct by CCD bin */
+
+ /* Correct the weighting of each CCD value in the hires output */
+ for (i = 0; i < 128; i++) {
+ ccdsum[1][i] = 10.0/twidth * ccdsum[0][i]/ccdsum[1][i]; /* Correction factor */
+ }
+ for (cx = j = 0; j < m->nwav2; j++) { /* For each wavelength */
- for (j = 0; j < m->nwav2; j++) {
- for (k = 0; k < mtx_nocoef2[j]; k++)
- coeff2[j][k].we *= ccdsum[coeff2[j][k].ix];
+ /* For each matrix value */
+ sx = mtx_index2[j]; /* Starting index */
+ for (k = 0; k < mtx_nocoef2[j]; k++, cx++, sx++) {
+ mtx_coef2[cx] *= ccdsum[1][sx];
}
}
-#endif /* NEVER */
+#endif
}
+#endif /* DO_CCDNORM */
#ifdef HIGH_RES_PLOT
- /* Plot resampled curves */
{
+ static munki_fc coeff2[MXNOWL][MXNOFC];
double *xx, *ss;
double **yy;
+ /* Convert the native filter cooeficient representation to */
+ /* a 2D array we can randomly index. */
+ for (cx = j = 0; j < m->nwav2; j++) { /* For each output wavelength */
+ if (j >= MXNOWL) { /* Assert */
+ a1loge(p->log,1,"munki: number of hires output wavelenths is > %d\n",MXNOWL);
+ return MUNKI_INT_ASSERT;
+ }
+
+ /* For each matrix value */
+ sx = mtx_index2[j]; /* Starting index */
+ for (k = 0; k < mtx_nocoef2[j]; k++, cx++, sx++) {
+ if (k >= MXNOFC) { /* Assert */
+ a1loge(p->log,1,"munki: number of hires filter coeefs is > %d\n",MXNOFC);
+ return MUNKI_INT_ASSERT;
+ }
+ coeff2[j][k].ix = sx;
+ coeff2[j][k].we = mtx_coef2[cx];
+ }
+ }
+
xx = dvectorz(-1, m->nraw-1); /* X index */
yy = dmatrixz(0, 5, -1, m->nraw-1); /* Curves distributed amongst 5 graphs */
@@ -6675,36 +7230,14 @@ munki_code munki_create_hr(munki *p, int ref) {
}
}
- printf("Normalized Hi-Res wavelength sampling curves:\n");
+ printf("Normalized Hi-Res wavelength sampling curves: %s\n",ref ? "refl" : "emis");
do_plot6(xx, yy[0], yy[1], yy[2], yy[3], yy[4], yy[5], m->nraw);
free_dvector(xx, -1, m->nraw-1);
free_dmatrix(yy, 0, 2, -1, m->nraw-1);
}
#endif /* HIGH_RES_PLOT */
- /* Convert into runtime format */
- {
- int xcount;
-
- if ((*pmtx_index2 = mtx_index2 = (int *)calloc(m->nwav2, sizeof(int))) == NULL) {
- a1logd(p->log,1,"munki: malloc mtx_index2 failed!\n");
- return MUNKI_INT_MALLOC;
- }
-
- xcount = 0;
- for (j = 0; j < m->nwav2; j++) {
- mtx_index2[j] = coeff2[j][0].ix;
- xcount += mtx_nocoef2[j];
- }
-
- if ((*pmtx_coef2 = mtx_coef2 = (double *)calloc(xcount, sizeof(double))) == NULL) {
- a1logd(p->log,1,"munki: malloc mtx_coef2 failed!\n");
- return MUNKI_INT_MALLOC;
- }
-
- for (i = j = 0; j < m->nwav2; j++)
- for (k = 0; k < mtx_nocoef2[j]; k++, i++)
- mtx_coef2[i] = coeff2[j][k].we;
- }
+#undef MXNOWL
+#undef MXNOFC
/* Basic capability is initialised */
m->hr_inited++;
@@ -6713,9 +7246,9 @@ munki_code munki_create_hr(munki *p, int ref) {
/* If both reflective and emissive samplings have been created, */
/* deal with upsampling the references and calibrations */
if (m->hr_inited == 2) {
-#ifdef SALONEINSTLIB
+#ifdef ONEDSTRAYLIGHTUS
double **slp; /* 2D Array of stray light values */
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
rspl *trspl; /* Upsample rspl */
cow sd[40 * 40]; /* Scattered data points of existing references */
datai glow, ghigh;
@@ -6765,6 +7298,7 @@ munki_code munki_create_hr(munki *p, int ref) {
vhigh[0] = sd[i].v[0];
}
+#ifdef NEVER
/* Add some corrections at short wavelengths */
/* (The combination of the diffraction grating and */
/* LED light source doesn't give us much to work with here.) */
@@ -6788,13 +7322,14 @@ munki_code munki_create_hr(munki *p, int ref) {
sd[i].v[0] = 0.2 * sd[0].v[0];
sd[i++].w = 1.0;
}
+#endif
glow[0] = m->wl_short2;
ghigh[0] = m->wl_long2;
gres[0] = m->nwav2;
avgdev[0] = 0.0;
- trspl->fit_rspl_w(trspl, 0, sd, i, glow, ghigh, gres, vlow, vhigh, 0.5, avgdev, NULL);
+ trspl->fit_rspl_w(trspl, 0, sd, i, glow, ghigh, gres, vlow, vhigh, 5.0, avgdev, NULL);
if ((*ref2 = (double *)calloc(m->nwav2, sizeof(double))) == NULL) {
raw2wav->del(raw2wav);
@@ -6806,6 +7341,8 @@ munki_code munki_create_hr(munki *p, int ref) {
/* Create upsampled version */
for (i = 0; i < m->nwav2; i++) {
pp.p[0] = XSPECT_WL(m->wl_short2, m->wl_long2, m->nwav2, i);
+ if (pp.p[0] < min_wl) /* Duplicate below this wl */
+ pp.p[0] = min_wl;
trspl->interp(trspl, &pp);
if (pp.v[0] < 0.0)
pp.v[0] = 0.0;
@@ -6813,6 +7350,7 @@ munki_code munki_create_hr(munki *p, int ref) {
}
+#ifdef NEVER
/* Add some corrections at short wavelengths */
if (ii == 0) {
/* 376.67 - 470 */
@@ -6839,6 +7377,7 @@ munki_code munki_create_hr(munki *p, int ref) {
}
}
+#endif
#ifdef HIGH_RES_PLOT
/* Plot original and upsampled reference */
@@ -6885,7 +7424,7 @@ munki_code munki_create_hr(munki *p, int ref) {
}
trspl->del(trspl);
-#ifdef SALONEINSTLIB
+#ifdef ONEDSTRAYLIGHTUS
/* Then the 2D stray light using linear interpolation */
slp = dmatrix(0, m->nwav1-1, 0, m->nwav1-1);
@@ -6929,7 +7468,7 @@ munki_code munki_create_hr(munki *p, int ref) {
}
}
}
-#else /* !SALONEINSTLIB */
+#else /* !ONEDSTRAYLIGHTUS */
/* Then setup 2D stray light using rspl */
if ((trspl = new_rspl(RSPL_NOFLAGS, 2, 1)) == NULL) {
a1logd(p->log,3,"munki: creating rspl for high res conversion failed\n");
@@ -6961,7 +7500,7 @@ munki_code munki_create_hr(munki *p, int ref) {
avgdev[1] = 0.0;
trspl->fit_rspl_w(trspl, 0, sd, m->nwav1 * m->nwav1, glow, ghigh, gres, NULL, NULL, 0.5, avgdev, NULL);
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
m->straylight2 = dmatrixz(0, m->nwav2-1, 0, m->nwav2-1);
@@ -6970,8 +7509,12 @@ munki_code munki_create_hr(munki *p, int ref) {
for (j = 0; j < m->nwav2; j++) { /* Input wavelength */
double p0, p1;
p0 = XSPECT_WL(m->wl_short2, m->wl_long2, m->nwav2, i);
+ if (p0 < min_wl) /* Duplicate below this wl */
+ p0 = min_wl;
p1 = XSPECT_WL(m->wl_short2, m->wl_long2, m->nwav2, j);
-#ifdef SALONEINSTLIB
+ if (p1 < min_wl) /* Duplicate below this wl */
+ p1 = min_wl;
+#ifdef ONEDSTRAYLIGHTUS
/* Do linear interp with clipping at ends */
{
int x0, x1, y0, y1;
@@ -7002,11 +7545,11 @@ munki_code munki_create_hr(munki *p, int ref) {
+ w1 * v0 * slp[x1][y0]
+ w1 * v1 * slp[x1][y1];
}
-#else /* !SALONEINSTLIB */
+#else /* !ONEDSTRAYLIGHTUS */
pp.p[0] = p0;
pp.p[1] = p1;
trspl->interp(trspl, &pp);
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
m->straylight2[i][j] = pp.v[0] * HIGHRES_WIDTH/10.0;
if (m->straylight2[i][j] > 0.0)
m->straylight2[i][j] = 0.0;
@@ -7077,11 +7620,11 @@ munki_code munki_create_hr(munki *p, int ref) {
}
#endif /* HIGH_RES_PLOT */
-#ifdef SALONEINSTLIB
+#ifdef ONEDSTRAYLIGHTUS
free_dmatrix(slp, 0, m->nwav1-1, 0, m->nwav1-1);
-#else /* !SALONEINSTLIB */
+#else /* !ONEDSTRAYLIGHTUS */
trspl->del(trspl);
-#endif /* !SALONEINSTLIB */
+#endif /* !ONEDSTRAYLIGHTUS */
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Allocate space for per mode calibration reference */
@@ -7278,22 +7821,9 @@ munki_code munki_conv2XYZ(
if (conv == NULL)
return MUNKI_INT_CIECONVFAIL;
- /* Don't report any wavelengths below the minimum for this mode */
- if ((s->min_wl-1e-3) > wl_short) {
- double wl;
- for (j = 0; j < m->nwav; j++) {
- wl = XSPECT_WL(m->wl_short, m->wl_long, m->nwav, j);
- if (wl >= (s->min_wl-1e-3))
- break;
- }
- six = j;
- wl_short = wl;
- nwl -= six;
- }
-
- a1logd(p->log,3,"munki_conv2XYZ got wl_short %f, wl_long %f, nwav %d, min_wl %f\n"
+ a1logd(p->log,3,"munki_conv2XYZ got wl_short %f, wl_long %f, nwav %d\n"
" after skip got wl_short %f, nwl = %d\n",
- m->wl_short, m->wl_long, m->nwav, s->min_wl, wl_short, nwl);
+ m->wl_short, m->wl_long, m->nwav, wl_short, nwl);
for (sms = 0.0, i = 1; i < 21; i++)
sms += opt_adj_weights[i];
@@ -7493,15 +8023,15 @@ munki_code munki_optimise_sensor(
new_int_time *= s->targoscale2;
a1logd(p->log,3,"Using compromse sensor target\n");
}
-#ifdef USE_HIGH_GAIN_MODE
- /* Hmm. It may not be a good idea to use high gain mode if it compromises */
+ /* Hmm. It seems not be a good idea to use high gain mode if it compromises */
/* the longer integration time which reduces noise. */
- if (new_int_time > m->max_int_time && permithg) {
- new_int_time /= m->highgain;
- new_gain_mode = 1;
- a1logd(p->log,3,"Switching to high gain mode\n");
+ if (s->auto_gain) {
+ if (new_int_time > m->max_int_time && permithg) {
+ new_int_time /= m->highgain;
+ new_gain_mode = 1;
+ a1logd(p->log,3,"Switching to high gain mode\n");
+ }
}
-#endif
}
a1logd(p->log,3,"after low light adjust, inttime %f, gain mode %d\n",new_int_time,new_gain_mode);
@@ -7616,10 +8146,8 @@ munki_interp_dark(
return MUNKI_INT_NOTCALIBRATED;
i = 0;
-#ifdef USE_HIGH_GAIN_MODE
- if (gainmode)
+ if (s->auto_gain && gainmode)
i = 2;
-#endif
for (j = -1; j < m->nraw; j++) {
double tt;
@@ -7654,7 +8182,7 @@ inst_opt_type munki_get_trig(munki *p) {
}
/* Switch thread handler */
-int munki_switch_thread(void *pp) {
+static int munki_switch_thread(void *pp) {
int nfailed = 0;
munki *p = (munki *)pp;
munkiimp *m = (munkiimp *)p->m;
@@ -7683,15 +8211,51 @@ int munki_switch_thread(void *pp) {
p->eventcallback(p->event_cntx, inst_event_switch);
}
} else if (ecode == mk_eve_spos_change) {
- if (p->eventcallback != NULL) {
- p->eventcallback(p->event_cntx, inst_event_mconf);
+#ifdef FILTER_SPOS_EVENTS
+ /* Signal change to filer thread */
+ m->spos_msec = msec_time();
+ m->spos_change++;
+#else
+ if (m->eventcallback != NULL) {
+ m->eventcallback(p->event_cntx, inst_event_mconf);
}
+#endif
}
}
a1logd(p->log,3,"Switch thread returning\n");
return rv;
}
+#ifdef FILTER_SPOS_EVENTS
+static int munki_spos_thread(void *pp) {
+ munki *p = (munki *)pp;
+ munkiimp *m = (munkiimp *)p->m;
+ int change = m->spos_change; /* Current count */
+
+ a1logd(p->log,3,"spos thread started\n");
+
+ for (;;) {
+
+ if (m->spos_th_term) {
+ m->spos_th_termed = 1;
+ break;
+ }
+
+ /* Do callback if change has persisted for 1 second */
+ if (change != m->spos_change
+ && (msec_time() - m->spos_msec) >= FILTER_TIME) {
+ change = m->spos_change;
+ if (p->eventcallback != NULL) {
+ p->eventcallback(p->event_cntx, inst_event_mconf);
+ }
+ }
+ msec_sleep(100);
+ }
+ return 0;
+}
+#endif
+
+
/* ============================================================ */
/* Low level commands */
@@ -8246,7 +8810,7 @@ munki_code munki_simulate_event(munki *p, mk_eve ecode, int timestamp) {
msec_sleep(50);
if (m->th_termed == 0) {
a1logd(p->log,1,"munki_simulate_event: terminate switch thread failed, canceling I/O\n");
- p->icom->usb_cancel_io(p->icom, &m->cancelt);
+ p->icom->usb_cancel_io(p->icom, &m->sw_cancel);
}
return rv;
@@ -8323,7 +8887,7 @@ munki_code munki_waitfor_switch_th(munki *p, mk_eve *ecode, int *timest, double
a1logd(p->log,2,"munki_waitfor_switch_th: Read 8 bytes from switch hit port\n");
/* Now read 8 bytes */
- se = p->icom->usb_read(p->icom, &m->cancelt, 0x83, buf, 8, &rwbytes, top);
+ se = p->icom->usb_read(p->icom, &m->sw_cancel, 0x83, buf, 8, &rwbytes, top);
if (se & ICOM_TO) {
a1logd(p->log,1,"munki_waitfor_switch_th: read 0x%x bytes, timed out\n",rwbytes);
@@ -8561,21 +9125,6 @@ munki_code munki_parse_eeprom(munki *p, unsigned char *buf, unsigned int len) {
if ((m->rmtx_coef1 = d->get_32_doubles(d, NULL, 184, 36 * 16)) == NULL)
return MUNKI_DATA_RANGE;
-#ifdef NEVER
-// ~~~ hack !!!
-m->rmtx_index1[4] = m->rmtx_index1[5] + 3;
-m->rmtx_index1[3] = m->rmtx_index1[4] + 3;
-m->rmtx_index1[2] = m->rmtx_index1[3] + 3;
-m->rmtx_index1[1] = m->rmtx_index1[2] + 3;
-m->rmtx_index1[0] = m->rmtx_index1[1] + 3;
-
-for(i = 0; i < 5; i++) {
- for (j = 0; j < 16; j++) {
- m->rmtx_coef1[i * 16 + j] = m->rmtx_coef1[5 * 16 + j];
- }
-}
-#endif
-
if (p->log->debug >= 7) {
a1logd(p->log,7,"Reflectance matrix:\n");
for(i = 0; i < 36; i++) {
diff --git a/spectro/munki_imp.h b/spectro/munki_imp.h
index a9af3a9..6af366e 100644
--- a/spectro/munki_imp.h
+++ b/spectro/munki_imp.h
@@ -89,6 +89,7 @@ struct _munki_state {
double targoscale; /* Optimal reading scale factor <= 1.0 */
double targmaxitime;/* maximum integration time to aim for (ie. 2.0 sec) */
double targoscale2; /* Proportion of targoscale allowed to meed targmaxitime */
+ int auto_gain; /* Whether high gain mode should be used */
int gainmode; /* Gain mode, 0 = normal, 1 = high */
double inttime; /* Integration time */
double invsampt; /* Invalid sample time */
@@ -104,8 +105,6 @@ struct _munki_state {
double maxscantime; /* Maximum scan time sets buffer size allocated */
- double min_wl; /* Minimum wavelegth to report for this mode */
-
/* calibration information for this mode */
int dark_valid; /* dark calibration factor valid */
time_t ddate; /* Date/time of last dark calibration */
@@ -145,6 +144,8 @@ struct _munki_state {
double dark_int_time3; /* Integration time used for dark data 3 */
double *dark_data3; /* [-1 nraw] of dark level to subtract for dark_int_time3. */
+ char padding[1]; /* to change structure size to invalidate cal file */
+
}; typedef struct _munki_state munki_state;
@@ -158,7 +159,7 @@ struct _munkiimp {
athread *th; /* Switch monitoring thread (NULL if not used) */
volatile int switch_count; /* Incremented in thread */
volatile int hide_switch; /* Set to supress switch event during read */
- usb_cancelt cancelt; /* Token to allow cancelling an outstanding I/O */
+ usb_cancelt sw_cancel; /* Token to allow cancelling switch I/O */
volatile int th_term; /* Thread terminate on error rather than retry */
volatile int th_termed; /* Thread has terminated */
inst_opt_type trig; /* Reading trigger mode */
@@ -284,6 +285,12 @@ struct _munkiimp {
int trig_se; /* Delayed trigger icoms error */
munki_code trig_rv; /* Delayed trigger result */
+ athread *spos_th; /* Position change filter thread */
+ volatile int spos_th_term; /* nz to terminate thread */
+ volatile int spos_th_termed; /* nz when terminated */
+ volatile int spos_change; /* counter that increments on an spos event change */
+ unsigned int spos_msec; /* Time when spos last changes */
+
}; typedef struct _munkiimp munkiimp;
/* Add an implementation structure */
@@ -342,6 +349,7 @@ void del_munkiimp(munki *p);
#define MUNKI_RD_NOFLASHES 0x3E /* No flashes recognized */
#define MUNKI_RD_NOAMBB4FLASHES 0x3F /* No ambient before flashes found */
#define MUNKI_RD_NOREFR_FOUND 0x40 /* Unable to measure refresh rate */
+#define MUNKI_RD_NOTRANS_FOUND 0x41 /* Unable to measure delay transition */
#define MUNKI_SPOS_PROJ 0x48 /* Sensor needs to be in projector position */
#define MUNKI_SPOS_SURF 0x49 /* Sensor needs to be in surface position */
@@ -392,8 +400,9 @@ char *munki_imp_get_serial_no(munki *p);
/* Set the measurement mode. It may need calibrating */
munki_code munki_imp_set_mode(
munki *p,
- mk_mode mmode, /* munki mode to use */
- int spec_en); /* nz to enable reporting spectral */
+ mk_mode mmode, /* Operating mode */
+ inst_mode mode /* Full mode mask for options */
+);
/* Implement get_n_a_cals */
munki_code munki_imp_get_n_a_cals(munki *p, inst_cal_type *pn_cals, inst_cal_type *pa_cals);
@@ -421,6 +430,12 @@ munki_code munki_imp_meas_refrate(
double *ref_rate
);
+/* Measure the display update delay */
+munki_code munki_imp_meas_delay(
+ munki *p,
+ int *msecdelay
+);
+
/* return nz if high res is supported */
int munki_imp_highres(munki *p);
@@ -549,6 +564,18 @@ munki_code munki_whitemeasure_buf(
unsigned char *buf /* Raw buffer */
);
+/* Take a measurement reading using the current mode (combined parts 1 & 2a) */
+/* Converts to completely processed output readings, without averaging or extracting */
+/* sample patches, for emissive measurement mode. */
+/* This is used for delay & refresh rate measurement. */
+munki_code munki_read_patches_all(
+ munki *p,
+ double **specrd, /* Return array [numpatches][nwav] of spectral reading values */
+ int numpatches, /* Number of sample to measure */
+ double *inttime, /* Integration time to use/used */
+ int gainmode /* Gain mode to use, 0 = normal, 1 = high */
+);
+
/* Take a measurement reading using the current mode, part 1 */
/* Converts to completely processed output readings. */
munki_code munki_read_patches_1(
@@ -795,8 +822,14 @@ inst_opt_type munki_get_trig(munki *p);
/* Set the trigger return */
void munki_set_trigret(munki *p, int val);
+#ifdef USE_THREAD
/* Switch thread handler */
-int munki_switch_thread(void *pp);
+static int munki_switch_thread(void *pp);
+#endif
+
+#ifdef FILTER_SPOS_EVENTS
+static int munki_spos_thread(void *pp);
+#endif
/* ============================================================ */
/* Low level commands */
diff --git a/spectro/oemarch.c b/spectro/oemarch.c
index 733156e..e27d25d 100644
--- a/spectro/oemarch.c
+++ b/spectro/oemarch.c
@@ -87,6 +87,8 @@ oem_target oemtargs = {
{ "/Applications/Spyder2pro 2.2/Spyder2pro.app/Contents/MacOSClassic/Spyder.lib", targ_spyd_pld },
{ "/Library/Application Support/X-Rite/Devices/i1d3xrdevice/Contents/Resources/Calibrations/*.edr", targ_i1d3_edr },
+ { "/Library/Application Support/X-Rite/Frameworks/XRiteDevice.framework/PlugIns/i1d3.xrdevice/Contents/Resources/Calibrations/*.edr",targ_i1d3_edr },
+
{ NULL }
},
{ /* Volume names */
@@ -168,7 +170,9 @@ int is_s4cal(xfile *xf);
int is_inno(xfile *xf);
int is_cab(xfile *xf);
static xfile *inno_extract(xfile *xi, char *tfilename, int verb);
-static xfile *msi_extract(xfile **pxf, xfile *xi, char *tname, int verb);
+static xfile *ai_extract_cab(xfile **pxf, xfile *xi, char *tname, int verb);
+//static xfile *aifile_extract(xfile **pxf, xfile *xi, char *tname, int verb);
+static xfile *msi_extract_cab(xfile **pxf, xfile *xi, char *tname, int verb);
static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb);
/* edr to ccss functions */
@@ -180,6 +184,9 @@ int is_ccss(xfile *xf);
int is_ccmx(xfile *xf);
#ifdef DEBUG
+
+# pragma message("######### oemarch DEBUG is defined! ########")
+
static void list_files(char *s, xfile *xf) {
int i;
@@ -281,28 +288,48 @@ xfile *oemarch_get_ifiles(xfile *files, int verb) {
/* If this could be i1d3 .edr files: */
if (arch->ttype & targ_i1d3_edr) {
- xfile *msi = NULL; /* .msi */
+ xfile *exe = NULL; /* .exe extracted */
+ xfile *msi = NULL; /* .msi extracted */
-#ifdef NEVER /* Don't have to do it this way */
+#ifdef NEVER /* Don't have to do it this way for most installs */
/* Extract .msi from it */
if ((msi = inno_extract(arch, "{tmp}\\XRD i1d3.msi", verb)) != NULL) {
/* Extract the .cab from it */
- if (msi_extract(&nfiles, msi, "XRD_i1d3.cab", verb) != NULL) {
+ if (msi_extract_cab(&nfiles, msi, "XRD_i1d3.cab", verb) != NULL) {
+ del_xf(msi);
+ continue;
+ }
+ if (msi_extract_cab(&nfiles, msi, "XRD_Manager.cab", verb) != NULL) {
del_xf(msi);
continue;
}
del_xf(msi);
}
+
+ /* Try and extract XRD Manager.exe from it */
+ if ((exe = inno_extract(arch, "{tmp}\\XRD Manager.exe", verb)) != NULL) {
+
+ /* Extract the "disk1.cab" from the AI installer exectutable */
+ if ((ai_extract_cab(&nfiles, exe, "disk1.cab", verb)) != NULL) {
+ del_xf(exe);
+ continue;
+ }
+ del_xf(exe);
+ }
#else
/* Extract the .cab directly from Setup.exe */
- if (msi_extract(&nfiles, arch, "XRD_i1d3.cab", verb) != NULL)
+ if (msi_extract_cab(&nfiles, arch, "XRD_i1d3.cab", verb) != NULL)
+ continue;
+ if (msi_extract_cab(&nfiles, arch, "XRD_Manager.cab", verb) != NULL)
continue;
- if (msi_extract(&nfiles, arch, "XRD_Manager.cab", verb) != NULL)
+
+ /* Extract the "disk1.cab" from the AI installer exectutable */
+ if ((ai_extract_cab(&nfiles, arch, "disk1.cab", verb)) != NULL)
continue;
#endif
}
- if (verb) printf("Warning: unhandled '%s' discarded\n",arch->name);
+ if (verb) printf("Warning: unhandled archive '%s' discarded\n",arch->name);
}
ofiles = files; /* Swap to new list */
files = nfiles;
@@ -350,7 +377,7 @@ xfile *oemarch_get_ifiles(xfile *files, int verb) {
if (cab_extract(&nfiles, dllcab, ".edr", verb) != NULL)
continue;
}
- if (verb) printf("Warning: unhandled '%s' discarded\n",dllcab->name);
+ if (verb) printf("Warning: unhandled dll/cab '%s' discarded\n",dllcab->name);
}
ofiles = files; /* Swap to new list */
files = nfiles;
@@ -381,7 +408,7 @@ xfile *oemarch_get_ifiles(xfile *files, int verb) {
if (edr_convert(&nfiles, files + i, verb) != NULL)
continue;
- if (verb) printf("Warning: unhandled '%s' discarded\n",files[i].name);
+ if (verb) printf("Warning: unhandled edr '%s' discarded\n",files[i].name);
}
ofiles = files; /* Swap to new list */
files = nfiles;
@@ -1295,7 +1322,7 @@ static xfile *edr_convert(xfile **pxf, xfile *xi, int verb) {
xfile *xf = NULL;
ccss *c;
- if (verb) printf("Translating '%s' (%d bytes)\n",xi->name, xi->len);
+ if (verb) printf("Translating '%s' (%d bytes)\n",xi->name, (int)xi->len);
if ((c = parse_EDR(xi->buf, xi->len, xi->name, verb)) == NULL) {
if (verb) printf("Failed to parse EDR '%s'\n",xi->name);
@@ -1306,7 +1333,7 @@ static xfile *edr_convert(xfile **pxf, xfile *xi, int verb) {
unsigned char *buf;
int len;
if (c->buf_write_ccss(c, &buf, &len)) {
- error("Failed to create ccss for '%s'",xi->name);
+ error("Failed to create ccss for '%s' error '%s'",xi->name,c->err);
}
/* Convert .edr file name to .ccss */
@@ -1356,9 +1383,10 @@ static void dump_bytes(FILE *fp, char *pfx, unsigned char *buf, int len) {
fprintf(fp,"\n");
}
}
+ fflush(fp);
}
-/* Take a 64 sized return buffer, and convert it to an ORD64 */
+/* Take a 64 sized return buffer, and convert it to an ORD64, little endian */
static ORD64 buf2ord64(unsigned char *buf) {
ORD64 val;
val = buf[7];
@@ -1372,7 +1400,7 @@ static ORD64 buf2ord64(unsigned char *buf) {
return val;
}
-/* Take a word sized return buffer, and convert it to an unsigned int */
+/* Take a word sized return buffer, and convert it to an unsigned int, little endian */
static unsigned int buf2uint(unsigned char *buf) {
unsigned int val;
val = buf[3];
@@ -1382,7 +1410,17 @@ static unsigned int buf2uint(unsigned char *buf) {
return val;
}
-/* Take a word sized return buffer, and convert it to an int */
+/* Inverted bytes version of above */
+static unsigned int ibuf2uint(unsigned char *buf) {
+ unsigned int val;
+ val = (0xff & ~buf[3]);
+ val = ((val << 8) + (0xff & ~buf[2]));
+ val = ((val << 8) + (0xff & ~buf[1]));
+ val = ((val << 8) + (0xff & ~buf[0]));
+ return val;
+}
+
+/* Take a word sized return buffer, and convert it to an int, little endian */
static int buf2int(unsigned char *buf) {
int val;
val = buf[3];
@@ -1392,7 +1430,7 @@ static int buf2int(unsigned char *buf) {
return val;
}
-/* Take a short sized return buffer, and convert it to an int */
+/* Take a short sized return buffer, and convert it to an int, little endian */
static int buf2short(unsigned char *buf) {
int val;
val = buf[1];
@@ -1431,7 +1469,7 @@ static ccss *parse_EDR(
char dispdesc[256];
int ttmin, ttmax; /* Min & max technology strings (inclusive) */
int *trefmodes; /* Corresponding refresh mode for tecnology */
- char **tsels; /* Corresponding UI selection chars */
+ char **tsels; /* Corresponding UI selection chars */
char **ttstrings; /* Corresponding technology strings */
int ttype; /* Technology type idex */
int nsets, set;
@@ -1480,7 +1518,7 @@ static ccss *parse_EDR(
trefmodes[15] = 0; tsels[15] = "o"; ttstrings[15] = "LED OLED";
trefmodes[16] = 0; tsels[16] = "a"; ttstrings[16] = "LED AMOLED";
trefmodes[17] = 1; tsels[17] = "m"; ttstrings[17] = "Plasma";
- trefmodes[18] = 0; tsels[18] = NULL; ttstrings[18] = "LCD RG Phosphor"; // is this LCD ??
+ trefmodes[18] = 0; tsels[18] = NULL; ttstrings[18] = "LCD RG Phosphor";
trefmodes[19] = 1; tsels[19] = NULL; ttstrings[19] = "Projector RGB Filter Wheel";
trefmodes[20] = 1; tsels[10] = NULL; ttstrings[20] = "Projector RGBW Filter Wheel";
trefmodes[21] = 1; tsels[21] = NULL; ttstrings[21] = "Projector RGBCMY Filter Wheel";
@@ -1629,6 +1667,7 @@ static ccss *parse_EDR(
samples[set].spec[j] *= 1000.0;
}
#ifdef PLOT_SAMPLES
+# pragma message("######### oemarch PLOT_SAMPLES defined! ########")
/* Plot the spectra */
{
double xx[500];
@@ -1911,7 +1950,26 @@ ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) {
return res;
}
-/* extract the given file from Setup.exe */
+/* extract the given file from Inno Setup.exe */
+/* Known versions needed:
+ 5.3.5 ColorMunkiDisplaySetup.exe
+ 5.3.10 i1d3Setup.exe
+ 5.4.2 V1.5 i1ProfilerSetup.exe
+*/
+
+/* Unicode to 8 bit strncmp */
+static int ustrncmp(char *w, char *c, int n) {
+ int i;
+ for (i = 0; i < n; i++, w += 2, c++) {
+ if ((w[0] == '\000' && w[1] == '\000')
+ || c[0] == '\000')
+ return 0;
+
+ if (w[0] != c[0] || w[1] != '\000')
+ return 1;
+ }
+ return 0;
+}
/* Return a list of xfiles, with one entry if successful */
/* Return NULL if not found or not inno file */
@@ -1919,8 +1977,12 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
int i, j, k;
unsigned char *ibuf;
unsigned long ilen;
- char *headerid = "Inno Setup Setup Data (5.3.10)";
+ char *headerid = "Inno Setup Setup Data ";
int headerlen = strlen(headerid);
+ int maj, min, bfix; /* Inno version */
+ int vers = 0; /* Version as int max * 1000 + min * 100 + bfix */
+ int unicode = 0; /* Is it unicode filenames ? */
+ int chsize = 1; /* Bytes per character */
unsigned int ldrbase = 0;
unsigned long haddr, srclen;
unsigned char *d1buf, *d2buf; /* Decompress buffer */
@@ -1939,14 +2001,15 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
ibuf = xi->buf;
ilen = xi->len;
- /* Search for the start of the loader. All the file offsets */
- /* are relative to this */
+ if (verb > 1) printf("inno_extract: ilen = %lu\n",ilen);
+
+ /* Search for the start of the loader. We need this because */
+ /* All the file offsets are relative to this. */
for (i = 0; i < (ilen - 4); i++) {
if (ibuf[i + 0] == 0x4d
&& ibuf[i + 1] == 0x5a
&& ibuf[i + 2] == 0x90
&& ibuf[i + 3] == 0x00) {
- if (verb > 1) printf("Found archive base 0x%x\n",i);
ldrbase = i;
break;
}
@@ -1955,26 +2018,51 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
if (verb) printf("Failed to locate loader base\n");
return NULL;
}
+ if (verb > 1) printf("Found archive base 0x%x\n",ldrbase);
/* Search for inno header pattern. */
- for (i = 0; i < (ilen - 64 - 4 - 5 - 4); i++) {
+ haddr = 0;
+ for (i = 1; i < (ilen - 64 - 4 - 5 - 4); i++) {
if (ibuf[i] == headerid[0]
&& strncmp((char *)ibuf + i, headerid, headerlen) == 0
&& ibuf[i + 64] != 'I'
&& ibuf[i + 65] != 'n'
&& ibuf[i + 66] != 'n'
&& ibuf[i + 67] != 'o') {
+
+ /* Grab the version */
+ for (j = 0; j < 64; j++) {
+ if (ibuf[i + j] == '\000')
+ break;
+ }
+ if (j >= 64) {
+ if (verb) printf("Failed to find null terminator after header\n");
+ continue;
+ }
+
+ if (sscanf((char *)ibuf + i + headerlen, " (%d.%d.%d) ",&maj,&min,&bfix) != 3) {
+ if (verb) printf("Failed to find Inno version number\n");
+ continue;
+ }
+ vers = maj * 1000 + min * 100 + bfix;
+
+ j = strlen((char *)ibuf + i);
+ if (strncmp((char *)ibuf + i + j -3, "(u)", 3) == 0) {
+ unicode = 1;
+ chsize = 2;
+ }
haddr = i;
}
}
- if (i >= (ilen - 64 - 4 - 5 - 4)) {
+
+ if (haddr == 0) {
if (verb) printf("Failed to locate header pattern\n");
return NULL;
}
- if (verb > 1) printf("Found header at 0x%x\n",i);
+ if (verb > 1) printf("Found header at 0x%x, Inno version %d.%d.%d%s\n",i,maj,min,bfix, unicode ? " Unicode" : "");
- /* Use the last header found (or cound search all found ?) */
+ /* Use the last header found (or could search all found ?) */
haddr += 64; /* Skip Inno header */
/* Next 9 bytes are the compression header */
@@ -1994,7 +2082,7 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
}
haddr += 5; /* Skip compression header */
- /* We'r now at the start of the compressed data */
+ /* We're now at the start of the compressed data which holds the filenames */
d1sz = cblocklen * 30;
if ((d1buf = (unsigned char *)malloc(d1sz)) == NULL) {
@@ -2016,6 +2104,7 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
}
if (verb > 1) printf("Decoded %ld bytes to created %ld bytes of Header output (ratio %.1f)\n",srclen,d1sz,(double)d1sz/srclen);
+// printf("d1buf, file names:\n");
// dump_bytes(stdout, " ", d1buf, d1sz);
/* - - - - - - - - - - - - - - - - -*/
@@ -2049,7 +2138,7 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
}
haddr += 5; /* Skip compression header */
- /* We're now at the start of the compressed data */
+ /* We're now at the start of the compressed data that holds the file data locations. */
d2sz = cblocklen * 10;
if ((d2buf = (unsigned char *)malloc(d2sz)) == NULL) {
@@ -2073,34 +2162,65 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
}
if (verb > 1) printf("Decoded %ld bytes to created %ld bytes of File Location output (ratio %.1f)\n",srclen,d1sz,(double)d1sz/srclen);
+// printf("d2buf, file location data:\n");
// dump_bytes(stdout, " ", d2buf, d2sz);
if (verb > 1) printf("Searching for file '%s' in Header\n",tfilename);
- for (i = 0; i < (d1sz - 101); i++) {
- if (d1buf[i+4] == tfilename[0]
- && strncmp((char *)d1buf + 4 + i, tfilename, filelen) == 0
- && d1buf[i+0] == filelen
- && d1buf[i+1] == 0
- && d1buf[i+2] == 0
- && d1buf[i+3] == 0) {
- if (verb > 1) printf("Found it at 0x%x\n",i);
- break;
+ if (unicode) {
+ for (i = 0; i < (d1sz - 101); i++) {
+ if (d1buf[i+4] == tfilename[0]
+ && ustrncmp((char *)d1buf + 4 + i, tfilename, filelen) == 0
+ && d1buf[i+0] == 2 * filelen
+ && d1buf[i+1] == 0
+ && d1buf[i+2] == 0
+ && d1buf[i+3] == 0) {
+ if (verb > 1) printf("Found it at 0x%x\n",i);
+ break;
+ }
+ }
+ if (i >= (d1sz - 101)) {
+ if (verb) printf("Failed to find file '%s'\n",tfilename);
+ free(d1buf);
+ free(d2buf);
+ return NULL;
+ }
+
+ } else {
+ for (i = 0; i < (d1sz - 101); i++) {
+ if (d1buf[i+4] == tfilename[0]
+ && strncmp((char *)d1buf + 4 + i, tfilename, filelen) == 0
+ && d1buf[i+0] == filelen
+ && d1buf[i+1] == 0
+ && d1buf[i+2] == 0
+ && d1buf[i+3] == 0) {
+ if (verb > 1) printf("Found it at 0x%x\n",i);
+ break;
+ }
+ }
+ if (i >= (d1sz - 101)) {
+ if (verb) printf("Failed to find file '%s'\n",tfilename);
+ free(d1buf);
+ free(d2buf);
+ return NULL;
}
}
- if (i >= (d1sz - 101)) {
- if (verb) printf("Failed to find file '%s'\n",tfilename);
- free(d1buf);
- free(d2buf);
- return NULL;
- }
+ fflush(stdout);
- /* Need to skip 8 more strings */
- i += 4 + filelen;
+ /* Need to skip 8 more strings containing other info about the file */
+ i += 4 + chsize * filelen;
for (j = 0; j < 8; j++) {
unsigned long len;
len = buf2uint(d1buf + i);
i += 4 + len;
+ if (i >= d1sz) {
+ if (verb) printf("Failed to skip 8 strings\n");
+ free(d1buf);
+ free(d2buf);
+ return NULL;
+ }
}
+ if (verb > 1) printf("At 0x%x after skippin another 8 strings\n",i);
+
/* Skip another 40 bytes to location entry index */
i += 20;
@@ -2108,13 +2228,12 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
if (verb > 1) printf("Got file location index %ld at 0x%x\n",ix,i);
-
/* Now get the ix file entry information. */
/* They are in 74 byte structures */
i = ix * 74;
if ((i + 74) > d2sz) {
- if (verb) printf("File location structure is out of range\n");
+ if (verb) printf("File location structure is out of range (%d > %lu)\n",i + 74, d2sz);
free(d1buf);
free(d2buf);
return NULL;
@@ -2141,7 +2260,8 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
free(d2buf);
return NULL;
}
- /* Sanity check */
+#ifdef NEVER
+ /* Sanity check it's an .msi file */
if (ibuf[ldrbase + fileso + 0] != 0xd0
|| ibuf[ldrbase + fileso + 1] != 0xcf
|| ibuf[ldrbase + fileso + 2] != 0x11
@@ -2151,6 +2271,7 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
free(d2buf);
return NULL;
}
+#endif
/* Copy to new buffer and free everything */
msisz = filesz;
@@ -2181,6 +2302,9 @@ static xfile *inno_extract(xfile *xi, char *tfilename, int verb) {
xf->buf = msibuf;
xf->len = filesz;
+ xf->ftype = file_dllcab;
+ xf->ttype = xi->ttype;
+
if (verb) printf("Returning '%s' length %ld from '%s'\n",xf->name,xf->len, xi->name);
return xf;
@@ -2274,22 +2398,25 @@ int is_dll(xfile *xf) {
return 0;
}
-/* Extract the .cab file from another file. */
+// ~~99 something strange about this code - it doesn't look for *tname.
+// ?? What's going on ??
+
+/* Extract a .cab file from another file. */
/* It's stored in the .msi uncompressed and contiguous, so we */
/* just need to identify where it is and its length. */
/* (This will work on any file that has the .cab file uncompressed and contiguous) */
/* Return NULL if not found */
-static xfile *msi_extract(xfile **pxf, xfile *xi, char *tname, int verb) {
+static xfile *msi_extract_cab(xfile **pxf, xfile *xi, char *tname, int verb) {
int i, j, k;
xfile *xf = NULL;
- char *fid = "i1d3.xrdevice"; /* File in .cab to look for */
+ char *fid = "i1d3.xrdevice"; /* Known file in .cab to look for ???? */
unsigned long fle = strlen(fid);
unsigned long cabo, cabsz;
size_t len;
if (verb) printf("Attempting to extract '%s' from '%s'\n",tname,xi->name);
- /* Search for a filename in the .cab */
+ /* Search for a filename that is expected to be in the right .cab */
for (i = 0; i < (xi->len - fle - 2); i++) {
if (xi->buf[i + 0] == 0x00
&& xi->buf[i + 1] == fid[0]
@@ -2299,7 +2426,7 @@ static xfile *msi_extract(xfile **pxf, xfile *xi, char *tname, int verb) {
}
}
if (i >= (xi->len - fle - 2)) {
- if (verb) printf(".cab not found\n");
+ if (verb) printf(".cab identifier file not found\n");
return NULL;
}
@@ -2313,12 +2440,12 @@ static xfile *msi_extract(xfile **pxf, xfile *xi, char *tname, int verb) {
&& xi->buf[i + 5] == 0x00
&& xi->buf[i + 6] == 0x00
&& xi->buf[i + 7] == 0x00) {
- if (verb > 1) printf("Found '%s' at 0x%x\n",tname,i);
+ if (verb > 1) printf("Found .cab sig at 0x%x\n",i);
break;
}
}
if (i < 0) {
- if (verb) printf(".cab not found\n");
+ if (verb) printf(".cab sig not found\n");
return NULL;
}
@@ -2354,6 +2481,299 @@ static xfile *msi_extract(xfile **pxf, xfile *xi, char *tname, int verb) {
return xf;
}
+/* Extract a .cab file from an "Advanced Installer" file. */
+/* It's stored in the file uncompressed and contiguous, but */
+/* with the first 0x200 bytes inverted, so we */
+/* just need to identify where it is and its length. */
+/* Return NULL if not found */
+static xfile *ai_extract_cab(xfile **pxf, xfile *xi, char *tname, int verb) {
+ int i, j, k;
+ xfile *xf = NULL;
+ unsigned long cabo, cabsz;
+ size_t len;
+
+ if (verb) printf("Attempting to extract '%s' from '%s'\n",tname,xi->name);
+
+ /* Search for inverted .cab signature */
+ for (i = 0; i < (xi->len - 8 - 4); i++) {
+ if (xi->buf[i + 0] == 0xb2
+ && xi->buf[i + 1] == 0xac
+ && xi->buf[i + 2] == 0xbc
+ && xi->buf[i + 3] == 0xb9
+ && xi->buf[i + 4] == 0xff
+ && xi->buf[i + 5] == 0xff
+ && xi->buf[i + 6] == 0xff
+ && xi->buf[i + 7] == 0xff) {
+ if (verb > 1) printf("Found inverted .cab sig at 0x%x\n",i);
+ break;
+ }
+ }
+ if (i > (xi->len - 8 - 4)) {
+ if (verb) printf(".cab sig not found\n");
+ return NULL;
+ }
+
+ /* Lookup the .cab size (really 64 bit, but we don't care) */
+ len = ibuf2uint(xi->buf + i + 8);
+
+ if (verb > 1) printf("'%s' is length %ld\n",tname,len);
+
+ if ((xi->len - i) < len) {
+ if (verb) printf("Not enough room for .cab file in source\n");
+ return NULL;
+ }
+
+ xf = add_xf(pxf);
+ xf->len = len;
+
+ if ((xf->buf = malloc(xf->len)) == NULL) {
+ fprintf(stderr,"maloc of .cab buffer failed\n");
+ exit(-1);
+ }
+ memmove(xf->buf, xi->buf + i ,xf->len);
+
+ /* Restor first 0x200 bytes */
+ for (i = 0; i < 0x200 && i < xf->len; i++) {
+ xf->buf[i] = ~xf->buf[i];
+ }
+
+ if ((xf->name = strdup(tname)) == NULL) {
+ fprintf(stderr,"maloc of .cab name failed\n");
+ exit(-1);
+ }
+
+ xf->ftype = file_dllcab;
+ xf->ttype = xi->ttype;
+
+ if (verb) printf("Extacted '%s' length %ld\n",xf->name,xf->len);
+
+save_xfile(xf, "temp.cab", NULL, verb);
+
+ return xf;
+}
+
+
+/* ================================================================ */
+
+/* Not used: */
+
+/* Given an offset into xfile, return the offset to any extra section in a PE file. */
+/* return 0 if none found or not a PE file */
+static int extraPEsection(xfile *xi, int boff, int verb) {
+ int i, j;
+ unsigned char *fbuf = xi->buf + boff;
+ int flen = xi->len - boff;
+ int off;
+ int nsect; /* Number of sections */
+ int ophsz; /* Optional header size */
+ int chars; /* File characteristics */
+ int plus = 0; /* PE32+ format */
+ int nddirs; /* Number of data directories */
+ int ddirroff; /* Offset of data directories */
+ unsigned int asects = 0; /* Offset after all the sections */
+
+ if (flen < 0x40
+ || fbuf[0] != 0x4d
+ || fbuf[1] != 0x5a) {
+ if (verb) printf("'%s' is not an executable file\n",xi->name);
+ return 0;
+ }
+
+ off = fbuf[0x3c] /* Offset to PE header */
+ + (fbuf[0x3d] << 8)
+ + (fbuf[0x3e] << 16)
+ + (fbuf[0x3f] << 24);
+
+ if (verb > 2) printf("PE header at 0x%x\n",off);
+
+ if (flen < (off + 0x18) || off > 0x1000 || (off & 7) != 0) {
+ if (verb) printf("'%s' is not a PE file (1)\n",xi->name);
+ return 0;
+ }
+
+ if (fbuf[off + 0] != 0x50 /* "PE" */
+ || fbuf[off + 1] != 0x45
+ || fbuf[off + 2] != 0x00
+ || fbuf[off + 3] != 0x00) {
+ if (verb) printf("'%s' is not a PE file (2)\n",xi->name);
+ return 0;
+ }
+
+ nsect = fbuf[off + 0x06] /* Number of sections */
+ + (fbuf[off + 0x07] << 8);
+
+ ophsz = fbuf[off + 0x14] /* Optional header size */
+ + (fbuf[off + 0x15] << 8);
+
+ chars = fbuf[off + 0x16] /* PE Characteristics */
+ + (fbuf[off + 0x17] << 8);
+ /*
+ 0x0002 = executable (no unresolved refs)
+ 0x1000 = .sys driver
+ 0x2000 = DLL
+ */
+
+ if (verb > 1) printf("Number of sections = %d, chars = 0x%x\n",nsect,chars);
+ if (verb > 1) printf("Opt header size = %d = 0x%x\n",ophsz,ophsz);
+
+ /* Skip to optional header */
+ off = off + 0x18;
+ if (flen < off + ophsz) {
+ if (verb) printf("'%s' not big enough for optional header\n",xi->name);
+ return 0;
+ }
+ if (verb > 2) printf("opt header at 0x%x\n",off);
+ if ( fbuf[off + 0] != 0x0b
+ || (fbuf[off + 1] != 0x01 && fbuf[off + 1] != 0x02)) {
+ if (verb) printf("'%s' is not a PE file (3)\n",xi->name);
+ return 0;
+ }
+ if (fbuf[off + 1] == 0x02)
+ plus = 1; /* PE32+ format */
+
+ if (plus) {
+ nddirs = fbuf[off+0x6c+0]
+ + (fbuf[off+0x6c+1] << 8)
+ + (fbuf[off+0x6c+2] << 16)
+ + (fbuf[off+0x6c+3] << 24);
+ ddirroff = 0x70;
+ } else {
+ nddirs = fbuf[off+0x5c+0]
+ + (fbuf[off+0x5c+1] << 8)
+ + (fbuf[off+0x5c+2] << 16)
+ + (fbuf[off+0x5c+3] << 24);
+ ddirroff = 0x60;
+ }
+
+ /* Go through each data directory */
+ for (i = 0; i < nddirs; i++) {
+ unsigned int addr, size;
+
+ j = off + ddirroff + 8 * i;
+
+ addr = fbuf[j+0]
+ + (fbuf[j+1] << 8)
+ + (fbuf[j+2] << 16)
+ + (fbuf[j+3] << 24);
+ size = fbuf[j+4]
+ + (fbuf[j+5] << 8)
+ + (fbuf[j+6] << 16)
+ + (fbuf[j+7] << 24);
+
+ if (verb > 2) printf("Data block %d addr 0x%x size %u\n",i,addr,size);
+ }
+
+ /* Skip to start of section headers */
+ off = off + ophsz;
+
+ /* Go through each section header and locat size used by them */
+ asects = 0;
+ for (i = 0; i < nsect; i++) {
+ char sname[9] = { '\000' };
+ unsigned int vaddr, vsize;
+ unsigned int paddr, psize;
+ unsigned int flags;
+
+ if (flen < (off + 0x28)) {
+ if (verb) printf("'%s' not big enough for section headers\n",xi->name);
+ return 0;
+ }
+
+ strncpy(sname, (char *)fbuf + off, 8);
+
+ vsize = fbuf[off+0x08+0]
+ + (fbuf[off+0x08+1] << 8)
+ + (fbuf[off+0x08+2] << 16)
+ + (fbuf[off+0x08+3] << 24);
+
+ vaddr = fbuf[off+0x0c+0]
+ + (fbuf[off+0x0c+1] << 8)
+ + (fbuf[off+0x0c+2] << 16)
+ + (fbuf[off+0x0c+3] << 24);
+
+ psize = fbuf[off+0x10+0]
+ + (fbuf[off+0x10+1] << 8)
+ + (fbuf[off+0x10+2] << 16)
+ + (fbuf[off+0x10+3] << 24);
+
+ paddr = fbuf[off+0x14+0]
+ + (fbuf[off+0x14+1] << 8)
+ + (fbuf[off+0x14+2] << 16)
+ + (fbuf[off+0x14+3] << 24);
+
+ flags = fbuf[off+0x24+0]
+ + (fbuf[off+0x24+1] << 8)
+ + (fbuf[off+0x24+2] << 16)
+ + (fbuf[off+0x24+3] << 24);
+
+ if (verb > 1) printf("Section '%s' phys off 0x%x size %u\n",sname,paddr,psize);
+
+ if ((paddr + psize) > asects)
+ asects = paddr + psize;
+ off += 0x28;
+ }
+ if (verb > 2) printf("After section hedares at 0x%x\n",off);
+
+ if (flen <= asects) {
+ if (verb) printf("No extra section at end\n");
+ return 0;
+ }
+
+ if (verb > 1) printf("Extra data at 0x%x, %d bytes\n",asects, flen - asects);
+
+ return boff + asects;
+}
+
+/* Not used */
+
+/* Extract a module from a PE "Advance Installer" .exe file */
+/* Return NULL if not found */
+static xfile *aifile_extract(xfile **pxf, xfile *xi, char *tname, int verb) {
+ xfile *xf = NULL;
+ int i, j;
+ int asects; /* Offset after all the sections */
+ int off;
+
+ /* First we parse up the PE to figure out how much room is */
+ /* used for known sections */
+ if ((asects = extraPEsection(xi, 0, verb)) == 0) {
+ return NULL;
+ }
+
+ /* Now we can search the "Advanced Installer" archive */
+ /* It seems to be a set of concatenated PE files ? */
+
+ for (i= 0, off = asects; off != 0; i++) {
+ printf("\nPE %d at 0x%x\n",i,off);
+ off = extraPEsection(xi, off, verb > 2 ? 2 : verb);
+ }
+
+ if (verb) printf(" pefile_extract_mod not implemented yet\n");
+ return NULL;
+
+#ifdef NEVER
+ xf = add_xf(pxf);
+ xf->len = len;
+
+ if ((xf->buf = malloc(xf->len)) == NULL) {
+ fprintf(stderr,"maloc of .cab buffer failed\n");
+ exit(-1);
+ }
+ memmove(xf->buf, xi->buf + i ,xf->len);
+
+ if ((xf->name = strdup(tname)) == NULL) {
+ fprintf(stderr,"maloc of .cab name failed\n");
+ exit(-1);
+ }
+
+ xf->ftype = file_dllcab;
+ xf->ttype = xi->ttype;
+
+ if (verb) printf("Extacted '%s' length %ld\n",xf->name,xf->len);
+
+ return xf;
+#endif
+}
/* ================================================================ */
/* Extract files of a given type from a .cab file */
@@ -2407,6 +2827,8 @@ static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb) {
unsigned long len = xi->len;
unsigned long off;
unsigned long filesize, headeroffset, datastart;
+ int headerres = 0, folderres = 0, datares = 0;
+ int hextra = 0;
int nofolders, nofiles, flags, comptype;
unsigned int totubytes;
int ufiles = 0;
@@ -2443,18 +2865,28 @@ static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb) {
fprintf(stderr,"'%s' has more than one folder\n",xi->name);
exit(-1);
}
- if (flags != 0) {
- fprintf(stderr,"'%s' has non-zero flags\n",xi->name);
+ if (flags != 0 && flags != 4) {
+ fprintf(stderr,"'%s' has unhandled flags 0x%x\n",xi->name,flags);
exit(-1);
}
+ if (flags & 4) { /* If researved fields */
+ // cbCFHeader, cbCFFolder, and cbCFData are present.
+ headerres = buf2short(buf + 0x24);
+ folderres = buf[0x26];
+ datares = buf[0x27];
+
+ hextra = 4 + headerres;
+ }
+
/* Read the first folders info (assumed flags == 0) */
- datastart = buf2uint(buf + 0x24);
- comptype = buf[0x2a];
+ datastart = buf2uint(buf + hextra + 0x24);
+ comptype = buf[hextra + 0x2a];
if (comptype!= 1) {
- fprintf(stderr,"'%s' doesn't use MSZip compression\n",xi->name);
+ fprintf(stderr,"'%s' doesn't use MSZip compression, uses %d\n",xi->name,comptype);
exit(-1);
}
+ /* Should skip folderres bytes here */
if (verb > 1) printf(".cab headeroffset = 0x%lx, datastart = 0x%lx, nofiles = %d\n",headeroffset,datastart,nofiles);
@@ -2502,7 +2934,7 @@ static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb) {
totubytes += ubytes;
- off += 8 + cbytes;
+ off += 8 + datares + cbytes;
}
@@ -2530,7 +2962,7 @@ static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb) {
cbytes = buf2short(buf + off + 0x04);
ubytes = buf2short(buf + off + 0x06);
- i_buf = buf + off + 8;
+ i_buf = buf + off + 8 + datares;
i_len = cbytes;
i_ix = 0;
@@ -2548,7 +2980,7 @@ static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb) {
/* The history buffer is meant to survive from one block to the next. */
/* Not sure what that means, as it seems to work as is... */
- off += 8 + cbytes;
+ off += 8 + datares + cbytes;
}
xf = add_xf(pxf);
@@ -2569,8 +3001,8 @@ static xfile *cab_extract(xfile **pxf, xfile *xi, char *text, int verb) {
fname[94] = '\000';
namelen = strlen(fname);
- /* Lop of the junk in the filename */
- if ((cp = strrchr(fname, '.')) != NULL)
+ /* Lop of the junk in the filename, if it's present */
+ if ((cp = strrchr(fname, '.')) != NULL && cp != strchr(fname, '.'))
*cp = '\000';
/* See if it's the type of file we want */
diff --git a/spectro/oemarch.h b/spectro/oemarch.h
index 72a3bb6..1b8c4a4 100644
--- a/spectro/oemarch.h
+++ b/spectro/oemarch.h
@@ -1,7 +1,7 @@
#ifndef OEMARCH_H
- /* OEM archive access library.
+ /* OEM archive access library. */
/* This supports installing OEM data files */
/*
@@ -29,7 +29,7 @@ typedef enum {
file_none = 0x0000, /* None */
file_vol = 0x0001, /* Volume name */
file_arch = 0x0002, /* Archive file */
- file_dllcab = 0x0004, /* .dll or .cab */
+ file_dllcab = 0x0004, /* .dll or .cab - msi ?? */
file_data = 0x0008 /* final data file */
} file_type;
diff --git a/spectro/oeminst.c b/spectro/oeminst.c
index 88efae0..2aa96e5 100644
--- a/spectro/oeminst.c
+++ b/spectro/oeminst.c
@@ -37,7 +37,7 @@ void usage(void) {
fprintf(stderr,"Install OEM data files, Version %s\n",ARGYLL_VERSION_STR);
fprintf(stderr,"Author: Graeme W. Gill, licensed under the GPL Version 2 or later\n");
fprintf(stderr,"usage: oeminst [-options] [infile(s)]\n");
- fprintf(stderr," -v Verbose\n");
+ fprintf(stderr," -v [level] Verbose\n");
fprintf(stderr," -n Don't install, show where files would be installed\n");
fprintf(stderr," -c Don't install, save files to current directory\n");
fprintf(stderr," -S d Specify the install scope u = user (def.), l = local system]\n");
@@ -88,6 +88,10 @@ main(int argc, char *argv[]) {
/* Verbosity */
else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
verb = 1;
+ if (na != NULL && na[0] >= '0' && na[0] <= '9') {
+ verb = atoi(na);
+ fa = nfa;
+ }
}
/* No install */
diff --git a/spectro/spec2cie.c b/spectro/spec2cie.c
index 99fe898..3f2e9d6 100644
--- a/spectro/spec2cie.c
+++ b/spectro/spec2cie.c
@@ -530,6 +530,7 @@ main(int argc, char *argv[])
illum = icxIT_none; /* Displays are assumed to be self luminous */
}
+
/* copy fields to output file (except spectral if nospec) */
for (i = 0; i < icg->t[0].nfields; i++) {
/* See if this is a input spectral field */
diff --git a/spectro/specbos.c b/spectro/specbos.c
new file mode 100644
index 0000000..f81f2d7
--- /dev/null
+++ b/spectro/specbos.c
@@ -0,0 +1,1674 @@
+
+/*
+ * Argyll Color Correction System
+ *
+ * JETI specbos 1211/1201 related functions
+ *
+ * Author: Graeme W. Gill
+ * Date: 13/3/2013
+ *
+ * Copyright 1996 - 2014, Graeme W. Gill
+ * All rights reserved.
+ *
+ * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
+ * see the License2.txt file for licencing details.
+ *
+ * Based on DTP92.c
+ */
+
+/*
+ If you make use of the instrument driver code here, please note
+ that it is the author(s) of the code who take responsibility
+ for its operation. Any problems or queries regarding driving
+ instruments with the Argyll drivers, should be directed to
+ the Argyll's author(s), and not to any other party.
+
+ If there is some instrument feature or function that you
+ would like supported here, it is recommended that you
+ contact Argyll's author(s) first, rather than attempt to
+ modify the software yourself, if you don't have firm knowledge
+ of the instrument communicate protocols. There is a chance
+ that an instrument could be damaged by an incautious command
+ sequence, and the instrument companies generally cannot and
+ will not support developers that they have not qualified
+ and agreed to support.
+ */
+
+/*
+
+ TTBD:
+
+ Should add a reflective and transmissive modes,
+ by doing a white calibration and dividing the measurement.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#ifndef SALONEINSTLIB
+#include "copyright.h"
+#include "aconfig.h"
+#include "numlib.h"
+#else /* !SALONEINSTLIB */
+#include "sa_config.h"
+#include "numsup.h"
+#endif /* !SALONEINSTLIB */
+#include "xspect.h"
+#include "insttypes.h"
+#include "conv.h"
+#include "icoms.h"
+#include "specbos.h"
+
+/* Default flow control */
+#define DEFFC fc_none
+
+static inst_code specbos_interp_code(inst *pp, int ec);
+
+#define MAX_MES_SIZE 500 /* Maximum normal message reply size */
+#define MAX_RD_SIZE 8000 /* Maximum reading message reply size */
+
+/* Interpret an icoms error into a SPECBOS error */
+static int icoms2specbos_err(int se) {
+ if (se != ICOM_OK) {
+ if (se & ICOM_TO)
+ return SPECBOS_TIMEOUT;
+ return SPECBOS_COMS_FAIL;
+ }
+ return SPECBOS_OK;
+}
+
+/* Do a full command/response echange with the specbos */
+/* (This level is not multi-thread safe) */
+/* Return the specbos error code. */
+static int
+specbos_fcommand(
+struct _specbos *p,
+char *in, /* In string */
+char *out, /* Out string buffer */
+int bsize, /* Out buffer size */
+double to, /* Timeout in seconds */
+int ntc, /* Number or termination chars */
+int ctype, /* 0 = normal, 1 = *init, 2 = refr reading */
+int nd /* nz to disable debug messages */
+) {
+ int se;
+ char *cp, *tc = "", *dp;
+
+ if (ctype == 0)
+ tc = "\r\006\025"; /* Return, Ack or Nak */
+ else if (ctype == 1)
+ tc = "\007\025"; /* Bell or Nak */
+ else if (ctype == 2)
+ tc = "\r\025"; /* Return or Nak */
+
+ if ((se = p->icom->write_read(p->icom, in, out, bsize, tc, ntc, to)) != 0) {
+ if (!nd) a1logd(p->log, 1, "specbos_fcommand: serial i/o failure on write_read '%s' 0x%x\n",icoms_fix(in),se);
+ return icoms2specbos_err(se);
+ }
+
+ /* See if there was an error, and remove any enquire codes */
+ for (dp = cp = out; *cp != '\000' && (out - dp) < bsize; cp++) {
+ if (*cp == '\025') { /* Got a Nak */
+ char buf[100];
+
+ if ((se = p->icom->write_read(p->icom, "*stat:err?\r", buf, 100, "\r", 1, 1.0)) != 0) {
+ if (!nd) a1logd(p->log, 1, "specbos_fcommand: serial i/o failure on write_read '%s'\n",icoms_fix(in));
+ if (sscanf(buf, "Error Code: %d ",&se) != 1) {
+ if (!nd) a1logd(p->log, 1, "specbos_fcommand: failed to parse error code '%s'\n",icoms_fix(buf));
+ return icoms2specbos_err(se);
+ }
+ }
+ break;
+ }
+ if (*cp == '\005') /* Got an Enquire */
+ continue; /* remove it */
+ *dp = *cp;
+ dp++;
+ }
+ out[bsize-1] = '\000';
+
+ if (!nd) a1logd(p->log, 4, "specbos_fcommand: command '%s' returned '%s'\n",
+ icoms_fix(in), icoms_fix(out));
+
+ return SPECBOS_OK;
+}
+
+/* Do a normal command/response echange with the specbos. */
+/* (This level is not multi-thread safe) */
+/* Return the inst code */
+static inst_code
+specbos_command(
+struct _specbos *p,
+char *in, /* In string */
+char *out, /* Out string buffer */
+int bsize, /* Out buffer size */
+double to) { /* Timout in seconds */
+ int rv = specbos_fcommand(p, in, out, bsize, to, 1, 0, 0);
+ return specbos_interp_code((inst *)p, rv);
+}
+
+/* Read another line of response */
+/* (This level is not multi-thread safe) */
+/* Return the inst code */
+static int
+specbos_readresp(
+struct _specbos *p,
+char *out, /* Out string buffer */
+int bsize, /* Out buffer size */
+double to /* Timeout in seconds */
+) {
+ int rv, se;
+ char *cp, *tc = "\r\006\025"; /* Return, Ack or Nak */
+
+ if ((se = p->icom->read(p->icom, out, bsize, tc, 1, to)) != 0) {
+ a1logd(p->log, 1, "specbos_readresp: serial i/o failure\n");
+ return icoms2specbos_err(se);
+ }
+ return inst_ok;
+}
+
+/* Establish communications with a specbos */
+/* Ignore the serial parameters - leave serial in default state. */
+/* Return SPECBOS_COMS_FAIL on failure to establish communications */
+static inst_code
+specbos_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
+ specbos *p = (specbos *) pp;
+ char buf[MAX_MES_SIZE];
+ baud_rate brt[] = { baud_921600, baud_115200, baud_38400, baud_nc };
+ unsigned int etime;
+ unsigned int i;
+ instType itype = pp->itype;
+ int se;
+
+ inst_code ev = inst_ok;
+
+ a1logd(p->log, 2, "specbos_init_coms: About to init Serial I/O\n");
+
+ amutex_lock(p->lock);
+
+ if (p->icom->port_type(p->icom) != icomt_serial
+ && p->icom->port_type(p->icom) != icomt_usbserial) {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 1, "specbos_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
+ }
+
+ /* The tick to give up on */
+ etime = msec_time() + (long)(1500.0 + 0.5);
+
+ a1logd(p->log, 1, "specbos_init_coms: Trying different baud rates (%u msec to go)\n",etime - msec_time());
+
+ /* Until we time out, find the correct baud rate */
+ for (i = 0; msec_time() < etime; i++) {
+ if (brt[i] == baud_nc) {
+ i = 0;
+ }
+ a1logd(p->log, 5, "specbos_init_coms: trying baud ix %d\n",brt[i]);
+ if ((se = p->icom->set_ser_port(p->icom, fc_none, brt[i], parity_none,
+ stop_1, length_8)) != ICOM_OK) {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 5, "specbos_init_coms: set_ser_port failed with 0x%x\n",se);
+ return specbos_interp_code((inst *)p, icoms2specbos_err(se));; /* Give up */
+ }
+
+
+ /* Check instrument is responding */
+ if (((ev = specbos_command(p, "*idn?\r", buf, MAX_MES_SIZE, 0.2)) & inst_mask)
+ != inst_coms_fail) {
+ break; /* We've got coms or user abort */
+ }
+
+ /* Check for user abort */
+ if (p->uicallback != NULL) {
+ inst_code ev;
+ if ((ev = p->uicallback(p->uic_cntx, inst_negcoms)) == inst_user_abort) {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 1, "specbos_init_coms: user aborted\n");
+ return inst_user_abort;
+ }
+ }
+ }
+
+ if (msec_time() >= etime) { /* We haven't established comms */
+ amutex_unlock(p->lock);
+ a1logd(p->log, 2, "specbos_init_coms: failed to establish coms\n");
+ return inst_coms_fail;
+ }
+
+ /* Check the response */
+ p->model = 0;
+
+ if (strncmp (buf, "SB05", 4) == 0) /* Special case */
+ p->model = 1201;
+ else {
+ if (strlen(buf) < 11
+ || sscanf(buf, "JETI_SB%d\r", &p->model) != 1) {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 2, "specbos_init_coms: unrecognised ident string '%s'\n",icoms_fix(buf));
+ return inst_protocol_error;
+ }
+ }
+
+ if (p->model != 1201 && p->model != 1211) {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 2, "specbos_init_coms: unrecognised model %04d\n",p->model);
+ return inst_unknown_model;
+ }
+ a1logd(p->log, 2, "specbos_init_coms: init coms has suceeded\n");
+
+ p->gotcoms = 1;
+
+#ifdef NEVER /* Test a change in baud rate on next plug in */
+ a1logd(p->log, 2, "specbos_init_coms: changing baudrate\n");
+// if ((ev = specbos_command(p, "*para:baud 384\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok)
+// if ((ev = specbos_command(p, "*para:baud 115\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok)
+ if ((ev = specbos_command(p, "*para:baud 921\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok)
+ {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ if ((ev = specbos_command(p, "*para:save\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+#endif
+
+ amutex_unlock(p->lock);
+
+ return inst_ok;
+}
+
+static inst_code set_default_disp_type(specbos *p);
+
+/*
+ Notes on commands
+
+ *conf is temporary, *para can be saved to instrument
+ Since we set the instrument up every time, use *conf ?
+ *PARAmeter:SAVE
+
+ Set calibration to auto on presense of ambient cap
+ *para:calibn 0
+
+ To check what mode it's in:
+ *contr:mhead?
+ 0 for emissive, 1 for ambient.
+
+ Set auto exposure
+ *para:expo 1 // Adapt
+ *para:adap 2 // Adapt if under or over
+ *conf:maxtin 4000 // Limit to 4 secs for display measurement rather than 60000
+
+ Set output format
+ *conf:form 10 // interpolated ASCII with wavelength
+ *conf:form 12 // H/L 32 bit float with length & checksum - doesn't seem to work :-(
+
+ Measurement function
+ *conf:func 6 // Radiometric spectrum
+
+ Set to wavelength range and step
+ *conf:wran 350 850 1
+
+ Set to average just 1 reading
+ *conf:aver 1
+
+ Do a configured measurement
+ *init
+
+ Fetch the results
+ *fetch:XYZ // Fetches XYZ whatever the function ?
+ *fetch 10 // Fetch configured function in format 10
+
+ Measure refresh
+ *conf:cycmod 1
+ *contr:cyctim 200 4000 // Returns msec
+
+ Set refresh sync mode
+ *conf:cycmod 1
+ *conf:cyctim cyctim // in usec
+
+ message terminations:
+
+ *xxx? \r after data \r\r after spectral ??
+ \025 Nak on error ??
+
+ *para
+ *conf
+ *contr \006 Ack on success,
+ \025 Nak on error
+
+ All enquiries and parameter setting: '\r'
+
+ *init \006 Ack on command accepted
+ \025 Nak on error
+ \007 Bell on completion
+
+ *fetch
+ *calc
+ *calib
+ *stat
+ *help
+ *fetch \r after data, \r\r after spectral ??
+
+*/
+
+static inst_code specbos_get_diffpos(specbos *p, int *pos, int nd);
+
+/* Diffuser position thread. */
+/* Poll the instrument at 500msec intervals */
+int specbos_diff_thread(void *pp) {
+ int nfailed = 0;
+ specbos *p = (specbos *)pp;
+ inst_code rv = inst_ok;
+ a1logd(p->log,3,"Diffuser thread started\n");
+ for (nfailed = 0; nfailed < 5;) {
+ int pos;
+
+ amutex_lock(p->lock);
+ rv = specbos_get_diffpos(p, &pos, 1);
+ amutex_unlock(p->lock);
+
+ if (p->th_term) {
+ p->th_termed = 1;
+ break;
+ }
+ if (rv != inst_ok) {
+ nfailed++;
+ a1logd(p->log,3,"Diffuser thread failed with 0x%x\n",rv);
+ continue;
+ }
+ if (pos != p->dpos) {
+ p->dpos = pos;
+ if (p->eventcallback != NULL) {
+ p->eventcallback(p->event_cntx, inst_event_mconf);
+ }
+ }
+ msec_sleep(500);
+ }
+ a1logd(p->log,3,"Diffuser thread returning\n");
+ return rv;
+}
+
+/* Initialise the SPECBOS */
+/* return non-zero on an error, with dtp error code */
+static inst_code
+specbos_init_inst(inst *pp) {
+ specbos *p = (specbos *)pp;
+ char mes[100];
+ char buf[MAX_MES_SIZE];
+ inst_code ev = inst_ok;
+
+ a1logd(p->log, 2, "specbos_init_inst: called\n");
+
+ if (p->gotcoms == 0)
+ return inst_internal_error; /* Must establish coms before calling init */
+
+ amutex_lock(p->lock);
+
+ /* Restore the instrument to it's default settings */
+ if ((ev = specbos_command(p, "*conf:default\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok)
+ return ev;
+
+ /* Set calibration type to auto on ambient cap */
+ if ((ev = specbos_command(p, "*para:calibn 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ /* Set auto exposure/integration time */
+ /* Set calibration type to auto on ambient cap */
+ if ((ev = specbos_command(p, "*para:expo 1\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok
+ || (ev = specbos_command(p, "*para:adapt 2\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ p->measto = 20.0; /* default */
+
+ if (p->model == 1211)
+ p->measto = 5.0; /* Same overall time as i1d3 ?? */
+ else if (p->model == 1201)
+ p->measto = 15.0;
+
+ /* Set maximum integration time to speed up display measurement */
+ sprintf(mes, "*conf:maxtin %d\r", (int)(p->measto * 1000.0+0.5));
+ if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ /* Set the measurement function to be Radiometric spectrum */
+ if ((ev = specbos_command(p, "*conf:func 6\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ /* Set the measurement format to ASCII */
+ if ((ev = specbos_command(p, "*conf:form 4\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ if ((ev = specbos_command(p, "*para:wavbeg?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ if (sscanf(buf, "Predefined start wave: %lf ",&p->wl_short) != 1) {
+ amutex_unlock(p->lock);
+ a1loge(p->log, 1, "specbos_init_inst: failed to parse start wave\n");
+ return ev;
+ }
+ a1logd(p->log, 1, " Short wl range %f\n",p->wl_short);
+
+ if ((ev = specbos_command(p, "*para:wavend?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ if (sscanf(buf, "Predefined end wave: %lf ",&p->wl_long) != 1) {
+ amutex_unlock(p->lock);
+ a1loge(p->log, 1, "specbos_init_inst: failed to parse end wave\n");
+ return ev;
+ }
+ if (p->wl_long > 830.0) /* Could go to 1000 with 1211 */
+ p->wl_long = 830.0;
+
+ a1logd(p->log, 1, " Long wl range %f\n",p->wl_long);
+
+ p->nbands = (int)((p->wl_long - p->wl_short + 1.0)/1.0 + 0.5);
+
+ /* Set the wavelength range and resolution */
+ sprintf(mes, "*conf:wran %d %d 1\r", (int)(p->wl_short+0.5), (int)(p->wl_long+0.5));
+ if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ /* Set to average just 1 reading */
+ if ((ev = specbos_command(p, "*conf:aver 1\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ if (p->log->verb) {
+ int val;
+ char *sp;
+
+ if ((ev = specbos_command(p, "*idn?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ if ((sp = strrchr(buf, '\r')) != NULL)
+ *sp = '\000';
+ a1logv(p->log, 1, " Identificaton: %s\n",buf);
+
+ if ((ev = specbos_command(p, "*vers?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+
+ if ((sp = strrchr(buf, '\r')) != NULL)
+ *sp = '\000';
+ a1logv(p->log, 1, " Firmware: %s\n",buf);
+
+ if ((ev = specbos_command(p, "*para:spnum?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ if (sscanf(buf, "spectrometer number: %d ",&val) == 1) {
+ a1logv(p->log, 1, " Spectrometer number: %d\n",val);
+ }
+
+ if ((ev = specbos_command(p, "*para:serno?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ if (sscanf(buf, "serial number: %d ",&val) == 1) {
+ a1logv(p->log, 1, " Serial number: %d\n",val);
+ }
+ }
+
+ /* Start the diffuser monitoring thread */
+ if ((p->th = new_athread(specbos_diff_thread, (void *)p)) == NULL) {
+ amutex_unlock(p->lock);
+ return SPECBOS_INT_THREADFAILED;
+ }
+
+ p->inited = 1;
+ a1logd(p->log, 2, "specbos_init_inst: instrument inited OK\n");
+ amutex_unlock(p->lock);
+
+ return inst_ok;
+}
+
+static inst_code specbos_measure_set_refresh(specbos *p);
+static inst_code specbos_imp_set_refresh(specbos *p);
+
+/* Get the ambient diffuser position */
+/* (This is not multithread safe) */
+static inst_code
+specbos_get_diffpos(
+ specbos *p, /* Object */
+ int *pos, /* 0 = display, 1 = ambient */
+ int nd /* nz = no debug message */
+) {
+ char buf[MAX_RD_SIZE];
+ int ec;
+
+ /* See if we're in emissive or ambient mode */
+ if ((ec = specbos_fcommand(p, "*contr:mhead?\r", buf, MAX_MES_SIZE, 1.0, 1, 0, nd)) != inst_ok) {
+ return specbos_interp_code((inst *)p, ec);
+ }
+ if (sscanf(buf, "mhead: %d ",pos) != 1) {
+ a1logd(p->log, 2, "specbos_init_coms: unrecognised measuring head string '%s'\n",icoms_fix(buf));
+ return inst_protocol_error;
+ }
+ return inst_ok;
+}
+
+/* Read a single sample */
+/* Return the dtp error code */
+static inst_code
+specbos_read_sample(
+inst *pp,
+char *name, /* Strip name (7 chars) */
+ipatch *val, /* Pointer to instrument patch value */
+instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
+ specbos *p = (specbos *)pp;
+ char buf[MAX_RD_SIZE];
+ int ec;
+ int user_trig = 0;
+ int pos = -1;
+ inst_code rv = inst_protocol_error;
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ amutex_lock(p->lock);
+
+ if (p->trig == inst_opt_trig_user) {
+ amutex_unlock(p->lock);
+
+ if (p->uicallback == NULL) {
+ a1logd(p->log, 1, "specbos: inst_opt_trig_user but no uicallback function set!\n");
+ return inst_unsupported;
+ }
+
+ for (;;) {
+ if ((rv = p->uicallback(p->uic_cntx, inst_armed)) != inst_ok) {
+ if (rv == inst_user_abort) {
+ return rv; /* Abort */
+ }
+ if (rv == inst_user_trig) {
+ user_trig = 1;
+ break; /* Trigger */
+ }
+ }
+ msec_sleep(200);
+ }
+ /* Notify of trigger */
+ if (p->uicallback)
+ p->uicallback(p->uic_cntx, inst_triggered);
+ amutex_lock(p->lock);
+
+ /* Progromatic Trigger */
+ } else {
+ /* Check for abort */
+ if (p->uicallback != NULL
+ && (rv = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort) {
+ amutex_unlock(p->lock);
+ return rv; /* Abort */
+ }
+ }
+
+ /* See if we're in emissive or ambient mode */
+ if ((rv = specbos_get_diffpos(p, &pos, 0) ) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+
+ if (p->mode & inst_mode_ambient) {
+ if (pos != 1) {
+ amutex_unlock(p->lock);
+ return specbos_interp_code((inst *)p, SPECBOS_SPOS_AMB);
+ }
+ } else {
+ if (pos != 0) {
+ amutex_unlock(p->lock);
+ return specbos_interp_code((inst *)p, SPECBOS_SPOS_EMIS);
+ }
+ }
+
+ /* Make sure the target laser is off */
+ if ((rv = specbos_command(p, "*contr:laser 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+
+ /* Attempt a refresh display frame rate calibration if needed */
+ if (p->refrmode != 0 && p->rrset == 0) {
+ if ((rv = specbos_measure_set_refresh(p)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+ }
+
+ /* Trigger a measurement */
+ if ((ec = specbos_fcommand(p, "*init\r", buf, MAX_MES_SIZE, 5.0 * p->measto + 2.0 , 1, 1, 0)) != SPECBOS_OK) {
+ amutex_unlock(p->lock);
+ return specbos_interp_code((inst *)p, ec);
+ }
+
+ /* Read the XYZ */
+ if ((ec = specbos_fcommand(p, "*fetch:XYZ\r", buf, MAX_RD_SIZE, 0.5, 3, 0, 0)) != SPECBOS_OK) {
+ amutex_unlock(p->lock);
+ return specbos_interp_code((inst *)p, ec);
+ }
+
+ if (sscanf(buf, " X: %lf Y: %lf Z: %lf ",
+ &val->XYZ[0], &val->XYZ[1], &val->XYZ[2]) == 3) {
+
+ /* This may not change anything since instrument may clamp */
+ if (clamp)
+ icmClamp3(val->XYZ, val->XYZ);
+ val->loc[0] = '\000';
+ if (p->mode & inst_mode_ambient) {
+ val->mtype = inst_mrt_ambient;
+ } else
+ val->mtype = inst_mrt_emission;
+ val->XYZ_v = 1; /* These are absolute XYZ readings */
+ val->sp.spec_n = 0;
+ val->duration = 0.0;
+ rv = inst_ok;
+ } else {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 1, "specbos_read_sample: failed to parse '%s'\n",buf);
+ return inst_protocol_error;
+ }
+
+ /* spectrum data is returned only if requested */
+ if (p->mode & inst_mode_spectral) {
+ int i, xsize;
+ char *cp, *ncp;
+
+ /* (Format 12 doesn't seem to work on the 1211) */
+ /* (Format 9 reportedly doesn't work on the 1201) */
+ /* The folling works on the 1211 and is reported to work on the 1201 */
+
+ /* Fetch the spectral readings */
+ if ((ec = specbos_fcommand(p, "*fetch:sprad\r", buf, MAX_RD_SIZE, 1.0, 2+p->nbands+1, 0, 0)) != SPECBOS_OK) {
+ return specbos_interp_code((inst *)p, ec);
+ }
+
+ val->sp.spec_n = p->nbands;
+ val->sp.spec_wl_short = p->wl_short;
+ val->sp.spec_wl_long = p->wl_long;
+
+ /* Spectral data is in W/nm/m^2 */
+ val->sp.norm = 1.0;
+ cp = buf;
+ for (i = -2; i < val->sp.spec_n; i++) {
+ if ((ncp = strchr(cp, '\r')) == NULL) {
+ amutex_unlock(p->lock);
+ a1logd(p->log, 1, "specbos_read_sample: failed to parse spectral\n");
+ return inst_protocol_error;
+ }
+ *ncp = '\000';
+ if (i >= 0) {
+ val->sp.spec[i] = 1000.0 * atof(cp); /* Convert to mW/m^2/nm */
+ if (p->mode & inst_mode_ambient)
+ val->mtype = inst_mrt_ambient;
+ }
+ cp = ncp+1;
+ }
+ }
+ amutex_unlock(p->lock);
+
+
+ if (user_trig)
+ return inst_user_trig;
+ return rv;
+}
+
+/* Set the instrument to match the current refresh settings */
+/* (Not thread safe) */
+static inst_code
+specbos_imp_set_refresh(specbos *p) {
+ char buf[MAX_MES_SIZE];
+ inst_code rv;
+
+ if (p->model == 1201)
+ return inst_unsupported;
+
+ /* Set synchronised read if we should do so */
+ if (p->refrmode != 0 && p->refrvalid) {
+ char mes[100];
+ if ((rv = specbos_command(p, "*conf:cycmod 1\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ return rv;
+ }
+ sprintf(mes,"*conf:cyctim %f\r",p->refperiod * 1e6);
+ if ((rv = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ return rv;
+ }
+ a1logd(p->log,5,"specbos_imp_set_refresh set refresh rate to %f Hz\n",1.0/p->refperiod);
+ } else {
+ if ((rv = specbos_command(p, "*conf:cycmod 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ return rv;
+ }
+ a1logd(p->log,5,"specbos_imp_set_refresh set non-refresh mode\n");
+ }
+ return inst_ok;
+}
+
+/* Implementation of read refresh rate */
+/* (Not thread safe) */
+/* Return 0.0 if none detectable */
+static inst_code
+specbos_imp_measure_refresh(
+specbos *p,
+double *ref_rate
+) {
+ char buf[MAX_MES_SIZE], *cp;
+ double refperiod = 0.0;
+ int ec;
+ inst_code rv;
+
+ if (p->model == 1201)
+ return inst_unsupported;
+
+ /* Make sure the target laser is off */
+ if ((rv = specbos_command(p, "*contr:laser 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ return rv;
+ }
+
+ if ((ec = specbos_fcommand(p, "*contr:cyctim 200 4000\r", buf, MAX_MES_SIZE, 5.0, 1, 2, 0)) != SPECBOS_OK) {
+ return specbos_interp_code((inst *)p, ec);
+ }
+
+ if ((cp = strchr(buf, 'c')) == NULL)
+ cp = buf;
+ if (sscanf(cp, "cyctim[ms]: %lf ", &refperiod) != 1) {
+ a1logd(p->log, 1, "specbos_read_refrate rate: failed to parse string '%s'\n",icoms_fix(buf));
+ *ref_rate = 0.0;
+ return inst_misread;
+ }
+
+ if (refperiod == 0.0)
+ *ref_rate = 0.0;
+ else
+ *ref_rate = 1000.0/refperiod;
+
+ return inst_ok;
+}
+
+/* Read an emissive refresh rate */
+static inst_code
+specbos_read_refrate(
+inst *pp,
+double *ref_rate
+) {
+ specbos *p = (specbos *)pp;
+ char buf[MAX_MES_SIZE];
+ double refrate;
+ inst_code rv;
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ amutex_lock(p->lock);
+ if ((rv = specbos_imp_measure_refresh(p, &refrate)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+ amutex_unlock(p->lock);
+
+ if (refrate == 0.0)
+ return inst_misread;
+
+ *ref_rate = refrate;
+
+ return inst_ok;
+}
+
+/* Measure and then set refperiod, refrate if possible */
+static inst_code
+specbos_measure_set_refresh(
+ specbos *p /* Object */
+) {
+ inst_code rv;
+ double refrate = 0.0;
+ int mul;
+ double pval;
+
+ amutex_lock(p->lock);
+ if ((rv = specbos_imp_measure_refresh(p, &refrate)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+
+ if (refrate != 0.0) {
+ p->refrate = refrate;
+ p->refrvalid = 1;
+ p->refperiod = 1.0/refrate;
+ } else {
+ p->refrate = 0.0;
+ p->refrvalid = 0;
+ p->refperiod = 0.0;
+ }
+ p->rrset = 1;
+
+ if ((rv = specbos_imp_set_refresh(p)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+ amutex_unlock(p->lock);
+
+ return inst_ok;
+}
+
+/* Return needed and available inst_cal_type's */
+static inst_code specbos_get_n_a_cals(inst *pp, inst_cal_type *pn_cals, inst_cal_type *pa_cals) {
+ specbos *p = (specbos *)pp;
+ inst_cal_type n_cals = inst_calt_none;
+ inst_cal_type a_cals = inst_calt_none;
+
+ if (p->refrmode != 0) {
+ if (p->rrset == 0)
+ n_cals |= inst_calt_ref_freq;
+ a_cals |= inst_calt_ref_freq;
+ }
+
+ if (pn_cals != NULL)
+ *pn_cals = n_cals;
+
+ if (pa_cals != NULL)
+ *pa_cals = a_cals;
+
+ return inst_ok;
+}
+
+/* Request an instrument calibration. */
+inst_code specbos_calibrate(
+inst *pp,
+inst_cal_type *calt, /* Calibration type to do/remaining */
+inst_cal_cond *calc, /* Current condition/desired condition */
+char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
+) {
+ specbos *p = (specbos *)pp;
+ inst_code ev;
+ inst_cal_type needed, available;
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ id[0] = '\000';
+
+ if ((ev = specbos_get_n_a_cals((inst *)p, &needed, &available)) != inst_ok)
+ return ev;
+
+ /* Translate inst_calt_all/needed into something specific */
+ if (*calt == inst_calt_all
+ || *calt == inst_calt_needed
+ || *calt == inst_calt_available) {
+ if (*calt == inst_calt_all)
+ *calt = (needed & inst_calt_n_dfrble_mask) | inst_calt_ap_flag;
+ else if (*calt == inst_calt_needed)
+ *calt = needed & inst_calt_n_dfrble_mask;
+ else if (*calt == inst_calt_available)
+ *calt = available & inst_calt_n_dfrble_mask;
+
+ a1logd(p->log,4,"specbos_calibrate: doing calt 0x%x\n",calt);
+
+ if ((*calt & inst_calt_n_dfrble_mask) == 0) /* Nothing todo */
+ return inst_ok;
+ }
+
+ /* See if it's a calibration we understand */
+ if (*calt & ~available & inst_calt_all_mask) {
+ return inst_unsupported;
+ }
+
+ if ((*calt & inst_calt_ref_freq) && p->refrmode != 0) {
+ inst_code ev = inst_ok;
+
+
+ if (*calc != inst_calc_emis_80pc) {
+ *calc = inst_calc_emis_80pc;
+ return inst_cal_setup;
+ }
+
+ /* Do refresh display rate calibration */
+ if ((ev = specbos_measure_set_refresh(p)) != inst_ok)
+ return ev;
+
+ *calt &= ~inst_calt_ref_freq;
+ }
+ return inst_ok;
+}
+
+/* Return the last calibrated refresh rate in Hz. Returns: */
+static inst_code specbos_get_refr_rate(inst *pp,
+double *ref_rate
+) {
+ specbos *p = (specbos *)pp;
+ if (p->refrvalid) {
+ *ref_rate = p->refrate;
+ return inst_ok;
+ } else if (p->rrset) {
+ *ref_rate = 0.0;
+ return inst_misread;
+ }
+ return inst_needs_cal;
+}
+
+/* Set the calibrated refresh rate in Hz. */
+/* Set refresh rate to 0.0 to mark it as invalid */
+/* Rates outside the range 5.0 to 150.0 Hz will return an error */
+static inst_code specbos_set_refr_rate(inst *pp,
+double ref_rate
+) {
+ specbos *p = (specbos *)pp;
+ inst_code rv;
+
+ a1logd(p->log,5,"specbos_set_refr_rate %f Hz\n",ref_rate);
+
+ if (ref_rate != 0.0 && (ref_rate < 5.0 || ref_rate > 150.0))
+ return inst_bad_parameter;
+
+ p->refrate = ref_rate;
+ if (ref_rate == 0.0)
+ p->refrvalid = 0;
+ else {
+ p->refperiod = 1.0/ref_rate;
+ p->refrvalid = 1;
+ }
+ p->rrset = 1;
+
+ /* Set the instrument to given refresh rate */
+ amutex_lock(p->lock);
+ if ((rv = specbos_imp_set_refresh(p)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+ amutex_unlock(p->lock);
+
+ return inst_ok;
+}
+
+
+/* Error codes interpretation */
+static char *
+specbos_interp_error(inst *pp, int ec) {
+// specbos *p = (specbos *)pp;
+ ec &= inst_imask;
+ switch (ec) {
+ case SPECBOS_INTERNAL_ERROR:
+ return "Internal software error";
+ case SPECBOS_TIMEOUT:
+ return "Communications timeout";
+ case SPECBOS_COMS_FAIL:
+ return "Communications failure";
+ case SPECBOS_UNKNOWN_MODEL:
+ return "Not a JETI specbos";
+ case SPECBOS_DATA_PARSE_ERROR:
+ return "Data from specbos didn't parse as expected";
+ case SPECBOS_SPOS_EMIS:
+ return "Ambient filter should be removed";
+ case SPECBOS_SPOS_AMB:
+ return "Ambient filter should be used";
+
+ case SPECBOS_OK:
+ return "No device error";
+
+ case SPECBOS_COMMAND:
+ return "Command";
+ case SPECBOS_PASSWORD:
+ return "Password";
+ case SPECBOS_DIGIT:
+ return "Digit";
+ case SPECBOS_ARG_1:
+ return "Argument 1";
+ case SPECBOS_ARG_2:
+ return "Argument 2";
+ case SPECBOS_ARG_3:
+ return "Argument 3";
+ case SPECBOS_ARG_4:
+ return "Argument 4";
+ case SPECBOS_PARAM:
+ return "Parameter argument";
+ case SPECBOS_CONFIG_ARG:
+ return "Config argument";
+ case SPECBOS_CONTROL_ARG:
+ return "Control argument";
+ case SPECBOS_READ_ARG:
+ return "Read argument";
+ case SPECBOS_FETCH_ARG:
+ return "Fetch argument";
+ case SPECBOS_MEAS_ARG:
+ return "Measuring argument";
+ case SPECBOS_CALC_ARG:
+ return "Calculation argument";
+ case SPECBOS_CAL_ARG:
+ return "Calibration argument";
+ case SPECBOS_PARAM_CHSUM:
+ return "Parameter checksum";
+ case SPECBOS_USERFILE_CHSUM:
+ return "Userfile checksum";
+ case SPECBOS_USERFILE2_CHSUM:
+ return "Userfile2 checksum";
+ case SPECBOS_USERFILE2_ARG:
+ return "Userfile2 argument";
+ case SPECBOS_OVEREXPOSED:
+ return "Overexposure";
+ case SPECBOS_UNDEREXPOSED:
+ return "Underexposure";
+ case SPECBOS_ADAPT_INT_TIME:
+ return "Adaption integration time";
+ case SPECBOS_NO_SHUTTER:
+ return "Shutter doesn't exist";
+ case SPECBOS_NO_DARK_MEAS:
+ return "No dark measurement";
+ case SPECBOS_NO_REF_MEAS:
+ return "No reference measurement";
+ case SPECBOS_NO_TRANS_MEAS:
+ return "No transmission measurement";
+ case SPECBOS_NO_RADMTRC_CALC:
+ return "No radiometric calculation";
+ case SPECBOS_NO_CCT_CALC:
+ return "No CCT calculation";
+ case SPECBOS_NO_CRI_CALC:
+ return "No CRI calculation";
+ case SPECBOS_NO_DARK_COMP:
+ return "No dark compensation";
+ case SPECBOS_NO_LIGHT_MEAS:
+ return "No light measurement";
+ case SPECBOS_NO_PEAK_CALC:
+ return "No peak calculation";
+ case SPECBOS_CAL_DATA:
+ return "Calibration data";
+ case SPECBOS_EXCEED_CAL_WL:
+ return "Exceeded calibration wavelength";
+ case SPECBOS_SCAN_BREAK:
+ return "Scan break";
+ case SPECBOS_TO_CYC_OPT_TRIG:
+ return "Timeout cycle on optical trigger";
+ case SPECBOS_DIV_CYC_TIME:
+ return "Divider cycle time";
+ case SPECBOS_WRITE_FLASH_PARM:
+ return "Write parameter to flash";
+ case SPECBOS_READ_FLASH_PARM:
+ return "Read parameter from flash";
+ case SPECBOS_FLASH_ERASE:
+ return "Erase flash";
+ case SPECBOS_NO_CALIB_FILE:
+ return "No calibration file";
+ case SPECBOS_CALIB_FILE_HEADER:
+ return "Calibration file header";
+ case SPECBOS_WRITE_CALIB_FILE:
+ return "Write calibration file";
+ case SPECBOS_CALIB_FILE_VALS:
+ return "Calibration file values";
+ case SPECBOS_CALIB_FILE_NO:
+ return "Calibration file number";
+ case SPECBOS_CLEAR_CALIB_FILE:
+ return "Clear calibration file";
+ case SPECBOS_CLEAR_CALIB_ARG:
+ return "Clear calibration file argument";
+ case SPECBOS_NO_LAMP_FILE:
+ return "No lamp file";
+ case SPECBOS_LAMP_FILE_HEADER:
+ return "Lamp file header";
+ case SPECBOS_WRITE_LAMP_FILE:
+ return "Write lamp file";
+ case SPECBOS_LAMP_FILE_VALS:
+ return "Lamp file values";
+ case SPECBOS_LAMP_FILE_NO:
+ return "Lamp file number";
+ case SPECBOS_CLEAR_LAMP_FILE:
+ return "Clear lamp file";
+ case SPECBOS_CLEAR_LAMP_FILE_ARG:
+ return "Clear lamp file argument";
+ case SPECBOS_RAM_CHECK:
+ return "RAM check";
+ case SPECBOS_DATA_OUTPUT:
+ return "Data output";
+ case SPECBOS_RAM_LOW:
+ return "Insufcient RAM";
+ case SPECBOS_FIRST_MEM_ALLOC:
+ return "First memory allocation";
+ case SPECBOS_SECOND_MEM_ALLOC:
+ return "Second memory allocation";
+ case SPECBOS_THIRD_MEM_ALLOC:
+ return "Third memory allocation";
+ case SPECBOS_RADMTRC_WL_RANGE:
+ return "Wavelength range for radiometric calculation";
+ case SPECBOS_BOOT_BAT_POWER:
+ return "Boot by battery power";
+ case SPECBOS_TRIG_CONF_1:
+ return "Trigger configuration 1";
+ case SPECBOS_TRIG_CONF_2:
+ return "Trigger configuration 2";
+
+ case SPECBOS_INT_THREADFAILED:
+ return "Starting diffuser position thread failed";
+
+ default:
+ return "Unknown error code";
+ }
+}
+
+
+/* Convert a machine specific error code into an abstract dtp code */
+static inst_code
+specbos_interp_code(inst *pp, int ec) {
+
+ ec &= inst_imask;
+ switch (ec) {
+
+ case SPECBOS_OK:
+ return inst_ok;
+
+ case SPECBOS_INTERNAL_ERROR:
+ case SPECBOS_INT_THREADFAILED:
+ return inst_internal_error | ec;
+
+ case SPECBOS_TIMEOUT:
+ case SPECBOS_COMS_FAIL:
+ return inst_coms_fail | ec;
+
+ case SPECBOS_UNKNOWN_MODEL:
+ return inst_unknown_model | ec;
+
+ case SPECBOS_DATA_PARSE_ERROR:
+ return inst_protocol_error | ec;
+
+ case SPECBOS_SPOS_EMIS:
+ case SPECBOS_SPOS_AMB:
+ return inst_wrong_config | ec;
+
+ case SPECBOS_COMMAND:
+ case SPECBOS_DIGIT:
+ case SPECBOS_ARG_1:
+ case SPECBOS_ARG_2:
+ case SPECBOS_ARG_3:
+ case SPECBOS_ARG_4:
+ case SPECBOS_PARAM:
+ case SPECBOS_CONFIG_ARG:
+ case SPECBOS_CONTROL_ARG:
+ case SPECBOS_READ_ARG:
+ case SPECBOS_FETCH_ARG:
+ case SPECBOS_MEAS_ARG:
+ case SPECBOS_CALC_ARG:
+ case SPECBOS_CAL_ARG:
+ return inst_bad_parameter | ec;
+
+ case SPECBOS_OVEREXPOSED:
+ case SPECBOS_UNDEREXPOSED:
+ return inst_misread | ec;
+
+ case SPECBOS_PASSWORD:
+ case SPECBOS_PARAM_CHSUM:
+ case SPECBOS_USERFILE_CHSUM:
+ case SPECBOS_USERFILE2_CHSUM:
+ case SPECBOS_USERFILE2_ARG:
+ case SPECBOS_ADAPT_INT_TIME:
+ case SPECBOS_NO_SHUTTER:
+ case SPECBOS_NO_DARK_MEAS:
+ case SPECBOS_NO_REF_MEAS:
+ case SPECBOS_NO_TRANS_MEAS:
+ case SPECBOS_NO_RADMTRC_CALC:
+ case SPECBOS_NO_CCT_CALC:
+ case SPECBOS_NO_CRI_CALC:
+ case SPECBOS_NO_DARK_COMP:
+ case SPECBOS_NO_LIGHT_MEAS:
+ case SPECBOS_NO_PEAK_CALC:
+ case SPECBOS_CAL_DATA:
+ case SPECBOS_EXCEED_CAL_WL:
+ case SPECBOS_SCAN_BREAK:
+ case SPECBOS_TO_CYC_OPT_TRIG:
+ case SPECBOS_DIV_CYC_TIME:
+ case SPECBOS_WRITE_FLASH_PARM:
+ case SPECBOS_READ_FLASH_PARM:
+ case SPECBOS_FLASH_ERASE:
+ case SPECBOS_NO_CALIB_FILE:
+ case SPECBOS_CALIB_FILE_HEADER:
+ case SPECBOS_WRITE_CALIB_FILE:
+ case SPECBOS_CALIB_FILE_VALS:
+ case SPECBOS_CALIB_FILE_NO:
+ case SPECBOS_CLEAR_CALIB_FILE:
+ case SPECBOS_CLEAR_CALIB_ARG:
+ case SPECBOS_NO_LAMP_FILE:
+ case SPECBOS_LAMP_FILE_HEADER:
+ case SPECBOS_WRITE_LAMP_FILE:
+ case SPECBOS_LAMP_FILE_VALS:
+ case SPECBOS_LAMP_FILE_NO:
+ case SPECBOS_CLEAR_LAMP_FILE:
+ case SPECBOS_CLEAR_LAMP_FILE_ARG:
+ case SPECBOS_RAM_CHECK:
+ case SPECBOS_DATA_OUTPUT:
+ case SPECBOS_RAM_LOW:
+ case SPECBOS_FIRST_MEM_ALLOC:
+ case SPECBOS_SECOND_MEM_ALLOC:
+ case SPECBOS_THIRD_MEM_ALLOC:
+ case SPECBOS_RADMTRC_WL_RANGE:
+ case SPECBOS_BOOT_BAT_POWER:
+ case SPECBOS_TRIG_CONF_1:
+ case SPECBOS_TRIG_CONF_2:
+ return inst_hardware_fail | ec;
+ }
+ return inst_other_error | ec;
+}
+
+/* Destroy ourselves */
+static void
+specbos_del(inst *pp) {
+ if (pp != NULL) {
+ specbos *p = (specbos *)pp;
+ if (p->th != NULL) { /* Terminate diffuser monitor thread */
+ int i;
+ p->th_term = 1; /* Tell thread to exit on error */
+ for (i = 0; p->th_termed == 0 && i < 5; i++)
+ msec_sleep(100); /* Wait for thread to terminate */
+ if (i >= 5) {
+ a1logd(p->log,3,"specbos diffuser thread termination failed\n");
+ }
+ p->th->del(p->th);
+ }
+ if (p->icom != NULL)
+ p->icom->del(p->icom);
+ amutex_del(p->lock);
+ free(p);
+ }
+}
+
+/* Return the instrument mode capabilities */
+void specbos_capabilities(inst *pp,
+inst_mode *pcap1,
+inst2_capability *pcap2,
+inst3_capability *pcap3) {
+ specbos *p = (specbos *)pp;
+ inst_mode cap1 = 0;
+ inst2_capability cap2 = 0;
+
+ cap1 |= inst_mode_emis_tele
+ | inst_mode_ambient
+ | inst_mode_colorimeter
+ | inst_mode_spectral
+ | inst_mode_emis_refresh_ovd
+ | inst_mode_emis_norefresh_ovd
+ ;
+
+ /* can inst2_has_sensmode, but not report it asynchronously */
+ cap2 |= inst2_prog_trig
+ | inst2_user_trig
+ | inst2_disptype
+ | inst2_has_target /* Has a laser target */
+ ;
+
+ if (p->model != 1201) {
+ cap2 |= inst2_emis_refr_meas;
+ cap2 |= inst2_set_refresh_rate;
+ cap2 |= inst2_get_refresh_rate;
+ }
+
+ if (pcap1 != NULL)
+ *pcap1 = cap1;
+ if (pcap2 != NULL)
+ *pcap2 = cap2;
+ if (pcap3 != NULL)
+ *pcap3 = inst3_none;
+}
+
+/* Return current or given configuration available measurement modes. */
+static inst_code specbos_meas_config(
+inst *pp,
+inst_mode *mmodes,
+inst_cal_cond *cconds,
+int *conf_ix
+) {
+ specbos *p = (specbos *)pp;
+ inst_code ev;
+ inst_mode mval;
+ int pos;
+
+ if (mmodes != NULL)
+ *mmodes = inst_mode_none;
+ if (cconds != NULL)
+ *cconds = inst_calc_unknown;
+
+ if (conf_ix == NULL
+ || *conf_ix < 0
+ || *conf_ix > 1) {
+ /* Return current configuration measrement modes */
+ amutex_lock(p->lock);
+ if ((ev = specbos_get_diffpos(p, &pos, 0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ amutex_unlock(p->lock);
+ } else {
+ /* Return given configuration measurement modes */
+ pos = *conf_ix;
+ }
+
+ if (pos == 1) {
+ mval = inst_mode_emis_ambient;
+ } else if (pos == 0) {
+ mval |= inst_mode_emis_tele;
+ }
+
+ /* Add the extra dependent and independent modes */
+ mval |= inst_mode_emis_refresh_ovd
+ | inst_mode_emis_norefresh_ovd
+ | inst_mode_colorimeter
+ | inst_mode_spectral;
+
+ if (mmodes != NULL)
+ *mmodes = mval;
+
+ /* Return configuration index returned */
+ if (conf_ix != NULL)
+ *conf_ix = pos;
+
+ return inst_ok;
+}
+
+/* Check device measurement mode */
+inst_code specbos_check_mode(inst *pp, inst_mode m) {
+ inst_mode cap;
+
+ if (!pp->gotcoms)
+ return inst_no_coms;
+ if (!pp->inited)
+ return inst_no_init;
+
+ pp->capabilities(pp, &cap, NULL, NULL);
+
+ /* Simple test */
+ if (m & ~cap)
+ return inst_unsupported;
+
+ /* Only tele emission mode supported */
+ if (!IMODETST(m, inst_mode_emis_tele)
+ && !IMODETST(m, inst_mode_emis_ambient)) {
+ return inst_unsupported;
+ }
+
+ return inst_ok;
+}
+
+/* Set device measurement mode */
+inst_code specbos_set_mode(inst *pp, inst_mode m) {
+ specbos *p = (specbos *)pp;
+ int refrmode;
+ inst_code ev;
+
+ if ((ev = specbos_check_mode(pp, m)) != inst_ok)
+ return ev;
+
+ p->mode = m;
+
+
+ if (p->model != 1201) { /* Can't set refresh mode on 1201 */
+
+ /* Effective refresh mode may change */
+ refrmode = p->refrmode;
+ if ( IMODETST(p->mode, inst_mode_emis_norefresh_ovd)) { /* Must test this first! */
+ refrmode = 0;
+ } else if (IMODETST(p->mode, inst_mode_emis_refresh_ovd)) {
+ refrmode = 1;
+ }
+
+ if (p->refrmode != refrmode) {
+ p->rrset = 0; /* This is a hint we may have swapped displays */
+ p->refrvalid = 0;
+ }
+ p->refrmode = refrmode;
+ }
+
+ return inst_ok;
+}
+
+inst_disptypesel specbos_disptypesel[3] = {
+ {
+ inst_dtflags_default,
+ 1,
+ "nl",
+ "Non-Refresh display",
+ 0,
+ 0
+ },
+ {
+ inst_dtflags_none, /* flags */
+ 2, /* cbid */
+ "rc", /* sel */
+ "Refresh display", /* desc */
+ 1, /* refr */
+ 1 /* ix */
+ },
+ {
+ inst_dtflags_end,
+ 0,
+ "",
+ "",
+ 0,
+ 0
+ }
+};
+
+/* Get mode and option details */
+static inst_code specbos_get_disptypesel(
+inst *pp,
+int *pnsels, /* Return number of display types */
+inst_disptypesel **psels, /* Return the array of display types */
+int allconfig, /* nz to return list for all configs, not just current. */
+int recreate /* nz to re-check for new ccmx & ccss files */
+) {
+ specbos *p = (specbos *)pp;
+ inst_code rv = inst_ok;
+
+ if ((!allconfig && (p->mode & inst_mode_ambient)) /* If set to Ambient */
+ || p->model == 1201) { /* Or 1201, return empty list */
+
+ if (pnsels != NULL)
+ *pnsels = 0;
+
+ if (psels != NULL)
+ *psels = NULL;
+
+ return inst_ok;
+ }
+
+
+ if (pnsels != NULL)
+ *pnsels = 2;
+
+ if (psels != NULL)
+ *psels = specbos_disptypesel;
+
+ return inst_ok;
+}
+
+/* Given a display type entry, setup for that type */
+static inst_code set_disp_type(specbos *p, inst_disptypesel *dentry) {
+ inst_code rv;
+ int refrmode;
+
+ refrmode = dentry->refr;
+
+ a1logd(p->log,5,"specbos set_disp_type refmode %d\n",refrmode);
+
+ if ( IMODETST(p->mode, inst_mode_emis_norefresh_ovd)) { /* Must test this first! */
+ refrmode = 0;
+ } else if (IMODETST(p->mode, inst_mode_emis_refresh_ovd)) {
+ refrmode = 1;
+ }
+
+ if (p->refrmode != refrmode)
+ p->rrset = 0; /* This is a hint we may have swapped displays */
+ p->refrmode = refrmode;
+
+ amutex_lock(p->lock);
+ if ((rv = specbos_imp_set_refresh(p)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return rv;
+ }
+ amutex_unlock(p->lock);
+
+ return inst_ok;
+}
+
+/* Set the display type */
+static inst_code specbos_set_disptype(inst *pp, int ix) {
+ specbos *p = (specbos *)pp;
+ inst_code ev;
+ inst_disptypesel *dentry;
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ if (p->model == 1201) /* No display type to select on 1201 */
+ return inst_unsupported;
+
+ if (ix < 0 || ix >= 2)
+ return inst_unsupported;
+
+ a1logd(p->log,5,"specbos specbos_set_disptype ix %d\n",ix);
+ dentry = &specbos_disptypesel[ix];
+
+ if ((ev = set_disp_type(p, dentry)) != inst_ok) {
+ return ev;
+ }
+
+ return inst_ok;
+}
+
+/*
+ * set or reset an optional mode
+ *
+ * Some options talk to the instrument, and these will
+ * error if it hasn't been initialised.
+ */
+static inst_code
+specbos_get_set_opt(inst *pp, inst_opt_type m, ...)
+{
+ specbos *p = (specbos *)pp;
+ char buf[MAX_MES_SIZE];
+ inst_code ev = inst_ok;
+
+ a1logd(p->log, 5, "specbos_get_set_opt: opt type 0x%x\n",m);
+
+ /* Record the trigger mode */
+ if (m == inst_opt_trig_prog
+ || m == inst_opt_trig_user) {
+ p->trig = m;
+ return inst_ok;
+ }
+
+ /* Set laser target state */
+ if (m == inst_opt_set_target_state) {
+ va_list args;
+ int state = 0;
+
+ va_start(args, m);
+ state = va_arg(args, int);
+ va_end(args);
+
+ amutex_lock(p->lock);
+ if (state == 2) {
+ int lstate = -1;
+ if ((ev = specbos_command(p, "*contr:laser?\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ a1loge(p->log, 1, "specbos_get_set_opt: failed to send laser? command\n");
+ return ev;
+ }
+ if (sscanf(buf, "laser: %d ",&lstate) != 1) {
+ amutex_unlock(p->lock);
+ a1loge(p->log, 1, "specbos_get_set_opt: failed to parse laser state\n");
+ return ev;
+ }
+ a1logd(p->log, 5, " Laser state = %d\n",lstate);
+ if (lstate == 0)
+ lstate = 1;
+ else if (lstate == 1)
+ lstate = 0;
+ if (lstate == 0 || lstate == 1) {
+ char mes[100];
+ sprintf(mes,"*contr:laser %d\r",lstate);
+ if ((ev = specbos_command(p, mes, buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ }
+ } else if (state == 1) {
+ if ((ev = specbos_command(p, "*contr:laser 1\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ } else if (state == 0) {
+ if ((ev = specbos_command(p, "*contr:laser 0\r", buf, MAX_MES_SIZE, 1.0)) != inst_ok) {
+ amutex_unlock(p->lock);
+ return ev;
+ }
+ }
+ amutex_unlock(p->lock);
+ return inst_ok;
+ }
+
+ if (!p->gotcoms)
+ return inst_no_coms;
+ if (!p->inited)
+ return inst_no_init;
+
+ return inst_unsupported;
+}
+
+/* Constructor */
+extern specbos *new_specbos(icoms *icom, instType itype) {
+ specbos *p;
+ if ((p = (specbos *)calloc(sizeof(specbos),1)) == NULL) {
+ a1loge(icom->log, 1, "new_specbos: malloc failed!\n");
+ return NULL;
+ }
+
+ p->log = new_a1log_d(icom->log);
+
+ p->init_coms = specbos_init_coms;
+ p->init_inst = specbos_init_inst;
+ p->capabilities = specbos_capabilities;
+ p->meas_config = specbos_meas_config;
+ p->check_mode = specbos_check_mode;
+ p->set_mode = specbos_set_mode;
+ p->get_disptypesel = specbos_get_disptypesel;
+ p->set_disptype = specbos_set_disptype;
+ p->get_set_opt = specbos_get_set_opt;
+ p->read_sample = specbos_read_sample;
+ p->read_refrate = specbos_read_refrate;
+ p->get_n_a_cals = specbos_get_n_a_cals;
+ p->calibrate = specbos_calibrate;
+ p->get_refr_rate = specbos_get_refr_rate;
+ p->set_refr_rate = specbos_set_refr_rate;
+ p->interp_error = specbos_interp_error;
+ p->del = specbos_del;
+
+ p->icom = icom;
+ p->itype = icom->itype;
+ if (p->itype == instSpecbos1201)
+ p->model = 1201;
+
+ amutex_init(p->lock);
+
+ return p;
+}
+
diff --git a/spectro/specbos.h b/spectro/specbos.h
new file mode 100644
index 0000000..2bc601e
--- /dev/null
+++ b/spectro/specbos.h
@@ -0,0 +1,160 @@
+#ifndef SPECBOS_H
+
+/*
+ * Argyll Color Correction System
+ *
+ * JETI specbos related defines
+ *
+ * Author: Graeme W. Gill
+ * Date: 13/3/2013
+ *
+ * Copyright 2001 - 2013, Graeme W. Gill
+ * All rights reserved.
+ *
+ * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
+ * see the License2.txt file for licencing details.
+ *
+ * Based on DTP02.h
+ */
+
+/*
+ If you make use of the instrument driver code here, please note
+ that it is the author(s) of the code who take responsibility
+ for its operation. Any problems or queries regarding driving
+ instruments with the Argyll drivers, should be directed to
+ the Argyll's author(s), and not to any other party.
+
+ If there is some instrument feature or function that you
+ would like supported here, it is recommended that you
+ contact Argyll's author(s) first, rather than attempt to
+ modify the software yourself, if you don't have firm knowledge
+ of the instrument communicate protocols. There is a chance
+ that an instrument could be damaged by an incautious command
+ sequence, and the instrument companies generally cannot and
+ will not support developers that they have not qualified
+ and agreed to support.
+ */
+
+#include "inst.h"
+
+/* Fake Error codes */
+#define SPECBOS_INTERNAL_ERROR 0xff01 /* Internal software error */
+#define SPECBOS_TIMEOUT 0xff02 /* Communication timeout */
+#define SPECBOS_COMS_FAIL 0xff03 /* Communication failure */
+#define SPECBOS_UNKNOWN_MODEL 0xff04 /* Not a JETI specbos */
+#define SPECBOS_DATA_PARSE_ERROR 0xff05 /* Read data parsing error */
+
+#define SPECBOS_SPOS_EMIS 0xff06 /* Needs to be in emsissive configuration */
+#define SPECBOS_SPOS_AMB 0xff07 /* Needs to be in ambient configuration */
+
+/* Real instrument error code */
+#define SPECBOS_OK 0
+
+#define SPECBOS_COMMAND 4
+#define SPECBOS_PASSWORD 7
+#define SPECBOS_DIGIT 8
+#define SPECBOS_ARG_1 10
+#define SPECBOS_ARG_2 11
+#define SPECBOS_ARG_3 12
+#define SPECBOS_ARG_4 13
+#define SPECBOS_PARAM 20
+#define SPECBOS_CONFIG_ARG 21
+#define SPECBOS_CONTROL_ARG 22
+#define SPECBOS_READ_ARG 23
+#define SPECBOS_FETCH_ARG 24
+#define SPECBOS_MEAS_ARG 25
+#define SPECBOS_CALC_ARG 26
+#define SPECBOS_CAL_ARG 27
+#define SPECBOS_PARAM_CHSUM 101
+#define SPECBOS_USERFILE_CHSUM 102
+#define SPECBOS_USERFILE2_CHSUM 103
+#define SPECBOS_USERFILE2_ARG 104
+#define SPECBOS_OVEREXPOSED 120
+#define SPECBOS_UNDEREXPOSED 121
+#define SPECBOS_ADAPT_INT_TIME 123
+#define SPECBOS_NO_SHUTTER 130
+#define SPECBOS_NO_DARK_MEAS 131
+#define SPECBOS_NO_REF_MEAS 132
+#define SPECBOS_NO_TRANS_MEAS 133
+#define SPECBOS_NO_RADMTRC_CALC 134
+#define SPECBOS_NO_CCT_CALC 135
+#define SPECBOS_NO_CRI_CALC 136
+#define SPECBOS_NO_DARK_COMP 137
+#define SPECBOS_NO_LIGHT_MEAS 138
+#define SPECBOS_NO_PEAK_CALC 139
+#define SPECBOS_CAL_DATA 140
+#define SPECBOS_EXCEED_CAL_WL 141
+#define SPECBOS_SCAN_BREAK 147
+#define SPECBOS_TO_CYC_OPT_TRIG 160
+#define SPECBOS_DIV_CYC_TIME 161
+#define SPECBOS_WRITE_FLASH_PARM 170
+#define SPECBOS_READ_FLASH_PARM 171
+#define SPECBOS_FLASH_ERASE 172
+#define SPECBOS_NO_CALIB_FILE 180
+#define SPECBOS_CALIB_FILE_HEADER 181
+#define SPECBOS_WRITE_CALIB_FILE 182
+#define SPECBOS_CALIB_FILE_VALS 183
+#define SPECBOS_CALIB_FILE_NO 184
+#define SPECBOS_CLEAR_CALIB_FILE 186
+#define SPECBOS_CLEAR_CALIB_ARG 187
+#define SPECBOS_NO_LAMP_FILE 190
+#define SPECBOS_LAMP_FILE_HEADER 191
+#define SPECBOS_WRITE_LAMP_FILE 192
+#define SPECBOS_LAMP_FILE_VALS 193
+#define SPECBOS_LAMP_FILE_NO 194
+#define SPECBOS_CLEAR_LAMP_FILE 196
+#define SPECBOS_CLEAR_LAMP_FILE_ARG 197
+#define SPECBOS_RAM_CHECK 200
+#define SPECBOS_DATA_OUTPUT 220
+#define SPECBOS_RAM_LOW 225
+#define SPECBOS_FIRST_MEM_ALLOC 230
+#define SPECBOS_SECOND_MEM_ALLOC 231
+#define SPECBOS_THIRD_MEM_ALLOC 232
+#define SPECBOS_RADMTRC_WL_RANGE 251
+#define SPECBOS_BOOT_BAT_POWER 280
+#define SPECBOS_TRIG_CONF_1 500
+#define SPECBOS_TRIG_CONF_2 501
+
+/* Internal software errors */
+#define SPECBOS_INT_THREADFAILED 1000
+
+/* SPECBOS communication object */
+struct _specbos {
+ INST_OBJ_BASE
+
+ amutex lock; /* Command lock */
+
+ int model; /* JETI specbos model number */
+ /* 1201 */
+ /* 1211 */
+
+ inst_mode mode; /* Currently instrument mode */
+
+ int refrmode; /* nz if in refresh display mode */
+ /* (1201 has a refresh mode ?? but can't measure frequency) */
+ int rrset; /* Flag, nz if the refresh rate has been determined */
+ double refperiod; /* if > 0.0 in refmode, target int time quantization */
+ double refrate; /* Measured refresh rate in Hz */
+ int refrvalid; /* nz if refrate is valid */
+
+ inst_opt_type trig; /* Reading trigger mode */
+
+ double measto; /* Expected measurement timeout value */
+ int nbands; /* Number of spectral bands */
+ double wl_short;
+ double wl_long;
+
+ /* Other state */
+ athread *th; /* Diffuser position monitoring thread */
+ volatile int th_term; /* nz to terminate thread */
+ volatile int th_termed; /* nz when thread terminated */
+ int dpos; /* Diffuser position, 0 = emissive, 1 = ambient */
+
+ }; typedef struct _specbos specbos;
+
+/* Constructor */
+extern specbos *new_specbos(icoms *icom, instType itype);
+
+
+#define SPECBOS_H
+#endif /* SPECBOS_H */
diff --git a/spectro/spotread.c b/spectro/spotread.c
index 3218243..4d65916 100644
--- a/spectro/spotread.c
+++ b/spectro/spotread.c
@@ -21,6 +21,9 @@
/* TTBD
*
+ * Make -V average the spectrum too (if present), and allow it to
+ * be saved to a .sp file.
+ *
* Should fix plot so that it is a separate object running its own thread,
* so that it can be sent a graph without needing to be clicked in all the time.
*
@@ -287,10 +290,10 @@ usage(char *diag, ...) {
fprintf(stderr," -t Use transmission measurement mode\n");
fprintf(stderr," -e Use emissive measurement mode (absolute results)\n");
fprintf(stderr," -eb Use display white brightness relative measurement mode\n");
- fprintf(stderr," -ew Use display white relative measurement mode\n");
+ fprintf(stderr," -ew Use display white point relative chromatically adjusted mode\n");
fprintf(stderr," -p Use telephoto measurement mode (absolute results)\n");
fprintf(stderr," -pb Use projector white brightness relative measurement mode\n");
- fprintf(stderr," -pw Use projector white relative measurement mode\n");
+ fprintf(stderr," -pw Use projector white point relative chromatically adjusted mode\n");
fprintf(stderr," -a Use ambient measurement mode (absolute results)\n");
fprintf(stderr," -f Use ambient flash measurement mode (absolute results)\n");
cap2 = inst_show_disptype_options(stderr, " -y ", icmps, 0);
@@ -334,6 +337,7 @@ usage(char *diag, ...) {
fprintf(stderr," -X file.ccss Use Colorimeter Calibration Spectral Samples for calibration\n");
}
fprintf(stderr," -Y r|n Override refresh, non-refresh display mode\n");
+ fprintf(stderr," -Y R:rate Override measured refresh rate with rate Hz\n");
fprintf(stderr," -Y A Use non-adaptive integration time mode (if available).\n");
// fprintf(stderr," -Y U Test i1pro2 UV measurement mode\n");
fprintf(stderr," -W n|h|x Override serial port flow control: n = none, h = HW, x = Xon/Xoff\n");
@@ -361,7 +365,8 @@ int main(int argc, char *argv[]) {
int ambient = 0; /* 1 = Use ambient emissive mode, 2 = ambient flash mode */
int highres = 0; /* Use high res mode if available */
int uvmode = 0; /* ~~~ i1pro2 test mode ~~~ */
- int refrmode = -1; /* -1 = default, 0 = non-refresh mode, 1 = non-refresh mode */
+ int refrmode = -1; /* -1 = default, 0 = non-refresh mode, 1 = refresh mode */
+ double refrate = 0.0; /* 0.0 = default, > 0.0 = override refresh rate */
int nadaptive = 0; /* Use non-apative mode if available */
int doYxy= 0; /* Display Yxy instead of Lab */
int doLCh= 0; /* Display LCh instead of Lab */
@@ -398,6 +403,7 @@ int main(int argc, char *argv[]) {
xsp2cie *sp2cie = NULL; /* default conversion */
xsp2cie *sp2cief[26]; /* FWA corrected conversions */
double wXYZ[3] = { -10.0, 0, 0 };/* White XYZ for display white relative */
+ double chmat[3][3]; /* Chromatic adapation matrix */
double Lab[3] = { -10.0, 0, 0}; /* Last Lab */
double rXYZ[3] = { 0.0, -10.0, 0}; /* Reference XYZ */
double rLab[3] = { -10.0, 0, 0}; /* Reference Lab */
@@ -467,8 +473,10 @@ int main(int argc, char *argv[]) {
} else if (argv[fa][1] == 'c') {
fa = nfa;
if (na == NULL) usage("Paramater expected following -c");
- comport = atoi(na);
- if (comport < 1 || comport > 40) usage("-c parameter %d out of range",comport);
+ {
+ comport = atoi(na);
+ if (comport < 1 || comport > 40) usage("-c parameter %d out of range",comport);
+ }
/* Display type */
} else if (argv[fa][1] == 'y') {
@@ -702,19 +710,6 @@ int main(int argc, char *argv[]) {
if (na == NULL) usage("Parameter expected after -K");
strncpy(ccxxname,na,MAXNAMEL-1); ccxxname[MAXNAMEL-1] = '\000';
- /* Serial port flow control */
- } else if (argv[fa][1] == 'W') {
- fa = nfa;
- if (na == NULL) usage("Parameter expected after -W");
- if (na[0] == 'n' || na[0] == 'N')
- fc = fc_none;
- else if (na[0] == 'h' || na[0] == 'H')
- fc = fc_Hardware;
- else if (na[0] == 'x' || na[0] == 'X')
- fc = fc_XonXOff;
- else
- usage("-W parameter '%c' not recognised",na[0]);
-
/* Extra flags */
} else if (argv[fa][1] == 'Y') {
if (na == NULL)
@@ -726,12 +721,32 @@ int main(int argc, char *argv[]) {
refrmode = 1;
} else if (na[0] == 'n') {
refrmode = 0;
+ } else if (na[0] == 'R') {
+ if (na[1] != ':')
+ usage("-Y R:rate syntax incorrect");
+ refrate = atof(na+2);
+ if (refrate < 5.0 || refrate > 150.0)
+ usage("-Y R:rate %f Hz not in valid range",refrate);
/* ~~~ i1pro2 test code ~~~ */
} else if (na[0] == 'U') {
uvmode = 1;
} else {
usage("-Y parameter '%c' not recognised",na[0]);
}
+ fa = nfa;
+
+ /* Serial port flow control */
+ } else if (argv[fa][1] == 'W') {
+ fa = nfa;
+ if (na == NULL) usage("Parameter expected after -W");
+ if (na[0] == 'n' || na[0] == 'N')
+ fc = fc_none;
+ else if (na[0] == 'h' || na[0] == 'H')
+ fc = fc_Hardware;
+ else if (na[0] == 'x' || na[0] == 'X')
+ fc = fc_XonXOff;
+ else
+ usage("-W parameter '%c' not recognised",na[0]);
} else
usage("Flag -%c not recognised",argv[fa][1]);
@@ -765,7 +780,6 @@ int main(int argc, char *argv[]) {
if ((ipath = icmps->get_path(icmps, comport)) == NULL)
error("No instrument at port %d",comport);
-
/* Setup the instrument ready to do reads */
if ((it = new_inst(ipath, 0, g_log, DUIH_FUNC_AND_CONTEXT)) == NULL) {
usage("Unknown, inappropriate or no instrument detected");
@@ -852,14 +866,7 @@ int main(int argc, char *argv[]) {
|| it->check_mode(it, inst_mode_emis_ambient) != inst_ok) {
printf("Requested ambient light capability,\n");
printf("and instrument doesn't support it.\n");
- if (!IMODETST(cap, inst_mode_emis_spot)) {
- it->del(it);
- return -1;
- } else {
- printf("Will use emissive mode instead,\n");
- printf("but note that light level readings may be wrong!\n");
-
- }
+ return -1;
} else {
if (verb) {
printf("Please make sure the instrument is fitted with\n");
@@ -884,6 +891,12 @@ int main(int argc, char *argv[]) {
} else if (emiss || tele) {
+ /* If there is a tele mode but no emission, use tele */
+ if (!IMODETST(cap, inst_mode_emis_spot)
+ && IMODETST(cap, inst_mode_emis_tele)) {
+ tele = 1;
+ }
+
if (tele) {
if (!IMODETST(cap, inst_mode_emis_tele)
|| it->check_mode(it, inst_mode_emis_tele) != inst_ok) {
@@ -915,10 +928,8 @@ int main(int argc, char *argv[]) {
refrmode = -1;
}
}
-
/* Set display type */
if (dtype != 0) {
-
if (cap2 & inst2_disptype) {
int ix;
if ((ix = inst_get_disptype_index(it, dtype, 0)) < 0) {
@@ -973,21 +984,6 @@ int main(int argc, char *argv[]) {
printf("Disable initial-calibrate not supported\n");
}
}
- if (highres) {
- if (IMODETST(cap, inst_mode_highres)) {
- inst_code ev;
- if ((ev = it->get_set_opt(it, inst_opt_highres)) != inst_ok) {
- printf("\nSetting high res mode failed with error :'%s' (%s)\n",
- it->inst_interp_error(it, ev), it->interp_error(it, ev));
- it->del(it);
- return -1;
- }
- highres = 1;
- } else if (verb) {
- printf("high resolution ignored - instrument doesn't support high res. mode\n");
- }
- }
-
/* Set it to the appropriate mode */
/* Should look at instrument type & user spec ??? */
@@ -1032,6 +1028,16 @@ int main(int argc, char *argv[]) {
smode |= inst_mode_spectral;
}
+ if (highres) {
+ if (IMODETST(cap, inst_mode_highres)) {
+ mode |= inst_mode_highres;
+ smode |= inst_mode_highres;
+ } else if (verb) {
+ printf("high resolution ignored - instrument doesn't support high res. mode\n");
+ highres = 0;
+ }
+ }
+
// ~~~ i1pro2 test code ~~~ */
if (uvmode) {
if (!IMODETST(cap, inst_mode_ref_uv)) {
@@ -1128,6 +1134,21 @@ int main(int argc, char *argv[]) {
}
}
+ if (refrate > 0.0) {
+ if (!(cap2 & inst2_set_refresh_rate)) {
+ if (verb)
+ printf("Attempted to set refresh rate and instrument doesn't support setting it (ignored)\n");
+ refrate = 0.0;
+ } else {
+ if ((rv = it->set_refr_rate(it, refrate)) != inst_ok) {
+ printf("\nSetting instrument refresh rate to %f Hz failed with error :'%s' (%s)\n",
+ refrate, it->inst_interp_error(it, rv), it->interp_error(it, rv));
+ it->del(it);
+ return -1;
+ }
+ }
+ }
+
/* If non-standard observer wasn't set by a CCSS file above */
if (obType != icxOT_default && (cap2 & inst2_ccss) && ccssset == 0) {
if ((rv = it->get_set_opt(it, inst_opt_set_ccss_obs, obType, 0)) != inst_ok) {
@@ -1138,7 +1159,12 @@ int main(int argc, char *argv[]) {
}
}
- /* If it batter powered, show the status of the battery */
+ /* Warm the user that they should do a frequency calibration */
+ if (it->needs_calibration(it) & inst_calt_ref_freq) {
+ printf("Please read an 80%% white patch first to calibrate refresh frequency\n");
+ }
+
+ /* If it battery powered, show the status of the battery */
if ((cap2 & inst2_has_battery)) {
double batstat = 0.0;
if ((rv = it->get_set_opt(it, inst_stat_battery, &batstat)) != inst_ok) {
@@ -1186,6 +1212,8 @@ int main(int argc, char *argv[]) {
inst_set_uih('K', 'K', DUIH_CMND);
inst_set_uih('s', 's', DUIH_CMND);
inst_set_uih('S', 'S', DUIH_CMND);
+ if (cap2 & inst2_has_target)
+ inst_set_uih('t', 't', DUIH_CMND);
inst_set_uih('f', 'f', DUIH_CMND);
inst_set_uih('F', 'F', DUIH_CMND);
inst_set_uih('q', 'q', DUIH_ABORT);
@@ -1239,7 +1267,7 @@ int main(int argc, char *argv[]) {
/* Read spots until the user quits */
for (ix = 1;; ix++) {
ipatch val;
- double XYZ[3]; /* XYZ scaled 0..100 or absolute */
+ double XYZ[3] = { 0.0, 0.0, 0.0 }; /* XYZ scaled 0..100 or absolute */
double tXYZ[3];
#ifndef SALONEINSTLIB
double cct, vct, vdt;
@@ -1250,6 +1278,43 @@ int main(int argc, char *argv[]) {
int dofwa = 0; /* Do FWA compensation */
int fidx = -1; /* FWA compensated index, default = none */
+#ifdef NEVER // test i1d3 min_int_time code
+ {
+ double cval;
+ char *cp;
+
+ if ((rv = it->get_set_opt(it, inst_opt_get_min_int_time, &cval)) != inst_ok) {
+ printf("\nGetting min_int)time failed with error :'%s' (%s)\n",
+ it->inst_interp_error(it, rv), it->interp_error(it, rv));
+ it->del(it);
+ return -1;
+ }
+ printf("Current min int time = %f\n",cval);
+
+ if ((cp = getenv("I1D3_MIN_INT_TIME")) != NULL) {
+ cval = atof(cp);
+
+ printf("Setting int time %f\n",cval);
+ if ((rv = it->get_set_opt(it, inst_opt_set_min_int_time, cval)) != inst_ok) {
+ printf("\nSetting min_int_time failed with error :'%s' (%s)\n",
+ it->inst_interp_error(it, rv), it->interp_error(it, rv));
+ it->del(it);
+ return -1;
+ }
+
+ if ((rv = it->get_set_opt(it, inst_opt_get_min_int_time, &cval)) != inst_ok) {
+ printf("\nGetting min_int)time failed with error :'%s' (%s)\n",
+ it->inst_interp_error(it, rv), it->interp_error(it, rv));
+ it->del(it);
+ return -1;
+ }
+
+ printf("Check current min int time = %f\n",cval);
+ }
+ }
+
+#endif // NEVER
+
if (savdrd != -1 && IMODETST(cap, inst_mode_s_ref_spot)
&& it->check_mode(it, inst_mode_s_ref_spot) == inst_ok) {
inst_stat_savdrd sv;
@@ -1429,6 +1494,8 @@ int main(int argc, char *argv[]) {
printf("Hit 'r' to set reference\n");
#endif /* SALONEINSTLIB */
printf("'h' to toggle high res., 'k' to do a calibration\n");
+ if (cap2 & inst2_has_target)
+ printf("'t' to toggle laser target\n");
}
if (uswitch)
printf("Hit ESC or Q to exit, instrument switch or any other key to take a reading: ");
@@ -1610,9 +1677,21 @@ int main(int argc, char *argv[]) {
if (ch == 0x1b || ch == 0x03 || ch == 'q' || ch == 'Q') { /* Or ^C */
break;
}
+ if ((cap2 & inst2_has_target) && ch == 't') { // Toggle target
+ inst_code ev;
+ if ((ev = it->get_set_opt(it, inst_opt_set_target_state, 2)) != inst_ok) {
+ printf("\nToggling target failed with error :'%s' (%s)\n",
+ it->inst_interp_error(it, ev), it->interp_error(it, ev));
+ it->del(it);
+ return -1;
+ }
+ --ix;
+ continue;
+ }
if (ch == 'H' || ch == 'h') { /* Toggle high res mode */
if (IMODETST(cap, inst_mode_highres)) {
inst_code ev;
+ /* Hmm. Could simply re-do set_mode() here instead */
if (highres) {
if ((ev = it->get_set_opt(it, inst_opt_stdres)) != inst_ok) {
printf("\nSetting std res mode failed with error :'%s' (%s)\n",
@@ -1778,7 +1857,7 @@ int main(int argc, char *argv[]) {
double refr;
inst_code ev;
- if (!(cap2 & inst2_refresh_rate)) {
+ if (!(cap2 & inst2_get_refresh_rate)) {
printf("\nInstrument isn't capable of refresh rate calibration\n");
--ix;
continue;
@@ -2063,7 +2142,7 @@ int main(int argc, char *argv[]) {
#endif /* SALONEINSTLIB */
if (emiss > 1 || tele > 1) {
- if (wXYZ[0] < 0.0) {
+ if (wXYZ[0] < 0.0) { /* If we haven't save a white ref. yet */
if (XYZ[1] < 10.0)
error ("White of XYZ %f %f %f doesn't seem reasonable",XYZ[0], XYZ[1], XYZ[2]);
printf("\n Making result XYZ: %f %f %f, D50 Lab: %f %f %f white reference.\n",
@@ -2071,6 +2150,13 @@ int main(int argc, char *argv[]) {
wXYZ[0] = XYZ[0];
wXYZ[1] = XYZ[1];
wXYZ[2] = XYZ[2];
+#ifndef SALONEINSTLIB
+ { /* Compute a Chromatic adapation matrix to D50 */
+ icmXYZNumber s_wp;
+ icmAry2XYZ(s_wp, wXYZ);
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD, icmD50, s_wp, chmat);
+ }
+#endif /* !SALONEINSTLIB */
continue;
}
if (emiss == 2 || tele == 2) {
@@ -2080,12 +2166,14 @@ int main(int argc, char *argv[]) {
XYZ[2] = 100.0 * XYZ[2] / wXYZ[1];
}
#ifndef SALONEINSTLIB
- else {
+ else { /* emiss == 3, white point relative */
/* Normalize to white and scale to 0..100 */
- XYZ[0] = XYZ[0] * icmD50_100.X / wXYZ[0];
- XYZ[1] = XYZ[1] * icmD50_100.Y / wXYZ[1];
- XYZ[2] = XYZ[2] * icmD50_100.Z / wXYZ[2];
+// XYZ[0] = XYZ[0] * icmD50_100.X / wXYZ[0];
+// XYZ[1] = XYZ[1] * icmD50_100.Y / wXYZ[1];
+// XYZ[2] = XYZ[2] * icmD50_100.Z / wXYZ[2];
+ icmMulBy3x3(XYZ, chmat, XYZ);
+ icmScale3(XYZ, XYZ, 100.0);
}
/* recompute Lab */
@@ -2174,25 +2262,25 @@ int main(int argc, char *argv[]) {
printf(" Apparent flash duration = %f seconds\n",val.duration);
if (cap2 & inst2_ambient_mono) {
printf(" Ambient = %.1f Lux%s\n",
- 3.141592658 * XYZ[1], ambient == 2 ? "-Seconds" : "");
+ XYZ[1], ambient == 2 ? "-Seconds" : "");
if (ambient != 2)
printf(" Suggested EV @ ISO100 for %.1f Lux incident light = %.1f\n",
- 3.141592658 * XYZ[1],
- log(3.141592658 * XYZ[1]/2.5)/log(2.0));
+ XYZ[1],
+ log(XYZ[1]/2.5)/log(2.0));
} else {
#ifndef SALONEINSTLIB
printf(" Ambient = %.1f Lux%s, CCT = %.0fK (Delta E %f)\n",
- 3.1415926 * XYZ[1], ambient == 2 ? "-Seconds" : "",
+ XYZ[1], ambient == 2 ? "-Seconds" : "",
cct, cct_de);
if (ambient != 2)
printf(" Suggested EV @ ISO100 for %.1f Lux incident light = %.1f\n",
- 3.141592658 * XYZ[1],
- log(3.141592658 * XYZ[1]/2.5)/log(2.0));
+ XYZ[1],
+ log(XYZ[1]/2.5)/log(2.0));
printf(" Closest Planckian temperature = %.0fK (Delta E %f)\n",vct, vct_de);
printf(" Closest Daylight temperature = %.0fK (Delta E %f)\n",vdt, vdt_de);
#else /* SALONEINSTLIB */
printf(" Ambient = %.1f Lux%s\n",
- 3.1415926 * XYZ[1], ambient == 2 ? "-Seconds" : "");
+ XYZ[1], ambient == 2 ? "-Seconds" : "");
#endif /* SALONEINSTLIB */
}
#ifndef SALONEINSTLIB
diff --git a/spectro/spyd2.c b/spectro/spyd2.c
index f8f9bac..dc09cea 100644
--- a/spectro/spyd2.c
+++ b/spectro/spyd2.c
@@ -7,7 +7,7 @@
* Author: Graeme W. Gill
* Date: 17/9/2007
*
- * Copyright 2006 - 2013, Graeme W. Gill
+ * Copyright 2006 - 2014, Graeme W. Gill
* All rights reserved.
*
* (Based initially on i1disp.c)
@@ -26,7 +26,7 @@
The purchaser of a Spyder 2 instrument should have received a copy
of this firmware along with their instrument, and should therefore be able to
- enable the Argyll driver for this instrument by using the spyd2en utility
+ enable the Argyll driver for this instrument by using the oeminst utility
to create a spyd2PLD.bin file.
[ The Spyder 3 & 4 don't need a PLD firmware file. ]
@@ -1869,7 +1869,8 @@ spyd2_GetAmbientReading(
// a1logd(p->log, 4, "spyd2_GetAmbientReading: combined ambient = %f Lux\n",amb);
/* Compute the Y value */
- XYZ[1] = amb; /* cd/m^2 ??? - not very accurate, due to */
+// XYZ[1] = amb; /* cd/m^2 ??? - not very accurate, due to */
+ XYZ[1] = 3.141592654 * amb; /* Lux ??? - not very accurate, due to */
/* spectral response and/or integration angle. */
XYZ[0] = icmD50.X * XYZ[1]; /* Convert to D50 neutral */
XYZ[2] = icmD50.Z * XYZ[1];
@@ -1889,7 +1890,7 @@ xspect *spyd4_cals = NULL; /* [nocals] Device spectrum */
/* calibration data. */
static inst_code
-spyd4_set_cal(
+spyd4_set_cal_ix(
spyd2 *p, /* Object */
int ix /* Selection, 0 .. spyd4_nocals-1 */
) {
@@ -1907,8 +1908,14 @@ spyd4_set_cal(
/* default calibration selections, to be faithful to the Manufacturers */
/* intentions. */
- if (standardObserver(oc, icxOT_CIE_1931_2)) {
- return spyd2_interp_code((inst *)p, SPYD2_DISP_SEL_RANGE) ;
+ if (p->obType == icxOT_custom) {
+ oc[0] = &p->custObserver[0];
+ oc[1] = &p->custObserver[1];
+ oc[2] = &p->custObserver[2];
+ } else {
+ if (standardObserver(oc, p->obType)) {
+ return spyd2_interp_code((inst *)p, SPYD2_DISP_SEL_RANGE) ;
+ }
}
/* We compute X,Y & Z independently. */
@@ -2163,7 +2170,6 @@ spyd4_comp_calmat(
/* Copy the matrix into place */
for (i = 0; i < 7; i++) {
for (j = 0; j < 3; j++) {
-//calm[i][j] = 0.5;
p->cal_A[1][j][2+i] = calm[i][j];
}
}
@@ -2236,6 +2242,104 @@ spyd4_comp_calmat(
}
+/* Preset the calibration to a spectral sample type. */
+/* ccmat[][] is set to unity */
+static inst_code
+spyd2_set_speccal(
+ spyd2 *p,
+ xspect *samples, /* Array of nsamp spectral samples, or RGBcmfs for MIbLSr */
+ int nsamp /* Number of samples */
+) {
+ int i;
+
+ /* Save a the spectral samples to the current state */
+ if (p->samples != NULL)
+ free(p->samples);
+ p->nsamp = 0;
+ if ((p->samples = (xspect *)calloc(sizeof(xspect), nsamp)) == NULL) {
+ a1loge(p->log, inst_internal_error, "spyd2_set_speccal: malloc failed\n");
+ return inst_internal_error;
+ }
+ for (i = 0; i < nsamp; i++ )
+ p->samples[i] = samples[i]; /* Struct copy */
+ p->nsamp = nsamp;
+
+ p->icx = (99 << 1) | 1; /* Out of range index */
+
+ icmSetUnity3x3(p->ccmat); /* No matrix */
+
+ return inst_ok;
+}
+
+
+/* Preset the calibration to a matrix. The spectral type is set to none */
+static inst_code
+spyd2_set_matcal(spyd2 *p, double mtx[3][3]) {
+ if (mtx == NULL) {
+ icmSetUnity3x3(p->ccmat);
+ } else {
+ if (p->cbid == 0) {
+ a1loge(p->log, 1, "spyd2: can't set col_cor_mat over non-base display type\n");
+ return inst_wrong_setup;
+ }
+ icmCpy3x3(p->ccmat, mtx);
+ }
+
+ return inst_ok;
+}
+
+
+/* Set the calibration to the currently preset type */
+static inst_code
+spyd2_set_cal(spyd2 *p) {
+ inst_code ev = inst_ok;
+
+ if (p->samples != NULL && p->nsamp > 0) {
+
+ /* Create matrix for specified samples */
+ if ((ev = spyd4_comp_calmat(p, p->obType, p->custObserver, p->samples, p->nsamp))
+ != inst_ok) {
+ a1logd(p->log, 1, "spyd2_set_cal: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ return ev;
+ }
+
+ p->icx = (99 << 1) | 1; /* Out of range index */
+ icmSetUnity3x3(p->ccmat); /* to be sure to be sure... */
+
+ } else {
+
+ if (p->hwver >= 7) {
+ if ((p->icx >> 1) > spyd4_nocals)
+ return inst_unsupported;
+
+ /* Create the calibration matrix from internal spectral data */
+ if ((ev = spyd4_set_cal_ix(p, p->icx >> 1)) != inst_ok)
+ return ev;
+ }
+
+ }
+
+ if (p->log->debug >= 4) {
+ int i;
+ if (p->hwver >= 7) {
+ a1logd(p->log,4,"Spectral calibration matrix:\n");
+ for (i = 0; i < 7; i++) {
+ a1logd(p->log,4," %f %f %f\n",
+ p->cal_A[1][0][2+i], p->cal_A[1][1][2+i], p->cal_A[1][2][2+i]);
+ }
+ }
+ a1logd(p->log,4,"ccmat = %f %f %f\n",
+ p->ccmat[0][0], p->ccmat[0][1], p->ccmat[0][2]);
+ a1logd(p->log,4," %f %f %f\n",
+ p->ccmat[1][0], p->ccmat[1][1], p->ccmat[1][2]);
+ a1logd(p->log,4," %f %f %f\n\n",
+ p->ccmat[2][0], p->ccmat[2][1], p->ccmat[2][2]);
+ a1logd(p->log,4,"\n");
+ }
+
+ return inst_ok;
+}
+
/* ------------------------------------------------------------ */
/* Read all the relevant register values */
@@ -2472,7 +2576,7 @@ spyd2_download_pld(
a1logd(p->log, 2, "spyd2_download_pld: called\n");
if (*spyder2_pld_size == 0 || *spyder2_pld_size == 0x11223344) {
- a1logd(p->log, 1, "spyd2_download_pld: No PLD pattern available! (have you run spyd2en ?)\n");
+ a1logd(p->log, 1, "spyd2_download_pld: No PLD pattern available! (have you run oeminst ?)\n");
return spyd2_interp_code((inst *)p, SPYD2_NO_PLD_PATTERN) ;
}
@@ -2652,8 +2756,8 @@ spyd2_init_coms(inst *pp, baud_rate br, flow_control fc, double tout) {
a1logd(p->log, 2, "spyd2_init_coms: about to init coms\n");
if (p->icom->port_type(p->icom) != icomt_usb) {
- a1logd(p->log, 1, "spyd2_init_coms: coms is not the right type!\n");
- return spyd2_interp_code((inst *)p, SPYD2_UNKNOWN_MODEL);
+ a1logd(p->log, 1, "spyd2_init_coms: wrong communications type for device!\n");
+ return inst_coms_fail;
}
a1logd(p->log, 2, "spyd2_init_coms: about to init USB\n");
@@ -2864,8 +2968,9 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
} else {
/* Check for abort */
if (p->uicallback != NULL
- && (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_trig)
+ && (ev = p->uicallback(p->uic_cntx, inst_armed)) == inst_user_abort) {
return ev; /* Abort */
+ }
}
if (IMODETST(p->mode, inst_mode_emis_ambient)) {
@@ -2900,6 +3005,7 @@ instClamping clamp) { /* NZ if clamp XYZ/Lab to be +ve */
val->sp.spec_n = 0;
val->duration = 0.0;
+
if (user_trig)
return inst_user_trig;
return ev;
@@ -2913,23 +3019,17 @@ inst *pp,
double mtx[3][3]
) {
spyd2 *p = (spyd2 *)pp;
+ inst_code ev = inst_ok;
if (!p->gotcoms)
return inst_no_coms;
if (!p->inited)
return inst_no_init;
- if (mtx == NULL) {
- icmSetUnity3x3(p->ccmat);
- } else {
- if (p->cbid == 0) {
- a1loge(p->log, 1, "spyd2: can't set col_cor_mat over non base display type\n");
- inst_wrong_setup;
- }
- icmCpy3x3(p->ccmat, mtx);
- }
-
- return inst_ok;
+ if ((ev = spyd2_set_matcal(p, mtx)) != inst_ok)
+ return ev;
+
+ return spyd2_set_cal(p);
}
/* Use a Colorimeter Calibration Spectral Set to set the */
@@ -2955,11 +3055,12 @@ int no_sets
if ((ev = set_default_disp_type(p)) != inst_ok)
return ev;
} else {
- /* Use given spectral samples */
- if ((ev = spyd4_comp_calmat(p, p->obType, p->custObserver, sets, no_sets)) != inst_ok)
- return ev;
- p->icx = (99 << 1) | 1; /* Out of range index */
+ if ((ev = spyd2_set_speccal(p, sets, no_sets)) != inst_ok)
+ return ev;
+
+ ev = spyd2_set_cal(p);
}
+
return ev;
}
@@ -3031,8 +3132,8 @@ char id[CALIDLEN] /* Condition identifier (ie. white reference ID) */
if ((*calt & inst_calt_ref_freq) && p->refrmode != 0) {
- if (*calc != inst_calc_emis_white) {
- *calc = inst_calc_emis_white;
+ if (*calc != inst_calc_emis_80pc) {
+ *calc = inst_calc_emis_80pc;
return inst_cal_setup;
}
@@ -3120,7 +3221,7 @@ spyd2_interp_error(inst *pp, int ec) {
case SPYD2_BAD_EE_SIZE:
return "Serial EEProm read size > 256";
case SPYD2_NO_PLD_PATTERN:
- return "No PLD firmware pattern is available (have you run spyd2en ?)";
+ return "No PLD firmware pattern is available (have you run oeminst ?)";
case SPYD2_NO_COMS:
return "Communications hasn't been established";
case SPYD2_NOT_INITED:
@@ -3206,6 +3307,8 @@ spyd2_del(inst *pp) {
if (p->icom != NULL)
p->icom->del(p->icom);
inst_del_disptype_list(p->dtlist, p->ndtlist);
+ if (p->samples != NULL)
+ free(p->samples);
free(p);
}
@@ -3235,7 +3338,8 @@ inst3_capability *pcap3) {
cap2 |= inst2_prog_trig
| inst2_user_trig
| inst2_ccmx
- | inst2_refresh_rate
+ | inst2_get_refresh_rate
+ | inst2_set_refresh_rate
| inst2_emis_refr_meas
;
@@ -3386,7 +3490,7 @@ inst_disptypesel spyd4_disptypesel[8] = {
{
inst_dtflags_default,
1,
- "n",
+ "nl",
"Generic Non-Refresh Display",
0,
1
@@ -3394,7 +3498,7 @@ inst_disptypesel spyd4_disptypesel[8] = {
{
inst_dtflags_none, /* flags */
2, /* cbid */
- "r", /* sel */
+ "rc", /* sel */
"Generic Refresh Display", /* desc */
1, /* refr */
1 /* ix = hw bit + spec table << 1 */
@@ -3512,35 +3616,22 @@ static inst_code set_disp_type(spyd2 *p, inst_disptypesel *dentry) {
}
p->refrmode = refrmode;
- if (dentry->flags & inst_dtflags_ccss) {
+ if (dentry->flags & inst_dtflags_ccss) { /* Spectral sample */
- if ((ev = spyd4_comp_calmat(p, p->obType, p->custObserver, dentry->sets, dentry->no_sets))
- != inst_ok) {
- a1logd(p->log, 1, "spyd4_set_disp_type: comp_calmat ccss failed with rv = 0x%x\n",ev);
+ if ((ev = spyd2_set_speccal(p, dentry->sets, dentry->no_sets)) != inst_ok)
return ev;
- }
- p->icx = (99 << 1) | 1; /* Out of range index */
- icmSetUnity3x3(p->ccmat);
- } else {
-
- if (p->hwver >= 7) {
- if ((p->icx >> 1) > spyd4_nocals)
- return inst_unsupported;
-
- /* Create the calibration matrix */
- if ((ev = spyd4_set_cal(p, p->icx >> 1)) != inst_ok)
- return ev;
- }
+ } else { /* Matrix */
if (dentry->flags & inst_dtflags_ccmx) {
- icmCpy3x3(p->ccmat, dentry->mat);
+ if ((ev = spyd2_set_matcal(p, dentry->mat)) != inst_ok)
+ return ev;
} else {
- icmSetUnity3x3(p->ccmat);
+ if ((ev = spyd2_set_matcal(p, NULL)) != inst_ok) /* Noop */
+ return ev;
}
}
-
- return inst_ok;
+ return spyd2_set_cal(p);
}
@@ -3662,7 +3753,7 @@ spyd2_get_set_opt(inst *pp, inst_opt_type m, ...) {
p->custObserver[2] = custObserver[2];
}
- return inst_ok;
+ return spyd2_set_cal(p); /* Recompute calibration */
}
/* Operate the LED */
diff --git a/spectro/spyd2.h b/spectro/spyd2.h
index d3a208c..2c34d88 100644
--- a/spectro/spyd2.h
+++ b/spectro/spyd2.h
@@ -147,9 +147,11 @@ struct _spyd2 {
double refrate; /* Current refresh rate. Set to DEFREFR if not measurable */
int refrvalid; /* nz if refrate was measured */
double gain; /* hwver == 5 gain value (default 4) */
- double ccmat[3][3]; /* Colorimeter correction matrix */
icxObserverType obType; /* ccss observer to use */
xspect custObserver[3]; /* Custom ccss observer to use */
+ double ccmat[3][3]; /* Colorimeter correction matrix, unity if none */
+ xspect *samples; /* Copy of current calibration spectral samples, NULL if none */
+ int nsamp; /* Number of samples, 0 if none */
int prevraw[8]; /* Previous raw reading values */
int prevrawinv; /* Previous raw readings invalid flag - after an abort */
diff --git a/spectro/spyd2PLD.h b/spectro/spyd2PLD.h
index 4a71cd8..19d2a48 100644
--- a/spectro/spyd2PLD.h
+++ b/spectro/spyd2PLD.h
@@ -2,7 +2,7 @@
/* Spyder 2 Colorimeter Xilinx XCS05XL firmware pattern */
/* needs to be transfered here for the instrument to work. */
-/* The end user should see the spyd2en utility.*/
+/* The end user should see the oeminst utility.*/
static unsigned int pld_size = 0x11223344; /* Endian indicator */
static unsigned int pld_space = 6824;
diff --git a/spectro/spyd2setup.h b/spectro/spyd2setup.h
index def83b6..60375dd 100644
--- a/spectro/spyd2setup.h
+++ b/spectro/spyd2setup.h
@@ -63,7 +63,7 @@ int setup_spyd2() {
if ((no_paths = xdg_bds(NULL, &bin_paths, xdg_data, xdg_read, xdg_user,
"ArgyllCMS/spyd2PLD.bin" XDG_FUDGE "color/spyd2PLD.bin"
)) < 1) {
- a1logd(g_log, 1, "etup_spyd2: failed to find PLD file\n");
+ a1logd(g_log, 1, "setup_spyd2: failed to find PLD file\n");
break;
}
diff --git a/spectro/ss_imp.c b/spectro/ss_imp.c
index b4c5d8a..359d4c4 100644
--- a/spectro/ss_imp.c
+++ b/spectro/ss_imp.c
@@ -512,7 +512,7 @@ void ss_command(ss *p, double tmo) {
p->sbuf[2] = '\00'; /* write_read terminates on nul */
p->rbuf = p->_rbuf; /* Reset read pointer */
- if ((se = p->icom->write_read(p->icom, p->_sbuf, p->_rbuf, SS_MAX_RD_SIZE, '\n', 1, tmo)) != 0) {
+ if ((se = p->icom->write_read(p->icom, p->_sbuf, p->_rbuf, SS_MAX_RD_SIZE, "\n", 1, tmo)) != 0) {
p->snerr = icoms2ss_err(se);
return;
}
diff --git a/spectro/strange.cal b/spectro/strange.cal
index 23c1e87..c7f0179 100644
--- a/spectro/strange.cal
+++ b/spectro/strange.cal
@@ -2,7 +2,7 @@ CAL
DESCRIPTOR "Argyll Device Calibration Curves"
ORIGINATOR "Argyll synthcal"
-CREATED "Sat Mar 09 18:33:22 2013"
+CREATED "Fri Jan 31 13:50:43 2014"
KEYWORD "DEVICE_CLASS"
DEVICE_CLASS "DISPLAY"
KEYWORD "COLOR_REP"
@@ -16,260 +16,260 @@ END_DATA_FORMAT
NUMBER_OF_SETS 256
BEGIN_DATA
-0.0000 0.0000 0.0000 0.0000
-3.9216e-003 5.6752e-005 0.011879 0.018606
-7.8431e-003 1.8439e-004 0.020682 0.030226
-0.011765 3.6735e-004 0.028607 0.040147
-0.015686 5.9908e-004 0.036009 0.049103
-0.019608 8.7544e-004 0.043047 0.057404
-0.023529 1.1935e-003 0.049807 0.065218
-0.027451 1.5511e-003 0.056344 0.072650
-0.031373 1.9464e-003 0.062696 0.079768
-0.035294 2.3779e-003 0.068891 0.086623
-0.039216 2.8443e-003 0.074949 0.093253
-0.043137 3.3446e-003 0.080888 0.099687
-0.047059 3.8778e-003 0.086719 0.10595
-0.050980 4.4431e-003 0.092453 0.11205
-0.054902 5.0396e-003 0.098100 0.11802
-0.058824 5.6668e-003 0.10367 0.12386
-0.062745 6.3239e-003 0.10916 0.12958
-0.066667 7.0104e-003 0.11458 0.13520
-0.070588 7.7258e-003 0.11995 0.14072
-0.074510 8.4696e-003 0.12525 0.14615
-0.078431 9.2413e-003 0.13049 0.15149
-0.082353 0.010040 0.13569 0.15675
-0.086275 0.010867 0.14083 0.16194
-0.090196 0.011720 0.14593 0.16706
-0.094118 0.012599 0.15099 0.17211
-0.098039 0.013504 0.15600 0.17710
-0.10196 0.014436 0.16097 0.18203
-0.10588 0.015392 0.16590 0.18690
-0.10980 0.016374 0.17080 0.19172
-0.11373 0.017380 0.17567 0.19649
-0.11765 0.018411 0.18049 0.20121
-0.12157 0.019467 0.18529 0.20588
-0.12549 0.020546 0.19006 0.21051
-0.12941 0.021650 0.19480 0.21509
-0.13333 0.022777 0.19950 0.21963
-0.13725 0.023927 0.20418 0.22414
-0.14118 0.025101 0.20884 0.22860
-0.14510 0.026298 0.21347 0.23303
-0.14902 0.027518 0.21807 0.23742
-0.15294 0.028760 0.22265 0.24177
-0.15686 0.030025 0.22720 0.24610
-0.16078 0.031312 0.23174 0.25039
-0.16471 0.032621 0.23625 0.25465
-0.16863 0.033953 0.24074 0.25888
-0.17255 0.035306 0.24521 0.26308
-0.17647 0.036681 0.24965 0.26725
-0.18039 0.038077 0.25408 0.27139
-0.18431 0.039495 0.25849 0.27551
-0.18824 0.040935 0.26288 0.27960
-0.19216 0.042395 0.26725 0.28366
-0.19608 0.043876 0.27161 0.28770
-0.20000 0.045378 0.27595 0.29172
-0.20392 0.046901 0.28027 0.29571
-0.20784 0.048445 0.28457 0.29968
-0.21176 0.050009 0.28886 0.30363
-0.21569 0.051594 0.29313 0.30755
-0.21961 0.053198 0.29738 0.31146
-0.22353 0.054824 0.30163 0.31534
-0.22745 0.056469 0.30585 0.31920
-0.23137 0.058134 0.31006 0.32304
-0.23529 0.059819 0.31426 0.32687
-0.23922 0.061523 0.31844 0.33067
-0.24314 0.063248 0.32261 0.33446
-0.24706 0.064992 0.32677 0.33822
-0.25098 0.066755 0.33091 0.34197
-0.25490 0.068538 0.33504 0.34570
-0.25882 0.070340 0.33916 0.34942
-0.26275 0.072162 0.34326 0.35312
-0.26667 0.074002 0.34736 0.35680
-0.27059 0.075862 0.35144 0.36046
-0.27451 0.077740 0.35551 0.36411
-0.27843 0.079638 0.35956 0.36774
-0.28235 0.081554 0.36361 0.37136
-0.28627 0.083489 0.36764 0.37496
-0.29020 0.085442 0.37167 0.37855
-0.29412 0.087415 0.37568 0.38213
-0.29804 0.089405 0.37968 0.38569
-0.30196 0.091414 0.38367 0.38923
-0.30588 0.093442 0.38765 0.39276
-0.30980 0.095487 0.39162 0.39628
-0.31373 0.097551 0.39559 0.39979
-0.31765 0.099633 0.39954 0.40328
-0.32157 0.10173 0.40348 0.40676
-0.32549 0.10385 0.40741 0.41022
-0.32941 0.10599 0.41133 0.41368
-0.33333 0.10814 0.41524 0.41712
-0.33725 0.11031 0.41915 0.42055
-0.34118 0.11250 0.42304 0.42396
-0.34510 0.11471 0.42693 0.42737
-0.34902 0.11693 0.43080 0.43076
-0.35294 0.11918 0.43467 0.43414
-0.35686 0.12144 0.43853 0.43752
-0.36078 0.12371 0.44238 0.44088
-0.36471 0.12601 0.44623 0.44422
-0.36863 0.12832 0.45006 0.44756
-0.37255 0.13065 0.45389 0.45089
-0.37647 0.13300 0.45770 0.45421
-0.38039 0.13536 0.46151 0.45751
-0.38431 0.13774 0.46532 0.46081
-0.38824 0.14014 0.46911 0.46410
-0.39216 0.14255 0.47290 0.46737
-0.39608 0.14499 0.47668 0.47064
-0.40000 0.14743 0.48045 0.47390
-0.40392 0.14990 0.48421 0.47715
-0.40784 0.15238 0.48797 0.48038
-0.41176 0.15488 0.49172 0.48361
-0.41569 0.15740 0.49546 0.48683
-0.41961 0.15993 0.49920 0.49004
-0.42353 0.16248 0.50293 0.49324
-0.42745 0.16505 0.50665 0.49644
-0.43137 0.16763 0.51037 0.49962
-0.43529 0.17023 0.51407 0.50279
-0.43922 0.17284 0.51778 0.50596
-0.44314 0.17547 0.52147 0.50912
-0.44706 0.17812 0.52516 0.51227
-0.45098 0.18079 0.52884 0.51541
-0.45490 0.18347 0.53252 0.51854
-0.45882 0.18616 0.53619 0.52167
-0.46275 0.18888 0.53985 0.52479
-0.46667 0.19161 0.54351 0.52789
-0.47059 0.19435 0.54716 0.53100
-0.47451 0.19711 0.55080 0.53409
-0.47843 0.19989 0.55444 0.53718
-0.48235 0.20268 0.55807 0.54025
-0.48627 0.20549 0.56170 0.54332
-0.49020 0.20832 0.56532 0.54639
-0.49412 0.21116 0.56894 0.54944
-0.49804 0.21402 0.57255 0.55249
-0.50196 0.21689 0.57615 0.55553
-0.50588 0.21978 0.57975 0.55857
-0.50980 0.22268 0.58334 0.56160
-0.51373 0.22560 0.58693 0.56462
-0.51765 0.22854 0.59051 0.56763
-0.52157 0.23149 0.59409 0.57064
-0.52549 0.23445 0.59766 0.57364
-0.52941 0.23744 0.60122 0.57663
-0.53333 0.24043 0.60478 0.57962
-0.53725 0.24345 0.60834 0.58260
-0.54118 0.24648 0.61189 0.58557
-0.54510 0.24952 0.61543 0.58854
-0.54902 0.25258 0.61897 0.59150
-0.55294 0.25565 0.62251 0.59445
-0.55686 0.25874 0.62603 0.59740
-0.56078 0.26185 0.62956 0.60034
-0.56471 0.26497 0.63308 0.60328
-0.56863 0.26811 0.63659 0.60621
-0.57255 0.27126 0.64010 0.60913
-0.57647 0.27442 0.64361 0.61205
-0.58039 0.27760 0.64711 0.61496
-0.58431 0.28080 0.65060 0.61787
-0.58824 0.28401 0.65410 0.62077
-0.59216 0.28724 0.65758 0.62366
-0.59608 0.29048 0.66106 0.62655
-0.60000 0.29373 0.66454 0.62943
-0.60392 0.29701 0.66801 0.63231
-0.60784 0.30029 0.67148 0.63518
-0.61176 0.30359 0.67494 0.63805
-0.61569 0.30691 0.67840 0.64091
-0.61961 0.31024 0.68186 0.64376
-0.62353 0.31358 0.68531 0.64661
-0.62745 0.31694 0.68875 0.64945
-0.63137 0.32032 0.69220 0.65229
-0.63529 0.32371 0.69563 0.65513
-0.63922 0.32711 0.69907 0.65795
-0.64314 0.33053 0.70249 0.66078
-0.64706 0.33397 0.70592 0.66360
-0.65098 0.33741 0.70934 0.66641
-0.65490 0.34088 0.71276 0.66922
-0.65882 0.34435 0.71617 0.67202
-0.66275 0.34785 0.71958 0.67482
-0.66667 0.35135 0.72298 0.67761
-0.67059 0.35487 0.72638 0.68040
-0.67451 0.35841 0.72978 0.68318
-0.67843 0.36196 0.73317 0.68596
-0.68235 0.36552 0.73656 0.68873
-0.68627 0.36910 0.73994 0.69150
-0.69020 0.37269 0.74332 0.69426
-0.69412 0.37630 0.74670 0.69702
-0.69804 0.37992 0.75007 0.69977
-0.70196 0.38356 0.75344 0.70252
-0.70588 0.38721 0.75681 0.70527
-0.70980 0.39087 0.76017 0.70801
-0.71373 0.39455 0.76353 0.71075
-0.71765 0.39824 0.76688 0.71348
-0.72157 0.40195 0.77023 0.71620
-0.72549 0.40567 0.77358 0.71893
-0.72941 0.40940 0.77692 0.72164
-0.73333 0.41315 0.78026 0.72436
-0.73725 0.41692 0.78360 0.72707
-0.74118 0.42069 0.78693 0.72977
-0.74510 0.42448 0.79026 0.73247
-0.74902 0.42829 0.79359 0.73517
-0.75294 0.43211 0.79691 0.73786
-0.75686 0.43594 0.80023 0.74055
-0.76078 0.43979 0.80354 0.74323
-0.76471 0.44365 0.80686 0.74591
-0.76863 0.44752 0.81016 0.74859
-0.77255 0.45141 0.81347 0.75126
-0.77647 0.45531 0.81677 0.75393
-0.78039 0.45923 0.82007 0.75659
-0.78431 0.46316 0.82336 0.75925
-0.78824 0.46710 0.82666 0.76191
-0.79216 0.47106 0.82994 0.76456
-0.79608 0.47503 0.83323 0.76721
-0.80000 0.47902 0.83651 0.76985
-0.80392 0.48302 0.83979 0.77249
-0.80784 0.48703 0.84307 0.77512
-0.81176 0.49105 0.84634 0.77776
-0.81569 0.49509 0.84961 0.78038
-0.81961 0.49915 0.85287 0.78301
-0.82353 0.50321 0.85614 0.78563
-0.82745 0.50729 0.85940 0.78825
-0.83137 0.51139 0.86265 0.79086
-0.83529 0.51550 0.86591 0.79347
-0.83922 0.51962 0.86916 0.79608
-0.84314 0.52375 0.87241 0.79868
-0.84706 0.52790 0.87565 0.80128
-0.85098 0.53206 0.87889 0.80387
-0.85490 0.53624 0.88213 0.80646
-0.85882 0.54042 0.88537 0.80905
-0.86275 0.54463 0.88860 0.81163
-0.86667 0.54884 0.89183 0.81421
-0.87059 0.55307 0.89506 0.81679
-0.87451 0.55731 0.89828 0.81937
-0.87843 0.56157 0.90150 0.82194
-0.88235 0.56584 0.90472 0.82450
-0.88627 0.57012 0.90793 0.82707
-0.89020 0.57441 0.91115 0.82963
-0.89412 0.57872 0.91436 0.83218
-0.89804 0.58304 0.91756 0.83474
-0.90196 0.58738 0.92077 0.83729
-0.90588 0.59173 0.92397 0.83983
-0.90980 0.59609 0.92717 0.84238
-0.91373 0.60046 0.93036 0.84492
-0.91765 0.60485 0.93356 0.84745
-0.92157 0.60925 0.93675 0.84999
-0.92549 0.61366 0.93993 0.85252
-0.92941 0.61809 0.94312 0.85504
-0.93333 0.62253 0.94630 0.85757
-0.93725 0.62698 0.94948 0.86009
-0.94118 0.63145 0.95266 0.86261
-0.94510 0.63593 0.95583 0.86512
-0.94902 0.64042 0.95900 0.86763
-0.95294 0.64493 0.96217 0.87014
-0.95686 0.64945 0.96534 0.87264
-0.96078 0.65398 0.96850 0.87515
-0.96471 0.65852 0.97166 0.87765
-0.96863 0.66308 0.97482 0.88014
-0.97255 0.66765 0.97798 0.88263
-0.97647 0.67223 0.98113 0.88512
-0.98039 0.67683 0.98428 0.88761
-0.98431 0.68144 0.98743 0.89009
-0.98824 0.68606 0.99058 0.89258
-0.99216 0.69069 0.99372 0.89505
-0.99608 0.69534 0.99686 0.89753
-1.0000 0.70000 1.0000 0.90000
+0.00000 0.00000 0.00000 0.00000
+3.92157e-003 5.67518e-005 0.0118787 0.0186065
+7.84314e-003 1.84387e-004 0.0206820 0.0302263
+0.0117647 3.67355e-004 0.0286065 0.0401466
+0.0156863 5.99076e-004 0.0360094 0.0491028
+0.0196078 8.75445e-004 0.0430471 0.0574042
+0.0235294 1.19354e-003 0.0498068 0.0652184
+0.0274510 1.55112e-003 0.0563438 0.0726496
+0.0313725 1.94640e-003 0.0626960 0.0797678
+0.0352941 2.37789e-003 0.0688909 0.0866232
+0.0392157 2.84433e-003 0.0749493 0.0932533
+0.0431373 3.34462e-003 0.0808876 0.0996872
+0.0470588 3.87782e-003 0.0867187 0.105948
+0.0509804 4.44307e-003 0.0924533 0.112053
+0.0549020 5.03962e-003 0.0981003 0.118020
+0.0588235 5.66676e-003 0.103667 0.123859
+0.0627451 6.32388e-003 0.109160 0.129583
+0.0666667 7.01040e-003 0.114585 0.135201
+0.0705882 7.72579e-003 0.119946 0.140720
+0.0745098 8.46956e-003 0.125248 0.146148
+0.0784314 9.24125e-003 0.130494 0.151490
+0.0823529 0.0100404 0.135689 0.156754
+0.0862745 0.0108667 0.140834 0.161942
+0.0901961 0.0117197 0.145932 0.167061
+0.0941176 0.0125991 0.150986 0.172112
+0.0980392 0.0135045 0.155998 0.177102
+0.101961 0.0144356 0.160971 0.182031
+0.105882 0.0153921 0.165905 0.186904
+0.109804 0.0163738 0.170803 0.191723
+0.113725 0.0173803 0.175665 0.196491
+0.117647 0.0184114 0.180495 0.201210
+0.121569 0.0194668 0.185292 0.205882
+0.125490 0.0205464 0.190059 0.210508
+0.129412 0.0216498 0.194796 0.215092
+0.133333 0.0227769 0.199504 0.219634
+0.137255 0.0239274 0.204184 0.224136
+0.141176 0.0251012 0.208838 0.228600
+0.145098 0.0262980 0.213466 0.233027
+0.149020 0.0275177 0.218069 0.237418
+0.152941 0.0287600 0.222648 0.241774
+0.156863 0.0300249 0.227204 0.246097
+0.160784 0.0313121 0.231737 0.250388
+0.164706 0.0326215 0.236248 0.254647
+0.168627 0.0339528 0.240737 0.258876
+0.172549 0.0353061 0.245205 0.263076
+0.176471 0.0366810 0.249654 0.267247
+0.180392 0.0380775 0.254082 0.271391
+0.184314 0.0394954 0.258491 0.275507
+0.188235 0.0409345 0.262882 0.279597
+0.192157 0.0423948 0.267254 0.283662
+0.196078 0.0438762 0.271609 0.287702
+0.200000 0.0453784 0.275946 0.291718
+0.203922 0.0469014 0.280266 0.295710
+0.207843 0.0484450 0.284570 0.299680
+0.211765 0.0500091 0.288857 0.303627
+0.215686 0.0515937 0.293128 0.307552
+0.219608 0.0531985 0.297384 0.311455
+0.223529 0.0548235 0.301625 0.315338
+0.227451 0.0564686 0.305851 0.319201
+0.231373 0.0581337 0.310063 0.323043
+0.235294 0.0598187 0.314260 0.326866
+0.239216 0.0615234 0.318443 0.330670
+0.243137 0.0632478 0.322613 0.334456
+0.247059 0.0649918 0.326769 0.338223
+0.250980 0.0667553 0.330911 0.341972
+0.254902 0.0685382 0.335041 0.345703
+0.258824 0.0703403 0.339159 0.349418
+0.262745 0.0721617 0.343264 0.353115
+0.266667 0.0740022 0.347356 0.356797
+0.270588 0.0758618 0.351437 0.360461
+0.274510 0.0777403 0.355505 0.364110
+0.278431 0.0796377 0.359563 0.367744
+0.282353 0.0815539 0.363608 0.371362
+0.286275 0.0834889 0.367643 0.374965
+0.290196 0.0854424 0.371666 0.378553
+0.294118 0.0874146 0.375679 0.382127
+0.298039 0.0894052 0.379681 0.385686
+0.301961 0.0914143 0.383672 0.389231
+0.305882 0.0934417 0.387653 0.392763
+0.309804 0.0954873 0.391624 0.396281
+0.313725 0.0975512 0.395585 0.399786
+0.317647 0.0996332 0.399536 0.403277
+0.321569 0.101733 0.403477 0.406756
+0.325490 0.103851 0.407409 0.410222
+0.329412 0.105987 0.411331 0.413676
+0.333333 0.108141 0.415244 0.417117
+0.337255 0.110313 0.419147 0.420546
+0.341176 0.112503 0.423042 0.423963
+0.345098 0.114710 0.426927 0.427368
+0.349020 0.116935 0.430804 0.430762
+0.352941 0.119177 0.434672 0.434144
+0.356863 0.121437 0.438532 0.437515
+0.360784 0.123714 0.442383 0.440875
+0.364706 0.126009 0.446225 0.444224
+0.368627 0.128321 0.450060 0.447563
+0.372549 0.130650 0.453886 0.450890
+0.376471 0.132997 0.457704 0.454207
+0.380392 0.135360 0.461514 0.457514
+0.384314 0.137741 0.465317 0.460811
+0.388235 0.140139 0.469111 0.464097
+0.392157 0.142554 0.472898 0.467374
+0.396078 0.144986 0.476678 0.470641
+0.400000 0.147435 0.480450 0.473898
+0.403922 0.149900 0.484214 0.477145
+0.407843 0.152383 0.487972 0.480383
+0.411765 0.154882 0.491722 0.483612
+0.415686 0.157398 0.495465 0.486831
+0.419608 0.159931 0.499200 0.490042
+0.423529 0.162480 0.502929 0.493243
+0.427451 0.165046 0.506651 0.496436
+0.431373 0.167628 0.510366 0.499619
+0.435294 0.170227 0.514075 0.502794
+0.439216 0.172842 0.517776 0.505961
+0.443137 0.175474 0.521472 0.509119
+0.447059 0.178122 0.525160 0.512269
+0.450980 0.180787 0.528842 0.515410
+0.454902 0.183467 0.532518 0.518543
+0.458824 0.186164 0.536187 0.521668
+0.462745 0.188877 0.539850 0.524785
+0.466667 0.191606 0.543507 0.527895
+0.470588 0.194351 0.547158 0.530996
+0.474510 0.197113 0.550803 0.534090
+0.478431 0.199890 0.554441 0.537176
+0.482353 0.202684 0.558074 0.540254
+0.486275 0.205493 0.561701 0.543325
+0.490196 0.208318 0.565322 0.546388
+0.494118 0.211159 0.568937 0.549444
+0.498039 0.214016 0.572547 0.552493
+0.501961 0.216889 0.576150 0.555535
+0.505882 0.219777 0.579748 0.558569
+0.509804 0.222681 0.583341 0.561597
+0.513725 0.225601 0.586928 0.564617
+0.517647 0.228536 0.590510 0.567631
+0.521569 0.231487 0.594086 0.570638
+0.525490 0.234454 0.597657 0.573638
+0.529412 0.237436 0.601222 0.576631
+0.533333 0.240434 0.604782 0.579618
+0.537255 0.243447 0.608337 0.582598
+0.541176 0.246476 0.611887 0.585571
+0.545098 0.249520 0.615431 0.588538
+0.549020 0.252579 0.618971 0.591499
+0.552941 0.255654 0.622505 0.594453
+0.556863 0.258744 0.626035 0.597401
+0.560784 0.261849 0.629559 0.600343
+0.564706 0.264970 0.633079 0.603279
+0.568627 0.268105 0.636594 0.606208
+0.572549 0.271256 0.640103 0.609132
+0.576471 0.274422 0.643608 0.612049
+0.580392 0.277603 0.647109 0.614961
+0.584314 0.280800 0.650604 0.617867
+0.588235 0.284011 0.654095 0.620766
+0.592157 0.287237 0.657581 0.623661
+0.596078 0.290478 0.661063 0.626549
+0.600000 0.293735 0.664540 0.629431
+0.603922 0.297006 0.668012 0.632308
+0.607843 0.300292 0.671480 0.635180
+0.611765 0.303593 0.674944 0.638045
+0.615686 0.306909 0.678403 0.640906
+0.619608 0.310239 0.681857 0.643761
+0.623529 0.313585 0.685308 0.646610
+0.627451 0.316945 0.688754 0.649454
+0.631373 0.320320 0.692195 0.652293
+0.635294 0.323709 0.695633 0.655126
+0.639216 0.327114 0.699066 0.657954
+0.643137 0.330533 0.702495 0.660777
+0.647059 0.333966 0.705919 0.663595
+0.650980 0.337414 0.709340 0.666408
+0.654902 0.340877 0.712756 0.669215
+0.658824 0.344354 0.716169 0.672018
+0.662745 0.347846 0.719577 0.674816
+0.666667 0.351352 0.722981 0.677608
+0.670588 0.354873 0.726381 0.680396
+0.674510 0.358408 0.729778 0.683179
+0.678431 0.361958 0.733170 0.685957
+0.682353 0.365522 0.736559 0.688730
+0.686275 0.369100 0.739943 0.691498
+0.690196 0.372693 0.743324 0.694262
+0.694118 0.376300 0.746701 0.697021
+0.698039 0.379921 0.750074 0.699775
+0.701961 0.383557 0.753443 0.702525
+0.705882 0.387207 0.756808 0.705270
+0.709804 0.390871 0.760170 0.708010
+0.713725 0.394549 0.763528 0.710746
+0.717647 0.398242 0.766882 0.713477
+0.721569 0.401948 0.770233 0.716204
+0.725490 0.405669 0.773580 0.718927
+0.729412 0.409404 0.776923 0.721645
+0.733333 0.413153 0.780263 0.724358
+0.737255 0.416916 0.783599 0.727068
+0.741176 0.420693 0.786932 0.729773
+0.745098 0.424484 0.790261 0.732473
+0.749020 0.428289 0.793587 0.735170
+0.752941 0.432108 0.796909 0.737862
+0.756863 0.435940 0.800228 0.740550
+0.760784 0.439787 0.803543 0.743234
+0.764706 0.443648 0.806855 0.745914
+0.768627 0.447523 0.810164 0.748589
+0.772549 0.451411 0.813469 0.751261
+0.776471 0.455314 0.816770 0.753928
+0.780392 0.459230 0.820069 0.756592
+0.784314 0.463160 0.823364 0.759251
+0.788235 0.467103 0.826656 0.761906
+0.792157 0.471061 0.829944 0.764558
+0.796078 0.475032 0.833230 0.767205
+0.800000 0.479017 0.836512 0.769849
+0.803922 0.483016 0.839790 0.772489
+0.807843 0.487028 0.843066 0.775124
+0.811765 0.491054 0.846339 0.777756
+0.815686 0.495094 0.849608 0.780385
+0.819608 0.499147 0.852874 0.783009
+0.823529 0.503214 0.856137 0.785630
+0.827451 0.507294 0.859397 0.788247
+0.831373 0.511388 0.862654 0.790860
+0.835294 0.515496 0.865908 0.793469
+0.839216 0.519617 0.869158 0.796075
+0.843137 0.523751 0.872406 0.798677
+0.847059 0.527899 0.875651 0.801276
+0.850980 0.532061 0.878892 0.803871
+0.854902 0.536236 0.882131 0.806462
+0.858824 0.540424 0.885367 0.809050
+0.862745 0.544626 0.888599 0.811634
+0.866667 0.548841 0.891829 0.814215
+0.870588 0.553070 0.895056 0.816792
+0.874510 0.557311 0.898280 0.819366
+0.878431 0.561567 0.901501 0.821936
+0.882353 0.565835 0.904719 0.824503
+0.886275 0.570117 0.907935 0.827066
+0.890196 0.574412 0.911147 0.829626
+0.894118 0.578721 0.914357 0.832183
+0.898039 0.583042 0.917564 0.834736
+0.901961 0.587377 0.920768 0.837286
+0.905882 0.591725 0.923969 0.839833
+0.909804 0.596087 0.927168 0.842376
+0.913725 0.600461 0.930363 0.844916
+0.917647 0.604849 0.933556 0.847453
+0.921569 0.609249 0.936747 0.849986
+0.925490 0.613663 0.939934 0.852516
+0.929412 0.618090 0.943119 0.855044
+0.933333 0.622530 0.946301 0.857567
+0.937255 0.626984 0.949481 0.860088
+0.941176 0.631450 0.952658 0.862606
+0.945098 0.635929 0.955832 0.865120
+0.949020 0.640421 0.959003 0.867631
+0.952941 0.644927 0.962172 0.870139
+0.956863 0.649445 0.965339 0.872644
+0.960784 0.653976 0.968502 0.875146
+0.964706 0.658521 0.971664 0.877645
+0.968627 0.663078 0.974822 0.880141
+0.972549 0.667648 0.977978 0.882634
+0.976471 0.672231 0.981132 0.885124
+0.980392 0.676827 0.984283 0.887610
+0.984314 0.681436 0.987431 0.890094
+0.988235 0.686058 0.990577 0.892575
+0.992157 0.690692 0.993721 0.895053
+0.996078 0.695340 0.996862 0.897528
+1.00000 0.700000 1.00000 0.900000
END_DATA
diff --git a/spectro/synthread.c b/spectro/synthread.c
index c4312f1..3a23c31 100644
--- a/spectro/synthread.c
+++ b/spectro/synthread.c
@@ -451,6 +451,9 @@ printf("~1 omax = %f %f %f\n", md.omax[0], md.omax[1], md.omax[2]);
if ((ti = icg->find_kword(icg, 0, "FULL_SPREAD_PATCHES")) >= 0)
ocg->add_kword(ocg, 0, "FULL_SPREAD_PATCHES",icg->t[0].kdata[ti], NULL);
+ if ((ti = icg->find_kword(icg, 0, "DARK_REGION_EMPHASIS")) >= 0)
+ ocg->add_kword(ocg, 0, "DARK_REGION_EMPHASIS",icg->t[0].kdata[ti], NULL);
+
/* Fields we want */
ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t);
diff --git a/spectro/usbio.c b/spectro/usbio.c
index 3db1535..f8a0529 100644
--- a/spectro/usbio.c
+++ b/spectro/usbio.c
@@ -14,7 +14,7 @@
* see the License2.txt file for licencing details.
*/
-/* These routines supliement the class code in ntio.c and unixio.c */
+/* These routines supliement the class code in icoms_nt.c and icoms_ux.c */
/* with common and USB specific routines */
#include <stdio.h>
@@ -51,35 +51,42 @@ int in_usb_rw = 0;
void usb_init_cancel(usb_cancelt *p) {
amutex_init(p->cmtx);
+ amutex_init(p->cond);
-#ifdef NATIVE_USB
p->hcancel = NULL;
-#else
-# ifdef USE_LIBUSB1
- p->hcancel = NULL;
-# else
- p->hcancel = (void *)-1;
-# endif
-#endif
}
void usb_uninit_cancel(usb_cancelt *p) {
amutex_del(p->cmtx);
+ amutex_del(p->cond);
}
-/* Used by implementation */
-static void usb_lock_cancel(usb_cancelt *p) {
+/* Used by caller of icoms to re-init for wait_io */
+/* Must be called before icoms_usb_wait_io() */
+void usb_reinit_cancel(usb_cancelt *p) {
+
amutex_lock(p->cmtx);
-}
-static void usb_unlock_cancel(usb_cancelt *p) {
+ p->hcancel = NULL;
+ p->state = 0;
+ amutex_lock(p->cond); /* Block until IO is started */
+
amutex_unlock(p->cmtx);
}
+/* Wait for the given transaction to be pending or complete. */
+static int icoms_usb_wait_io(
+ icoms *p,
+ usb_cancelt *cancelt
+) {
+ amutex_lock(cancelt->cond); /* Wait for unlock */
+ amutex_unlock(cancelt->cond); /* Free it up for next time */
+ return ICOM_OK;
+}
+
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Include the USB implementation dependent function implementations */
-#ifdef NATIVE_USB
# ifdef NT
# include "usbio_nt.c"
# endif
@@ -87,11 +94,12 @@ static void usb_unlock_cancel(usb_cancelt *p) {
# include "usbio_ox.c"
# endif
# if defined(UNIX_X11)
-# include "usbio_lx.c"
+# if defined(__FreeBSD__)
+# include "usbio_bsd.c"
+# else
+# include "usbio_lx.c"
+# endif
# endif
-#else /* Using libusb */
-# include "usbio_lusb.c"
-#endif
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* I/O routines supported by icoms - uses platform independent */
@@ -415,19 +423,20 @@ double tout)
/* Read characters into the buffer */
/* Return string will be terminated with a nul */
-/* Read only in paket sized chunks, and retry if */
+/* Read only in packet sized chunks, and retry if */
/* the bytes requested aren'r read, untill we get a */
/* timeout or a terminating char is read */
static int
icoms_usb_ser_read(icoms *p,
char *rbuf, /* Buffer to store characters read */
int bsize, /* Buffer size */
-char tc, /* Terminating characer */
-int ntc, /* Number of terminating characters */
+char *tc, /* Terminating characers, NULL if none */
+int ntc, /* Number of terminating characters needed to terminate */
double tout) /* Time out in seconds */
{
int j, rbytes;
- long toc, i, top; /* Timout count, counter, timeout period */
+ long ttop, top; /* Total timeout period, timeout period */
+ unsigned int stime, etime; /* Start and end times of USB operation */
char *rrbuf = rbuf; /* Start of return buffer */
int ep = p->rd_ep; /* End point */
icom_usb_trantype type; /* bulk or interrupt */
@@ -463,50 +472,74 @@ double tout) /* Time out in seconds */
return ICOM_SYS;
}
- for (i = 0; i < bsize; i++) rbuf[i] = 0;
+ for (j = 0; j < bsize; j++) rbuf[j] = 0;
- tout *= 1000.0; /* Timout in msec */
- bsize--; /* Allow space for null */
+ bsize -= 1; /* Allow space for null */
+ bsize -= p->ms_bytes; /* Allow space for modem status bytes */
- /* Have to do this in one go, because libusb has no way */
- /* of timing out and returning the number of characters read */
- /* up to the timeout, and it looses characters. */
- top = (int)(tout + 0.5); /* Timeout period in msecs */
- toc = (int)(tout/top + 0.5); /* Number of timout periods in timeout */
- if (toc < 1)
- toc = 1;
+ /* The DTP94 doesn't cope with a timeout on OS X, so we need to avoid */
+ /* them by giving each read the largest timeout period possible. */
+ /* This also reduces the problem of libusb 0.1 not returning the */
+ /* number of characters read on a timeou. */
+
+ ttop = (int)(tout * 1000.0 + 0.5); /* Total timeout period in msecs */
+
+ a1logd(p->log, 8, "\nicoms_usb_ser_read: ep 0x%x, ttop %d, quant %d\n", p->rd_ep, ttop, p->rd_qa);
- a1logd(p->log, 8, "\nicoms_usb_ser_read: end point 0x%x, read quanta %d\n",p->rd_ep,p->rd_qa);
/* Until data is all read, we time out, or the user aborts */
- for (i = toc, j = 0; i > 0 && bsize > 1 && j < ntc ;) {
+ stime = msec_time();
+ top = ttop;
+ for (j = 0; top > 0 && bsize > 1 && j < ntc ;) {
int c, rv;
int rsize = p->rd_qa < bsize ? p->rd_qa : bsize;
- a1logd(p->log, 8, "icoms_usb_ser_read: attempting to read %d bytes from usb, top = %d, i = %d, j = %d\n",bsize > p->rd_qa ? p->rd_qa : bsize,top,i,j);
- /* We read one read quanta at a time (usually 8 bytes), to avoid */
- /* problems with libusb loosing characters whenever it times out. */
+ a1logd(p->log, 8, "icoms_usb_ser_read: attempting to read %d bytes from usb, top = %d, j = %d\n",bsize > p->rd_qa ? p->rd_qa : bsize,top,j);
+
rv = icoms_usb_transaction(p, NULL, &rbytes, type, (unsigned char)ep, (unsigned char *)rbuf, rsize, top);
- if (rv != 0 && rv != ICOM_SHORT) {
- a1logd(p->log, 8, "icoms_usb_ser_read: read failed with 0x%x, rbuf = '%s'\n",rv,icoms_fix(rrbuf));
- if (rv != ICOM_TO) {
- retrv |= rv;
- break;
+ etime = msec_time();
+
+ if (rbytes > 0) { /* Account for bytes read */
+
+ /* Account for modem status bytes. Modem bytes are per usb read. */
+ if (p->ms_bytes) { /* Throw away modem bytes */
+ int nb = rbytes < p->ms_bytes ? rbytes : p->ms_bytes;
+ rbytes -= nb;
+ memmove(rbuf, rbuf+nb, rbytes);
+ a1logd(p->log, 8, "icoms_usb_ser_read: discarded %d modem bytes\n",nb);
}
- i--; /* Timeout */
- } else { /* Account for bytes read */
- a1logd(p->log, 8, "icoms_usb_ser_read: read read %d bytes, rbuf = '%s'\n",rbytes,icoms_fix(rrbuf));
- i = toc;
+
+ a1logd(p->log, 8, "icoms_usb_ser_read: read %d bytes, rbuf = '%s'\n",rbytes,icoms_fix(rrbuf));
+
bsize -= rbytes;
- while(rbytes) { /* Count termination characters */
- if (*rbuf++ == tc)
- j++;
- rbytes--;
+ if (tc != NULL) {
+ while(rbytes--) { /* Count termination characters */
+ char ch = *rbuf++, *tcp = tc;
+
+ while(*tcp != '\000') {
+ if (ch == *tcp)
+ j++;
+ tcp++;
+ }
+ }
+ } else {
+ rbuf += rbytes;
}
}
- }
- if (i <= 0) /* Must have timed out */
- retrv |= ICOM_TO;
+ /* Deal with any errors */
+ if (rv != ICOM_OK && rv != ICOM_SHORT) {
+ a1logd(p->log, 8, "icoms_usb_ser_read: read failed with 0x%x, rbuf = '%s'\n",rv,icoms_fix(rrbuf));
+ retrv |= rv;
+ break;
+ }
+
+ top = ttop - (etime - stime); /* Remaining time */
+ if (top <= 0) { /* Run out of time */
+ a1logd(p->log, 8, "icoms_usb_ser_read: read ran out of time\n");
+ retrv |= ICOM_TO;
+ break;
+ }
+ }
*rbuf = '\000';
@@ -533,7 +566,8 @@ char **pnames /* List of process names to try and kill before opening */
) {
a1logd(p->log, 8, "icoms_set_usb_port: About to set usb port characteristics\n");
- if (p->port_type(p) == icomt_usb) {
+ if (p->port_type(p) == icomt_usb
+ || p->port_type(p) == icomt_usbserial) {
int rv;
if (p->is_open)
@@ -546,21 +580,12 @@ char **pnames /* List of process names to try and kill before opening */
p->write = icoms_usb_ser_write;
p->read = icoms_usb_ser_read;
+ } else {
+ a1logd(p->log, 8, "icoms_set_usb_port: Not a USB port!\n");
+ return ICOM_NOTS;
}
a1logd(p->log, 6, "icoms_set_usb_port: usb port characteristics set ok\n");
-#ifndef NATIVE_USB
- /* libusb doesn't have any facility for re-directing its */
- /* debug messages. Since we're moving away from it, */
- /* ignore the problem. */
- if (p->log->debug >= 8) { /* Could this go inside usb_open_port ? */
-# ifdef USE_LIBUSB1
- libusb_set_debug(NULL, p->log->debug);
-# else
- usb_set_debug(p->debug);
-# endif
- }
-#endif /* NATIVE_USB */
return ICOM_OK;
}
@@ -575,6 +600,7 @@ icoms *p
p->usb_control = icoms_usb_control;
p->usb_read = icoms_usb_rw;
p->usb_write = icoms_usb_rw;
+ p->usb_wait_io = icoms_usb_wait_io;
p->usb_cancel_io = icoms_usb_cancel_io;
p->usb_resetep = icoms_usb_resetep;
p->usb_clearhalt = icoms_usb_clearhalt;
@@ -582,4 +608,5 @@ icoms *p
/* ---------------------------------------------------------------------------------*/
+
#endif /* ENABLE_USB */
diff --git a/spectro/usbio.h b/spectro/usbio.h
index 5c982ae..1181801 100644
--- a/spectro/usbio.h
+++ b/spectro/usbio.h
@@ -23,8 +23,6 @@
#endif
-#ifdef NATIVE_USB
-
/* Standard USB protocol defines */
# include "iusb.h"
@@ -131,6 +129,22 @@ struct usb_idevice {
# if defined(UNIX) && !defined(__APPLE__)
+# if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+
+/* BSD USB context */
+struct usb_idevice {
+ /* icompath stuff: */
+ char *dpath; /* Device path */
+ int nconfig; /* Number of configurations */
+ int config; /* This config (always 1) */
+ int nifce; /* Number of interfaces */
+ usb_ep ep[32]; /* Information about each end point for general usb i/o */
+ /* Stuff setup when device is open: */
+ int fd; /* Device file descriptor */
+};
+
+# else
+
/* Linux USB context */
struct usb_idevice {
/* icompath stuff: */
@@ -150,43 +164,11 @@ struct usb_idevice {
pthread_mutex_t lock; /* Protect reqs list */
struct _usbio_req *reqs; /* linked list of current reqs */
};
-
-# endif /* Linux */
-
-#else /* !NATIVE_USB - Using libusb */
-
-# ifdef USE_LIBUSB1
-
-# include "libusb.h"
-# define usb_idevice libusb_device
-# define IUSB_ENDPOINT_DIR_MASK LIBUSB_ENDPOINT_DIR_MASK
-# define IUSB_ENDPOINT_IN LIBUSB_ENDPOINT_IN
-# define IUSB_ENDPOINT_OUT LIBUSB_ENDPOINT_OUT
-# define IUSB_REQ_RECIP_DEVICE LIBUSB_RECIPIENT_DEVICE
-# define IUSB_REQ_RECIP_INTERFACE LIBUSB_RECIPIENT_INTERFACE
-# define IUSB_REQ_RECIP_ENDPOINT LIBUSB_RECIPIENT_ENDPOINT
-# define IUSB_REQ_TYPE_STANDARD LIBUSB_REQUEST_TYPE_STANDARD
-# define IUSB_REQ_TYPE_CLASS LIBUSB_REQUEST_TYPE_CLASS
-# define IUSB_REQ_TYPE_VENDOR LIBUSB_REQUEST_TYPE_VENDOR
-# define IUSB_ENDPOINT_TYPE_MASK LIBUSB_TRANSFER_TYPE_MASK
-
-# else
-
-# include "usb.h"
-# define usb_idevice usb_device
-# define IUSB_ENDPOINT_DIR_MASK USB_ENDPOINT_DIR_MASK
-# define IUSB_ENDPOINT_IN USB_ENDPOINT_IN
-# define IUSB_ENDPOINT_OUT USB_ENDPOINT_OUT
-# define IUSB_REQ_RECIP_DEVICE USB_RECIP_DEVICE
-# define IUSB_REQ_RECIP_INTERFACE USB_RECIP_INTERFACE
-# define IUSB_REQ_RECIP_ENDPOINT USB_RECIP_ENDPOINT
-# define IUSB_REQ_TYPE_STANDARD USB_TYPE_STANDARD
-# define IUSB_REQ_TYPE_CLASS USB_TYPE_CLASS
-# define IUSB_REQ_TYPE_VENDOR USB_TYPE_VENDOR
-# define IUSB_ENDPOINT_TYPE_MASK USB_ENDPOINT_TYPE_MASK
-
-# endif
-#endif
+
+# endif /* Linux */
+
+# endif /* UNIX */
+
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -202,6 +184,8 @@ typedef enum {
/* Cancelation token. */
struct _usb_cancelt {
amutex cmtx;
+ int state; /* 0 = init, 1 = pending, 2 = complete */
+ amutex cond; /* Wait for state 0->1 sync. mutex */
void *hcancel; /* Pointer to implementation cancel handle */
};
@@ -237,6 +221,9 @@ void usb_install_signal_handlers(icoms *p);
/* (used inside usb_close_port(), hid_close_port() */
void usb_delete_from_cleanup_list(icoms *p);
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+
#ifdef __cplusplus
}
#endif
diff --git a/spectro/usbio_bsd.c b/spectro/usbio_bsd.c
new file mode 100644
index 0000000..7649caf
--- /dev/null
+++ b/spectro/usbio_bsd.c
@@ -0,0 +1,764 @@
+
+/* General USB I/O support, BSD native implementation. */
+/* This file is conditionaly #included into usbio.c */
+
+/*
+ * Argyll Color Correction System
+ *
+ * Author: Graeme W. Gill
+ * Date: 2006/22/4
+ *
+ * Copyright 2006 - 2013 Graeme W. Gill
+ * All rights reserved.
+ *
+ * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
+ * see the License2.txt file for licencing details.
+ */
+
+/*
+ !!!! This driver is incomplete and non-functional !!!!
+
+ BSD uses fd per end point, so simplifies things.
+
+ No clear ep or abort i/o though, so we could try clear halt,
+ or close fd and see if that works in aborting transaction ?
+
+ Posix aio would probably work, but it's not loaded by default :-(
+
+ Could use libusb20 API, but not backwards or cross compatible,
+ and is very likely to be buggy ?
+
+ */
+
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <sys/ioctl.h>
+#if defined(__FreeBSD__)
+# include <dev/usb/usb_ioctl.h> /* Not sure what's going on with FreeBSD... */
+#else
+# include <dev/usb/usb.h> /* The usual include for BSD */
+#endif
+
+/* select() defined, but not poll(), so emulate poll() */
+#if defined(FD_CLR) && !defined(POLLIN)
+#include "pollem.h"
+#define poll_x pollem
+#else
+#include <sys/poll.h> /* Else assume poll() is native */
+#define poll_x poll
+#endif
+
+/* Add paths to USB connected instruments */
+/* Return an icom error */
+int usb_get_paths(
+icompaths *p
+) {
+ int i, j;
+ char *paths[] = {
+#if defined(__FreeBSD__)
+ "/dev/usb/[0-9]*.*.0", /* FreeBSD >= 8 */
+ "/dev/ugen[0-9]*", /* FreeBSD < 8, but no .E */
+#else
+ "/dev/ugen/[0-9]*.00", /* NetBSD, OpenBSD */
+#endif
+ NULL
+ };
+ int vid, pid;
+ int nconfig = 0, nep = 0;
+ char *dpath;
+ instType itype;
+ struct usb_idevice *usbd = NULL;
+
+ a1logd(p->log, 6, "usb_get_paths: about to look through usb devices:\n");
+
+ /* See what device names to look for */
+ for (j = 0; ; j++) {
+ glob_t g;
+ int fd;
+ struct usb_device_info di;
+ int rv, found = 0;
+
+ if (paths[j] == NULL)
+ break;
+
+ memset(&g, 0, sizeof(g));
+
+ if (glob(paths[j], GLOB_NOSORT, NULL, &g) != 0) {
+ continue;
+ }
+
+ /* For all the nodes found by the glob */
+ for (i = 0; i < g.gl_pathc; i++) {
+
+#if defined(__FreeBSD__)
+ /* Skip anything with an end point number */
+ if (j == 1 && strchr(g.gl_pathv[i], '.') != NULL)
+ continue;
+#endif
+ if ((fd = open(g.gl_pathv[i], O_RDONLY)) < 0)
+ continue;
+
+ if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
+ continue;
+
+ vid = di.udi_vendorNo;
+ pid = di.udi_productNo;
+
+ a1logd(p->log, 6, "usb_get_paths: checking vid 0x%04x, pid 0x%04x\n",vid,pid);
+
+ /* Do a preliminary match */
+ if ((itype = inst_usb_match(vid, pid, 0)) == instUnknown) {
+ a1logd(p->log, 6 , "usb_get_paths: instrument not reconized\n");
+ continue;
+ }
+
+ // ~~99 need to check number of end points ~~~
+ // ~~99 and number of configs
+ nconfig = 1;
+
+//USB_GET_DEVICEINFO struct usb_device_info
+//USB_GET_DEVICE_DESC struct usb_device_descriptor
+
+ /* Allocate an idevice so that we can fill in the end point information */
+ if ((usbd = (struct usb_idevice *) calloc(sizeof(struct usb_idevice), 1)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "icoms: calloc failed!\n");
+ close(fd);
+ globfree(&g);
+ return ICOM_SYS;
+ }
+
+ usbd->nconfig = nconfig;
+
+ /* Found a known instrument ? */
+ if ((itype = inst_usb_match(vid, pid, nep)) != instUnknown) {
+ char pname[400], *cp;
+
+ a1logd(p->log, 2, "usb_get_paths: found instrument vid 0x%04x, pid 0x%04x\n",vid,pid);
+
+ /* Create the base device path */
+ dpath = g.gl_pathv[i];
+#if defined(__FreeBSD__)
+ if (j == 0) { /* Remove .0 */
+ if ((cp = strrchr(dpath, '.')) != NULL
+ && cp[1] == '0' && cp[2] == '\000')
+ *cp = '\000';
+ }
+#else
+ /* Remove .00 */
+ if ((cp = strrchr(dpath, '.')) != NULL
+ && cp[1] == '0' && cp[2] == '0' && cp[3] == '\000')
+ *cp = '\000';
+#endif
+ if ((usbd->dpath = strdup(dpath)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "usb_get_paths: strdup path failed!\n");
+ free(usbd);
+ close(fd);
+ globfree(&g);
+ return ICOM_SYS;
+ }
+
+ /* Create a path/identification */
+ sprintf(pname,"%s (%s)", dpath, inst_name(itype));
+ if ((usbd->dpath = strdup(dpath)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "usb_get_paths: strdup path failed!\n");
+ free(usbd);
+ close(fd);
+ globfree(&g);
+ return ICOM_SYS;
+ }
+
+ /* Add the path and ep info to the list */
+ if ((rv = p->add_usb(p, pname, vid, pid, nep, usbd, itype)) != ICOM_OK)
+ return rv;
+
+
+ } else {
+ free(usbd);
+ }
+
+ close(fd);
+ }
+ globfree(&g);
+
+ /* Only try one glob string */
+ break;
+ }
+
+ a1logd(p->log, 8, "usb_get_paths: returning %d paths and ICOM_OK\n",p->npaths);
+ return ICOM_OK;
+}
+
+/* Copy usb_idevice contents from icompaths to icom */
+/* return icom error */
+int usb_copy_usb_idevice(icoms *d, icompath *s) {
+ int i;
+ if (s->usbd == NULL) {
+ d->usbd = NULL;
+ return ICOM_OK;
+ }
+ if ((d->usbd = calloc(sizeof(struct usb_idevice), 1)) == NULL) {
+ a1loge(d->log, ICOM_SYS, "usb_copy_usb_idevice: malloc\n");
+ return ICOM_SYS;
+ }
+ if ((d->usbd->dpath = strdup(s->usbd->dpath)) == NULL) {
+ a1loge(d->log, ICOM_SYS, "usb_copy_usb_idevice: malloc\n");
+ return ICOM_SYS;
+ }
+ /* Copy the ep info */
+ d->nconfig = s->usbd->nconfig;
+ d->nifce = s->usbd->nifce;
+ d->config = s->usbd->config;
+ for (i = 0; i < 32; i++)
+ d->ep[i] = s->usbd->ep[i]; /* Struct copy */
+ return ICOM_OK;
+}
+
+/* Cleanup and then free a usb dev entry */
+void usb_del_usb_idevice(struct usb_idevice *usbd) {
+
+ if (usbd == NULL)
+ return;
+
+ if (usbd->dpath != NULL)
+ free(usbd->dpath);
+ free(usbd);
+}
+
+/* Cleanup any USB specific icoms state */
+void usb_del_usb(icoms *p) {
+
+ usb_del_usb_idevice(p->usbd);
+}
+
+/* Close an open USB port */
+/* If we don't do this, the port and/or the device may be left in an unusable state. */
+void usb_close_port(icoms *p) {
+
+ a1logd(p->log, 6, "usb_close_port: called\n");
+
+#ifdef NEVER // ~~99
+ if (p->is_open && p->usbd != NULL) {
+ struct usbdevfs_urb urb;
+ unsigned char buf[8+IUSB_DESC_TYPE_DEVICE_SIZE];
+ int iface, rv;
+
+ /* Release all the interfaces */
+ for (iface = 0; iface < p->nifce; iface++)
+ ioctl(p->usbd->fd, USBDEVFS_RELEASEINTERFACE, &iface);
+
+ /* Workaround for some bugs - reset device on close */
+ if (p->uflags & icomuf_reset_before_close) {
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_RESET, NULL)) != 0) {
+ a1logd(p->log, 1, "usb_close_port: reset returned %d\n",rv);
+ }
+ }
+
+ if (p->usbd->running) { /* If reaper is still running */
+ unsigned char buf[1] = { 0 };
+
+ a1logd(p->log, 6, "usb_close_port: waking reaper thread to trigger exit\n");
+ p->usbd->shutdown = 1;
+
+ if (write(p->usbd->sd_pipe[1], buf, 1) < 1) {
+ a1logd(p->log, 1, "usb_close_port: writing to sd_pipe failed with '%s'\n", strerror(errno));
+ /* Hmm. We could be in trouble ? */
+ }
+ }
+ a1logd(p->log, 6, "usb_close_port: waiting for reaper thread\n");
+ pthread_join(p->usbd->thread, NULL); /* Wait for urb reaper thread to exit */
+ close(p->usbd->fd);
+ pthread_mutex_destroy(&p->usbd->lock);
+ close(p->usbd->sd_pipe[0]);
+ close(p->usbd->sd_pipe[1]);
+
+ a1logd(p->log, 6, "usb_close_port: usb port has been released and closed\n");
+ }
+ p->is_open = 0;
+#endif // ~~99
+
+ /* Find it and delete it from our static cleanup list */
+ usb_delete_from_cleanup_list(p);
+}
+
+static void *urb_reaper(void *context); /* Declare */
+
+/* Open a USB port for all our uses. */
+/* This always re-opens the port */
+/* return icom error */
+static int usb_open_port(
+icoms *p,
+int config, /* Configuration number */
+int wr_ep, /* Write end point */
+int rd_ep, /* Read end point */
+icomuflags usbflags,/* Any special handling flags */
+int retries, /* > 0 if we should retry set_configuration (100msec) */
+char **pnames /* List of process names to try and kill before opening */
+) {
+ int rv, tries = 0;
+ a1logd(p->log, 8, "usb_open_port: Make sure USB port is open, tries %d\n",retries);
+
+ if (p->is_open)
+ p->close_port(p);
+
+#ifdef NEVER // ~~99
+ /* Make sure the port is open */
+ if (!p->is_open) {
+ int rv, i, iface;
+ kkill_nproc_ctx *kpc = NULL;
+
+ if (config != 1) {
+ /* Nothing currently needs it, so we haven't implemented it yet... */
+ a1loge(p->log, ICOM_NOTS, "usb_open_port: native driver cant handle config %d\n",config);
+ return ICOM_NOTS;
+ }
+
+ /* Do open retries */
+ for (tries = 0; retries >= 0; retries--, tries++) {
+
+ a1logd(p->log, 8, "usb_open_port: About to open USB port '%s'\n",p->usbd->dpath);
+
+ if (tries > 0) {
+ //msec_sleep(i_rand(50,100));
+ msec_sleep(77);
+ }
+
+ p->uflags = usbflags;
+
+ /* We should only do a set configuration if the device has more than one */
+ /* possible configuration and it is currently not the desired configuration, */
+ /* but we should avoid doing a set configuration if the OS has already */
+ /* selected the configuration we want, since two set configs seem to */
+ /* mess up the Spyder2, BUT we can't do a get config because this */
+ /* messes up the i1pro-D. */
+
+ /* Linux set_configuration(1) by default, so we don't need to do anything */
+ p->cconfig = 1;
+
+ if (p->cconfig != config) {
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_SETCONFIGURATION, &config)) != 0) {
+ a1logd(p->log, 1, "icoms_usb_setconfig failed with %d\n",rv);
+ return ICOM_SYS;
+ }
+ p->cconfig = config;
+ a1logd(p->log, 6, "usb_open_port: set config %d OK\n",config);
+ }
+
+ /* We're done */
+ break;
+ }
+
+ if (kpc != NULL)
+ kpc->del(kpc);
+
+ /* Claim all the interfaces */
+ for (iface = 0; iface < p->nifce; iface++) {
+
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_CLAIMINTERFACE, &iface)) < 0) {
+ struct usbdevfs_getdriver getd;
+ getd.interface = iface;
+
+ a1logd(p->log, 1, "usb_open_port: Claiming USB port '%s' interface %d initally failed with %d\n",p->usbd->dpath,iface,rv);
+
+ /* Detatch the existing interface if kernel driver is active. */
+ if (p->uflags & icomuf_detach
+ && ioctl(p->usbd->fd, USBDEVFS_GETDRIVER, &getd) == 0) {
+ struct usbdevfs_ioctl cmd;
+ a1logd(p->log, 1, "usb_open_port: Attempting kernel detach\n");
+ cmd.ifno = iface;
+ cmd.ioctl_code = USBDEVFS_DISCONNECT;
+ cmd.data = NULL;
+ ioctl(p->usbd->fd, USBDEVFS_IOCTL, &cmd);
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_CLAIMINTERFACE, &iface)) < 0) {
+ a1loge(p->log, ICOM_SYS, "usb_open_port: Claiming USB port '%s' interface %d failed after detach with %d\n",p->usbd->dpath,iface,rv);
+ return ICOM_SYS;
+ }
+ } else {
+ a1loge(p->log, ICOM_SYS, "usb_open_port: Claiming USB port '%s' interface %d failed with %d\n",p->usbd->dpath,iface,rv);
+ return ICOM_SYS;
+ }
+ }
+ }
+
+ /* Clear any errors. */
+ /* (Some I/F seem to hang if we do this, some seem to hang if we don't !) */
+ /* The ColorMunki on Linux only starts every second time if we don't do this. */
+ if (!(p->uflags & icomuf_no_open_clear)) {
+ for (i = 0; i < 32; i++) {
+ if (!p->ep[i].valid)
+ continue;
+ p->usb_clearhalt(p, p->ep[i].addr);
+ }
+ }
+
+ /* Set "serial" coms values */
+ p->wr_ep = wr_ep;
+ p->rd_ep = rd_ep;
+ p->rd_qa = p->EPINFO(rd_ep).packetsize;
+ if (p->rd_qa == 0)
+ p->rd_qa = 8;
+ a1logd(p->log, 8, "usb_open_port: 'serial' read quanta = packet size = %d\n",p->rd_qa);
+
+ /* Start the reaper thread to handle URB completions */
+ if ((rv = pipe(p->usbd->sd_pipe)) < 0) {
+ a1loge(p->log, ICOM_SYS, "usb_open_port: creat pipe failed with %d\n",rv);
+ return ICOM_SYS;
+ }
+ pthread_mutex_init(&p->usbd->lock, NULL);
+
+ p->usbd->running = 1;
+ if ((rv = pthread_create(&p->usbd->thread, NULL, urb_reaper, (void*)p)) < 0) {
+ p->usbd->running = 0;
+ a1loge(p->log, ICOM_SYS, "usb_open_port: creating urb reaper thread failed with %s\n",rv);
+ return ICOM_SYS;
+ }
+
+ p->is_open = 1;
+ a1logd(p->log, 8, "usb_open_port: USB port is now open\n");
+ }
+
+#endif // ~~99
+ /* Install the cleanup signal handlers, and add to our cleanup list */
+ usb_install_signal_handlers(p);
+
+ return ICOM_OK;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - */
+/* Our universal USB transfer function */
+static int icoms_usb_transaction(
+ icoms *p,
+ usb_cancelt *cancelt,
+ int *transferred,
+ icom_usb_trantype ttype, /* transfer type */
+ unsigned char endpoint, /* 0x80 for control write, 0x00 for control read */
+ unsigned char *buffer,
+ int length,
+ unsigned int timeout /* In msec */
+) {
+ int type;
+ int remlen;
+ unsigned char *bp;
+ int xlength = 0;
+ int i;
+ int reqrv = ICOM_OK;
+
+#ifdef NEVER // ~~99
+ in_usb_rw++;
+ a1logd(p->log, 8, "icoms_usb_transaction: req type 0x%x ep 0x%x size %d\n",ttype,endpoint,length);
+
+ if (!p->usbd->running) {
+ in_usb_rw--;
+ a1logv(p->log, 1, "icoms_usb_transaction: reaper thread is not running\n");
+ return ICOM_SYS;
+ }
+
+ /* Translate icoms transfer type of Linux */
+ switch (ttype) {
+ case icom_usb_trantype_command:
+ type = USBDEVFS_URB_TYPE_CONTROL;
+ break;
+ case icom_usb_trantype_interrutpt:
+ type = USBDEVFS_URB_TYPE_INTERRUPT;
+ break;
+ case icom_usb_trantype_bulk:
+ type = USBDEVFS_URB_TYPE_BULK;
+ break;
+ }
+
+ /* Setup the icom req and urbs */
+ req.urbs = NULL;
+ pthread_mutex_init(&req.lock, NULL);
+ pthread_cond_init(&req.cond, NULL);
+
+ /* Linux historically only copes with 16384 length urbs, */
+ /* so break up longer requests into multiple urbs */
+
+ req.cancelled = 0;
+ req.nourbs = req.nurbs = (length + (1 << 14)-1) >> 14;
+ if ((req.urbs = (usbio_urb *)calloc(sizeof(usbio_urb), req.nourbs)) == NULL) {
+ in_usb_rw--;
+ a1loge(p->log, ICOM_SYS, "icoms_usb_transaction: control transfer too big! (%d)\n",length);
+ return ICOM_SYS;
+ }
+
+ bp = buffer;
+ remlen = length;
+ for (i = 0; i < req.nurbs; i++) {
+ req.urbs[i].req = &req;
+ req.urbs[i].urbno = i;
+ /* Setup Linux URB */
+ req.urbs[i].urb.usercontext = &req.urbs[i];
+ req.urbs[i].urb.type = type;
+ if (type != USBDEVFS_URB_TYPE_CONTROL)
+ req.urbs[i].urb.endpoint = endpoint;
+ if (remlen > 16384)
+ req.urbs[i].urb.buffer_length = 16384;
+ else
+ req.urbs[i].urb.buffer_length = remlen;
+ req.urbs[i].urb.buffer = (void *)bp;
+ remlen -= req.urbs[i].urb.buffer_length;
+ bp += req.urbs[i].urb.buffer_length;
+ req.urbs[i].urb.status = -EINPROGRESS;
+ }
+a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,req.nourbs);
+
+ /* Add our request to the req list so that it can be cancelled on reap failure */
+ pthread_mutex_lock(&p->usbd->lock);
+ req.next = p->usbd->reqs;
+ p->usbd->reqs = &req;
+ pthread_mutex_unlock(&p->usbd->lock);
+
+ /* submit the URBs */
+ for (i = 0; i < req.nurbs; i++) {
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_SUBMITURB, &req.urbs[i].urb)) < 0) {
+ a1logd(p->log, 1, "coms_usb_transaction: Submitting urb to fd %d failed with %d\n",p->usbd->fd, rv);
+ req.urbs[i].urb.status = ICOM_SYS; /* Mark it as failed to submit */
+ req.nourbs--;
+ }
+ }
+
+ if (cancelt != NULL) {
+ amutex_lock(cancelt->cmtx);
+ cancelt->hcancel = (void *)&req;
+ cancelt->state = 1;
+ amutex_unlock(cancelt->cond); /* Signal any thread waiting for IO start */
+ amutex_unlock(cancelt->cmtx);
+ }
+
+ /* Wait for the reaper to wake us, or for a timeout, */
+ /* or for the reaper to die. */
+ pthread_mutex_lock(&req.lock);
+ if (req.nourbs > 0) {
+ struct timeval tv;
+ struct timespec ts;
+
+ // this is unduly complicated...
+ gettimeofday(&tv, NULL);
+ ts.tv_sec = tv.tv_sec + timeout/1000;
+ ts.tv_nsec = (tv.tv_usec + (timeout % 1000) * 1000) * 1000L;
+ if (ts.tv_nsec > 1000000000L) {
+ ts.tv_nsec -= 1000000000L;
+ ts.tv_sec++;
+ }
+
+ for(;;) { /* Ignore spurious wakeups */
+ if ((rv = pthread_cond_timedwait(&req.cond, &req.lock, &ts)) != 0) {
+ if (rv != ETIMEDOUT) {
+ pthread_mutex_unlock(&req.lock);
+ a1logd(p->log, 1, "coms_usb_transaction: pthread_cond_timedwait failed with %d\n",rv);
+ rv = ICOM_SYS;
+ goto done;
+ }
+
+ /* Timed out - cancel the remaining URB's */
+ a1logd(p->log, 8, "coms_usb_transaction: time out - cancel remaining URB's\n");
+ reqrv = ICOM_TO;
+ if (!req.cancelled && (rv = cancel_req(p, &req, -1)) != ICOM_OK) {
+ pthread_mutex_unlock(&req.lock);
+ reqrv = ICOM_SYS;
+ /* Since cancelling failed, we can't wait for them to be reaped */
+ goto done;
+ }
+
+ /* Wait for the cancelled URB's to be reaped */
+ for (;req.nourbs > 0;) { /* Ignore spurious wakeups */
+ if ((rv = pthread_cond_wait(&req.cond, &req.lock)) != 0) {
+ pthread_mutex_unlock(&req.lock);
+ a1logd(p->log, 1, "coms_usb_transaction: pthread_cond_wait failed with %d\n",rv);
+ reqrv = ICOM_SYS;
+ /* Waiting for reap failed, so give up */
+ goto done;
+ }
+ }
+ } else {
+ a1logd(p->log, 8, "coms_usb_transaction: reap - %d left\n",req.nourbs);
+ }
+ if (req.nourbs <= 0)
+ break; /* All urbs's are done */
+ }
+ }
+ pthread_mutex_unlock(&req.lock);
+
+ /* Compute the overall result by going through the urbs. */
+ for (i = 0; i < req.nurbs; i++) {
+ int stat = req.urbs[i].urb.status;
+ xlength += req.urbs[i].urb.actual_length;
+
+ if (stat == ICOM_SYS) { /* Submit or cancel failed */
+ reqrv = ICOM_SYS;
+ } else if (reqrv == ICOM_OK && stat < 0 && stat != -ECONNRESET) { /* Error result */
+ if ((endpoint & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT)
+ reqrv = ICOM_USBW;
+ else
+ reqrv = ICOM_USBR;
+ } else if (reqrv == ICOM_OK && stat == -ECONNRESET) { /* Cancelled */
+ reqrv = ICOM_CANC;
+ } else if (reqrv == ICOM_OK
+ && req.urbs[i].urb.actual_length < req.urbs[i].urb.buffer_length) {
+ /* Disregard any following urb's status - they are probably cancelled */
+ break;
+ }
+ /* reqrv == ICOM_TO will ignore urb status */
+ }
+
+ if (ttype == icom_usb_trantype_command)
+ xlength += IUSB_REQ_HEADER_SIZE; /* Account for header - linux doesn't */
+
+ /* requested size wasn't transferred ? */
+ if (reqrv == ICOM_OK && xlength != length)
+ reqrv = ICOM_SHORT;
+
+ if (transferred != NULL)
+ *transferred = xlength;
+
+done:;
+ if (cancelt != NULL) {
+ amutex_lock(cancelt->cmtx);
+ cancelt->hcancel = (void *)NULL;
+ if (cancelt->state == 0)
+ amutex_unlock(cancelt->cond);
+ cancelt->state = 2;
+ amutex_unlock(cancelt->cmtx);
+ }
+
+ /* Remove our request from the list */
+ pthread_mutex_lock(&p->usbd->lock);
+ preq = &p->usbd->reqs;
+ while (*preq != &req && *preq != NULL) /* Find it */
+ preq = &((*preq)->next);
+ if (*preq != NULL)
+ *preq = (*preq)->next;
+ pthread_mutex_unlock(&p->usbd->lock);
+
+ if (req.urbs != NULL)
+ free(req.urbs);
+ pthread_cond_destroy(&req.cond);
+ pthread_mutex_destroy(&req.lock);
+
+ if (in_usb_rw < 0)
+ exit(0);
+
+ in_usb_rw--;
+
+ a1logd(p->log, 8, "coms_usb_transaction: returning err 0x%x and %d bytes\n",reqrv, xlength);
+#endif // ~~99
+
+ return reqrv;
+}
+
+
+/* Return error icom error code */
+static int icoms_usb_control_msg(
+icoms *p,
+int *transferred,
+int requesttype, int request,
+int value, int index, unsigned char *bytes, int size,
+int timeout) {
+ int reqrv = ICOM_OK;
+ int dirw = (requesttype & IUSB_REQ_DIR_MASK) == IUSB_REQ_HOST_TO_DEV ? 1 : 0;
+ unsigned char *buf;
+
+ a1logd(p->log, 8, "icoms_usb_control_msg: type 0x%x req 0x%x size %d\n",requesttype,request,size);
+
+#ifdef NEVER // ~~99
+ /* Allocate a buffer for the ctrl header + payload */
+ if ((buf = calloc(1, IUSB_REQ_HEADER_SIZE + size)) == NULL) {
+ a1loge(p->log, ICOM_SYS, "icoms_usb_control_msg: calloc failed\n");
+ return ICOM_SYS;
+ }
+
+ /* Setup the control header */
+ buf[0] = requesttype;
+ buf[1] = request;
+ short2buf(buf + 2, value);
+ short2buf(buf + 4, index);
+ short2buf(buf + 6, size);
+
+ /* If it's a write, copy the write data into the buffer */
+ if (dirw)
+ memcpy(buf + IUSB_REQ_HEADER_SIZE, bytes, size);
+
+ reqrv = icoms_usb_transaction(p, NULL, transferred, icom_usb_trantype_command,
+ dirw ? 0x80 : 0x00, buf, IUSB_REQ_HEADER_SIZE + size, timeout);
+
+ /* If read, copy the data back */
+ if (!dirw)
+ memcpy(bytes, buf + IUSB_REQ_HEADER_SIZE, size);
+
+ if (transferred != NULL) /* Adjust for header size requested */
+ *transferred -= IUSB_REQ_HEADER_SIZE;
+
+ free(buf);
+
+#endif // ~~99
+ a1logd(p->log, 8, "icoms_usb_control_msg: returning err 0x%x and %d bytes\n",reqrv, *transferred);
+ return reqrv;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Time out error return value */
+
+#define USBIO_ERROR_TIMEOUT -ETIMEDOUT
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* Cancel i/o in another thread */
+int icoms_usb_cancel_io(
+ icoms *p,
+ usb_cancelt *cancelt
+) {
+ int rv = ICOM_OK;
+#ifdef NEVER // ~~99
+ a1logd(p->log, 8, "icoms_usb_cancel_io called\n");
+ usb_lock_cancel(cancelt);
+ if (cancelt->hcancel != NULL)
+ rv = cancel_req(p, (usbio_req *)cancelt->hcancel, -1);
+ usb_unlock_cancel(cancelt);
+
+ if (rv != ICOM_OK) /* Assume this could be because of faulty device */
+ rv = ICOM_USBW;
+#endif // ~~99
+
+ return rv;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Reset and end point data toggle to 0 */
+int icoms_usb_resetep(
+ icoms *p,
+ int ep /* End point address */
+) {
+ int rv = ICOM_OK;
+
+#ifdef NEVER // ~~99
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_RESETEP, &ep)) != 0) {
+ a1logd(p->log, 1, "icoms_usb_resetep failed with %d\n",rv);
+ rv = ICOM_USBW;
+ }
+#endif // ~~99
+ return rv;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Clear a halt on an end point */
+int icoms_usb_clearhalt(
+ icoms *p,
+ int ep /* End point address */
+) {
+ int rv = ICOM_OK;
+
+#ifdef NEVER // ~~99
+ if ((rv = ioctl(p->usbd->fd, USBDEVFS_CLEAR_HALT, &ep)) != 0) {
+ a1logd(p->log, 1, "icoms_usb_clearhalt failed with %d\n",rv);
+ rv = ICOM_USBW;
+ }
+#endif // ~~99
+ return rv;
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - */
+
diff --git a/spectro/usbio_lusb.c b/spectro/usbio_lusb.c
deleted file mode 100644
index f78bcca..0000000
--- a/spectro/usbio_lusb.c
+++ /dev/null
@@ -1,897 +0,0 @@
-
-/* General USB I/O support, legacy Libusb 0.1/1.0 implementation, no longer */
-/* used by default, but can be configured in the Jamfile. */
-/* The corresponding libusb code is not distributed with the current source */
-/* though, and would have to be copied from ArgyllCMS V1.4.0 */
-
-/* This file is conditionaly #included into usbio.c */
-
-/*
- * Argyll Color Correction System
- *
- * Author: Graeme W. Gill
- * Date: 2006/22/4
- *
- * Copyright 2006 - 2013 Graeme W. Gill
- * All rights reserved.
- *
- * This material is licenced under the GNU GENERAL PUBLIC LICENSE Version 2 or later :-
- * see the License2.txt file for licencing details.
- */
-
-/* To simplify error messages: */
-#ifdef USE_LIBUSB1
-# define USB_STRERROR(RV) libusb_strerror(RV)
-#else
-# define USB_STRERROR(RV) usb_strerror()
-#endif
-
-#ifdef USE_LIBUSB1
-# define usb_device libusb_device
-# define usb_device_descriptor libusb_device_descriptor
-# define usb_dev_handle libusb_device_handle
-# define usb_config_descriptor libusb_config_descriptor
-# define usb_strerror libusb_strerror
-#endif
-
-#if defined(__FreeBSD__) /* Shut spurious warnings up */
-# define CASTFIX (intptr_t)
-#else
-# define CASTFIX
-#endif
-
-/* Check a USB Vendor and product ID, and add the device */
-/* to the icoms path if it is supported. */
-/* (this is used to help implement usb_get_paths) */
-/* return icom error */
-static int usb_check_and_add(
-icompaths *p,
-struct usb_device *usbd
-) {
- instType itype;
- int nep; /* Number of end points */
-
- struct usb_device_descriptor descriptor;
-
-#ifdef USE_LIBUSB1
- enum libusb_error rv;
-
- if ((rv = libusb_get_device_descriptor(usbd, &descriptor)) != LIBUSB_SUCCESS) {
- a1loge(p->log, ICOM_SYS, "usb_check_and_add: failed with %d (%s)\n",
- rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
-#else
- descriptor = usbd->descriptor; /* Copy */
-#endif
- a1logd(p->log, 6, "usb_check_and_add: called with VID 0x%x, PID 0x%x\n",descriptor.idVendor, descriptor.idProduct);
-
-#ifdef USE_LIBUSB1
-#if defined(NT) || defined(__APPLE__)
- /* Ignore libusb1 HID driver capability */
- {
- struct libusb_config_descriptor *confdesc = NULL;
-
- /* If not obviously HID, we need to fetch the config descriptor */
- if (descriptor.bDeviceClass != LIBUSB_CLASS_HID
- && (rv = libusb_get_config_descriptor(usbd, 0, &confdesc)) != LIBUSB_SUCCESS) {
- /* This seems to happen for hubs etc., so ignore it */
- a1logd(p->log, 6 , "usb_check_and_add: get conf desc. failed - device not reconized\n");
- return ICOM_OK;
- }
-
- if (descriptor.bDeviceClass == LIBUSB_CLASS_HID
- || (confdesc->bNumInterfaces > 0
- && confdesc->interface[0]. num_altsetting > 0
- && confdesc->interface[0].altsetting[0].bInterfaceClass == LIBUSB_CLASS_HID)) {
- int i;
- /* See if this devices is already in the list via the HID interface */
- /* (This may not be 100% correct in the face of multiple instances
- of the same device, if Windows allows different drivers for different
- instances of the same device type.) */
- for (i = 0; i < p->npaths; i++) {
- if (p->paths[i]->vid == descriptor.idVendor
- && p->paths[i]->pid == descriptor.idProduct)
- break; /* Yes */
- }
- if (i < p->npaths) {
- a1logd(p->log, 6, "Is an HID device and already added\n");
- if (confdesc != NULL)
- libusb_free_config_descriptor(confdesc);
- return ICOM_OK;
- }
- }
- if (confdesc != NULL)
- libusb_free_config_descriptor(confdesc);
- }
-#endif
-#endif
-
- /* The i1pro2 is detected by checking the number of end points, */
- /* so set this value in icom now by looking at the descriptor */
- {
-#ifdef USE_LIBUSB1
- struct libusb_config_descriptor *confdesc;
- const struct libusb_interface_descriptor *ifd;
-
- if (libusb_get_config_descriptor(usbd, 0, &confdesc) != LIBUSB_SUCCESS) {
- /* This seems to happen for hubs etc., so ignore it */
- a1logd(p->log, 6 , "usb_check_and_add: get conf desc. failed - device not reconized\n");
- return ICOM_OK;
- }
-
- ifd = &confdesc->interface[0].altsetting[0];
- nep = ifd->bNumEndpoints;
- if (confdesc != NULL)
- libusb_free_config_descriptor(confdesc);
-#else
- struct usb_interface_descriptor *ifd;
- ifd = &usbd->config[0].interface[0].altsetting[0];
- nep = ifd->bNumEndpoints;
-#endif
- }
-
- if ((itype = inst_usb_match((unsigned int)descriptor.idVendor,
- (unsigned int)descriptor.idProduct, nep)) != instUnknown) {
- char pname[400];
-
- a1logd(p->log, 2, "usb_check_and_add: found known instrument VID 0x%x, PID 0x%x\n",
- descriptor.idVendor, descriptor.idProduct);
-
- /* Create a path/identification */
- /* (devnum doesn't seem valid ?) */
-#ifdef USE_LIBUSB1
- libusb_ref_device(usbd); /* Keep it */
- sprintf(pname,"usb:/bus%d/dev%d/ (%s)",libusb_get_bus_number(usbd),libusb_get_device_address(usbd), inst_name(itype));
-#else
-# if defined(UNIX)
- sprintf(pname,"usb:/bus%d/dev%d (%s)",usbd->bus->location >> 24, usbd->devnum, inst_name(itype));
-# else
- sprintf(pname,"usb:/bus%lu/dev%d (%s)",usbd->bus->location, usbd->devnum, inst_name(itype));
-# endif
-#endif
-
- /* Add the path to the list */
- p->add_usb(p, pname, descriptor.idVendor, descriptor.idProduct, nep, usbd, itype);
- return ICOM_OK;
- }
- a1logd(p->log, 6 , "usb_check_and_add: device not reconized\n");
-
- return ICOM_OK;
-}
-
-#ifdef USE_LIBUSB1
-
-/* Add paths of USB connected instruments */
-/* return icom error */
-int usb_get_paths(
-icompaths *p
-) {
- ssize_t i, nlist;
- struct libusb_device **list;
-
- /* Scan the USB busses for instruments we recognise */
- /* We're not expecting any of our instruments to be an interface on a device. */
-
- /* Use the default context to avoid worying about versions */
- /* of libusb1 that don't reference count them. (ie. would need */
- /* copies in both icompaths and icoms) */
-
- libusb_init(NULL); /* Use default context */
-
- /* Enable lower level debugging of device finding */
- if (p->log->debug >= 8)
- libusb_set_debug(NULL, p->log->debug);
-
- if ((nlist = libusb_get_device_list(NULL, &list)) < 0) {
- a1loge(p->log, ICOM_SYS, "usb_get_paths: get_device_list failed with %d (%s)\n",
- nlist,USB_STRERROR(nlist));
- return ICOM_SYS;
- }
-
- a1logd(p->log, 6, "usb_get_paths: about to look through devices:\n");
-
- for (i = 0; i < nlist; i++) {
- usb_check_and_add(p, list[i]);
- }
-
- libusb_free_device_list(list, 1);
-
- a1logd(p->log, 8, "usb_get_paths: returning %d paths and ICOM_OK\n",p->npaths);
- return ICOM_OK;
-}
-
-#else /* !USE_LIBUSB1 */
-
-/* Add paths of USB connected instruments */
-/* return icom error */
-int usb_get_paths(
-icompaths *p
-) {
- struct usb_bus *bus;
- int rv;
-
- /* Enable lower level debugging of device finding */
- if (p->log->debug >= 8)
- usb_set_debug(p->log->debug);
-
- /* Scan the USB busses for instruments we recognise */
- /* We're not expecting any of our instruments to be an interface on a device. */
-
- usb_init();
- if ((rv = usb_find_busses()) < 0) {
- a1loge(p->log, ICOM_SYS, "usb_get_paths: find_busses failed with %d (%s)\n",
- rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- if ((rv = usb_find_devices()) < 0) {
- a1loge(p->log, ICOM_SYS, "usb_get_paths: usb_find_devices failed with %d (%s)\n",
- rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
-
- a1logd(p->log, 6, "usb_get_paths: about to look through busses:\n");
-
- for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
- struct usb_device *dev;
- a1logd(p->log, 6, "usb_get_paths: about to look through devices:\n");
- for (dev = bus->devices; dev != NULL; dev = dev->next) {
- if ((rv = usb_check_and_add(p, dev)) != ICOM_OK)
- return rv;
- }
- }
- a1logd(p->log, 8, "usb_get_paths: returning %d paths and ICOM_OK\n",p->npaths);
- return ICOM_OK;
-}
-#endif /* !USE_LIBUSB1 */
-
-/* Copy usb_idevice contents from icompaths to icom */
-/* return icom error */
-int usb_copy_usb_idevice(icoms *d, icompath *s) {
- if (s->usbd == NULL) {
- d->usbd = NULL;
- return ICOM_OK;
- }
-
- d->usbd = s->usbd; /* Copy pointer */
-#ifdef USE_LIBUSB1
- libusb_ref_device(d->usbd);
-#endif
- return ICOM_OK;
-}
-
-/* Cleanup and then free a usb dev entry */
-void usb_del_usb_idevice(struct usb_idevice *usbd) {
-
- if (usbd == NULL)
- return;
-
-#ifdef USE_LIBUSB1
- libusb_unref_device(usbd);
-#endif
-}
-
-/* Cleanup any USB specific icoms state */
-void usb_del_usb(icoms *p) {
-
-#ifdef USE_LIBUSB1
- usb_del_usb_idevice(p->usbd);
-#endif /* USE_LIBUSB1 */
-}
-
-/* Close an open USB port */
-/* If we don't do this, the port and/or the device may be left in an unusable state. */
-void usb_close_port(icoms *p) {
-
- a1logd(p->log, 8, "usb_close_port: called\n");
-
- if (p->is_open && p->usbh != NULL) {
- int iface;
-
- for (iface = 0; iface < p->nifce; iface++) {
-#ifdef USE_LIBUSB1
- libusb_release_interface(p->usbh, iface);
-#else
- usb_release_interface(p->usbh, iface);
-#endif
- }
-
- /* Workaround for some bugs */
- if (p->uflags & icomuf_reset_before_close) {
-#ifdef USE_LIBUSB1
- libusb_reset_device(p->usbh);
-#else
- usb_reset(p->usbh);
-#endif
- }
-
- /* Close as well, othewise we can't re-open */
- {
-#ifdef USE_LIBUSB1
- libusb_close(p->usbh);
-#else
- usb_close(p->usbh);
-#endif
- }
- p->usbh = NULL;
-
- a1logd(p->log, 8, "usb_close_port: port has been released and closed\n");
- }
- p->is_open = 0;
-
- /* Find it and delete it from our static cleanup list */
- usb_delete_from_cleanup_list(p);
-
-}
-
-/* Open a USB port for all our uses. */
-/* This always re-opens the port */
-/* return icom error */
-static int usb_open_port(
-icoms *p,
-int config, /* Configuration number */
-int wr_ep, /* Write end point */
-int rd_ep, /* Read end point */
-icomuflags usbflags,/* Any special handling flags */
-int retries, /* > 0 if we should retry set_configuration (100msec) */
-char **pnames /* List of process names to try and kill before opening */
-) {
- int tries = 0;
- a1logd(p->log, 8, "usb_open_port: Make sure USB port is open, tries %d\n",retries);
-
- if (p->is_open)
- p->close_port(p);
-
- /* Make sure the port is open */
- if (!p->is_open) {
- struct usb_device_descriptor descriptor;
-#ifdef USE_LIBUSB1
- const struct libusb_interface_descriptor *ifd;
- struct libusb_config_descriptor *confdesc;
-#else
- struct usb_interface_descriptor *ifd;
-#endif
- int rv, i, iface;
- kkill_nproc_ctx *kpc = NULL;
-
- /* Do open retries */
- for (tries = 0; retries >= 0; retries--, tries++) {
-
- a1logd(p->log, 8, "usb_open_port: About to open USB port '%s'\n",p->name);
-
- if (tries > 0) {
- //msec_sleep(i_rand(50,100));
- msec_sleep(77);
- }
- if (tries > 0 && pnames != NULL && kpc == NULL) {
-#if defined(__APPLE__) || defined(NT)
- if ((kpc = kkill_nprocess(pnames, p->log)) == NULL)
- a1logd(p->log, 1, "usb_open_port: kkill_nprocess returned error!\n");
-#endif /* __APPLE__ */
- }
-
-#ifdef USE_LIBUSB1
- if ((rv = libusb_open(p->usbd, &p->usbh)) != LIBUSB_SUCCESS)
-#else
- if ((p->usbh = usb_open(p->usbd)) == NULL)
-#endif
- {
- a1logd(p->log, 8, "usb_open_port: open '%s' config %d failed (%s) (Permissions ?)\n",p->name,config,USB_STRERROR(rv));
- if (retries <= 0) {
- if (kpc != NULL)
- kpc->del(kpc);
- a1loge(p->log, ICOM_SYS, "usb_open_port: open '%s' config %d failed (%s) (Permissions ?)\n",p->name,config,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- continue;
- } else if (p->debug)
- a1logd(p->log, 2, "usb_open_port: open port '%s' succeeded\n",p->name);
-
- /* Get a copy of the device descriptor so we can see device params */
-#ifdef USE_LIBUSB1
- if (libusb_get_device_descriptor(p->usbd, &descriptor) != LIBUSB_SUCCESS) {
- a1loge(p->log, ICOM_SYS, "usb_open_port: get device descriptor on '%s' failed with %d (%s)\n",p->name,rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
-#else
- descriptor = p->usbd->descriptor; /* Copy */
-#endif
-
- p->uflags = usbflags;
-
- a1logd(p->log, 8, "usb_open_port: Number of configurations = %d\n",
- descriptor.bNumConfigurations);
- p->nconfig = descriptor.bNumConfigurations;
- p->config = config;
-
-#if defined(UNIX_X11)
- /* only call set_configuration on Linux if the device has more than one */
- /* possible configuration, because Linux does a set_configuration by default, */
- /* and two of them mess up instruments like the Spyder2 */
-
- if (descriptor.bNumConfigurations > 1) {
-#endif
-
- /* Can't skip this, as it is needed to setup the interface and end points on OS X */
-#ifdef USE_LIBUSB1
- if ((rv = libusb_set_configuration(p->usbh, config)) < 0)
-#else
- if ((rv = usb_set_configuration(p->usbh, config)) < 0)
-#endif
- {
- a1logd(p->log, 8, "usb_open_port: configuring '%s' to %d failed with %d (%s)\n",p->name,config,rv,USB_STRERROR(rv));
- if (retries <= 0) {
- if (kpc != NULL)
- kpc->del(kpc);
- a1loge(p->log, ICOM_SYS, "usb_open_port: configuring '%s' to %d failed with %d (%s)\n",p->name,config,rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- /* reset the port and retry */
-#ifdef USE_LIBUSB1
- libusb_reset_device(p->usbh); // ~~999 ?????
- libusb_close(p->usbh);
-#else
- usb_reset(p->usbh);
- usb_close(p->usbh);
-#endif
- continue;
- }
-#if defined(UNIX_X11)
- } /* End of if bNumConfigurations > 1 */
-#endif
-
- /* We're done */
- break;
- }
-
- if (kpc != NULL)
- kpc->del(kpc);
-
- /* Claim all interfaces of this configuration */
-#ifdef USE_LIBUSB1
- if ((rv = libusb_get_active_config_descriptor(p->usbd, &confdesc)) != LIBUSB_SUCCESS) {
- a1loge(p->log, ICOM_SYS, "usb_open_port: get config desc. for '%s' failed with %d (%s)\n",p->name,rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- p->nifce = confdesc->bNumInterfaces;
-#else
- p->nifce = p->usbd->config->bNumInterfaces;
-#endif
-
-// a1logv(p->log, 8, "usb_open_port: Number of interfaces = %d\n",p->nifce);
-
- /* Claim all the interfaces */
- for (iface = 0; iface < p->nifce; iface++) {
- /* (Second parameter is bInterfaceNumber) */
-
-#ifdef USE_LIBUSB1
- if ((rv = libusb_claim_interface(p->usbh, iface)) < 0) {
- /* Detatch the existing interface if kernel driver is active. */
- if (p->uflags & icomuf_detach
- && libusb_kernel_driver_active(p->usbh, iface) == 1) {
- libusb_detach_kernel_driver (p->usbh, iface);
- if ((rv = libusb_claim_interface(p->usbh, iface)) < 0) {
- a1loge(p->log, ICOM_SYS, "usb_open_port: Claiming USB port '%s' interface %d failed after detach with %d (%s)\n",p->name,iface,rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- } else {
- a1loge(p->log, ICOM_SYS, "usb_open_port: Claiming USB port '%s' interface %d failed with %d (%s)\n",p->name,iface,rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- }
-#else
- if ((rv = usb_claim_interface(p->usbh, iface)) < 0) {
-# if LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP == 1
- /* Detatch the existing interface. */
- if (p->uflags & icomuf_detach) {
- usb_detach_kernel_driver_np(p->usbh, iface);
- if ((rv = usb_claim_interface(p->usbh, iface)) < 0) {
- a1loge(p->log, ICOM_SYS, "usb_open_port: Claiming USB port '%s' interface %d failed after detach with %d (%s)\n",p->name,iface,rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- }
-# else
- a1loge(p->log, ICOM_SYS, "usb_open_port: Claiming USB port '%s' interface %d failed with %d (%s)\n",p->name,iface,rv,USB_STRERROR(rv));
- return ICOM_SYS;
-# endif
- }
-#endif
-
- /* Fill in the end point details */
-#ifdef USE_LIBUSB1
- ifd = &confdesc->interface[iface].altsetting[0];
-#else
- ifd = &p->usbd->config[p->config-1].interface[iface].altsetting[0];
-#endif
-// a1logv(p->log, 8, "usb_open_port: Number of endpoints on iface %d = %d\n",iface, ifd->bNumEndpoints);
- p->nep = ifd->bNumEndpoints;
- for (i = 0; i < ifd->bNumEndpoints; i++) {
- int ad = ifd->endpoint[i].bEndpointAddress;
- p->EPINFO(ad).valid = 1;
- p->EPINFO(ad).addr = ad;
- p->EPINFO(ad).packetsize = ifd->endpoint[i].wMaxPacketSize;
- p->EPINFO(ad).type = ifd->endpoint[i].bmAttributes & IUSB_ENDPOINT_TYPE_MASK;
- /* Some I/F seem to hang if we do this, some seem to hang if we don't ! */
- if (!(p->uflags & icomuf_no_open_clear))
-#ifdef USE_LIBUSB1
- libusb_clear_halt(p->usbh, (unsigned char)ad);
-#else
- usb_clear_halt(p->usbh, ad);
-#endif
-// a1logv(p->log, 8, "usb_open_port: ep %d: endpoint addr %02x pktsze %d, type %d\n",i,ad,ifd->endpoint[i].wMaxPacketSize,p->EPINFO(ad).type);
- }
-
-#ifdef NEVER
- /* Get the serial number */
- {
- int rv;
- struct usb_device_descriptor descriptor;
-
- a1logd(p->log, 8, "usb_open_port: About to get device serial number\n");
-# ifdef USE_LIBUSB1
- if ((rv = libusb_get_device_descriptor(p->usbd, &descriptor)) != LIBUSB_SUCCESS) {
- a1loge(p->log, ICOM_SYS, "usb_open_port: get_device_descriptor failed with %d USB port '%s'\n",rv,p->name);
- return ICOM_SYS;
- }
-# else
- descriptor = dev->descriptor; /* Copy */
-# endif
- if ((rv = libusb_get_string_descriptor_ascii(p->usbh, descriptor.iSerialNumber, p->serialno, 32)) <= 0) {
- a1logd(p->log, 1, "usb_open_port: Failed to get device serial number %d (%s)\n",rv,USB_STRERROR(rv));
- p->serialno[0] = '\000';
- } else {
- a1logd(p->log, 1, "usb_open_port: Device serial number = '%s'\n",p->serialno);
- }
- }
-#endif /* NEVER */
- }
-
- /* Set "serial" coms values */
- p->wr_ep = wr_ep;
- p->rd_ep = rd_ep;
- p->rd_qa = p->EPINFO(rd_ep).packetsize;
- if (p->rd_qa == 0)
- p->rd_qa = 8;
- a1logd(p->log, 8, "usb_open_port: 'serial' read quanta = packet size = %d\n",p->rd_qa);
-
-#ifdef USE_LIBUSB1
- if (confdesc != NULL)
- libusb_free_config_descriptor(confdesc);
-#endif
-
- p->is_open = 1;
- a1logd(p->log, 8, "usb_open_port: USB port is now open\n");
- }
-
- /* Install the cleanup signal handlers, and add to our cleanup list */
- usb_install_signal_handlers(p);
-
- return ICOM_OK;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-/* Time out error return value */
-
-#ifdef USE_LIBUSB1
-#define USBIO_ERROR_TIMEOUT LIBUSB_ERROR_TIMEOUT
-#else
-# if defined(UNIX)
-#define USBIO_ERROR_TIMEOUT -ETIMEDOUT
-# else
-#define USBIO_ERROR_TIMEOUT -116 /* libusb-win32 code */
-# endif /* UNIX */
-#endif
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-#ifdef USE_LIBUSB1
-
-/* Callback functions */
-static void bulk_transfer_cb(struct libusb_transfer *transfer)
-{
- int *completed = transfer->user_data;
- *completed = 1;
- /* caller interprets results and frees transfer */
-}
-
-/* Version of libusb1 sync to async code that returns the pointer */
-/* to the transfer structure so that the transfer can be cancelled */
-/* by another thread. */
-/* Return an icoms error code */
-static int do_sync_usb_transfer(
- icoms *p,
- struct libusb_device_handle *dev_handle,
- usb_cancelt *cancelt,
- int *transferred,
- icom_usb_trantype ttype,
- unsigned char endpoint,
- unsigned char *buffer,
- int length,
- unsigned int timeout
-) {
- enum libusb_transfer_type type;
- struct libusb_transfer *transfer = libusb_alloc_transfer(0);
- int completed = 0;
- int rv;
-
- if (!transfer) {
- a1logd(p->log, 1, "do_sync_usb_transfer: transfer is NULL!\n");
- return ICOM_SYS;
- }
-
- /* Translate icoms transfer type of libusb1 */
- switch (ttype) {
- case icom_usb_trantype_command:
- type = LIBUSB_TRANSFER_TYPE_CONTROL;
- break;
- case icom_usb_trantype_interrutpt:
- type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
- break;
- case icom_usb_trantype_bulk:
- type = LIBUSB_TRANSFER_TYPE_BULK;
- break;
- }
-
- libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, length,
- bulk_transfer_cb, &completed, timeout);
- transfer->type = type;
-
- if ((rv = libusb_submit_transfer(transfer)) < 0) {
- libusb_free_transfer(transfer);
- a1logd(p->log, 1, "do_sync_usb_transfer: Submitting transfer failed with %d (%s)\n",rv,USB_STRERROR(rv));
- if ((endpoint & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT)
- return ICOM_USBW;
- else
- return ICOM_USBR;
- }
-
- if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
- cancelt->hcancel = (void *)transfer;
- usb_unlock_cancel(cancelt);
- }
-
- while (!completed) {
- if ((rv = libusb_handle_events_check(NULL, &completed)) < 0) {
- if (rv == LIBUSB_ERROR_INTERRUPTED)
- continue; /* Retry */
- /* Give up - cancel transfer and wait until complete */
- libusb_cancel_transfer(transfer);
- while (!completed) {
- if (libusb_handle_events_check(NULL, &completed) < 0)
- break;
- }
- if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
- cancelt->hcancel = NULL;
- usb_unlock_cancel(cancelt);
- }
- libusb_free_transfer(transfer);
- a1loge(p->log, ICOM_SYS, "do_sync_usb_transfer: handle_events failed with %d (%s)\n",rv,USB_STRERROR(rv));
- return ICOM_SYS;
- }
- }
-
- *transferred = transfer->actual_length;
- switch (transfer->status) {
- case LIBUSB_TRANSFER_COMPLETED:
- rv = ICOM_OK;
- break;
- case LIBUSB_TRANSFER_TIMED_OUT:
- rv = ICOM_TO;
- break;
- case LIBUSB_TRANSFER_STALL:
- case LIBUSB_TRANSFER_OVERFLOW:
- case LIBUSB_TRANSFER_NO_DEVICE:
- if ((endpoint & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT)
- rv = ICOM_USBW;
- else
- rv = ICOM_USBR;
- break;
- case LIBUSB_TRANSFER_CANCELLED:
- rv = ICOM_CANC;
- break;
- default:
- a1loge(p->log, ICOM_SYS, "do_sync_usb_transfer: transfer faile with %d (%s)\n",rv,USB_STRERROR(rv));
- rv = ICOM_SYS;
- }
-
- if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
- cancelt->hcancel = NULL;
- usb_unlock_cancel(cancelt);
- }
- libusb_free_transfer(transfer);
-
- /* requested size wasn't transferred */
- if (rv == ICOM_OK && *transferred != length)
- rv = ICOM_SHORT;
-
- return rv;
-}
-#endif /* USE_LIBUSB1 */
-
-/* Return icom error code */
-static int icoms_usb_control_msg(
-icoms *p,
-int *transferred,
-int requesttype, int request,
-int value, int index, unsigned char *bytes, int size,
-int timeout) {
- int rv;
-
- in_usb_rw++;
- a1logd(p->log, 8, "icoms_usb_control_msg: type 0x%x, req 0x%x, size %d\n",requesttype,request,size);
-
- if (transferred != NULL)
- *transferred = 0;
-#ifdef USE_LIBUSB1
- rv = libusb_control_transfer(p->usbh, (uint8_t)requesttype, (uint8_t)request,
- (uint16_t)value, (uint16_t)index, bytes, (uint16_t)size, timeout);
-#else
- rv = usb_control_msg(p->usbh, requesttype, request, value, index, (char *)bytes, size, timeout);
-#endif
- if (in_usb_rw < 0) /* interrupt recurssion */
- exit(0);
-
- in_usb_rw--;
-
- if (rv < 0) {
- if (rv == USBIO_ERROR_TIMEOUT) { /* Not a timeout */
- rv = ICOM_TO;
- } else {
- if (requesttype & IUSB_ENDPOINT_IN) /* Device to host */
- rv = ICOM_USBR; /* Read error */
- else
- rv = ICOM_USBW; /* Write error */
- }
- } else {
- if (transferred != NULL)
- *transferred = rv;
- if (rv != size) {
- rv = ICOM_SHORT;
- } else
- rv = ICOM_OK;
- }
- a1logd(p->log, 8, "icoms_usb_control_msg: returning err 0x%x and %d bytes\n",rv, *transferred);
- return rv;
-}
-
-/* Our versions of usblib read/write, that exit if a signal was caught */
-/* This is so that MSWindows works properly */
-/* return an icom error */
-static int icoms_usb_transaction(icoms *p, usb_cancelt *cancelt, int *xbytes,
- icom_usb_trantype type, int ep, unsigned char *bytes, int size, int timeout) {
- int rv;
-
- in_usb_rw++;
-
- a1logd(p->log, 8, "coms_usb_transaction: req type 0x%x ep 0x%x size %d\n",type,ep,size);
-#ifdef USE_LIBUSB1
- rv = do_sync_usb_transfer(p, p->usbh, cancelt, xbytes, type,
- (unsigned char)ep, bytes, size, timeout);
-#else
- if (xbytes != NULL)
- *xbytes = 0;
- if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
- cancelt->hcancel = (void *) CASTFIX ep;
- usb_lock_cancel(cancelt);
- }
- if (type == icom_usb_trantype_interrutpt) {
- if ((ep & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT)
- rv = usb_interrupt_write(p->usbh, ep, (char *)bytes, size, timeout);
- else
- rv = usb_interrupt_read(p->usbh, ep, (char *)bytes, size, timeout);
- } else { /* bulk */
- if ((ep & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT)
- rv = usb_bulk_write(p->usbh, ep, (char *)bytes, size, timeout);
- else
- rv = usb_bulk_read(p->usbh, ep, (char *)bytes, size, timeout);
- }
- if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
- cancelt->hcancel = (void *)-1;
- usb_lock_cancel(cancelt);
- }
- if (rv < 0) {
- if (rv == USBIO_ERROR_TIMEOUT)
- rv = ICOM_TO;
- else {
- if ((ep & IUSB_ENDPOINT_DIR_MASK) == IUSB_ENDPOINT_OUT)
- rv = ICOM_USBW;
- else
- rv = ICOM_USBR;
- }
- } else {
- if (xbytes != NULL)
- *xbytes = rv;
- if (rv != *xbytes)
- rv = ICOM_SHORT;
- else
- rv = ICOM_OK;
- }
-#endif
- if (in_usb_rw < 0) /* Signal handler recursion error */
- exit(0);
-
- in_usb_rw--;
-
- a1logd(p->log, 8, "coms_usb_transaction: returning err 0x%x and %d bytes\n",rv, *xbytes);
-
- return rv;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Cancel i/o in another thread */
-int icoms_usb_cancel_io(
- icoms *p,
- usb_cancelt *cancelt
-) {
- int rv = 0;
- usb_lock_cancel(cancelt);
-#ifdef USE_LIBUSB1
- if (cancelt->hcancel != NULL) {
- rv = libusb_cancel_transfer((struct libusb_transfer *)cancelt->hcancel);
- if (rv == LIBUSB_ERROR_NOT_FOUND)
- rv = 0;
- }
-#else
- if ((int) CASTFIX cancelt->hcancel >= 0) {
-// msec_sleep(1); /* Let device recover ? */
- rv = usb_resetep(p->usbh, (int) CASTFIX cancelt->hcancel); /* Not reliable ? */
-// msec_sleep(1); /* Let device recover ? */
- }
-#endif
- usb_unlock_cancel(cancelt);
-
- if (rv == 0)
- return ICOM_OK;
-
- a1logd(p->log, 1, "icoms_usb_cancel_io: failed with %d (%s)\n", rv,USB_STRERROR(rv));
- return ICOM_SYS;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Reset and end point data toggle to 0 */
-int icoms_usb_resetep(
- icoms *p,
- int ep /* End point address */
-) {
- int rv;
-#ifdef USE_LIBUSB1
- rv = libusb_resetep(p->usbh, (unsigned char)ep); /* Is this the same though ? */
-#else
- rv = usb_resetep(p->usbh, ep); /* Not reliable ? */
-#endif
-
- if (rv == 0)
- return ICOM_OK;
-
- a1logd(p->log, 1, "icoms_usb_resetep: failed with %d (%s)\n", rv,USB_STRERROR(rv));
- return ICOM_USBW;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - */
-/* Clear a halt on an end point */
-int icoms_usb_clearhalt(
- icoms *p,
- int ep /* End point address */
-) {
- int rv;
-#ifdef USE_LIBUSB1
- rv = libusb_clear_halt(p->usbh, (unsigned char)ep);
-#else
- rv = usb_clear_halt(p->usbh, ep);
-#endif
-
- if (rv == 0)
- return ICOM_OK;
-
- a1logd(p->log, 1, "icoms_usb_clearhalt: failed with %d (%s)\n", rv,USB_STRERROR(rv));
- return ICOM_USBW;
-}
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - */
-
diff --git a/spectro/usbio_lx.c b/spectro/usbio_lx.c
index 359f483..44307fd 100644
--- a/spectro/usbio_lx.c
+++ b/spectro/usbio_lx.c
@@ -71,12 +71,11 @@ static void short2buf(unsigned char *buf, int inv) {
/* Check a USB Vendor and product ID by reading the device descriptors, */
/* and add the device to the icoms path if it is supported. */
/* Return icom nz error code on fatal error */
-int usb_check_and_add_fd(
+static
+int usb_check_and_add(
a1log *log,
-icompaths *pp, /* icompaths to add to, or if NULL */
-icompath *p, /* icompath to set. */
-char *dpath, /* path to device - may be NULL */
-int fd /* device file descriptor */
+icompaths *pp, /* icompaths to add to */
+char *dpath /* path to device */
) {
int rv;
unsigned char buf[IUSB_DESC_TYPE_DEVICE_SIZE];
@@ -84,8 +83,15 @@ int fd /* device file descriptor */
unsigned int configix, nconfig, totlen;
instType itype;
struct usb_idevice *usbd = NULL;
+ int fd; /* device file descriptor */
- a1logd(log, 6, "usb_check_and_add_fd: with fd %d\n",fd);
+ a1logd(log, 6, "usb_check_and_add: givem '%s'\n",dpath);
+
+ /* Open the device so that we can read it */
+ if ((fd = open(dpath, O_RDONLY)) < 0) {
+ a1logd(log, 1, "usb_check_and_add: failed to open '%s'\n",dpath);
+ return ICOM_OK;
+ }
/* Read the device descriptor */
if ((rv = read(fd, buf, IUSB_DESC_TYPE_DEVICE_SIZE)) < 0
@@ -93,6 +99,7 @@ int fd /* device file descriptor */
|| buf[0] != IUSB_DESC_TYPE_DEVICE_SIZE
|| buf[1] != IUSB_DESC_TYPE_DEVICE) {
a1logd(log, 1, "usb_check_and_add: failed to read device descriptor\n");
+ close(fd);
return ICOM_OK;
}
@@ -106,12 +113,14 @@ int fd /* device file descriptor */
/* Do a preliminary match */
if ((itype = inst_usb_match(vid, pid, 0)) == instUnknown) {
a1logd(log, 6 , "usb_check_and_add: instrument not reconized\n");
+ close(fd);
return ICOM_OK;
}
/* Allocate an idevice so that we can fill in the end point information */
if ((usbd = (struct usb_idevice *) calloc(sizeof(struct usb_idevice), 1)) == NULL) {
a1loge(log, ICOM_SYS, "icoms: calloc failed!\n");
+ close(fd);
return ICOM_SYS;
}
@@ -130,16 +139,19 @@ int fd /* device file descriptor */
|| buf[1] != IUSB_DESC_TYPE_CONFIG) {
a1logd(log, 1, "usb_check_and_add: failed to read device config\n");
free(usbd);
+ close(fd);
return ICOM_OK;
}
if ((totlen = buf2ushort(buf + 2)) < 6) {
a1logd(log, 1, "usb_check_and_add: config desc size strange\n");
free(usbd);
+ close(fd);
return ICOM_OK;;
}
if ((buf2 = calloc(1, totlen)) == NULL) {
a1loge(log, ICOM_SYS, "usb_check_and_add: calloc of descriptor failed!\n");
+ close(fd);
return ICOM_SYS;
}
@@ -149,6 +161,7 @@ int fd /* device file descriptor */
a1logd(log, 1, "usb_check_and_add: failed to read device config details\n");
free(buf2);
free(usbd);
+ close(fd);
return ICOM_SYS;
}
@@ -194,6 +207,7 @@ int fd /* device file descriptor */
if (nep10 == 0xffff) { /* Hmm. Failed to find number of end points */
a1logd(log, 1, "usb_check_and_add: failed to find number of end points\n");
free(usbd);
+ close(fd);
return ICOM_SYS;
}
@@ -207,57 +221,28 @@ int fd /* device file descriptor */
/* Create a path/identification */
/* (devnum doesn't seem valid ?) */
- if (dpath == NULL) {
- sprintf(pname,"%s", inst_name(itype));
- if ((usbd->dpath = strdup("no_path")) == NULL) {
- a1loge(log, ICOM_SYS, "usb_check_and_add: strdup path failed!\n");
- free(usbd);
- return ICOM_SYS;
- }
- } else {
- sprintf(pname,"%s (%s)", dpath, inst_name(itype));
- if ((usbd->dpath = strdup(dpath)) == NULL) {
- a1loge(log, ICOM_SYS, "usb_check_and_add: strdup path failed!\n");
- free(usbd);
- return ICOM_SYS;
- }
+ sprintf(pname,"%s (%s)", dpath, inst_name(itype));
+ if ((usbd->dpath = strdup(dpath)) == NULL) {
+ a1loge(log, ICOM_SYS, "usb_check_and_add: strdup path failed!\n");
+ free(usbd);
+ close(fd);
+ return ICOM_SYS;
}
/* Add the path and ep info to the list */
- if (pp != NULL) {
- if ((rv = pp->add_usb(pp, pname, vid, pid, nep10, usbd, itype)) != ICOM_OK)
- return rv;
- } else {
- usbd->fd = fd;
- if ((rv = icompath_set_usb(log, p, pname, vid, pid, nep10, usbd, itype)) != ICOM_OK)
- return rv;
+ if ((rv = pp->add_usb(pp, pname, vid, pid, nep10, usbd, itype)) != ICOM_OK) {
+ close(fd);
+ return rv;
}
- } else {
- free(usbd);
- }
- return ICOM_OK;
-}
-/* Same as above, starting with the path */
-static int usb_check_and_add(
-icompaths *p,
-char *dpath
-) {
- int fd;
- int rv;
- a1logd(p->log, 6, "usb_check_and_add: givem '%s'\n",dpath);
- /* Open the device so that we can read it */
- if ((fd = open(dpath, O_RDONLY)) < 0) {
- a1logd(p->log, 1, "usb_check_and_add: failed to open '%s'\n",dpath);
- return ICOM_OK;
+ } else {
+ free(usbd);
}
- rv = usb_check_and_add_fd(p->log, p, NULL, dpath, fd);
-
close(fd);
- return rv;
+ return ICOM_OK;
}
/* Add paths to USB connected instruments */
@@ -268,7 +253,6 @@ icompaths *p
int vid, pid;
a1logd(p->log, 6, "usb_get_paths: about to look through buses:\n");
-
{
int j;
char *paths[3] = { "/dev/bus/usb", /* current, from udev */
@@ -307,7 +291,7 @@ icompaths *p
a1logd(p->log, 8, "usb_get_paths: about to stat %s\n",path2);
if (stat(path2, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
found = 1;
- if ((rv = usb_check_and_add(p, path2)) != ICOM_OK) {
+ if ((rv = usb_check_and_add(p->log, p, path2)) != ICOM_OK) {
closedir(d1);
return rv;
}
@@ -325,7 +309,7 @@ icompaths *p
a1logd(p->log, 8, "usb_get_paths: about to stat %s\n",path2);
if (stat(path2, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)) {
found = 1;
- if ((rv = usb_check_and_add(p, path2)) != ICOM_OK) {
+ if ((rv = usb_check_and_add(p->log, p, path2)) != ICOM_OK) {
closedir(d1);
return rv;
}
@@ -342,7 +326,6 @@ icompaths *p
return ICOM_OK;
}
-
/* Copy usb_idevice contents from icompaths to icom */
/* return icom error */
int usb_copy_usb_idevice(icoms *d, icompath *s) {
@@ -424,9 +407,6 @@ void usb_close_port(icoms *p) {
pthread_mutex_destroy(&p->usbd->lock);
close(p->usbd->sd_pipe[0]);
close(p->usbd->sd_pipe[1]);
- free(p->usbd->dpath);
- free(p->usbd);
- p->usbd = NULL;
a1logd(p->log, 6, "usb_close_port: usb port has been released and closed\n");
}
@@ -690,7 +670,7 @@ static void *urb_reaper(void *context) {
iurb = (usbio_urb *)out->usercontext;
req = iurb->req;
- a1logd(p->log, 8, "urb_reaper: urb reap URB %d with status %d bytes %d, usrbs left %d\n",iurb->urbno, out->status, out->actual_length, req->nourbs-1);
+ a1logd(p->log, 8, "urb_reaper: urb reap URB %d with status %d bytes %d, urbs left %d\n",iurb->urbno, out->status, out->actual_length, req->nourbs-1);
pthread_mutex_lock(&req->lock); /* Stop requester from missing reap */
req->nourbs--; /* We're reaped one */
@@ -841,9 +821,11 @@ a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,re
}
if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
cancelt->hcancel = (void *)&req;
- usb_unlock_cancel(cancelt);
+ cancelt->state = 1;
+ amutex_unlock(cancelt->cond); /* Signal any thread waiting for IO start */
+ amutex_unlock(cancelt->cmtx);
}
/* Wait for the reaper to wake us, or for a timeout, */
@@ -934,9 +916,12 @@ a1logd(p->log, 8, "icoms_usb_transaction: reset req 0x%p nourbs to %d\n",&req,re
done:;
if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
cancelt->hcancel = (void *)NULL;
- usb_unlock_cancel(cancelt);
+ if (cancelt->state == 0)
+ amutex_unlock(cancelt->cond);
+ cancelt->state = 2;
+ amutex_unlock(cancelt->cmtx);
}
/* Remove our request from the list */
@@ -1024,10 +1009,10 @@ int icoms_usb_cancel_io(
) {
int rv = ICOM_OK;
a1logd(p->log, 8, "icoms_usb_cancel_io called\n");
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
if (cancelt->hcancel != NULL)
rv = cancel_req(p, (usbio_req *)cancelt->hcancel, -1);
- usb_unlock_cancel(cancelt);
+ amutex_unlock(cancelt->cmtx);
if (rv != ICOM_OK) /* Assume this could be because of faulty device */
rv = ICOM_USBW;
diff --git a/spectro/usbio_nt.c b/spectro/usbio_nt.c
index 1711f0d..de9b265 100644
--- a/spectro/usbio_nt.c
+++ b/spectro/usbio_nt.c
@@ -25,7 +25,7 @@
#include <setupapi.h>
#include <driver_api.h>
-#define DEBUG /* Turn on debug messages */
+#undef DEBUG /* Turn on debug messages */
#define LIBUSBW1_MAX_DEVICES 255
#define LIBUSBW1_PATH_MAX 512
@@ -117,7 +117,8 @@ icompaths *p
unsigned char buf[IUSB_DESC_TYPE_DEVICE_SIZE];
_snprintf(dpath, LIBUSBW1_PATH_MAX - 1,"\\\\.\\libusb0-%04d", i+1);
- a1logd(p->log, 6, "usb_get_paths opening device '%s'\n",dpath);
+ if (i < 16) /* Suppress messages on unlikely ports */
+ a1logd(p->log, 6, "usb_get_paths opening device '%s'\n",dpath);
if ((handle = CreateFile(dpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,
NULL)) == INVALID_HANDLE_VALUE) {
@@ -323,6 +324,8 @@ icompaths *p
/* Add the path and ep info to the list */
if ((rv = p->add_usb(p, pname, vid, pid, nep10, usbd, itype)) != ICOM_OK)
return rv;
+
+
} else {
free(usbd);
}
@@ -409,10 +412,6 @@ void usb_close_port(icoms *p) {
}
CloseHandle(p->usbd->handle);
- free(p->usbd->dpath);
- free(p->usbd);
- p->usbd = NULL;
-
a1logd(p->log, 6, "usb_close_port: usb port has been released and closed\n");
}
p->is_open = 0;
@@ -565,6 +564,7 @@ char **pnames /* List of process names to try and kill before opening */
/* -------------------------------------------------------------- */
/* Our universal USB transfer function */
+/* It appears that we may return a timeout with valid characters. */
static int icoms_usb_transaction(
icoms *p,
usb_cancelt *cancelt,
@@ -596,12 +596,6 @@ static int icoms_usb_transaction(
if ((olaps.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
return ICOM_SYS;
- if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
- cancelt->hcancel = (void *)&endpoint;
- usb_unlock_cancel(cancelt);
- }
-
memset(&req, 0, sizeof(libusb_request));
req.endpoint.endpoint = endpoint;
@@ -616,9 +610,17 @@ static int icoms_usb_transaction(
goto done;
}
+ if (cancelt != NULL) {
+ amutex_lock(cancelt->cmtx);
+ cancelt->hcancel = (void *)&endpoint;
+ cancelt->state = 1;
+ amutex_unlock(cancelt->cond); /* Signal any thread waiting for IO start */
+ amutex_unlock(cancelt->cmtx);
+ }
+
if (WaitForSingleObject(olaps.hEvent, timeout) == WAIT_TIMEOUT) {
- /* Cancel the operation */
+ /* Cancel the operation, because it timed out */
memset(&req, 0, sizeof(libusb_request));
req.endpoint.endpoint = endpoint;
req.timeout = LIBUSBW1_DEFAULT_TIMEOUT;
@@ -638,9 +640,12 @@ static int icoms_usb_transaction(
}
done:;
if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
cancelt->hcancel = (void *)NULL;
- usb_unlock_cancel(cancelt);
+ if (cancelt->state == 0)
+ amutex_unlock(cancelt->cond); /* Make sure this gets unlocked */
+ cancelt->state = 2;
+ amutex_unlock(cancelt->cmtx);
}
CloseHandle(olaps.hEvent);
@@ -815,7 +820,7 @@ int icoms_usb_cancel_io(
usb_cancelt *cancelt
) {
int rv = ICOM_OK;
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
if (cancelt->hcancel != NULL) {
libusb_request req;
@@ -828,7 +833,7 @@ int icoms_usb_cancel_io(
a1logd(p->log, 1, "icoms_usb_cancel_io: failed with 0x%x\n",rv);
}
}
- usb_unlock_cancel(cancelt);
+ amutex_unlock(cancelt->cmtx);
return rv;
}
diff --git a/spectro/usbio_ox.c b/spectro/usbio_ox.c
index 24498fb..c92aed5 100644
--- a/spectro/usbio_ox.c
+++ b/spectro/usbio_ox.c
@@ -186,6 +186,7 @@ icompaths *p
IOObjectRelease(mit); /* Release the itterator */
return rv;
}
+
}
} else {
IOObjectRelease(ioob); /* Release found object */
@@ -402,7 +403,7 @@ char **pnames /* List of process names to try and kill before opening */
/* mess up the Spyder2, BUT we can't do a get config because this */
/* messes up the i1pro-D. */
- /* OS X doesn't do a set_configuration() by default */
+ /* OS X doesn't do a set_configuration() by default, so force one. */
p->cconfig = 0;
if (p->cconfig != config) {
@@ -462,7 +463,7 @@ char **pnames /* List of process names to try and kill before opening */
return ICOM_SYS;
}
(*pluginref)->Stop(pluginref);
- IODestroyPlugInInterface(pluginref);
+ IODestroyPlugInInterface(pluginref); // this stops IOServices though ??
if ((rv = (*(p->usbd->interfaces[i]))->USBInterfaceOpen(
p->usbd->interfaces[i])) != kIOReturnSuccess) {
@@ -703,9 +704,11 @@ static int icoms_usb_transaction(
}
if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
cancelt->hcancel = (void *)&req;
- usb_unlock_cancel(cancelt);
+ cancelt->state = 1;
+ amutex_unlock(cancelt->cond); /* Signal any thread waiting for IO start */
+ amutex_unlock(cancelt->cmtx);
}
/* Wait for the callback to complete */
@@ -757,7 +760,7 @@ static int icoms_usb_transaction(
/* If io was aborted, ClearPipeStall */
if (req.result == kIOReturnAborted) {
-#if defined(NEVER) && (InterfaceVersion > 182)
+#if (InterfaceVersion > 182)
(*p->usbd->interfaces[iix])->ClearPipeStallBothEnds(p->usbd->interfaces[iix], pno);
#else
(*p->usbd->interfaces[iix])->ClearPipeStall(p->usbd->interfaces[iix], pno);
@@ -787,9 +790,12 @@ static int icoms_usb_transaction(
done:;
if (cancelt != NULL) {
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
cancelt->hcancel = (void *)NULL;
- usb_unlock_cancel(cancelt);
+ if (cancelt->state == 0)
+ amutex_unlock(cancelt->cond);
+ cancelt->state = 2;
+ amutex_unlock(cancelt->cmtx);
}
pthread_cond_destroy(&req.cond);
@@ -865,7 +871,7 @@ int icoms_usb_cancel_io(
) {
int reqrv = ICOM_OK;
- usb_lock_cancel(cancelt);
+ amutex_lock(cancelt->cmtx);
usbio_req *req = (usbio_req *)cancelt->hcancel;
if (req != NULL) {
IOReturn rv;
@@ -875,7 +881,7 @@ int icoms_usb_cancel_io(
reqrv = ICOM_USBW;
}
}
- usb_unlock_cancel(cancelt);
+ amutex_unlock(cancelt->cmtx);
return reqrv;
}
@@ -911,7 +917,7 @@ int icoms_usb_clearhalt(
IOReturn rv;
int irv;
-#if defined(NEVER) && (InterfaceVersion > 182)
+#if (InterfaceVersion > 182)
if ((rv = (*p->usbd->interfaces[iix])->ClearPipeStallBothEnds(
p->usbd->interfaces[iix], pno)) != kIOReturnSuccess) {
a1logd(p->log, 1, "icoms_usb_clearhalt failed with 0x%x\n",rv);
diff --git a/spectro/webwin.c b/spectro/webwin.c
index d90239a..1de010a 100644
--- a/spectro/webwin.c
+++ b/spectro/webwin.c
@@ -35,6 +35,7 @@
#include "cgats.h"
#include "conv.h"
#include "dispwin.h"
+#include "webwin.h"
#include "conv.h"
#include "mongoose.h"
@@ -217,22 +218,35 @@ dispwin *p,
double r, double g, double b /* Color values 0.0 - 1.0 */
) {
int j;
+ double orgb[3]; /* Previous RGB value */
+ double kr, kf;
+ int update_delay = p->update_delay;
+ double xdelay = 0.0; /* Extra delay for response time */
debugr("webwin_set_color called\n");
if (p->nowin)
return 1;
- p->rgb[0] = r;
- p->rgb[1] = g;
- p->rgb[2] = b;
+ orgb[0] = p->rgb[0]; p->rgb[0] = r;
+ orgb[1] = p->rgb[1]; p->rgb[1] = g;
+ orgb[2] = p->rgb[2]; p->rgb[2] = b;
for (j = 0; j < 3; j++) {
if (p->rgb[j] < 0.0)
p->rgb[j] = 0.0;
else if (p->rgb[j] > 1.0)
p->rgb[j] = 1.0;
- p->r_rgb[j] = p->rgb[j];
+ p->r_rgb[j] = p->s_rgb[j] = p->rgb[j];
+ if (p->out_tvenc) {
+ p->r_rgb[j] = p->s_rgb[j] = ((235.0 - 16.0) * p->s_rgb[j] + 16.0)/255.0;
+
+ /* For video encoding the extra bits of precision are created by bit shifting */
+ /* rather than scaling, so we need to scale the fp value to account for this. */
+ if (p->pdepth > 8)
+ p->r_rgb[j] = (p->s_rgb[j] * 255 * (1 << (p->pdepth - 8)))
+ /((1 << p->pdepth) - 1.0);
+ }
}
/* This is probably not actually thread safe... */
@@ -242,12 +256,44 @@ double r, double g, double b /* Color values 0.0 - 1.0 */
msec_sleep(50);
}
+ /* Don't want extra delay if we're measuring update delay */
+ if (update_delay != 0 && p->do_resp_time_del) {
+ /* Compute am expected response time for the change in level */
+ kr = DISPLAY_RISE_TIME/log(1 - 0.9); /* Exponent constant */
+ kf = DISPLAY_FALL_TIME/log(1 - 0.9); /* Exponent constant */
+//printf("~1 k2 = %f\n",k2);
+ for (j = 0; j < 3; j++) {
+ double el, dl, n, t;
+
+ el = pow(p->rgb[j], 2.2);
+ dl = el - pow(orgb[j], 2.2); /* Change in level */
+ if (fabs(dl) > 0.01) { /* More than 1% change in level */
+ n = DISPLAY_SETTLE_AIM * el;
+ if (n < DISPLAY_ABS_AIM)
+ n = DISPLAY_ABS_AIM;
+//printf("~1 sl %f, el %f, log (%f / %f)\n",sl,el,n,fabs(sl - el));
+ if (dl > 0.0)
+ t = kr * log(n/dl);
+ else
+ t = kf * log(n/-dl);
+
+ if (t > xdelay)
+ xdelay = t;
+ }
+ }
+//printf("~1 xdelay = %f secs\n",xdelay);
+ xdelay *= 1000.0; /* To msec */
+ /* This is kind of a fudge since update delay is after latency, */
+ /* but displays with long delay (ie. CRT) have short latency, and visa versa */
+ if ((int)xdelay > update_delay)
+ update_delay = (int)xdelay;
+ }
+
/* Allow some time for the display to update before */
- /* a measurement can take place. This allows time for */
- /* the browser to update the background color, the CRT */
- /* refresh or LCD processing/update time, + */
+ /* a measurement can take place. This allows for CRT */
+ /* refresh, or LCD processing/update time, + */
/* display settling time (quite long for smaller LCD changes). */
- msec_sleep(200);
+ msec_sleep(update_delay);
return 0;
}
@@ -309,6 +355,13 @@ int webdisp, /* Port number */
double width, double height, /* Width and height in mm */
double hoff, double voff, /* Offset from center in fraction of screen, range -1.0 .. 1.0 */
int nowin, /* NZ if no window should be created - RAMDAC access only */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int verb, /* NZ for verbose prompts */
int ddebug /* >0 to print debug statements to stderr */
@@ -326,21 +379,30 @@ int ddebug /* >0 to print debug statements to stderr */
return NULL;
}
- /* !!!! Make changes in dispwin.c as well !!!! */
+ /* !!!! Make changes in dispwin.c & madvrwin.c as well !!!! */
p->name = strdup("Web Window");
p->nowin = nowin;
- p->native = 0;
+ p->native = native;
+ p->out_tvenc = out_tvenc;
p->blackbg = blackbg;
p->ddebug = ddebug;
- p->get_ramdac = webwin_get_ramdac;
- p->set_ramdac = webwin_set_ramdac;
- p->install_profile = webwin_install_profile;
+ p->get_ramdac = webwin_get_ramdac;
+ p->set_ramdac = webwin_set_ramdac;
+ p->install_profile = webwin_install_profile;
p->uninstall_profile = webwin_uninstall_profile;
- p->get_profile = webwin_get_profile;
- p->set_color = webwin_set_color;
+ p->get_profile = webwin_get_profile;
+ p->set_color = webwin_set_color;
p->set_update_delay = webwin_set_update_delay;
- p->set_callout = webwin_set_callout;
- p->del = webwin_del;
+ p->set_callout = webwin_set_callout;
+ p->del = webwin_del;
+
+ if (noramdac != NULL)
+ *noramdac = 1;
+ p->native &= ~1;
+
+ if (nocm != NULL)
+ *nocm = 1;
+ p->native &= ~2;
p->rgb[0] = p->rgb[1] = p->rgb[2] = 0.5; /* Set Grey as the initial test color */
@@ -361,6 +423,9 @@ int ddebug /* >0 to print debug statements to stderr */
p->ncix = 1;
+ p->pdepth = 8; /* Assume this by API */
+ p->edepth = 8;
+
/* Basic object is initialised, so create a web server */
options[0] = "listening_ports";
diff --git a/spectro/webwin.h b/spectro/webwin.h
index b298397..59b1d22 100644
--- a/spectro/webwin.h
+++ b/spectro/webwin.h
@@ -22,6 +22,13 @@ int webdisp, /* Port number */
double width, double height, /* Width and height in mm */
double hoff, double voff, /* Offset from center in fraction of screen, range -1.0 .. 1.0 */
int nowin, /* NZ if no window should be created - RAMDAC access only */
+int native, /* X0 = use current per channel calibration curve */
+ /* X1 = set native linear output and use ramdac high precn. */
+ /* 0X = use current color management cLut (MadVR) */
+ /* 1X = disable color management cLUT (MadVR) */
+int *noramdac, /* Return nz if no ramdac access. native is set to X0 */
+int *nocm, /* Return nz if no CM cLUT access. native is set to 0X */
+int out_tvenc, /* 1 = use RGB Video Level encoding */
int blackbg, /* NZ if whole screen should be filled with black */
int verb, /* NZ for verbose prompts */
int ddebug /* >0 to print debug statements to stderr */
diff --git a/target/ofps.c b/target/ofps.c
index fdea8cb..e485035 100644
--- a/target/ofps.c
+++ b/target/ofps.c
@@ -32,7 +32,7 @@
Some profiles are too rough, and slow/stall vertex placement.
Reducing the cache grid and/or smoothing the rspl values
- ay mitigate this to some degree, and make this more robust ??
+ may mitigate this to some degree, and make this more robust ??
*/
@@ -45,7 +45,7 @@
We then initially add sampling points at the largest estimated error
verticies of the veronoi natural neighbourhood.
- This gives us an optimal distribution measuring in mestimated position
+ This gives us an optimal distribution measuring in estimated position
error within a tollerance of 2:1
We then iteratively improve the distribution of point nodes by
@@ -84,7 +84,7 @@
all possible device channel values. This also applies at
higher dimensions (ie. the CMYK values exploring response
to different K values doesn't spread the CMY values
- evenly appart.)
+ evenly apart.)
Stratification seems to be somewhat at odds with the primary goal
of minimizing the maximum estimated error from any point in the
diff --git a/target/printtarg.c b/target/printtarg.c
index 25d889a..3ad3023 100644
--- a/target/printtarg.c
+++ b/target/printtarg.c
@@ -17,12 +17,20 @@
TTBD:
+ Add independent w & h patch scaling option.
+
+ Allow scaling minimum leading/trailing white space.
+
+ Add option to omit labelling.
+
Add "single pixel patch" mode, for pure digital processing for
abstract profile creation.
Add -h2 flag for Munki for super high-res chart ?
Note: i1Pro: Illum spot: 3.5mm Aperture: 4.5mm, Physical aperture: 4.55mm
+
Munki: Illum spot: 8.0mm Aperture: 6.0mm, Physical aperture: 7.63mm
+ Min patch size is 6mm x 6mm, below that increases delta E.
Add an option that allows including a scale gauge, to detect
accidental re-scaling.
@@ -31,6 +39,8 @@
rather than at the trailing edges.
Add direct PDF support, including NChannel output.
+
+ Add option to apply a scale to counteract the Adobe utility problem.
*/
/* This program generates a PostScript or TIFF print target file, */
@@ -98,7 +108,7 @@
* Improve EPS support to add a preview to each eps file.
*/
-#undef DEBUG
+#undef DEBUG /* Print edge details to stderr */
#undef FORCEN /* For testing, force DeviceN */
#define DEN_COMPRESS /* Compress density estimates > 1.0 */
/* - this biases it towards white spacers */
@@ -526,6 +536,7 @@ trend *new_ps_trend(
int nmask, /* Non zero if we are doing a DeviceN chart */
double pw, double ph, /* Page width and height in mm */
int eps, /* EPS flag */
+ int nocups, /* NZ to supress cups job ticket */
int rand, /* randomize */
int rstart /* Random start number/chart ID */
) {
@@ -595,6 +606,8 @@ trend *new_ps_trend(
fprintf(s->of,"%%%%PageOrder: Ascend\n");
fprintf(s->of,"%%%%BoundingBox: %d %d %d %d\n",0,0,ipw-1,iph-1);
fprintf(s->of,"%%%%Orientation: Portrait\n"); /* Rows are always virtical */
+ if (!nocups)
+ fprintf(s->of,"%%cupsJobTicket: cups-disable-cmm\n");
fprintf(s->of,"%%%%EndComments\n");
fprintf(s->of,"\n");
if (!eps) {
@@ -1733,6 +1746,7 @@ int hflag, /* Spectroscan/Munki high density modified */
int verb, /* Verbose flag */
int scanc, /* Scan compatible bits, 1 = .cht gen, 2 = wide first row */
int oft, /* PS/EPS/TIFF select (0,1,2) */
+int nocups, /* NZ to supress cups job ticket in PS/EPS */
depth2d tiffdpth, /* TIFF pixel depth */
double tiffres, /* TIFF resolution in DPI */
int ncha, /* flag, use nchannel alpha */
@@ -2438,7 +2452,7 @@ int *p_npat /* Return number of patches including padding */
if (oft == 0) { /* PS */
if (flags & IS_FPIF) { /* First page */
sprintf(psname,"%s.ps",bname);
- if ((tro = new_ps_trend(psname,npages,nmask,pw,ph,oft,rand,rstart)) == NULL)
+ if ((tro = new_ps_trend(psname,npages,nmask,pw,ph,oft,nocups,rand,rstart)) == NULL)
error ("Unable to create output rendering object file '%s'",psname);
if (verb)
printf("Creating file '%s'\n",psname);
@@ -2448,7 +2462,7 @@ int *p_npat /* Return number of patches including padding */
sprintf(psname,"%s_%02d.eps",bname,pif);
else
sprintf(psname,"%s.eps",bname);
- if ((tro = new_ps_trend(psname,npages,nmask,pw,ph,oft,rand,rstart)) == NULL)
+ if ((tro = new_ps_trend(psname,npages,nmask,pw,ph,oft,rand,rstart,nocups)) == NULL)
error ("Unable to create output rendering object file '%s'",psname);
if (verb)
printf("Creating file '%s'\n",psname);
@@ -2910,6 +2924,7 @@ void usage(char *diag, ...) {
fprintf(stderr," -M margin Set a page margin in mm and include it in TIFF\n");
fprintf(stderr," -P Don't limit strip length\n");
fprintf(stderr," -L Suppress any left paper clip border\n");
+ fprintf(stderr," -U Suppress CUPS cupsJobTicket: cups-disable-cmm in PS & EPS files\n");
fprintf(stderr," -p size Select page size from:\n");
for (pp = psizes; pp->name != NULL; pp++)
fprintf(stderr," %-8s [%.1f x %.1f mm]%s\n", pp->name, pp->w, pp->h,
@@ -2932,6 +2947,7 @@ char *argv[];
int rand = 1;
int qbits = 0; /* Quantization bits */
int oft = 0; /* Ouput File type, 0 = PS, 1 = EPS , 2 = TIFF */
+ int nocups = 0; /* Supress CUPS PS/EPS job ticket */
depth2d tiffdpth = bpc8_2d; /* TIFF pixel depth */
double tiffres = 100.0; /* TIFF resolution in DPI */
int ncha = 0; /* flag, use nchannel alpha */
@@ -2996,7 +3012,8 @@ char *argv[];
usage("Not enough arguments");
#ifdef DEBUG
- printf("target: DEBUG is #defined\n");
+# pragma message("######### printtarg DEBUG is #define ########")
+ fprintf(stderr,"target: DEBUG is #defined\n");
#endif
/* Find the default paper size */
@@ -3240,6 +3257,11 @@ char *argv[];
nolpcbord = 1;
}
+ /* Suppress CUPS job ticket */
+ else if (argv[fa][1] == 'U') {
+ nocups = 1;
+ }
+
/* Page size */
else if (argv[fa][1] == 'p') {
fa = nfa;
@@ -3646,12 +3668,12 @@ char *argv[];
pcol = pcold; /* Density spacer alues */
- sprintf(label, "Argyll Color Management System - Test chart \"%s\" (%s %d) %s",
+ sprintf(label, "ArgyllCMS - Chart \"%s\" (%s %d) %s",
psname, rand ? "Random Start" : "Chart ID", rstart, atm);
generate_file(itype, psname, cols, npat, applycal ? cal : NULL, label,
pap != NULL ? pap->w : cwidth, pap != NULL ? pap->h : cheight,
marg, nosubmarg, nollimit, nolpcbord, rand, rstart, saix, paix, ixord,
- pscale, sscale, hflag, verb, scanc, oft, tiffdpth, tiffres, ncha, tiffdith,
+ pscale, sscale, hflag, verb, scanc, oft, nocups, tiffdpth, tiffres, ncha, tiffdith,
tiffcomp, spacer, nmask, altrep, pcol, wp,
&sip, &pis, &plen, &glen, &tlen, &nppat);
@@ -3750,6 +3772,7 @@ char *argv[];
/* A half edge structure */
/* coordinate origin is top left */
struct _hedge {
+ int ix; /* Index for debug id */
double rgb[3]; /* Color this half edge transitions to */
int negh; /* 1 if this is a -ve major coordinate side half edge, 0 otherwise */
double mj; /* Major coordinate offset (ie. X coord for vertical edge) */
@@ -3761,7 +3784,7 @@ struct _hedge {
/* A patch identifier */
/* coordinate origin is top left */
struct _patch {
- char id[20]; /* ID string, Zeri length if a diagnostic rectangle */
+ char id[20]; /* ID string, Zero length if a diagnostic rectangle */
double xo; /* Location of the rectangle origin (bottom left ???) */
double yo;
double w; /* Size of the patch */
@@ -3799,7 +3822,7 @@ struct {
/* Raw half edge lists, [vertical, horizontal] */
int nhe[2];
- hedge *he[2];
+ hedge *he[2]; /* Pointer to start of hedhe linked list */
/* Patch identity information */
int npatches;
@@ -3942,33 +3965,173 @@ double y
/* .cht file. */
void et_write(char *fname, col *cols, int *rix, int si, int ei) {
FILE *of;
- hedge *ep;
+ hedge *ep0, *ep1, *epe;
int i, h;
//printf("~1 et has %d vertical and %d horizontal half edges\n", et.nhe[0], et.nhe[1]);
//printf("~1 et has %d patches\n", et.npatches);
+ /* Do X then Y */
for (h = 0; h < 2; h++) {
+
/* Create sorted list of vertical half edges */
if ((et.she[h] = (hedge **)malloc(sizeof(patch*) * et.nhe[h])) == NULL)
error("Malloc of array of vertical halfedge pointers failed");
- for (ep = et.he[h], i = 0; i < et.nhe[h]; i++, ep = ep->next)
- et.she[h][i] = ep;
+ for (ep0 = et.he[h], i = 0; i < et.nhe[h]; i++, ep0 = ep0->next)
+ et.she[h][i] = ep0;
/* Sort helf edges by their X location, then their Y0 location */
#define HEAP_COMPARE(A,B) (fabs(A->mj - B->mj) < 1e-6 ? A->mi0 < B->mi0 : A->mj < B->mj)
HEAPSORT(hedge *, et.she[h], et.nhe[h]);
#undef HEAP_COMPARE
-#ifdef NEVER
-for (i = 0; i < et.nhe[h]; i++) {
-printf("%s %d at %c = %f from %c = %f to %f\n",
-h == 0 ? "Vert" : "Horiz", i,
-h == 0 ? 'X' : 'Y', et.she[h][i]->mj,
-h == 0 ? 'Y' : 'X', et.she[h][i]->mi0, et.she[h][i]->mi1);
-}
-#endif /* NEVER */
+ /* Re-create the linked list in sorted order */
+ et.he[h] = NULL;
+ for (i = et.nhe[h]-1; i >= 0; i--) {
+ et.she[h][i]->next = et.he[h];
+ et.he[h] = et.she[h][i];
+ et.he[h]->ix = i;
+ }
+
+ free(et.she[h]);
+ et.she[h] = NULL;
+
+#ifdef DEBUG
+ fprintf(stderr,"Sorted %s half edges:\n",h ? "Vertical" : "Horizontal");
+ for (ep0 = et.he[h]; ep0 != NULL; ep0 = ep0->next) {
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f\n",
+ h == 0 ? "Vert" : "Horiz", ep0->ix,
+ h == 0 ? 'X' : 'Y', ep0->mj,
+ h == 0 ? 'Y' : 'X', ep0->mi0, ep0->mi1);
+ }
+#endif /* DEBUG */
+
+ /* Do a first pass to locate and split any part overlapping pairs of edges */
+ for (ep0 = et.he[h]; ep0 != NULL; ep0 = epe) {
+
+ /* Locate the end of the half edges at the same position */
+ for (epe = ep0; epe != NULL; epe = epe->next) {
+ if (epe == NULL || fabs(ep0->mj - epe->mj) > 1e-6)
+ break;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr,"Doing group from %d to %d\n",ep0->ix, epe ? epe->ix : -1);
+#endif
+
+ /* Look for overlapping half edges, and split them up so */
+ /* there are no overlaps */
+ for (; ep0 != epe; ep0 = ep0->next) {
+
+ for (ep1 = ep0->next; ep1 != epe; ep1 = ep1->next) {
+
+ if (ep1->mi0 > ep0->mi1) /* Out of range for overlap */
+ break;
+
+ /* If partial overlap */
+ if (ep0->mi0 < (ep1->mi0-1e-6)
+ && ep0->mi1 > (ep1->mi0+1e-6)
+ && ep0->mi1 < (ep1->mi1-1e-6)) {
+ hedge *ep0b, *ep1b;
+
+#ifdef DEBUG
+ fprintf(stderr,"Half edges partial overlap:\n");
+ fprintf(stderr,"i = %d, j = %d\n",ep0->ix,ep1->ix);
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
+ h == 0 ? "Vert" : "Horiz", ep0->ix,
+ h == 0 ? 'X' : 'Y', ep0->mj,
+ h == 0 ? 'Y' : 'X', ep0->mi0, ep0->mi1,
+ ep0->negh ? "Neg" : "Pos");
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
+ h == 0 ? "Vert" : "Horiz", ep1->ix,
+ h == 0 ? 'X' : 'Y', ep1->mj,
+ h == 0 ? 'Y' : 'X', ep1->mi0, ep1->mi1,
+ ep1->negh ? "Neg" : "Pos");
+#endif
+ /* Split up the two edges so that we have four edges */
+
+ if ((ep0b = (hedge *)calloc(sizeof(hedge), 1)) == NULL)
+ error("Malloc of half edge structure failed");
+ memcpy(ep0b, ep0, sizeof(hedge));
+
+ if ((ep1b = (hedge *)calloc(sizeof(hedge), 1)) == NULL)
+ error("Malloc of half edge structure failed");
+ memcpy(ep1b, ep1, sizeof(hedge));
+
+ ep0b->mi0 = ep1->mi0;
+ ep1b->mi1 = ep0->mi1;
+ ep0->mi1 = ep1->mi0;
+ ep1->mi0 = ep0->mi1;
+
+ /* Insert them in order into linked list */
+ ep1b->next = ep1;
+ ep0b->next = ep1b;
+ ep0->next = ep0b;
+
+ et.nhe[h] += 2;
+
+ /* If full overlap */
+ } else if (ep0->mi0 < (ep1->mi0-1e-6)
+ && ep0->mi1 > (ep1->mi1+1e-6)) {
+ hedge *ep0b, *ep0c;
+
+#ifdef DEBUG
+ fprintf(stderr,"Half edges full overlap:\n");
+ fprintf(stderr,"i = %d, j = %d\n",ep0->ix,ep1->ix);
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
+ h == 0 ? "Vert" : "Horiz", ep0->ix,
+ h == 0 ? 'X' : 'Y', ep0->mj,
+ h == 0 ? 'Y' : 'X', ep0->mi0, ep0->mi1,
+ ep0->negh ? "Neg" : "Pos");
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
+ h == 0 ? "Vert" : "Horiz", ep1->ix,
+ h == 0 ? 'X' : 'Y', ep1->mj,
+ h == 0 ? 'Y' : 'X', ep1->mi0, ep1->mi1,
+ ep1->negh ? "Neg" : "Pos");
+#endif
+ /* Split up the first edge so that we have four edges */
+
+ if ((ep0b = (hedge *)calloc(sizeof(hedge), 1)) == NULL)
+ error("Malloc of half edge structure failed");
+ memcpy(ep0b, ep0, sizeof(hedge));
+
+ if ((ep0c = (hedge *)calloc(sizeof(hedge), 1)) == NULL)
+ error("Malloc of half edge structure failed");
+ memcpy(ep0c, ep0, sizeof(hedge));
+
+ ep0b->mi0 = ep1->mi0;
+ ep0b->mi1 = ep1->mi1;
+ ep0c->mi0 = ep1->mi1;
+ ep0->mi1 = ep1->mi0;
+
+ /* Insert them in order into linked list */
+ ep0c->next = ep1->next;
+ ep1->next = ep0c;
+ ep0b->next = ep1;
+ ep0->next = ep0b;
+ et.nhe[h] += 2;
+ }
+ }
+ }
+ }
+
+ /* Now we can assume that edges match completely or not at all */
+
+ /* Re-create sorted list of vertical half edges */
+ /* (Instead of this we could convert the half edge matching loops */
+ /* below to use the linked list, like the above code.) */
+
+ if ((et.she[h] = (hedge **)malloc(sizeof(patch*) * et.nhe[h])) == NULL)
+ error("Malloc of array of vertical halfedge pointers failed");
+
+ for (ep0 = et.he[h], i = 0; i < et.nhe[h]; i++, ep0 = ep0->next)
+ et.she[h][i] = ep0;
+
+ /* Sort helf edges by their X location, then their Y0 location */
+#define HEAP_COMPARE(A,B) (fabs(A->mj - B->mj) < 1e-6 ? A->mi0 < B->mi0 : A->mj < B->mj)
+ HEAPSORT(hedge *, et.she[h], et.nhe[h]);
+#undef HEAP_COMPARE
et.nel[h] = 0;
et.nelp = &et.el[h]; /* Append next edge list here */
@@ -3980,7 +4143,7 @@ h == 0 ? 'Y' : 'X', et.she[h][i]->mi0, et.she[h][i]->mi1);
double *rgb = NULL; /* Contrast RGB */
elist *el; /* Current elist */
- el = *et.nelp;
+ el = *et.nelp; /* current end of lits */
/* Locate the end of the half edges at the same position */
for (ii = i; ii < et.nhe[h]; ii++) {
@@ -3988,11 +4151,13 @@ h == 0 ? 'Y' : 'X', et.she[h][i]->mi0, et.she[h][i]->mi1);
break;
}
-//printf("~1 doing group from %d to %d\n",i, ii);
+#ifdef DEBUG
+ fprintf(stderr,"Doing group from %d to %d\n",i, ii);
+#endif
+
/* Find half edge pairs */
/* Note that we assume that the half edges match perfectly, */
- /* or not at all. This will be normaly be the case with targets */
- /* generated by printtarg. */
+ /* or not at all. */
for (j = i; j < ii; j = nj, j++) {
int e, k = j+1;
double vv;
@@ -4013,25 +4178,26 @@ h == 0 ? 'Y' : 'X', et.she[h][i]->mi0, et.she[h][i]->mi1);
/* Found an overlapping non-matching edge */
nj = k;
-#ifdef NEVER
-fprintf(stderr,"i = %d, j = %d\n",i,j);
-fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
-h == 0 ? "Vert" : "Horiz", i,
-h == 0 ? 'X' : 'Y', et.she[h][j]->mj,
-h == 0 ? 'Y' : 'X', et.she[h][j]->mi0, et.she[h][j]->mi1,
-et.she[h][j]->negh ? "Neg" : "Pos");
-fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
-h == 0 ? "Vert" : "Horiz", i,
-h == 0 ? 'X' : 'Y', et.she[h][k]->mj,
-h == 0 ? 'Y' : 'X', et.she[h][k]->mi0, et.she[h][k]->mi1,
-et.she[h][k]->negh ? "Neg" : "Pos");
-#endif /* NEVER */
+#ifdef DEBUG
+ fprintf(stderr,"Half edges overlap but don't match:\n");
+ fprintf(stderr,"i = %d, j = %d\n",i,j);
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
+ h == 0 ? "Vert" : "Horiz", i,
+ h == 0 ? 'X' : 'Y', et.she[h][j]->mj,
+ h == 0 ? 'Y' : 'X', et.she[h][j]->mi0, et.she[h][j]->mi1,
+ et.she[h][j]->negh ? "Neg" : "Pos");
+ fprintf(stderr,"%s %d at %c = %f from %c = %f to %f, half %s\n",
+ h == 0 ? "Vert" : "Horiz", j,
+ h == 0 ? 'X' : 'Y', et.she[h][k]->mj,
+ h == 0 ? 'Y' : 'X', et.she[h][k]->mi0, et.she[h][k]->mi1,
+ et.she[h][k]->negh ? "Neg" : "Pos");
+#endif /* DEBUG */
error("Internal - half edges don't match");
} else {
- /* Must be a non-matching edge */
+ /* Must be a non-matching edge against the media */
nj = j;
- rgb = et.mrgb; /* Edge must be against media */
+ rgb = et.mrgb;
}
/* Compute vector delta in rgb */
diff --git a/target/targen.c b/target/targen.c
index 09dcc35..c868dc4 100644
--- a/target/targen.c
+++ b/target/targen.c
@@ -27,6 +27,7 @@
then suppliment the measured patches. Would have to add another
set of measurement columns to .ti1 & .ti2 to carry the
already measured values through, or do clumbsy post merge ?
+ (Latter is easiest).
Would be nice to be able to generate secondary
color ramps (ie. CMY for RGB space, RGB for CMYK space.)
@@ -103,11 +104,19 @@
#define VRML_DIAG /* Enable option to dump a VRML of the resulting full spread points */
#undef ADDRECCLIPPOINTS /* Add ink limited clipping points to regular grid */
#define EMPH_NEUTRAL /* Emphasise neutral axis, like CIE94 does */
-#define NEMPH_DEFAULT 0.5 /* Default emphasis == 2 x CIE94 */
+#define NEMPH_DEFAULT 0.5 /* Default neutral axis emphasis == 2 x CIE94 */
+#define XPOW_DEFAULT 1.0 /* Default extra device power value = none */
+#define DEMPH_DEFAULT 1.0 /* Default dark region emphasis == none */
#define DEFANGLE 0.3333 /* For simdlat and simplat */
#define SIMDLAT_TYPE SIMDLAT_BCC /* Simdlat geometry type */
#define MATCH_TOLL 1e-3 /* Tollerance of device value to consider a patch a duplicate */
+/* Display rise and fall time delay model. This is CRT like */
+#define DISPLAY_RISE_TIME 0.03 /* Assumed rise time to 90% of target level */
+#define DISPLAY_FALL_TIME 0.12 /* Assumed fall time to 90% of target level */
+#define DISPLAY_SETTLE_AIM 0.01 /* Aim for 1% of true level */
+#define DISPLAY_ABS_AIM 0.0001 /* Aim for .01% of true absolute level */
+
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
@@ -165,6 +174,8 @@ struct _pcpt {
/* Tuning parameters */
double nemph; /* neutral emphasis, 0.0 - 1.0. Default 0.35 for == CIE94 */
+ double idemph; /* inv. dark emphasis, 1.0 - 4.0. Default 1.0 == none */
+ double ixpow; /* inv. extra power Default 1.0 == none */
/* ICC profile based */
icmFile *fp;
@@ -200,10 +211,10 @@ pcpt_to_XYZ(pcpt *s, double *out, double *in) {
if (s->xmask == s->nmask) {
for (e = 0; e < s->di; e++)
- inv[e] = in[e];
+ inv[e] = icx_powlike(in[e], s->ixpow);
} else {
for (e = 0; e < s->di; e++)
- inv[e] = 1.0 - in[e];
+ inv[e] = 1.0 - icx_powlike(in[e], s->ixpow);
}
if (s->luo2 != NULL)
s->luo2->lookup(s->luo2, out, inv);
@@ -230,10 +241,10 @@ pcpt_to_rLab(pcpt *s, double *out, double *in) {
if (s->xmask == s->nmask) {
for (e = 0; e < s->di; e++)
- inv[e] = in[e];
+ inv[e] = icx_powlike(in[e], s->ixpow);
} else {
for (e = 0; e < s->di; e++)
- inv[e] = 1.0 - in[e];
+ inv[e] = 1.0 - icx_powlike(in[e], s->ixpow);
}
if (s->luo != NULL)
s->luo->lookup(s->luo, out, inv);
@@ -251,6 +262,7 @@ pcpt_to_rLab(pcpt *s, double *out, double *in) {
/* Perceptual conversion function */
/* Internal device values 0.0 - 1.0 are converted into perceptually uniform 0.0 - 100.0 */
+/* This is used by optimal spread functions ? */
static void
pcpt_to_nLab(pcpt *s, double *out, double *in) {
int e;
@@ -258,10 +270,10 @@ pcpt_to_nLab(pcpt *s, double *out, double *in) {
if (s->xmask == s->nmask) {
for (e = 0; e < s->di; e++)
- inv[e] = in[e];
+ inv[e] = icx_powlike(in[e], s->ixpow);
} else {
for (e = 0; e < s->di; e++)
- inv[e] = 1.0 - in[e];
+ inv[e] = 1.0 - icx_powlike(in[e], s->ixpow);
}
/* If we have some sort of perceptual conversion */
@@ -273,8 +285,9 @@ pcpt_to_nLab(pcpt *s, double *out, double *in) {
else if (s->mlu != NULL) {
s->mlu->lookup(s->mlu, lab, inv);
icmXYZ2Lab(&icmD50, lab, lab);
- } else
+ } else {
s->clu->dev_to_rLab(s->clu, lab, inv);
+ }
#ifdef EMPH_NEUTRAL /* Emphasise neutral axis, like CIE94 does */
{
@@ -283,13 +296,21 @@ pcpt_to_nLab(pcpt *s, double *out, double *in) {
c = sqrt(lab[1] * lab[1] + lab[2] * lab[2]); /* Compute chromanance */
// c = 2.6624 / (1.0 + 0.013 * c); /* Full strength scale factor */
- c = 3.0 / (1.0 + 0.03 * c); /* Full strength scale factor */
- c = 1.0 + s->nemph * (c - 1.0); /* Reduced strength scale factor */
+ c = 3.0 / (1.0 + 0.03 * c); /* Full strength scale factor */
+ c = 1.0 + s->nemph * (c - 1.0); /* Reduced strength scale factor */
lab[1] *= c; /* scale a & b */
lab[2] *= c;
}
#endif
+
+ /* Dark emphasis */
+ /* This doesn't actually match how demph is applied to device values... */
+ if (s->idemph < 1.0) {
+ double vv = lab[0];
+ lab[0] = 100.0 * pow(lab[0]/100.0, s->idemph);
+ }
+
/* Copy Lab values to output */
for (e = 0; e < (s->di < 3 ? s->di : 3); e++)
out[e] = lab[e];
@@ -611,7 +632,9 @@ inkmask xmask, /* external xcolorants mask */
inkmask nmask, /* internal xcolorants mask */
double *ilimit, /* ink sum limit (scale 1.0) input and return, -1 if default */
double *uilimit, /* underlying ink sum limit (scale 1.0) input and return, -1 if default */
-double nemph /* Neutral emphasis, 0.0 - 1.0. < 0.0 for default == CIE94 */
+double nemph, /* Neutral emphasis, 0.0 - 1.0. < 0.0 for default == CIE94 */
+double demph, /* Dark emphasis, 1.0 - 4.0. < 0.0 for default == none */
+double xpow /* Extra device power, default = none */
) {
int e;
pcpt *s;
@@ -638,6 +661,14 @@ double nemph /* Neutral emphasis, 0.0 - 1.0. < 0.0 for default == CIE94 */
nemph = NEMPH_DEFAULT;
s->nemph = nemph;
+ if (demph < 0.0)
+ demph = DEMPH_DEFAULT;
+ s->idemph = demph;
+
+ if (xpow < 0.0)
+ xpow = XPOW_DEFAULT;
+ s->ixpow = xpow;
+
/* See if we have a profile */
if (profName != NULL
&& profName[0] != '\000'
@@ -809,9 +840,11 @@ usage(int level, char *diag, ...) {
}
fprintf(stderr," -G Generate good optimized points rather than Fast\n");
fprintf(stderr," -e patches White test patches (default 4)\n");
+ fprintf(stderr," -B patches Black test patches (default 4 Grey/RGB, else 0)\n");
fprintf(stderr," -s steps Single channel steps (default grey 50, color 0)\n");
fprintf(stderr," -g steps Grey axis RGB or CMY steps (default 0)\n");
fprintf(stderr," -m steps Multidimensional device space cube steps (default 0)\n");
+ fprintf(stderr," -b steps Multidimensional body centered cubic steps (default 0)\n");
fprintf(stderr," -f patches Add iterative & adaptive full spread patches to total (default grey 0, color 836)\n");
fprintf(stderr," Default is Optimised Farthest Point Sampling (OFPS)\n");
fprintf(stderr," -t Use incremental far point for full spread\n");
@@ -830,7 +863,8 @@ usage(int level, char *diag, ...) {
fprintf(stderr," -p power Optional power-like value applied to all device values.\n");
fprintf(stderr," -c profile Optional device ICC or MPP pre-conditioning profile filename\n");
fprintf(stderr," (Use \"none\" to turn off any conditioning)\n");
- fprintf(stderr," -N emphasis Degree of neutral axis patch concentration 0.0-1.0 (default %.2f)\n",NEMPH_DEFAULT);
+ fprintf(stderr," -N nemphasis Degree of neutral axis patch concentration 0.0-1.0 (default %.2f)\n",NEMPH_DEFAULT);
+ fprintf(stderr," -V demphasis Degree of dark region patch concentration 1.0-4.0 (default %.2f = none)\n",DEMPH_DEFAULT);
fprintf(stderr," -F L,a,b,rad Filter out samples outside Lab sphere.\n");
#ifdef VRML_DIAG
fprintf(stderr," -w Dump diagnostic outfilel.wrl file (Lab locations)\n");
@@ -860,6 +894,8 @@ int dofilt(
return 0;
}
+static double disprespt(cgats *pp, int p1, int p2);
+
int main(int argc, char *argv[]) {
int i, j, k;
int fa, nfa, mfa; /* current argument we're looking at */
@@ -873,10 +909,12 @@ int main(int argc, char *argv[]) {
char *ident; /* Ink combination identifier (includes possible leading 'i') */
int good = 0; /* 0 - fast, 1 = good */
int esteps = 4; /* White color patches */
+ int Bsteps = -1; /* Black color patches */
int ssteps = -1; /* Single channel steps */
double xpow = 1.0; /* Power to apply to all device values created */
int gsteps = 0; /* Composite grey wedge steps */
int msteps = 0; /* Regular grid multidimensional steps */
+ int bsteps = 0; /* Regular body centered cubic grid multidimensional steps */
int fsteps = -1; /* Fitted Multidimensional patches */
int uselat = 0; /* Use incremental far point alg. for full spread points */
int userand = 0; /* Use random for full spread points, 2 = perceptual */
@@ -890,6 +928,7 @@ int main(int argc, char *argv[]) {
double ilimit = -1.0; /* Ink limit (scale 1.0) (default none) */
double uilimit = -1.0; /* Underlying (pre-calibration, scale 1.0) ink limit */
double nemph = NEMPH_DEFAULT;
+ double demph = DEMPH_DEFAULT;
int filter = 0; /* Filter values */
double filt[4] = { 50,0,0,0 };
static char fname[MAXNAMEL+1] = { 0 }; /* Output file base name */
@@ -920,7 +959,7 @@ int main(int argc, char *argv[]) {
mfa = 1; /* Minimum final 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 */
+ if (argv[fa][0] == '-') { /* Look for any flags */
char *na = NULL; /* next argument after flag, null if none */
if (argv[fa][2] != '\000')
@@ -940,7 +979,7 @@ int main(int argc, char *argv[]) {
usage(0, "Usage requested");
}
- else if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
+ else if (argv[fa][1] == 'v') {
verb = 1;
if (na != NULL && na[0] >= '0' && na[0] <= '9') {
verb = atoi(na);
@@ -978,51 +1017,70 @@ int main(int argc, char *argv[]) {
good = 1;
}
/* White color patches */
- else if (argv[fa][1] == 'e' || argv[fa][1] == 'E') {
+ else if (argv[fa][1] == 'e') {
int tt;
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -e");
if ((tt = atoi(na)) >= 0)
esteps = tt;
+ fa = nfa;
}
- /* Individual chanel steps */
- else if (argv[fa][1] == 's' || argv[fa][1] == 'S') {
+ /* Black color patches */
+ else if (argv[fa][1] == 'B') {
int tt;
+ if (na == NULL) usage(0,"Expect argument after -B");
+ if ((tt = atoi(na)) >= 0)
+ Bsteps = tt;
fa = nfa;
+ }
+ /* Individual chanel steps */
+ else if (argv[fa][1] == 's') {
+ int tt;
if (na == NULL) usage(0,"Expect argument after -s");
if ((tt = atoi(na)) >= 0)
ssteps = tt;
+ fa = nfa;
}
/* RGB or CMY grey wedge steps */
else if (argv[fa][1] == 'g') {
int tt;
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -g");
if ((tt = atoi(na)) >= 0)
gsteps = tt;
+ fa = nfa;
}
/* Multidimentional cube steps */
else if (argv[fa][1] == 'm') {
int tt;
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -m");
if ((tt = atoi(na)) >= 0) {
msteps = tt;
if (msteps == 1)
msteps = 2;
}
+ fa = nfa;
+ }
+ /* Multidimentional body centered cube steps */
+ else if (argv[fa][1] == 'b') {
+ int tt;
+ if (na == NULL) usage(0,"Expect argument after -b");
+ if ((tt = atoi(na)) >= 0) {
+ bsteps = tt;
+ if (bsteps == 1)
+ bsteps = 2;
+ }
+ fa = nfa;
}
/* Full even spread Multidimentional patches */
else if (argv[fa][1] == 'f') {
int tt;
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -f");
if ((tt = atoi(na)) >= 0)
fsteps = tt;
+ fa = nfa;
}
/* Use incremental far point algorithm for full spread */
- else if (argv[fa][1] == 't' || argv[fa][1] == 'T') {
+ else if (argv[fa][1] == 't') {
uselat = 1;
userand = 0;
useqrand = 0;
@@ -1031,7 +1089,8 @@ int main(int argc, char *argv[]) {
}
/* Random requested */
- else if (argv[fa][1] == 'r' || argv[fa][1] == 'R') {
+ else if (argv[fa][1] == 'r'
+ || argv[fa][1] == 'R') {
uselat = 0;
if (argv[fa][1] == 'R')
userand = 2;
@@ -1043,7 +1102,8 @@ int main(int argc, char *argv[]) {
}
/* Space filling quasi-random requested */
- else if (argv[fa][1] == 'q' || argv[fa][1] == 'Q') {
+ else if (argv[fa][1] == 'q'
+ || argv[fa][1] == 'Q') {
uselat = 0;
userand = 0;
if (argv[fa][1] == 'Q')
@@ -1075,14 +1135,13 @@ int main(int argc, char *argv[]) {
/* Simplex grid angle */
else if (argv[fa][1] == 'a') {
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -a");
simangle = atof(na);
+ fa = nfa;
}
/* Degree of iterative adaptation */
else if (argv[fa][1] == 'A') {
- fa = nfa;
if (na == NULL) usage(0,"Expected argument to average deviation flag -A");
if (na[0] == 'p') { /* (relative, for verification) */
perc_wght = atof(na+1);
@@ -1099,49 +1158,59 @@ int main(int argc, char *argv[]) {
if (dadapt < 0.0 || dadapt > 1.0)
usage(0,"Average Deviation argument %f must be between 0.0 and 1.0",dadapt);
}
+ fa = nfa;
}
/* Ink limit percentage */
- else if (argv[fa][1] == 'l' || argv[fa][1] == 'L') {
+ else if (argv[fa][1] == 'l') {
double tt;
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -l");
if ((tt = atof(na)) > 0.0)
uilimit = ilimit = 0.01 * tt;
+ fa = nfa;
}
/* Extra device power-like to use */
- else if (argv[fa][1] == 'p' || argv[fa][1] == 'P') {
+ else if (argv[fa][1] == 'p') {
double tt;
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -p");
if ((tt = atof(na)) > 0.0)
xpow = tt;
+ fa = nfa;
}
/* ICC profile for perceptual linearisation */
- else if (argv[fa][1] == 'c' || argv[fa][1] == 'C') {
- fa = nfa;
+ else if (argv[fa][1] == 'c') {
if (na == NULL) usage(0,"Expect argument after -c");
strncpy(pname,na,MAXNAMEL-1); pname[MAXNAMEL-1] = '\000';
+ fa = nfa;
}
/* Degree of neutral axis emphasis */
else if (argv[fa][1] == 'N') {
- fa = nfa;
if (na == NULL) usage(0,"Expected argument to neutral emphasis flag -N");
nemph = atof(na);
if (nemph < 0.0 || nemph > 10.0)
usage(0,"Neautral weighting argument %f to '-N' is out of range",nemph);
+ fa = nfa;
+ }
+
+ /* Degree of dark region emphasis */
+ else if (argv[fa][1] == 'V') {
+ if (na == NULL) usage(0,"Expected argument to dark emphasis flag -V");
+ demph = atof(na);
+ if (demph < 1.0 || demph > 4.0)
+ usage(0,"Dark weighting argument %f to '-V' is out of range",demph);
+ fa = nfa;
}
/* Filter out samples outside given sphere */
else if (argv[fa][1] == 'F') {
- fa = nfa;
if (na == NULL) usage(0,"Expect argument after -F");
if (sscanf(na, " %lf,%lf,%lf,%lf ",&filt[0], &filt[1], &filt[2], &filt[3]) != 4)
usage(0,"Argument to -F '%s' isn't correct",na);
filter = 1;
+ fa = nfa;
}
#ifdef VRML_DIAG
@@ -1187,6 +1256,13 @@ int main(int argc, char *argv[]) {
stime = clock();
/* Implement some defaults */
+ if (Bsteps < 0) {
+ if (xmask == ICX_W || xmask == ICX_K || xmask == ICX_RGB || xmask == ICX_IRGB)
+ Bsteps = 4;
+ else
+ Bsteps = 0;
+ }
+
if (di == 1) {
if (ssteps < 0)
ssteps = 50;
@@ -1201,22 +1277,22 @@ int main(int argc, char *argv[]) {
/* Do some sanity checking */
if (di == 1) {
- if (ssteps == 0 && fsteps == 0 && msteps == 0)
+ if (ssteps == 0 && fsteps == 0 && msteps == 0 && bsteps == 0)
error ("Must have some Gray steps");
if (gsteps > 0) {
warning ("Composite grey steps ignored for monochrome output");
gsteps = 0;
}
} else if (di == 3) {
- if (ssteps == 0 && fsteps == 0 && msteps == 0 && gsteps == 0)
+ if (ssteps == 0 && fsteps == 0 && msteps == 0 && bsteps == 0 && gsteps == 0)
error ("Must have some single or multi dimensional RGB or CMY steps");
} else {
- if (ssteps == 0 && fsteps == 0 && msteps == 0 && gsteps == 0)
+ if (ssteps == 0 && fsteps == 0 && msteps == 0 && bsteps == 0 && gsteps == 0)
error ("Must have some single or multi dimensional steps");
}
/* Deal with ICC, MPP or fallback profile */
- if ((pdata = new_pcpt(pname, xmask, nmask, &ilimit, &uilimit, nemph)) == NULL) {
+ if ((pdata = new_pcpt(pname, xmask, nmask, &ilimit, &uilimit, nemph, demph, xpow)) == NULL) {
error("Perceptual lookup object creation failed");
}
@@ -1231,6 +1307,10 @@ int main(int argc, char *argv[]) {
if (verb) {
printf("%s test chart\n",ident);
+ if (esteps > 0)
+ printf("White patches = %d\n",esteps);
+ if (Bsteps > 0)
+ printf("Black patches = %d\n",Bsteps);
if (ssteps > 0)
printf("Single channel steps = %d\n",ssteps);
if (gsteps > 0)
@@ -1239,6 +1319,8 @@ int main(int argc, char *argv[]) {
printf("Full spread patches = %d\n",fsteps);
if (msteps > 0)
printf("Multi-dimention cube steps = %d\n",msteps);
+ if (bsteps > 0)
+ printf("Multi-dimention body centered cube steps = %d\n",bsteps);
if (ilimit >= 0.0)
printf("Ink limit = %.1f%% (underlying %.1f%%)\n",ilimit * 100.0, uilimit * 100.0);
if (filter) {
@@ -1337,6 +1419,11 @@ int main(int argc, char *argv[]) {
pp->add_kword(pp, 0, "EXTRA_DEV_POW",buf, NULL);
}
+ if (demph > 1.0) {
+ sprintf(buf,"%f",demph);
+ pp->add_kword(pp, 0, "DARK_REGION_EMPHASIS",buf, NULL);
+ }
+
/* Only use optimsed full spread if <= 4 dimensions, else use ifarp */
if (di > 4
&& userand == 0 /* Not other high D useful method */
@@ -1372,21 +1459,88 @@ int main(int argc, char *argv[]) {
val[e] = 0.0; /* White is no colorant */
}
}
-
+
/* Apply general filter */
if (filter && dofilt(pdata, filt, val))
continue;
sprintf(buf,"%d",id++);
ary[0].c = buf;
+
+ if (xmask == nmask) {
+ for (e = 0; e < di; e++)
+ ary[1 + e].d = 100.0 * val[e];
+ } else {
+ for (e = 0; e < di; e++)
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
+ }
+
pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
+ ary[1 + di + 0].d = 100.0 * XYZ[0];
+ ary[1 + di + 1].d = 100.0 * XYZ[1];
+ ary[1 + di + 2].d = 100.0 * XYZ[2];
+
+ pp->add_setarr(pp, 0, ary);
+
+ if (fxlist != NULL) { /* Note in fixed list */
+ if (fxno >= fxlist_a) {
+ fxlist_a *= 2;
+ if ((fxlist = (fxpos *)realloc(fxlist, sizeof(fxpos) * fxlist_a)) == NULL)
+ error ("Failed to malloc fxlist");
+ }
+ for (e = 0; e < di; e++)
+ fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = pp->t[0].nsets;
+ fxno++;
+ }
+ }
+ }
+
+ /* Black color patches */
+ if (Bsteps > 0) {
+ int j, k, e;
+
+ for (j = k = 0; j < Bsteps; j++) {
+ double val[MXTD], XYZ[3];
+ cgats_set_elem ary[1 + MXTD + 3];
+
+ if (nmask & ICX_ADDITIVE) {
+ for (e = 0; e < di; e++) {
+ val[e] = 0.0; /* Black is no colorant */
+ }
+ } else {
+ for (e = 0; e < di; e++) {
+ val[e] = 1.0; /* Black is full colorant */
+ }
+ }
+
+ /* Apply general filter */
+ if (filter && dofilt(pdata, filt, val))
+ continue;
+
+ /* Do a simple ink limit */
+ if (uilimit < (double)di) {
+ double tot = 0.0;
+ for (e = 0; e < di; e++)
+ tot += val[e];
+ if (tot > uilimit) {
+ for (e = 0; e < di; e++)
+ val[e] *= uilimit/tot;
+ }
+ }
+
+ sprintf(buf,"%d",id++);
+ ary[0].c = buf;
+
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1401,12 +1555,17 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = pp->t[0].nsets;
fxno++;
}
+ k++;
}
+ sprintf(buf,"%d",k);
+ pp->add_kword(pp, 0, "BLACK_COLOR_PATCHES",buf, NULL);
+
}
- /* Primary wedge steps */
+ /* Primary (single channel) wedge steps */
if (ssteps > 0) {
sprintf(buf,"%d",ssteps);
pp->add_kword(pp, 0, "SINGLE_DIM_STEPS",buf, NULL);
@@ -1425,7 +1584,9 @@ int main(int argc, char *argv[]) {
val[e] = 0.0;
}
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
+ /* Extra power and dark emphasis */
+ for (e = 0; e < di; e++)
+ val[e] = icx_powlike(val[e], xpow * demph);
/* See if it is already in the fixed list */
if (fxlist != NULL) {
@@ -1452,13 +1613,16 @@ int main(int argc, char *argv[]) {
sprintf(buf,"%d",id++);
ary[0].c = buf;
+
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1473,6 +1637,7 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
fxno++;
}
}
@@ -1514,16 +1679,17 @@ int main(int argc, char *argv[]) {
val[e] = 0.0;
}
+ /* Extra power and dark emphasis */
+ for (e = 0; e < di; e++)
+ val[e] = icx_powlike(val[e], xpow * demph);
+
/* Apply general filter */
if (filter && dofilt(pdata, filt, val))
addp = 0;
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
-
- /* Compute sum that includes affect of power */
+ /* Check if over ink limit */
for (sum = 0.0, e = 0; e < di; e++)
- sum += icx_powlike(val[e], xpow);
-
+ sum += val[e];
if (sum > uilimit)
addp = 0;
@@ -1548,13 +1714,16 @@ int main(int argc, char *argv[]) {
sprintf(buf,"%d",id++);
ary[0].c = buf;
+
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1569,6 +1738,7 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
fxno++;
}
}
@@ -1594,16 +1764,17 @@ int main(int argc, char *argv[]) {
for (e = 0; e < di; e++)
val[e] = (double)gc[e]/(msteps-1);
+ /* Extra power and dark emphasis */
+ for (e = 0; e < di; e++)
+ val[e] = icx_powlike(val[e], xpow * demph);
+
/* Apply general filter */
if (filter && dofilt(pdata, filt, val))
addp = 0;
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
-
- /* Compute sum that includes affect of power */
+ /* Check if over ink limit */
for (sum = 0.0, e = 0; e < di; e++)
- sum += icx_powlike(val[e], xpow);
-
+ sum += val[e];
if (sum > uilimit)
addp = 0; /* Don't add patches over ink limit */
@@ -1630,13 +1801,16 @@ int main(int argc, char *argv[]) {
sprintf(buf,"%d",id++);
ary[0].c = buf;
+
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1651,11 +1825,11 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
fxno++;
}
}
- next_cpoint:;
/* Increment grid index and position */
for (j = 0; j < di; j++) {
gc[j]++;
@@ -1719,14 +1893,14 @@ int main(int argc, char *argv[]) {
if (addp) {
sprintf(buf,"%d",id++);
ary[0].c = buf;
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];;
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1741,6 +1915,7 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
fxno++;
}
}
@@ -1762,6 +1937,107 @@ int main(int argc, char *argv[]) {
#endif /* ADDRECCLIPPOINTS */
}
+ /* Regular body centered cubic gridded Multi dimension steps */
+ if (bsteps > 0) {
+ int gc[MXTD]; /* Grid coordinate */
+ int pass = 0; /* 0 = outer grid, 1 = inner grid */
+
+ sprintf(buf,"%d",bsteps);
+ pp->add_kword(pp, 0, "MULTI_DIM_BCC_STEPS",buf, NULL);
+
+ for (pass = 0; pass < 2; pass++) {
+
+ for (j = 0; j < di; j++)
+ gc[j] = 0; /* init coords */
+
+ for (;;) { /* For all grid points */
+ double sum, val[MXTD], XYZ[3];
+ int addp, e;
+
+ addp = 1; /* Default add the point */
+
+ for (e = 0; e < di; e++)
+ val[e] = (double)(pass * 0.5 + gc[e])/(bsteps-1);
+
+ /* Extra power and dark emphasis */
+ for (e = 0; e < di; e++)
+ val[e] = icx_powlike(val[e], xpow * demph);
+
+ /* Apply general filter */
+ if (filter && dofilt(pdata, filt, val))
+ addp = 0;
+
+ /* Check if over ink limit */
+ for (sum = 0.0, e = 0; e < di; e++)
+ sum += val[e];
+ if (sum > uilimit)
+ addp = 0; /* Don't add patches over ink limit */
+
+ /* See if it is already in the fixed list */
+ if (addp && fxlist != NULL) {
+ int k;
+ for (k = 0; k < fxno; k++) {
+ for (e = 0; e < di; e++) {
+ double tt;
+ tt = fabs(fxlist[k].p[e] - val[e]);
+ if (tt > MATCH_TOLL)
+ break; /* Not identical */
+ }
+ if (e >= di)
+ break; /* Was identical */
+ }
+ if (k < fxno) /* Found an identical patch */
+ addp = 0; /* Don't add the point */
+ }
+
+ /* Add patch to list if OK */
+ if (addp) {
+ cgats_set_elem ary[1 + MXTD + 3];
+
+ sprintf(buf,"%d",id++);
+ ary[0].c = buf;
+ if (xmask == nmask) {
+ for (e = 0; e < di; e++)
+ ary[1 + e].d = 100.0 * val[e];
+ } else {
+ for (e = 0; e < di; e++)
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
+ }
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
+ ary[1 + di + 0].d = 100.0 * XYZ[0];
+ ary[1 + di + 1].d = 100.0 * XYZ[1];
+ ary[1 + di + 2].d = 100.0 * XYZ[2];
+
+ pp->add_setarr(pp, 0, ary);
+
+ if (fxlist != NULL) { /* Note in fixed list */
+ if (fxno >= fxlist_a) {
+ fxlist_a *= 2;
+ if ((fxlist = (fxpos *)realloc(fxlist, sizeof(fxpos) * fxlist_a)) == NULL)
+ error ("Failed to malloc fxlist");
+ }
+ for (e = 0; e < di; e++)
+ fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
+ fxno++;
+ }
+ }
+
+ /* Increment grid index and position */
+ for (j = 0; j < di; j++) {
+ gc[j]++;
+ if ((pass == 0 && gc[j] < bsteps)
+ || (pass == 1 && gc[j] < (bsteps-1)))
+ break; /* No carry */
+ gc[j] = 0;
+ }
+ if (j >= di)
+ break; /* Done grid */
+ }
+ }
+ }
+
if (fsteps > fxno) { /* Top up with full spread (perceptually even) and other patch types */
/* Generate device random numbers. Don't check for duplicates */
@@ -1791,16 +2067,17 @@ int main(int argc, char *argv[]) {
val[e] = d_rand(0.0, 1.0);
}
+ /* Extra power and dark emphasis */
+ for (e = 0; e < di; e++)
+ val[e] = icx_powlike(val[e], xpow * demph);
+
/* Apply general filter */
if (filter && dofilt(pdata, filt, val))
continue;
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
-
- /* Compute sum that includes the affect of power */
+ /* Check if over ink limit */
for (sum = 0.0, e = 0; e < di; e++)
- sum += icx_powlike(val[e], xpow);
-
+ sum += val[e];
if (sum > uilimit)
continue;
@@ -1808,11 +2085,13 @@ int main(int argc, char *argv[]) {
ary[0].c = buf;
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1827,6 +2106,7 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
fxno++;
}
@@ -1917,16 +2197,14 @@ int main(int argc, char *argv[]) {
if (filter && dofilt(pdata, filt, val))
continue;
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
-
- /* Do a simple ink limit that include the effect of xpow */
+ /* Do a simple ink limit */
if (uilimit < (double)di) {
double tot = 0.0;
for (e = 0; e < di; e++)
- tot += icx_powlike(val[e],xpow);
+ tot += val[e];
if (tot > uilimit) {
for (e = 0; e < di; e++)
- val[e] = icx_powlike(icx_powlike(val[e],xpow) * uilimit/tot, 1.0/xpow);
+ val[e] = val[e] * uilimit/tot;
}
}
@@ -1934,11 +2212,13 @@ int main(int argc, char *argv[]) {
ary[0].c = buf;
if (xmask == nmask) {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * icx_powlike(val[e],xpow);
+ ary[1 + e].d = 100.0 * val[e];
} else {
for (e = 0; e < di; e++)
- ary[1 + e].d = 100.0 * (1.0 - icx_powlike(val[e],xpow));
+ ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -1953,6 +2233,7 @@ int main(int argc, char *argv[]) {
}
for (e = 0; e < di; e++)
fxlist[fxno].p[e] = val[e];
+ fxlist[fxno].eloc = -1;
fxno++;
}
}
@@ -1960,6 +2241,255 @@ int main(int argc, char *argv[]) {
}
}
+ /* Even the location of marked patches into sequence */
+ {
+ int ii, p1, p2, t1;
+
+ /* For each patch to be dispersed */
+ for (ii = 0; ii < fxno; ii++) {
+ if (fxlist[ii].eloc >= 0) {
+ p1 = fxlist[ii].eloc;
+
+ for (k = 0; k < 10; k++) { /* Retry 10 times */
+
+ /* Pick a random patch to exchange it with */
+ p2 = i_rand(0, pp->t[0].nsets-1);
+
+ /* Check it isn't one of our patches to be dispersed */
+ for (i = 0; i < fxno; i++) {
+ if (fxlist[i].eloc == p2)
+ break;
+ }
+ if (i < fxno)
+ continue; /* Try another patch to exchange with */
+
+ /* Swap */
+ for (j = 1; j < (1 + di + 3); j++) {
+ double tt = *((double *)pp->t[0].fdata[p1][j]);
+ *((double *)pp->t[0].fdata[p1][j]) = *((double *)pp->t[0].fdata[p2][j]);
+ *((double *)pp->t[0].fdata[p2][j]) = tt;
+ }
+ fxlist[ii].eloc = p2;
+
+ break;
+ }
+ }
+ }
+ }
+
+ /* If this seems to be for a CRT, optimise the patch order to minimise the */
+ /* response time delays */
+ if (nmask == ICX_RGB && pp->t[0].nsets > 1) {
+ int npat = pp->t[0].nsets;
+ char *nm; /* Don't move array */
+ double udelay, *delays, adelay;
+ double temp, trate; /* Annealing temperature & rate */
+ double tstart, tend;/* Annealing chedule range */
+
+ if ((nm = (char *)malloc(sizeof(char) * npat)) == NULL)
+ error ("Failed to malloc nm array");
+ if ((delays = (double *)malloc(sizeof(double) * npat)) == NULL)
+ error ("Failed to malloc delay array");
+
+ /* Set nm[] to mark patches that shouldn't be moved */
+ for (i = 0; i < npat; i++)
+ nm[i] = 0;
+ for (i = 0; i < fxno; i++) {
+ if (fxlist[i].eloc >= 0)
+ nm[fxlist[i].eloc] = 1;
+ }
+
+#ifdef NEVER
+ /* Randomly shuffle patches */
+ {
+ int p1, p2;
+
+ for (p1 = 0; p1 < npat; p1++) {
+
+ if (nm[p1])
+ continue;
+
+ p2 = i_rand(0, npat-1);
+ if (nm[p2])
+ continue;
+ for (j = 1; j < (1 + di + 3); j++) {
+ double tt = *((double *)pp->t[0].fdata[p1][j]);
+ *((double *)pp->t[0].fdata[p1][j]) = *((double *)pp->t[0].fdata[p2][j]);
+ *((double *)pp->t[0].fdata[p2][j]) = tt;
+ }
+ }
+ }
+#endif
+#ifdef NEVER
+ /* Simple sort by brightness */
+ {
+ int p1, p2;
+ double rgb1, rgb2;
+
+ for (p1 = 0; p1 < (npat-1); p1++) {
+
+ if (nm[p1])
+ continue;
+
+ rgb1 = pow(*((double *)pp->t[0].fdata[p1][1 + 0]), 2.2)
+ + pow(*((double *)pp->t[0].fdata[p1][1 + 1]), 2.2)
+ + pow(*((double *)pp->t[0].fdata[p1][1 + 2]), 2.2);
+
+ for (p2 = p1 + 1; p2 < npat; p2++) {
+
+ if (nm[p2])
+ continue;
+
+ rgb2 = pow(*((double *)pp->t[0].fdata[p2][1 + 0]), 2.2)
+ + pow(*((double *)pp->t[0].fdata[p2][1 + 1]), 2.2)
+ + pow(*((double *)pp->t[0].fdata[p2][1 + 2]), 2.2);
+
+ if (rgb2 < rgb1) {
+ for (j = 1; j < (1 + di + 3); j++) {
+ double tt = *((double *)pp->t[0].fdata[p1][j]);
+ *((double *)pp->t[0].fdata[p1][j]) = *((double *)pp->t[0].fdata[p2][j]);
+ *((double *)pp->t[0].fdata[p2][j]) = tt;
+ }
+ rgb1 = rgb2;
+ }
+ }
+ }
+ }
+#endif
+ /* Compute the current overall update delay */
+ udelay = 0.0;
+ for (i = 1; i < npat; i++) {
+ double xdelay;
+
+ xdelay = disprespt(pp, i-1, i);
+
+ delays[i] = xdelay;
+//printf("~1 delay[%d] = %f\n",i,xdelay);
+ udelay += xdelay;
+ }
+
+ if (verb)
+ printf("Extra display response delay = %f sec., optimizing....\n",udelay);
+
+ {
+ int nchunks, chsize;
+ int chstart, chend;
+
+ if (verb)
+ printf("%c%2d%%",cr_char,0); fflush(stdout);
+
+ /* We'll do this in chunks of 500 to make it linear time overall, */
+ /* at the cost of the best possible optimisation. */
+ nchunks = (int)ceil(npat/500.0);
+ chsize = (int)ceil(npat/nchunks);
+ for (chstart = 0; chstart < npat; chstart += chsize) {
+ int p1, p2, bp2;
+ double p1d, p2d, p1d1, p2d1;
+ double p1nd, p2nd, p1nd1, p2nd1;
+ double tdelay, de;
+ int noswapped;
+
+ chend = chstart + chsize+2;
+ if (chend > npat)
+ chend = npat;
+ noswapped = chend - chstart;
+//printf("~1 chstart %d, chend %d, size %d\n",chstart,chend, chend - chstart);
+
+ /* While we are still improving, and the improvement was significant */
+ for (;noswapped > 5;) {
+ noswapped = 0;
+
+ for (p1 = chstart + 1; p1 < chend; p1++) {
+ if (nm[p1])
+ continue;
+
+ p1d = delays[p1];
+
+ /* Locate the patch ahead of us that is best to swap with */
+ bp2 = -1;
+ for (p2 = p1 + 2; p2 < chend; p2++) {
+
+ if (nm[p2])
+ continue;
+
+ /* Compute effect of a swap on the total delay */
+ p2d = delays[p2];
+ p1nd = disprespt(pp, p2-1, p1);
+ p2nd = disprespt(pp, p1-1, p2);
+ p1d1 = p1nd1 = 0.0;
+ if ((p1+1) < chend) {
+ p1d1 = delays[p1+1];
+ p1nd1 = disprespt(pp, p2, p1+1);
+ }
+ p2d1 = p2nd1 = 0.0;
+ if ((p2+1) < chend) {
+ p2d1 = delays[p2+1];
+ p2nd1 = disprespt(pp, p1, p2+1);
+ }
+
+ tdelay = udelay - p1d - p2d - p1d1 - p2d1 + p1nd + p2nd + p1nd1 + p2nd1;
+
+ if (tdelay < udelay) {
+ bp2 = p2;
+ }
+ }
+ if (bp2 < 0) {
+ continue;
+ }
+
+ noswapped++;
+
+ p2 = bp2;
+
+ p2d = delays[p2];
+ p1nd = disprespt(pp, p2-1, p1);
+ p2nd = disprespt(pp, p1-1, p2);
+ p1d1 = p1nd1 = 0.0;
+ if ((p1+1) < chend) {
+ p1d1 = delays[p1+1];
+ p1nd1 = disprespt(pp, p2, p1+1);
+ }
+ p2d1 = p2nd1 = 0.0;
+ if ((p2+1) < chend) {
+ p2d1 = delays[p2+1];
+ p2nd1 = disprespt(pp, p1, p2+1);
+ }
+
+ tdelay = udelay - p1d - p2d - p1d1 - p2d1 + p1nd + p2nd + p1nd1 + p2nd1;
+
+ /* Swap the values */
+ udelay = tdelay;
+ delays[p2] = p1nd;
+ delays[p1] = p2nd;
+ if (p1 < (chend-1))
+ delays[p1+1] = p1nd1;
+ if (p2 < (chend-1))
+ delays[p2+1] = p2nd1;
+
+ for (j = 1; j < (1 + di + 3); j++) {
+ double tt = *((double *)pp->t[0].fdata[p1][j]);
+ *((double *)pp->t[0].fdata[p1][j]) = *((double *)pp->t[0].fdata[p2][j]);
+ *((double *)pp->t[0].fdata[p2][j]) = tt;
+ }
+//printf("~1 swaping %d and %d, udelay %f\n",p1,p2,udelay);
+ }
+//printf("~1 udelay %f\n",udelay);
+ if (verb) {
+ printf("%c%2d%%",cr_char,(int)(100.0 * (chend-1 - noswapped)/(npat-1.0)));
+ fflush(stdout);
+ }
+ }
+ }
+ if (verb)
+ printf("%c%2d%%",cr_char,100); fflush(stdout);
+ }
+ if (verb)
+ printf("\nOptimised display response delay = %f sec.\n",udelay);
+
+ free(delays);
+ free(nm);
+ }
+
/* Use ofps to measure the stats of the points */
/* Note that if new_ofps() fails it will exit() */
if (verb > 1
@@ -2001,11 +2531,6 @@ int main(int argc, char *argv[]) {
/* Lookup device values for target density */
pdata->den_to_dev(pdata, val, den);
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
-
- /* Apply extra power */
- for (e = 0; e < di; e++)
- val[e] = icx_powlike(val[e], xpow);
/* Do a simple ink limit */
if (uilimit < (double)di) {
@@ -2027,6 +2552,7 @@ int main(int argc, char *argv[]) {
for (e = 0; e < di; e++)
ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -2090,18 +2616,16 @@ int main(int argc, char *argv[]) {
val[0] = val[1] = val[2] = 0.5;
}
+ /* Apply extra power to device values (??) */
+ for (e = 0; e < di; e++)
+ val[e] = icx_powlike(val[e], xpow);
+
/* If target space isn't something we recognise, convert it */
if (ftarg != NULL) {
ftarg->dev_to_rLab(ftarg, lab, val);
pdata->rLab_to_dev(pdata, val, lab);
}
- pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
-
- /* Apply extra power */
- for (e = 0; e < di; e++)
- val[e] = icx_powlike(val[e], xpow);
-
/* Do a simple ink limit */
if (uilimit < (double)di) {
double tot = 0.0;
@@ -2121,6 +2645,8 @@ int main(int argc, char *argv[]) {
for (e = 0; e < di; e++)
ary[1 + e].d = 100.0 * (1.0 - val[e]);
}
+
+ pdata->dev_to_XYZ(pdata, XYZ, val); /* Add expected XYZ */
ary[1 + di + 0].d = 100.0 * XYZ[0];
ary[1 + di + 1].d = 100.0 * XYZ[1];
ary[1 + di + 2].d = 100.0 * XYZ[2];
@@ -2183,6 +2709,7 @@ int main(int argc, char *argv[]) {
rad = 15.0/pow(nsets, 1.0/(double)(di <= 3 ? di : 3));
for (i = 0; i < nsets; i++) {
+
/* Re-do any inversion before using dev_to_rLab() */
if (xmask == nmask) {
for (j = 0; j < di; j++)
@@ -2193,10 +2720,11 @@ int main(int argc, char *argv[]) {
idev[j] = 1.0 - dev[j];
}
}
+
pdata->dev_to_rLab(pdata, Lab, idev);
wrl->Lab2RGB(wrl, col, Lab);
- /* Fudge device locations into Lab space */
+ /* Fudge device locations into "Lab" space */
Lab[0] = 100.0 * dev[0];
Lab[1] = 100.0 * dev[1] - 50.0;
Lab[2] = 100.0 * dev[2] - 50.0;
@@ -2217,6 +2745,47 @@ int main(int argc, char *argv[]) {
return 0;
}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* Compte the display response time */
+static double disprespt(cgats *pp, int p1, int p2) {
+ double kr, kf;
+ double orgb[3], rgb[3];
+ double xdelay = 0.0;
+ int j;
+
+ kr = DISPLAY_RISE_TIME/log(1 - 0.9); /* Exponent constant */
+ kf = DISPLAY_FALL_TIME/log(1 - 0.9); /* Exponent constant */
+
+ orgb[0] = *((double *)pp->t[0].fdata[p1][1 + 0]) / 100.0;
+ orgb[1] = *((double *)pp->t[0].fdata[p1][1 + 1]) / 100.0;
+ orgb[2] = *((double *)pp->t[0].fdata[p1][1 + 2]) / 100.0;
+
+ rgb[0] = *((double *)pp->t[0].fdata[p2][1 + 0]) / 100.0;
+ rgb[1] = *((double *)pp->t[0].fdata[p2][1 + 1]) / 100.0;
+ rgb[2] = *((double *)pp->t[0].fdata[p2][1 + 2]) / 100.0;
+
+ for (j = 0; j < 3; j++) {
+ double el, dl, n, t;
+
+ el = pow(rgb[j], 2.2);
+ dl = el - pow(orgb[j], 2.2); /* Change in level */
+ if (fabs(dl) > 0.01) { /* More than 1% change in level */
+ n = DISPLAY_SETTLE_AIM * el;
+ if (n < DISPLAY_ABS_AIM)
+ n = DISPLAY_ABS_AIM;
+ if (dl > 0.0)
+ t = kr * log(n/dl);
+ else
+ t = kf * log(n/-dl);
+
+ if (t > xdelay)
+ xdelay = t;
+ }
+ }
+ return xdelay;
+}
+
diff --git a/target/targen.h b/target/targen.h
index 2f4665a..c99b551 100644
--- a/target/targen.h
+++ b/target/targen.h
@@ -23,6 +23,7 @@
struct _fxpos {
double p[MXTD]; /* Device coordinate position */
double v[MXTD]; /* Room for perceptual value */
+ int eloc; /* if >= 0, cgats index, to even location */
}; typedef struct _fxpos fxpos;
diff --git a/ttbd.txt b/ttbd.txt
index 925047a..d0891a2 100644
--- a/ttbd.txt
+++ b/ttbd.txt
@@ -1,9 +1,9 @@
-Argyll - Things To Be Done (in no particular priority)
+Argyll - Things To Be Done & odeas (in no particular priority)
--------------------------
Categories:
-1) Active list
+1) Ideas list
2) General
3) Documentation
4) Charts
@@ -17,8 +17,26 @@ Categories:
10) Calibration
11) Bugs
---------------------------------------------------------
- To be added:
+===================================================================
+Recent suggestions:
+
+ Add troublshooting section to tutorial:
+ colprof report fit DE's
+ iccgamut
+ transplot
+ xicclu fwd & bwd and both
+ cctiff through test chart path
+ cctiff soft proof
+
+ Add flat field support to scanin
+
+ Add "dynamic range" option to targen to concentrate
+ samples near black, + tweak colprof to skew grid
+ in that direction too.
+
+ Add DICOM support to dispcal.
+
+ Change CIECAM02 to simplified & improved version
add filtered mode for tiffgamut
@@ -27,12 +45,9 @@ Categories:
add option to dark cal spectro's evern N readings in dispsup.
+ Add some i1pro RevE UV support for improved FWA
---------------------------------------------------------
-
-*) Add some i1pro RevE UV support for improved FWA
-
-*) Add "single pixel chart" mode to printtarg and scanin.
+ Add "single pixel chart" mode to printtarg and scanin.
--------------------------------------------------------
1) List 2
diff --git a/tweak/refine.c b/tweak/refine.c
index 2d931ca..4d2104e 100644
--- a/tweak/refine.c
+++ b/tweak/refine.c
@@ -1225,7 +1225,8 @@ main(int argc, char *argv[]) {
NULL, NULL, /* Use default Maximum range of Lab' values */
PCSp_PCSp, /* Lab' -> Lab' transfer function */
NULL, NULL, /* Use default Maximum range of Lab' values */
- NULL /* Linear output transform Lab'->Lab */
+ NULL, /* Linear output transform Lab'->Lab */
+ NULL, NULL /* Default SET_APXLS range */
) != 0)
error("Setting 16 bit Lab->Lab Lut failed: %d, %s",wr_icc->errc,wr_icc->err);
diff --git a/ucmm/ucmm.c b/ucmm/ucmm.c
index dc5598f..52bd8f0 100644
--- a/ucmm/ucmm.c
+++ b/ucmm/ucmm.c
@@ -213,9 +213,9 @@ ucmm_error ucmm_install_monitor_profile(
char **paths;
char *tt;
- if (npaths = xdg_bds(&er, &paths, xdg_conf, xdg_write,
+ if ((npaths = xdg_bds(&er, &paths, xdg_conf, xdg_write,
scope == ucmm_local_system ? xdg_local : xdg_user,
- config_file) == 0) {
+ config_file)) == 0) {
return ucmm_open_config;
}
if ((conf_name = strdup(paths[0])) == NULL) {
@@ -225,7 +225,7 @@ ucmm_error ucmm_install_monitor_profile(
xdg_free(paths, npaths);
/* Combined sub-path and profile name */
- if ((data_pathfile = malloc(strlen(profile_dir) + 1 + strlen(profile))) == NULL)
+ if ((data_pathfile = malloc(strlen(profile_dir) + 1 + strlen(profile) + 1)) == NULL)
return ucmm_resource;
strcpy(data_pathfile, profile_dir);
@@ -238,9 +238,9 @@ ucmm_error ucmm_install_monitor_profile(
tt = profile;
strcat(data_pathfile, tt);
- if (npaths = xdg_bds(&er, &paths, xdg_conf, xdg_write,
+ if ((npaths = xdg_bds(&er, &paths, xdg_conf, xdg_write,
scope == ucmm_local_system ? xdg_local : xdg_user,
- data_pathfile) == 0) {
+ data_pathfile)) == 0) {
free(data_pathfile);
free(conf_name);
return ucmm_open_config;
@@ -514,9 +514,9 @@ ucmm_error ucmm_uninstall_monitor_profile(
char **paths;
char *tt;
- if (npaths = xdg_bds(&er, &paths, xdg_conf, xdg_read,
+ if ((npaths = xdg_bds(&er, &paths, xdg_conf, xdg_read,
scope == ucmm_local_system ? xdg_local : xdg_user,
- config_file) == 0) {
+ config_file)) == 0) {
return ucmm_open_config;
}
if ((conf_name = strdup(paths[0])) == NULL) {
@@ -527,7 +527,7 @@ ucmm_error ucmm_uninstall_monitor_profile(
if (profile != NULL) {
/* Combined sub-path and profile name */
- if ((data_pathfile = malloc(strlen(profile_dir) + 1 + strlen(profile))) == NULL)
+ if ((data_pathfile = malloc(strlen(profile_dir) + 1 + strlen(profile) + 1)) == NULL)
return ucmm_resource;
strcpy(data_pathfile, profile_dir);
@@ -540,9 +540,9 @@ ucmm_error ucmm_uninstall_monitor_profile(
tt = profile;
strcat(data_pathfile, tt);
- if (npaths = xdg_bds(&er, &paths, xdg_conf, xdg_read,
+ if ((npaths = xdg_bds(&er, &paths, xdg_conf, xdg_read,
scope == ucmm_local_system ? xdg_local : xdg_user,
- data_pathfile) == 0) {
+ data_pathfile)) == 0) {
free(data_pathfile);
free(conf_name);
return ucmm_open_config;
@@ -796,9 +796,9 @@ ucmm_error ucmm_get_monitor_profile(
char **paths;
char *tt;
- if (npaths = xdg_bds(&er, &paths, xdg_conf, xdg_read,
+ if ((npaths = xdg_bds(&er, &paths, xdg_conf, xdg_read,
scope == ucmm_local_system ? xdg_local : xdg_user,
- config_file) == 0) {
+ config_file)) == 0) {
continue;
}
if ((conf_name = strdup(paths[0])) == NULL) {
diff --git a/usb/55-Argyll.rules b/usb/55-Argyll.rules
index 3da9c69..5fef930 100644
--- a/usb/55-Argyll.rules
+++ b/usb/55-Argyll.rules
@@ -85,6 +85,6 @@ TEST=="/var/run/ConsoleKit/database", ENV{COLOR_MEASUREMENT_DEVICE}=="*?", ENV{A
ENV{COLOR_MEASUREMENT_DEVICE}=="*?", ENV{ACL_MANAGE}!="*?", MODE="660", GROUP="plugdev"
# Set ID_VENDOR and ID_MODEL acording to VID and PID
-IMPORT{program}="usb-db %p"
+TEST=="/lib/udev/usb-db", IMPORT{program}="usb-db %p"
LABEL="argyll_rules_end"
diff --git a/usb/ArgyllCMS.cat b/usb/ArgyllCMS.cat
index d401490..4634140 100644
--- a/usb/ArgyllCMS.cat
+++ b/usb/ArgyllCMS.cat
Binary files differ
diff --git a/usb/ArgyllCMS.inf b/usb/ArgyllCMS.inf
index 64f5eca..115d981 100644
--- a/usb/ArgyllCMS.inf
+++ b/usb/ArgyllCMS.inf
@@ -1,213 +1,213 @@
-;--------------------------------------------------------------------------
-; Copyright 2012 Graeme W. Gill.
-;
-; Permission is hereby granted, free of charge, to any person obtaining a copy
-; of this file, to deal
-; in this file without restriction, including without limitation the rights
-; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-; copies of this file, and to permit persons to whom this file is
-; furnished to do so, subject to the following conditions:
-;
-; The above copyright notice and this permission notice shall be included in
-; all copies or substantial portions of this file.
-;
-; THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-; OUT OF OR IN CONNECTION WITH THIS FILE OR THE USE OR OTHER DEALINGS IN
-; THIS FILE.
-;--------------------------------------------------------------------------
-
-; ==== Strings ====
-
-[Strings]
-
-DeviceGUID = {247e32a0-32f9-11df-aacc-0002a5d5c51b}
-
-Date = "01/17/2012" ; MM/DD/YYYY
-libusb0ver = "1.2.6.0"
-
-Libusb_ClassName = "Argyll LibUSB-win32 devices"
-Libusb_DiskName = "LibUSB-win32 Device Install Disk"
-
-libusb0_SvcDesc = "LibUSB-win32 libusb0 - Kernel Driver 2012/1/17, 1.2.6.0"
-
-; ==== Version ====
-
-[Version]
-Signature = "$Windows NT$"
-DriverVer = %Date%,%libusb0ver%
-Provider = "ArgyllCMS"
-
-; (Note the ClassGuid must not be quoted or a string substitution to work on Win2K)
-Class = %Libusb_ClassName%
-ClassGuid = {817cffe0-328b-11df-9b9f-0002a5d5c51b} ; LibUSB-win32 ClassGUID
-CatalogFile = "ArgyllCMS.cat"
-CatalogFile.NTAMD64 = "ArgyllCMS_x64.cat"
-
-[ClassInstall32]
-AddReg=class_install_add_reg
-
-[class_install_add_reg]
-HKR,,,,%Libusb_ClassName%
-HKR,,Icon,,"-20" ; -20 is for the USB icon
-
-; ==== Files Sources and Destinations ====
-
-[SourceDisksNames]
-1 = %Libusb_DiskName%
-
-[SourceDisksFiles]
-libusb0.sys = 1,\bin\x86,
-
-[SourceDisksFiles.amd64]
-libusb0.sys = 1,\bin\amd64,
-
-[DestinationDirs]
-libusb0_files_sys = 10,system32\drivers
-
-; ==== libusb0 Device driver ====
-
-[libusb0_files_sys]
-libusb0.sys,libusb0.sys
-
-; For each one of these, there must be one for Services !!!
-[LIBUSB0_DEV]
-CopyFiles = Libusb0_files_sys
-
-[LIBUSB0_DEV.HW]
-AddReg = libusb0_add_reg_hw
-
-[libusb0_add_reg]
-HKR,,DevLoader,,*ntkern
-HKR,,NTMPDriver,,libusb0.sys
-
-[libusb0_add_reg_hw]
-HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID%
-HKR,,SurpriseRemovalOK,0x00010001,1 ; Device properties
-
-[LIBUSB0_DEV.Services]
-AddService = libusb0, 0x00000002, libusb0_add_service
-
-[libusb0_add_service]
-DisplayName = %libusb0_SvcDesc%
-ServiceType = 1
-StartType = 3
-ErrorControl = 0
-ServiceBinary = %12%\libusb0.sys
-
-; ==== Manufacturers ====
-
-[Manufacturer]
-"HCFR Association"=HCFR_Devices,NTx86,NTamd64
-"Sequel Imaging"=Sequel_Devices,NTx86,NTamd64
-"X-Rite"=X_Rite_Devices,NTx86,NTamd64
-"ColorVision"=ColorVision_Devices,NTx86,NTamd64
-"Gretag Macbeth/X-Rite"=GM_X_Rite_Devices,NTx86,NTamd64
-"Hughski Ltd"=Hughski_Devices,NTx86,NTamd64
-
-; ==== Devices ====
-
-[HCFR_Devices]
-"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
-"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
-
-[Sequel_Devices]
-"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
-
-[X_Rite_Devices]
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
-"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
-"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
-"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
-"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
-"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
-
-[ColorVision_Devices]
-"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
-"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
-"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
-"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
-
-[GM_X_Rite_Devices]
-"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
-"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
-"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
-"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
-"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
-
-[Hughski_Devices]
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
-
-
-[HCFR_Devices.NTx86]
-"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
-"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
-
-[Sequel_Devices.NTx86]
-"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
-
-[X_Rite_Devices.NTx86]
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
-"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
-"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
-"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
-"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
-"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
-
-[ColorVision_Devices.NTx86]
-"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
-"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
-"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
-"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
-
-[GM_X_Rite_Devices.NTx86]
-"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
-"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
-"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
-"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
-"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
-
-[Hughski_Devices.NTx86]
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
-
-
-[HCFR_Devices.NTamd64]
-"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
-"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
-
-[Sequel_Devices.NTamd64]
-"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
-
-[X_Rite_Devices.NTamd64]
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
-"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
-"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
-"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
-"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
-"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
-
-[ColorVision_Devices.NTamd64]
-"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
-"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
-"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
-"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
-
-[GM_X_Rite_Devices.NTamd64]
-"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
-"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
-"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
-"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
-"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
-
-[Hughski_Devices.NTamd64]
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
-
+;--------------------------------------------------------------------------
+; Copyright 2012 Graeme W. Gill.
+;
+; Permission is hereby granted, free of charge, to any person obtaining a copy
+; of this file, to deal
+; in this file without restriction, including without limitation the rights
+; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of this file, and to permit persons to whom this file is
+; furnished to do so, subject to the following conditions:
+;
+; The above copyright notice and this permission notice shall be included in
+; all copies or substantial portions of this file.
+;
+; THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+; OUT OF OR IN CONNECTION WITH THIS FILE OR THE USE OR OTHER DEALINGS IN
+; THIS FILE.
+;--------------------------------------------------------------------------
+
+; ==== Strings ====
+
+[Strings]
+
+DeviceGUID = {247e32a0-32f9-11df-aacc-0002a5d5c51b}
+
+Date = "01/17/2012" ; MM/DD/YYYY
+libusb0ver = "1.2.6.0"
+
+Libusb_ClassName = "Argyll LibUSB-win32 devices"
+Libusb_DiskName = "LibUSB-win32 Device Install Disk"
+
+libusb0_SvcDesc = "LibUSB-win32 libusb0 - Kernel Driver 2012/1/17, 1.2.6.0"
+
+; ==== Version ====
+
+[Version]
+Signature = "$Windows NT$"
+DriverVer = %Date%,%libusb0ver%
+Provider = "ArgyllCMS"
+
+; (Note the ClassGuid must not be quoted or a string substitution to work on Win2K)
+Class = %Libusb_ClassName%
+ClassGuid = {817cffe0-328b-11df-9b9f-0002a5d5c51b} ; LibUSB-win32 ClassGUID
+CatalogFile = "ArgyllCMS.cat"
+CatalogFile.NTAMD64 = "ArgyllCMS_x64.cat"
+
+[ClassInstall32]
+AddReg=class_install_add_reg
+
+[class_install_add_reg]
+HKR,,,,%Libusb_ClassName%
+HKR,,Icon,,"-20" ; -20 is for the USB icon
+
+; ==== Files Sources and Destinations ====
+
+[SourceDisksNames]
+1 = %Libusb_DiskName%
+
+[SourceDisksFiles]
+libusb0.sys = 1,\bin\x86,
+
+[SourceDisksFiles.amd64]
+libusb0.sys = 1,\bin\amd64,
+
+[DestinationDirs]
+libusb0_files_sys = 10,system32\drivers
+
+; ==== libusb0 Device driver ====
+
+[libusb0_files_sys]
+libusb0.sys,libusb0.sys
+
+; For each one of these, there must be one for Services !!!
+[LIBUSB0_DEV]
+CopyFiles = Libusb0_files_sys
+
+[LIBUSB0_DEV.HW]
+AddReg = libusb0_add_reg_hw
+
+[libusb0_add_reg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,libusb0.sys
+
+[libusb0_add_reg_hw]
+HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID%
+HKR,,SurpriseRemovalOK,0x00010001,1 ; Device properties
+
+[LIBUSB0_DEV.Services]
+AddService = libusb0, 0x00000002, libusb0_add_service
+
+[libusb0_add_service]
+DisplayName = %libusb0_SvcDesc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 0
+ServiceBinary = %12%\libusb0.sys
+
+; ==== Manufacturers ====
+
+[Manufacturer]
+"HCFR Association"=HCFR_Devices,NTx86,NTamd64
+"Sequel Imaging"=Sequel_Devices,NTx86,NTamd64
+"X-Rite"=X_Rite_Devices,NTx86,NTamd64
+"ColorVision"=ColorVision_Devices,NTx86,NTamd64
+"Gretag Macbeth/X-Rite"=GM_X_Rite_Devices,NTx86,NTamd64
+"Hughski Ltd"=Hughski_Devices,NTx86,NTamd64
+
+; ==== Devices ====
+
+[HCFR_Devices]
+"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
+"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
+
+[Sequel_Devices]
+"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
+
+[X_Rite_Devices]
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
+"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
+"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
+"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
+"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
+"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
+
+[ColorVision_Devices]
+"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
+"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
+"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
+"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
+
+[GM_X_Rite_Devices]
+"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
+"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
+"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
+"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
+"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
+
+[Hughski_Devices]
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
+
+
+[HCFR_Devices.NTx86]
+"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
+"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
+
+[Sequel_Devices.NTx86]
+"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
+
+[X_Rite_Devices.NTx86]
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
+"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
+"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
+"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
+"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
+"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
+
+[ColorVision_Devices.NTx86]
+"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
+"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
+"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
+"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
+
+[GM_X_Rite_Devices.NTx86]
+"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
+"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
+"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
+"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
+"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
+
+[Hughski_Devices.NTx86]
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
+
+
+[HCFR_Devices.NTamd64]
+"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
+"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
+
+[Sequel_Devices.NTamd64]
+"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
+
+[X_Rite_Devices.NTamd64]
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
+"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
+"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
+"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
+"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
+"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
+
+[ColorVision_Devices.NTamd64]
+"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
+"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
+"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
+"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
+
+[GM_X_Rite_Devices.NTamd64]
+"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
+"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
+"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
+"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
+"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
+
+[Hughski_Devices.NTamd64]
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
+
diff --git a/usb/ArgyllCMS.inf.d b/usb/ArgyllCMS.inf.d
index cb7eb5d..7836493 100644
--- a/usb/ArgyllCMS.inf.d
+++ b/usb/ArgyllCMS.inf.d
@@ -1,34 +1,34 @@
-
-[HCFR_Devices#PLAT#]
-"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
-"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
-
-[Sequel_Devices#PLAT#]
-"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
-
-[X_Rite_Devices#PLAT#]
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
-"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
-"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
-"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
-"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
-"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
-"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
-
-[ColorVision_Devices#PLAT#]
-"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
-"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
-"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
-"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
-
-[GM_X_Rite_Devices#PLAT#]
-"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
-"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
-"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
-"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
-"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
-
-[Hughski_Devices#PLAT#]
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
-"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
-
+
+[HCFR_Devices#PLAT#]
+"Colorimtre HCFR V3.1 (Argyll)" = LIBUSB0_DEV, USB\VID_04DB&PID_005B
+"Colorimtre HCFR V4.0 (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_FE17
+
+[Sequel_Devices#PLAT#]
+"Eye-One Display 1 (Argyll)" = LIBUSB0_DEV, USB\VID_0670&PID_0001
+
+[X_Rite_Devices#PLAT#]
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5001
+"HueyL (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5010
+"Eye-One Display 3 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_5020
+"ColorMunki Smile (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_6003
+"DTP20 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D020
+"DTP92Q (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D092
+"DTP94 (Argyll)" = LIBUSB0_DEV, USB\VID_0765&PID_D094
+
+[ColorVision_Devices#PLAT#]
+"Spyder1 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0100
+"Spyder2 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0200
+"Spyder3 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0300
+"Spyder4 (Argyll)" = LIBUSB0_DEV, USB\VID_085C&PID_0400
+
+[GM_X_Rite_Devices#PLAT#]
+"Eye-One Pro (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2000
+"Eye-One Monitor (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2001
+"Eye-One Display 2 (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2003
+"Huey (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2005
+"ColorMunki (Argyll)" = LIBUSB0_DEV, USB\VID_0971&PID_2007
+
+[Hughski_Devices#PLAT#]
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_273F&PID_1001
+"ColorHug (Argyll)" = LIBUSB0_DEV, USB\VID_04D8&PID_F8DA
+
diff --git a/usb/ArgyllCMS.inf.t b/usb/ArgyllCMS.inf.t
index d810d4f..5721a3f 100644
--- a/usb/ArgyllCMS.inf.t
+++ b/usb/ArgyllCMS.inf.t
@@ -1,111 +1,111 @@
-;--------------------------------------------------------------------------
-; Copyright 2012 Graeme W. Gill.
-;
-; Permission is hereby granted, free of charge, to any person obtaining a copy
-; of this file, to deal
-; in this file without restriction, including without limitation the rights
-; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-; copies of this file, and to permit persons to whom this file is
-; furnished to do so, subject to the following conditions:
-;
-; The above copyright notice and this permission notice shall be included in
-; all copies or substantial portions of this file.
-;
-; THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-; OUT OF OR IN CONNECTION WITH THIS FILE OR THE USE OR OTHER DEALINGS IN
-; THIS FILE.
-;--------------------------------------------------------------------------
-
-; ==== Strings ====
-
-[Strings]
-
-DeviceGUID = {247e32a0-32f9-11df-aacc-0002a5d5c51b}
-
-Date = "01/17/2012" ; MM/DD/YYYY
-libusb0ver = "1.2.6.0"
-
-Libusb_ClassName = "Argyll LibUSB-win32 devices"
-Libusb_DiskName = "LibUSB-win32 Device Install Disk"
-
-libusb0_SvcDesc = "LibUSB-win32 libusb0 - Kernel Driver 2012/1/17, 1.2.6.0"
-
-; ==== Version ====
-
-[Version]
-Signature = "$Windows NT$"
-DriverVer = %Date%,%libusb0ver%
-Provider = "ArgyllCMS"
-
-; (Note the ClassGuid must not be quoted or a string substitution to work on Win2K)
-Class = %Libusb_ClassName%
-ClassGuid = {817cffe0-328b-11df-9b9f-0002a5d5c51b} ; LibUSB-win32 ClassGUID
-CatalogFile = "ArgyllCMS.cat"
-CatalogFile.NTAMD64 = "ArgyllCMS_x64.cat"
-
-[ClassInstall32]
-AddReg=class_install_add_reg
-
-[class_install_add_reg]
-HKR,,,,%Libusb_ClassName%
-HKR,,Icon,,"-20" ; -20 is for the USB icon
-
-; ==== Files Sources and Destinations ====
-
-[SourceDisksNames]
-1 = %Libusb_DiskName%
-
-[SourceDisksFiles]
-libusb0.sys = 1,\bin\x86,
-
-[SourceDisksFiles.amd64]
-libusb0.sys = 1,\bin\amd64,
-
-[DestinationDirs]
-libusb0_files_sys = 10,system32\drivers
-
-; ==== libusb0 Device driver ====
-
-[libusb0_files_sys]
-libusb0.sys,libusb0.sys
-
-; For each one of these, there must be one for Services !!!
-[LIBUSB0_DEV]
-CopyFiles = Libusb0_files_sys
-
-[LIBUSB0_DEV.HW]
-AddReg = libusb0_add_reg_hw
-
-[libusb0_add_reg]
-HKR,,DevLoader,,*ntkern
-HKR,,NTMPDriver,,libusb0.sys
-
-[libusb0_add_reg_hw]
-HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID%
-HKR,,SurpriseRemovalOK,0x00010001,1 ; Device properties
-
-[LIBUSB0_DEV.Services]
-AddService = libusb0, 0x00000002, libusb0_add_service
-
-[libusb0_add_service]
-DisplayName = %libusb0_SvcDesc%
-ServiceType = 1
-StartType = 3
-ErrorControl = 0
-ServiceBinary = %12%\libusb0.sys
-
-; ==== Manufacturers ====
-
-[Manufacturer]
-"HCFR Association"=HCFR_Devices,NTx86,NTamd64
-"Sequel Imaging"=Sequel_Devices,NTx86,NTamd64
-"X-Rite"=X_Rite_Devices,NTx86,NTamd64
-"ColorVision"=ColorVision_Devices,NTx86,NTamd64
-"Gretag Macbeth/X-Rite"=GM_X_Rite_Devices,NTx86,NTamd64
-"Hughski Ltd"=Hughski_Devices,NTx86,NTamd64
-
-; ==== Devices ====
+;--------------------------------------------------------------------------
+; Copyright 2012 Graeme W. Gill.
+;
+; Permission is hereby granted, free of charge, to any person obtaining a copy
+; of this file, to deal
+; in this file without restriction, including without limitation the rights
+; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+; copies of this file, and to permit persons to whom this file is
+; furnished to do so, subject to the following conditions:
+;
+; The above copyright notice and this permission notice shall be included in
+; all copies or substantial portions of this file.
+;
+; THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+; OUT OF OR IN CONNECTION WITH THIS FILE OR THE USE OR OTHER DEALINGS IN
+; THIS FILE.
+;--------------------------------------------------------------------------
+
+; ==== Strings ====
+
+[Strings]
+
+DeviceGUID = {247e32a0-32f9-11df-aacc-0002a5d5c51b}
+
+Date = "01/17/2012" ; MM/DD/YYYY
+libusb0ver = "1.2.6.0"
+
+Libusb_ClassName = "Argyll LibUSB-win32 devices"
+Libusb_DiskName = "LibUSB-win32 Device Install Disk"
+
+libusb0_SvcDesc = "LibUSB-win32 libusb0 - Kernel Driver 2012/1/17, 1.2.6.0"
+
+; ==== Version ====
+
+[Version]
+Signature = "$Windows NT$"
+DriverVer = %Date%,%libusb0ver%
+Provider = "ArgyllCMS"
+
+; (Note the ClassGuid must not be quoted or a string substitution to work on Win2K)
+Class = %Libusb_ClassName%
+ClassGuid = {817cffe0-328b-11df-9b9f-0002a5d5c51b} ; LibUSB-win32 ClassGUID
+CatalogFile = "ArgyllCMS.cat"
+CatalogFile.NTAMD64 = "ArgyllCMS_x64.cat"
+
+[ClassInstall32]
+AddReg=class_install_add_reg
+
+[class_install_add_reg]
+HKR,,,,%Libusb_ClassName%
+HKR,,Icon,,"-20" ; -20 is for the USB icon
+
+; ==== Files Sources and Destinations ====
+
+[SourceDisksNames]
+1 = %Libusb_DiskName%
+
+[SourceDisksFiles]
+libusb0.sys = 1,\bin\x86,
+
+[SourceDisksFiles.amd64]
+libusb0.sys = 1,\bin\amd64,
+
+[DestinationDirs]
+libusb0_files_sys = 10,system32\drivers
+
+; ==== libusb0 Device driver ====
+
+[libusb0_files_sys]
+libusb0.sys,libusb0.sys
+
+; For each one of these, there must be one for Services !!!
+[LIBUSB0_DEV]
+CopyFiles = Libusb0_files_sys
+
+[LIBUSB0_DEV.HW]
+AddReg = libusb0_add_reg_hw
+
+[libusb0_add_reg]
+HKR,,DevLoader,,*ntkern
+HKR,,NTMPDriver,,libusb0.sys
+
+[libusb0_add_reg_hw]
+HKR,,DeviceInterfaceGUIDs,0x10000,%DeviceGUID%
+HKR,,SurpriseRemovalOK,0x00010001,1 ; Device properties
+
+[LIBUSB0_DEV.Services]
+AddService = libusb0, 0x00000002, libusb0_add_service
+
+[libusb0_add_service]
+DisplayName = %libusb0_SvcDesc%
+ServiceType = 1
+StartType = 3
+ErrorControl = 0
+ServiceBinary = %12%\libusb0.sys
+
+; ==== Manufacturers ====
+
+[Manufacturer]
+"HCFR Association"=HCFR_Devices,NTx86,NTamd64
+"Sequel Imaging"=Sequel_Devices,NTx86,NTamd64
+"X-Rite"=X_Rite_Devices,NTx86,NTamd64
+"ColorVision"=ColorVision_Devices,NTx86,NTamd64
+"Gretag Macbeth/X-Rite"=GM_X_Rite_Devices,NTx86,NTamd64
+"Hughski Ltd"=Hughski_Devices,NTx86,NTamd64
+
+; ==== Devices ====
diff --git a/usb/ArgyllCMS_x64.cat b/usb/ArgyllCMS_x64.cat
index d401490..11d6f5f 100644
--- a/usb/ArgyllCMS_x64.cat
+++ b/usb/ArgyllCMS_x64.cat
Binary files differ
diff --git a/usb/Jamfile b/usb/Jamfile
index 403e3f2..8df0fba 100644
--- a/usb/Jamfile
+++ b/usb/Jamfile
@@ -42,6 +42,14 @@ if $(CREATE_INFS) = true {
GenFileNND ArgyllCMS.inf : "sed s/#PLAT#// $(_d) >> $(_i)" : ArgyllCMS.inf.t ArgyllCMS.inf.d ;
GenFileNND ArgyllCMS.inf : "sed s/#PLAT#/.NTx86/ $(_d) >> $(_i)" : ArgyllCMS.inf.t ArgyllCMS.inf.d ;
GenFileNND ArgyllCMS.inf : "sed s/#PLAT#/.NTamd64/ $(_d) >> $(_i)" : ArgyllCMS.inf.t ArgyllCMS.inf.d ;
+
+ # If we have the tools and the .inf file has changed,
+ # create valid (but unsigned) .cat files.
+ if $(NT) && [ GLOB $(PATH) : inf2cat.exe ] {
+ _b = [ NormPaths makecat.bat ] ;
+ # echo "SUBDIR = '" $(SUBDIR) "'" ;
+ GenFileNNDnc ArgyllCMS.cat : $(_b) $(SUBDIR) : ArgyllCMS.inf ;
+ }
}
diff --git a/usb/Readme.txt b/usb/Readme.txt
index 999db32..f8a1c2b 100644
--- a/usb/Readme.txt
+++ b/usb/Readme.txt
@@ -6,3 +6,6 @@ library that uses the device drivers.
The source to the kernel driver is here, but not built with
Argyll. The pre-built, signed drivers are used.
+The libusb-win32 .dll is not by ArgyllCMS.
+
+
diff --git a/usb/afiles b/usb/afiles
index fe1116b..4dbc3c1 100644
--- a/usb/afiles
+++ b/usb/afiles
@@ -4,6 +4,7 @@ binfiles.osx
binfiles.lx
Readme.txt
Jamfile
+makecat.bat
45-Argyll.rules
55-Argyll.rules
Argyll
diff --git a/usb/makecat.bat b/usb/makecat.bat
new file mode 100644
index 0000000..b6aa61e
--- /dev/null
+++ b/usb/makecat.bat
@@ -0,0 +1,13 @@
+rem Create plausible .cat files
+rem got directory %1
+cd %1
+rmdir /S /Q tmp
+mkdir tmp\bin\x86
+mkdir tmp\bin\amd64
+copy ArgyllCMS.inf tmp
+copy bin\libusb-win32-bin-README.txt tmp\bin
+copy bin\amd64\libusb0.sys tmp\bin\amd64\libusb0.sys
+copy bin\x86\libusb0.sys tmp\bin\x86\libusb0.sys
+inf2cat /v /driver:tmp /os:2000,XP_X86,Vista_X86,7_X86,XP_X64,Vista_X64,7_X64
+copy tmp\argyllcms.cat ArgyllCMS.cat
+copy tmp\argyllcms_x64.cat ArgyllCMS_x64.cat
diff --git a/xicc/cam02.c b/xicc/cam02.c
index 1ab6abc..3684a78 100644
--- a/xicc/cam02.c
+++ b/xicc/cam02.c
@@ -39,6 +39,21 @@
/* Note that all whites are assumed to be normalised (ie. Y = 1.0) */
/*
+ TTBD: Should convert to using Timo Kunkel and Erik Reinhard's simplified
+ and improved version of CIECAM02 (ie. "CIECAM02-KR").
+
+ The rgbp compression has it's problems in terms of perceptual
+ uniformity. A color with one component near zero might shift
+ all the components to -ve values on inverse conversion - ie.
+ a 1 DE shift in Jab becomes a masive DE in XYZ/Lab/perceptual,
+ with (say) a darl red becomong black because the blue
+ value is small. One way around this is to re-introduce
+ a flag to turn off perfect symetry by disabling
+ expansion on the reverse conversion.
+
+ */
+
+/*
Various additions and changes have been made to allow the CAM
conversions to and from an unbounded range of XYZ and Jab values,
in a (somewhat) geometrically consistent maner. This is because
@@ -106,6 +121,7 @@
#include "numlib.h"
#define ENABLE_COMPR /* [Def] Enable XYZ compression */
+#undef ENABLE_DECOMPR /* [Undef] Enable XYZ de-compression */
#define ENABLE_BLUE_ANGLE_FIX /* [Def] Limit maximum blue angle */
#define ENABLE_DDL /* [Def] Enable k1,k2,k3 overall ss limit values (seems to be the best scheme) */
#undef ENABLE_SS /* [Undef] Disable overall ss limit values (not the scheme used) */
@@ -123,10 +139,10 @@
#undef DISABLE_HHKR /* Debug - disable Helmholtz-Kohlraush */
#ifdef ENABLE_COMPR
-# define BC_WHMINY 0.3 /* [0.3] Compression direction minimum Y value */
-# define BC_RANGE_R 0.01 /* [0.01] Set compression range as prop. of distance to neutral - red */
-# define BC_RANGE_G 0.05 /* [0.05] Set compression range as prop. of distance to neutral - green*/
-# define BC_RANGE_B 0.10 /* [0.10] Set compression range as prop. of distance to neutral - blue */
+# define BC_WHMINY 0.2 /* [0.2] Compression direction minimum Y value */
+# define BC_RANGE_R 0.01 /* [0.02] Set comp. range as prop. of distance to neutral - red */
+# define BC_RANGE_G 0.01 /* [0.02] Set comp. range as prop. of distance to neutral - green*/
+# define BC_RANGE_B 0.01 /* [0.02] Set comp. range as prop. of distance to neutral - blue */
# define BC_MAXRANGE 0.13 /* [0.13] Maximum compression range */
# define BC_LIMIT 0.7 /* [0.7] Correction limit (abs. rgbp distance shift) */
#endif /* ENABLE_COMPR */
@@ -174,7 +190,7 @@ double minj = 1e38, maxj = -1e38;
static void cam_free(cam02 *s);
static int set_view(struct _cam02 *s, ViewingCondition Ev, double Wxyz[3],
- double La, double Yb, double Lv, double Yf, double Fxyz[3],
+ double La, double Yb, double Lv, double Yf, double Yg, double Gxyz[3],
int hk);
static int XYZ_to_cam(struct _cam02 *s, double *Jab, double *xyz);
static int cam_to_XYZ(struct _cam02 *s, double *xyz, double *Jab);
@@ -263,7 +279,9 @@ double Yb, /* Relative Luminance of Background to reference white (range 0.0 ..
double Lv, /* Luminance of white in the Viewing/Scene/Image field (cd/m^2) */
/* Ignored if Ev is set to other than vc_none */
double Yf, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
-double Fxyz[3], /* The Flare white coordinates (typically the Ambient color) */
+double Yg, /* Flare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+double Gxyz[3], /* The Glare white coordinates (typically the Ambient color) */
+ /* If <= 0 will Wxyz will be used. */
int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
) {
double tt, t1, t2;
@@ -271,7 +289,8 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
int i;
if (Ev == vc_none) {
- /* Compute the internal parameters by interpolation */
+ /* Compute the internal parameters from the */
+ /* ratio of La to Lv by interpolation */
int i;
double r, bf;
/* Dark, dim, average, above average */
@@ -302,26 +321,32 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
s->F = t_F[i] * (1.0 - bf) + t_F[i+1] * bf;
} else {
/* Compute the internal parameters by category */
+ /* Fake up Lv according to category */
switch(Ev) {
case vc_dark:
s->C = 0.525;
s->Nc = 0.8;
s->F = 0.8;
+ Lv = La/0.033;
break;
case vc_dim:
s->C = 0.59;
s->Nc = 0.95;
s->F = 0.9;
+ Lv = La/0.1;
+ break;
+ case vc_average:
+ default:
+ s->C = 0.69;
+ s->Nc = 1.0;
+ s->F = 1.0;
+ Lv = La/0.2;
break;
case vc_cut_sheet:
s->C = 0.41;
s->Nc = 0.8;
s->F = 0.8;
- break;
- default: /* average */
- s->C = 0.69;
- s->Nc = 1.0;
- s->F = 1.0;
+ Lv = La/0.02; // ???
break;
}
}
@@ -331,12 +356,21 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
s->Wxyz[0] = Wxyz[0];
s->Wxyz[1] = Wxyz[1];
s->Wxyz[2] = Wxyz[2];
- s->Yb = Yb > 0.005 ? Yb : 0.005; /* Set minimum to avoid divide by 0.0 */
s->La = La;
+ s->Yb = Yb > 0.005 ? Yb : 0.005; /* Set minimum to avoid divide by 0.0 */
+ s->Lv = Lv;
s->Yf = Yf;
- s->Fxyz[0] = Fxyz[0];
- s->Fxyz[1] = Fxyz[1];
- s->Fxyz[2] = Fxyz[2];
+ s->Yg = Yg;
+ if (Gxyz[0] > 0.0 && Gxyz[1] > 0.0 && Gxyz[2] > 0.0) {
+ tt = Wxyz[1]/Gxyz[1]; /* Scale to white ref white */
+ s->Gxyz[0] = tt * Gxyz[0];
+ s->Gxyz[1] = tt * Gxyz[1];
+ s->Gxyz[2] = tt * Gxyz[2];
+ } else {
+ s->Gxyz[0] = Wxyz[0];
+ s->Gxyz[1] = Wxyz[1];
+ s->Gxyz[2] = Wxyz[2];
+ }
s->hk = hk;
/* The rgba vectors */
@@ -365,10 +399,15 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
/* Compute values that only change with viewing parameters */
/* Figure out the Flare contribution to the flareless XYZ input */
- tt = s->Yf * s->Wxyz[1]/s->Fxyz[1];
- s->Fsxyz[0] = tt * s->Fxyz[0];
- s->Fsxyz[1] = tt * s->Fxyz[1];
- s->Fsxyz[2] = tt * s->Fxyz[2];
+ s->Fsxyz[0] = s->Yf * s->Wxyz[0];
+ s->Fsxyz[1] = s->Yf * s->Wxyz[1];
+ s->Fsxyz[2] = s->Yf * s->Wxyz[2];
+
+ /* Add in the Glare contribution from the ambient */
+ tt = s->Yg * s->La/s->Lv;
+ s->Fsxyz[0] += tt * s->Gxyz[0];
+ s->Fsxyz[1] += tt * s->Gxyz[1];
+ s->Fsxyz[2] += tt * s->Gxyz[2];
/* Rescale so that the sum of the flare and the input doesn't exceed white */
s->Fsc = s->Wxyz[1]/(s->Fsxyz[1] + s->Wxyz[1]);
@@ -522,7 +561,8 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
printf("Relative liminance of background Yb = %f\n", s->Yb);
printf("Adapting liminance La = %f\n", s->La);
printf("Flare Yf = %f\n", s->Yf);
- printf("Flare color Fxyz = %f %f %f\n", s->Fxyz[0], s->Fxyz[1], s->Fxyz[2]);
+ printf("Glare Yg = %f\n", s->Yg);
+ printf("Glare color Gxyz = %f %f %f\n", s->Gxyz[0], s->Gxyz[1], s->Gxyz[2]);
printf("Internal parameters:\n");
printf("Surround Impact C = %f\n", s->C);
@@ -569,7 +609,7 @@ double XYZ[3]
XYZi[2] = XYZ[2];
#endif
- TRACE(("\nForward conversion:\n"))
+ TRACE(("\nCIECAM02 Forward conversion:\n"))
TRACE(("XYZ = %f %f %f\n",XYZ[0], XYZ[1], XYZ[2]))
#ifdef DISABLE_MATRIX
@@ -622,7 +662,7 @@ double XYZ[3]
/* but compressing towards white seems to be the best.) */
icmSub3(cvec, wrgb, rgbp); /* Direction of white target */
- TRACE(("rgbp %f %f %f\n", rgbp[0], rgbp[1], rgbp[2]))
+ TRACE(("ch %d, rgbp %f %f %f\n", i, rgbp[0], rgbp[1], rgbp[2]))
TRACE(("cvec %f %f %f\n", cvec[0], cvec[1], cvec[2]))
if (cvec[i] < 1e-9) { /* compression direction can't correct this coord */
@@ -632,7 +672,7 @@ double XYZ[3]
/* Scale compression vector to make it move a unit in normal direction */
icmScale3(cvec, cvec, 1.0/cvec[i]); /* Normalized vector to white */
- TRACE(("cvec %f %f %f\n", cvec[0], cvec[1], cvec[2]))
+ TRACE(("ncvec %f %f %f\n", cvec[0], cvec[1], cvec[2]))
/* Compute intersection of correction direction with this limit plane */
/* (This corresponds with finding displacement of rgbp by cvec */
@@ -971,7 +1011,7 @@ double Jab[3]
#endif
- TRACE(("\nReverse conversion:\n"))
+ TRACE(("\nCIECAM02 Reverse conversion:\n"))
TRACE(("Jab %f %f %f\n",Jab[0], Jab[1], Jab[2]))
JJ = Jab[0] * 0.01; /* J/100 */
@@ -1153,7 +1193,7 @@ double Jab[3]
#endif
-#ifdef ENABLE_COMPR
+#ifdef ENABLE_DECOMPR
/* Undo soft limiting */
{
double tt; /* Temporary */
@@ -1181,7 +1221,7 @@ double Jab[3]
/* but compressing towards white seems to be the best.) */
icmSub3(cvec, wrgb, rgbp); /* Direction of white target */
- TRACE(("rgbp %f %f %f\n", rgbp[0], rgbp[1], rgbp[2]))
+ TRACE(("ch %d, rgbp %f %f %f\n", i, rgbp[0], rgbp[1], rgbp[2]))
TRACE(("cvec %f %f %f\n", cvec[0], cvec[1], cvec[2]))
if (cvec[i] < 1e-9) { /* compression direction can't correct this coord */
diff --git a/xicc/cam02.h b/xicc/cam02.h
index 9491572..a42e71f 100644
--- a/xicc/cam02.h
+++ b/xicc/cam02.h
@@ -6,10 +6,8 @@
* CIECAM02, "The CIECAM02 Color Appearance Model"
* by Nathan Moroney, Mark D. Fairchild, Robert W.G. Hunt, Changjun Li,
* M. Ronnier Luo and Todd Newman, IS&T/SID Tenth Color Imaging
- * Conference, with the addition of the Viewing Flare
- * model described on page 487 of "Digital Color Management",
- * by Edward Giorgianni and Thomas Madden, and the
- * Helmholtz-Kohlraush effect, using the equation
+ * Conference, with the addition of a Viewing Flare+Glare
+ * model, and the Helmholtz-Kohlraush effect, using the equation
* the Bradford-Hunt 96C model as detailed in Mark Fairchilds
* book "Color Appearance Models".
*
@@ -19,7 +17,7 @@
*
* This file is based on cam97s3.h by Graeme Gill.
*
- * Copyright 2004 - 2011 Graeme W. Gill
+ * Copyright 2004 - 2013 Graeme W. Gill
* Please refer to COPYRIGHT file for details.
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
* see the License.txt file for licencing details.
@@ -88,13 +86,18 @@
/* The Background relative luminance Yb is typically assumed to */
/* be 0.18 .. 0.2, and is assumed to be grey. */
-/* The source of flare light depends on the type of display system. */
-/* For a CRT, it will be the Ambient light reflecting off the glass surface. */
-/* (This implies Yf = Lamb * reflectance/Lv) */
-/* For a reflection print, it will be the Illuminant or Ambient reflecting from the media */
-/* surface. (Yf = Li * reflectance) */
-/* For a projected image, it will be stray projector light, scattered by the */
-/* surround, screen and air particles. (Yf = Li * reflectance_and_scattering) */
+/* Flare is assumed to be stray light from light parts of the */
+/* image illuminating dark parts of the image, and is display technology dependent. */
+/* In theory reflective systems have no Flare ? */
+
+/* Glare is assumed to be stray ambient light reflecting from the display */
+/* surface, dust, or entering the observers eye directly, and as a result */
+/* fogging the dark parts of the image. */
+/* This is typically the major source of veiling light ? */
+
+/* By separatedly specifiying these two, the effect can be automatically */
+/* scalled according to the ambient light level, modelling the effect of */
+/* reduced glare in a darkened viewing environment. */
/*
@@ -135,7 +138,9 @@ struct _cam02 {
double Lv, /* Luminance of white in the Viewing/Scene/Image field (cd/m^2) */
/* Ignored if Ev is set */
double Yf, /* Flare as a fraction of the reference white (range 0.0 .. 1.0) */
- double Fxyz[3], /* The Flare white coordinates (typically the Ambient color) */
+ double Yg, /* Glare as a fraction of the ambient (range 0.0 .. 1.0) */
+ double Gxyz[3], /* The Glare white coordinates (ie. the Ambient color) */
+ /* If <= 0 will Wxyz will be used. */
int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
);
@@ -146,11 +151,13 @@ struct _cam02 {
/* Private: */
/* Scene parameters */
ViewingCondition Ev; /* Enumerated Viewing Condition */
+ double Lv; /* Luminance of white in the Viewing/Image cd/m^2 */
double La; /* Adapting/Surround Luminance cd/m^2 */
double Wxyz[3]; /* Reference/Adapted White XYZ (Y range 0.0 .. 1.0) */
double Yb; /* Relative Luminance of Background to reference white (Y range 0.0 .. 1.0) */
double Yf; /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- double Fxyz[3]; /* The Flare white coordinates (typically the Ambient color) */
+ double Yg; /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ double Gxyz[3]; /* The Glare white coordinates (typically the Ambient color) */
/* Internal parameters */
double C; /* Surround Impact */
@@ -163,9 +170,9 @@ struct _cam02 {
double crange[3]; /* ENABLE_COMPR compression range */
double Va[3], Vb[3], VttA[3], Vttd[3]; /* rgba vectors */
double dcomp[3]; /* Vttd in terms of VttA, Va, Vb */
- double Fsc; /* Flare scale */
- double Fisc; /* Inverse flare scale */
- double Fsxyz[3]; /* Scaled Flare color coordinates */
+ double Fsc; /* Flare+Glare scale */
+ double Fisc; /* Inverse Flare+Glare scale */
+ double Fsxyz[3]; /* Scaled Flare+Glare color coordinates */
double rgbW[3]; /* Sharpened cone response white values */
double D; /* Degree of chromatic adaption */
double Drgb[3]; /* Chromatic transformation value */
diff --git a/xicc/cam02plot.c b/xicc/cam02plot.c
index ca68b52..f397e09 100644
--- a/xicc/cam02plot.c
+++ b/xicc/cam02plot.c
@@ -575,7 +575,8 @@ main(int argc, char *argv[]) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
0.00, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- white[4], /* The Flare color coordinates (typically the Ambient color) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ white[4], /* The Glare color coordinates (typically the Ambient color) */
use_hk /* use Helmholtz-Kohlraush flag */
);
@@ -592,7 +593,8 @@ main(int argc, char *argv[]) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
0.00, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- white[4], /* The Flare color coordinates (typically the Ambient color) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ white[4], /* The Glare color coordinates (typically the Ambient color) */
use_hk /* use Helmholtz-Kohlraush flag */
);
diff --git a/xicc/cam02ref.h b/xicc/cam02ref.h
index de75f6b..8965b7a 100644
--- a/xicc/cam02ref.h
+++ b/xicc/cam02ref.h
@@ -41,7 +41,8 @@ struct _cam02ref {
double Lv, /* Luminance of white in the Viewing/Scene/Image field (cd/m^2) */
/* Ignored if Ev is set */
double Yf, /* Flare as a fraction of the reference white (range 0.0 .. 1.0) */
- double Fxyz[3], /* The Flare white coordinates (typically the Ambient color) */
+ double Yg, /* Glare as a fraction of the ambient (range 0.0 .. 1.0) */
+ double Gxyz[3], /* The Glare white coordinates (typically the Ambient color) */
int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
);
@@ -51,9 +52,10 @@ struct _cam02ref {
/* Private: */
/* Scene parameters */
ViewingCondition Ev; /* Enumerated Viewing Condition */
+ double Lv; /* Luminance of white in the Viewing/Image cd/m^2 */
+ double La; /* Adapting/Surround Luminance cd/m^2 */
double Wxyz[3]; /* Reference/Adapted White XYZ (Y range 0.0 .. 1.0) */
double Yb; /* Relative Luminance of Background to reference white (Y range 0.0 .. 1.0) */
- double La; /* Adapting/Surround Luminance cd/m^2 */
double Yf; /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
double Fxyz[3]; /* The Flare white coordinates (typically the Ambient color) */
@@ -120,7 +122,7 @@ double Lv /* Luminence of white in the Viewing/Scene/Image field (cd/m^2) */
static void cam02ref_free(cam02ref *s);
static int cam02ref_set_view(cam02ref *s, ViewingCondition Ev, double Wxyz[3],
- double Yb, double La, double Lv, double Yf, double Fxyz[3], int hk);
+ double Yb, double La, double Lv, double Yf, double Yg, double Gxyz[3], int hk);
static int cam02ref_XYZ_to_cam(cam02ref *s, double *Jab, double *xyz);
static int cam02ref_cam_to_XYZ(cam02ref *s, double XYZ[3], double Jab[3]);
@@ -156,7 +158,8 @@ double Yb, /* Relative Luminence of Background to reference white */
double Lv, /* Luminence of white in the Viewing/Scene/Image field (cd/m^2) */
/* Ignored if Ev is set to other than vc_none */
double Yf, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
-double Fxyz[3], /* The Flare white coordinates (typically the Ambient color) */
+double Yg, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+double Gxyz[3], /* The Glare white coordinates (typically the Ambient color) */
int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
) {
double tt;
@@ -171,9 +174,16 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
s->Yb = Yb > 0.005 ? Yb : 0.005; /* Set minimum to avoid divide by 0.0 */
s->La = La;
s->Yf = Yf;
- s->Fxyz[0] = Fxyz[0];
- s->Fxyz[1] = Fxyz[1];
- s->Fxyz[2] = Fxyz[2];
+ if (Gxyz[0] > 0.0 && Gxyz[1] > 0.0 && Gxyz[2] > 0.0) {
+ tt = Wxyz[1]/Gxyz[1]; /* Scale to white ref white */
+ s->Gxyz[0] = tt * Gxyz[0];
+ s->Gxyz[1] = tt * Gxyz[1];
+ s->Gxyz[2] = tt * Gxyz[2];
+ } else {
+ s->Gxyz[0] = Wxyz[0];
+ s->Gxyz[1] = Wxyz[1];
+ s->Gxyz[2] = Wxyz[2];
+ }
s->hk = hk;
/* Compute the internal parameters by category */
@@ -182,38 +192,42 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
s->C = 0.525;
s->Nc = 0.8;
s->F = 0.8;
+ Lv = La/0.033;
break;
case vc_dim:
s->C = 0.59;
s->Nc = 0.95;
s->F = 0.9;
+ Lv = La/0.1;
break;
- case vc_cut_sheet:
- s->C = 0.41;
- s->Nc = 0.8;
- s->F = 0.8;
- break;
+ case vc_average:
default: /* average */
s->C = 0.69;
s->Nc = 1.0;
s->F = 1.0;
+ Lv = La/0.2;
+ break;
+ case vc_cut_sheet:
+ s->C = 0.41;
+ s->Nc = 0.8;
+ s->F = 0.8;
+ Lv = La/0.02; // ???
break;
}
+ s->Lv = Lv;
/* Compute values that only change with viewing parameters */
/* Figure out the Flare contribution to the flareless XYZ input */
- tt = s->Yf * s->Wxyz[1]/s->Fxyz[1];
- s->Fsxyz[0] = tt * s->Fxyz[0];
- s->Fsxyz[1] = tt * s->Fxyz[1];
- s->Fsxyz[2] = tt * s->Fxyz[2];
-
- /* Rescale so that the sum of the flare and the input doesn't exceed white */
- s->Fsc = s->Wxyz[1]/(s->Fsxyz[1] + s->Wxyz[1]);
- s->Fsxyz[0] *= s->Fsc;
- s->Fsxyz[1] *= s->Fsc;
- s->Fsxyz[2] *= s->Fsc;
- s->Fisc = 1.0/s->Fsc;
+ s->Fsxyz[0] = s->Yf * s->Wxyz[0];
+ s->Fsxyz[1] = s->Yf * s->Wxyz[1];
+ s->Fsxyz[2] = s->Yf * s->Wxyz[2];
+
+ /* Add in the Glare contribution from the ambient */
+ tt = s->Yg * s->La/s->Lv;
+ s->Fsxyz[0] += tt * s->Gxyz[0];
+ s->Fsxyz[1] += tt * s->Gxyz[1];
+ s->Fsxyz[2] += tt * s->Gxyz[2];
/* Sharpened cone response white values */
s->rgbW[0] = 0.7328 * s->Wxyz[0] + 0.4296 * s->Wxyz[1] - 0.1624 * s->Wxyz[2];
diff --git a/xicc/cam02test.c b/xicc/cam02test.c
index 3dafc9c..eba27d6 100644
--- a/xicc/cam02test.c
+++ b/xicc/cam02test.c
@@ -405,6 +405,7 @@ main(void) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
tFlair[c], /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
twhite[c], /* The Flare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -416,6 +417,7 @@ main(void) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
tFlair[c], /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
twhite[c], /* The Flare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -558,7 +560,8 @@ main(void) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
0.00, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- sp_white[c],/* The Flare color coordinates (typically the Ambient color) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ sp_white[c],/* The Glare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -570,7 +573,8 @@ main(void) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
0.00, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- sp_white[c],/* The Flare color coordinates (typically the Ambient color) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ sp_white[c],/* The Glare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -710,7 +714,8 @@ main(void) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
0.00, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- white[c], /* The Flare color coordinates (typically the Ambient color) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ white[c], /* The Glare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -722,7 +727,8 @@ main(void) {
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
0.00, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- white[c], /* The Flare color coordinates (typically the Ambient color) */
+ 0.00, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ white[c], /* The Glare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -941,8 +947,9 @@ main(void) {
34.0, /* Adapting/Surround Luminance cd/m^2 */
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
- 0.01, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- white[c], /* The Flare color coordinates (typically the Ambient color) */
+ 0.0, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
+ 0.0, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ white[c], /* The Glare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
@@ -1122,8 +1129,9 @@ main(void) {
34.0, /* Adapting/Surround Luminance cd/m^2 */
0.20, /* Relative Luminance of Background to reference white */
0.0, /* Luminance of white in image - not used */
- 0.01, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- white[c], /* The Flare color coordinates (typically the Ambient color) */
+ 0.0, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
+ 0.0, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ white[c], /* The Glare color coordinates (typically the Ambient color) */
USE_HK /* use Helmholtz-Kohlraush flag */
);
diff --git a/xicc/ccss.c b/xicc/ccss.c
index cd9b4e4..6b5ebeb 100644
--- a/xicc/ccss.c
+++ b/xicc/ccss.c
@@ -4,7 +4,7 @@
* Colorimeter Correction Matrix
*
* Author: Graeme W. Gill
- * Date: 1r9/8/2010
+ * Date: 9/8/2010
*
* Copyright 2010 Graeme W. Gill
* All rights reserved.
@@ -112,7 +112,11 @@ cgats **pocg /* return CGATS structure */
ocg->add_kword(ocg, 0, "SPECTRAL_NORM",buf, NULL);
/* Fields we want */
- ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t);
+ if (ocg->add_field(ocg, 0, "SAMPLE_ID", nqcs_t) < 0) {
+ sprintf(p->err, "cgats add_field SAMPLE_ID failed with '%s'!",ocg->err);
+ ocg->del(ocg); /* Clean up */
+ return 2;
+ }
nsetel += 1; /* For id */
/* Generate fields for spectral values */
@@ -124,7 +128,11 @@ cgats **pocg /* return CGATS structure */
* (p->samples[0].spec_wl_long - p->samples[0].spec_wl_short) + 0.5);
sprintf(buf,"SPEC_%03d",nm);
- ocg->add_field(ocg, 0, buf, r_t);
+ if (ocg->add_field(ocg, 0, buf, r_t) < 0) {
+ sprintf(p->err, "cgats add_field %s failed with '%s'",buf,ocg->err);
+ ocg->del(ocg); /* Clean up */
+ return 2;
+ }
}
nsetel += p->samples[0].spec_n; /* Spectral values */
diff --git a/xicc/iccgamut.c b/xicc/iccgamut.c
index 7bd3b4c..bb97f26 100644
--- a/xicc/iccgamut.c
+++ b/xicc/iccgamut.c
@@ -81,10 +81,11 @@ void usage(char *diag) {
fprintf(stderr," w:x:y Adapted white point as x, y\n");
fprintf(stderr," a:adaptation Adaptation luminance in cd.m^2 (default 50.0)\n");
fprintf(stderr," b:background Background %% of image luminance (default 20)\n");
- fprintf(stderr," l:scenewhite Scene white in cd.m^2 if surround = auto (default 250)\n");
- fprintf(stderr," f:flare Flare light %% of image luminance (default 1)\n");
- fprintf(stderr," f:X:Y:Z Flare color as XYZ (default media white)\n");
- fprintf(stderr," f:x:y Flare color as x, y\n");
+ fprintf(stderr," l:imagewhite Image white in cd.m^2 if surround = auto (default 250)\n");
+ fprintf(stderr," f:flare Flare light %% of image luminance (default 0)\n");
+ fprintf(stderr," g:glare Flare light %% of ambient (default 1)\n");
+ fprintf(stderr," g:X:Y:Z Flare color as XYZ (default media white, Abs: D50)\n");
+ fprintf(stderr," g:x:y Flare color as x, y\n");
fprintf(stderr," -s Create special cube surface topology plot\n");
fprintf(stderr,"\n");
exit(1);
@@ -93,8 +94,8 @@ void usage(char *diag) {
int
main(int argc, char *argv[]) {
int fa,nfa; /* argument we're looking at */
- char prof_name[100];
- char *xl, out_name[100];
+ char prof_name[MAXNAMEL+1];
+ char *xl, out_name[MAXNAMEL+4+1];
icmFile *fp;
icc *icco;
xicc *xicco;
@@ -119,8 +120,9 @@ main(int argc, char *argv[]) {
double vc_b = -1.0; /* Background % overide */
double vc_l = -1.0; /* Scene luminance override */
double vc_f = -1.0; /* Flare % overide */
- double vc_fXYZ[3] = {-1.0, -1.0, -1.0}; /* Flare color override in XYZ */
- double vc_fxy[2] = {-1.0, -1.0}; /* Flare color override in x,y */
+ double vc_g = -1.0; /* Glare % overide */
+ double vc_gXYZ[3] = {-1.0, -1.0, -1.0}; /* Glare color override in XYZ */
+ double vc_gxy[2] = {-1.0, -1.0}; /* Glare color override in x,y */
icxLuBase *luo;
@@ -328,18 +330,22 @@ main(int argc, char *argv[]) {
vc_b = atof(na+2);
} else if (na[0] == 'l' || na[0] == 'L') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]l) missing ':'");
+ usage("Viewing conditions (-cl) missing ':'");
vc_l = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ if (na[1] != ':')
+ usage("Viewing conditions (-cf) missing ':'");
+ vc_f = atof(na+2);
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc_fXYZ[0] = x; vc_fXYZ[1] = y; vc_fXYZ[2] = z;
+ vc_gXYZ[0] = x; vc_gXYZ[1] = y; vc_gXYZ[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc_fxy[0] = x; vc_fxy[1] = y;
+ vc_gxy[0] = x; vc_gxy[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
- vc_f = x;
+ vc_g = x;
} else
- usage("Unrecognised parameters after -cf");
+ usage("Unrecognised parameters after -cg");
} else
usage("Unrecognised parameters after -c");
}
@@ -357,7 +363,7 @@ main(int argc, char *argv[]) {
}
if (fa >= argc || argv[fa][0] == '-') usage("Expected profile name");
- strcpy(prof_name,argv[fa]);
+ strncpy(prof_name, argv[fa],MAXNAMEL); prof_name[MAXNAMEL] = '\000';
/* Open up the profile for reading */
if ((fp = new_icmFileStd_name(prof_name,"r")) == NULL)
@@ -431,17 +437,19 @@ main(int argc, char *argv[]) {
vc.Lv = vc_l;
if (vc_f >= 0.0)
vc.Yf = vc_f/100.0;
- if (vc_fXYZ[1] > 0.0) {
+ if (vc_g >= 0.0)
+ vc.Yg = vc_g/100.0;
+ if (vc_gXYZ[1] > 0.0) {
/* Normalise it to current media white */
- vc.Fxyz[0] = vc_fXYZ[0]/vc_fXYZ[1] * vc.Fxyz[1];
- vc.Fxyz[2] = vc_fXYZ[2]/vc_fXYZ[1] * vc.Fxyz[1];
+ vc.Gxyz[0] = vc_gXYZ[0]/vc_gXYZ[1] * vc.Gxyz[1];
+ vc.Gxyz[2] = vc_gXYZ[2]/vc_gXYZ[1] * vc.Gxyz[1];
}
- if (vc_fxy[0] >= 0.0) {
- double x = vc_fxy[0];
- double y = vc_fxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ if (vc_gxy[0] >= 0.0) {
+ double x = vc_gxy[0];
+ double y = vc_gxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc.Fxyz[0] = x/y * vc.Fxyz[1];
- vc.Fxyz[2] = z/y * vc.Fxyz[1];
+ vc.Gxyz[0] = x/y * vc.Gxyz[1];
+ vc.Gxyz[2] = z/y * vc.Gxyz[1];
}
fl |= ICX_CLIP_NEAREST; /* Don't setup rev uncessarily */
diff --git a/xicc/monctest.c b/xicc/monctest.c
index 29c9298..8630099 100644
--- a/xicc/monctest.c
+++ b/xicc/monctest.c
@@ -37,7 +37,8 @@ void usage(void);
#undef NORMONLY /* Defined to use 0.0 - 1.0 limited curve */
#undef ORDER_STEP /* Step orders from 2 to SHAPE_ORDERS */
-#define SHAPE_ORDS 30 /* Number of order to use */
+//#define SHAPE_ORDS 30 /* Number of order to use */
+#define SHAPE_ORDS 12 /* Number of order to use */
#define ABS_MAX_PNTS 100
@@ -169,7 +170,7 @@ int main() {
xa[i] = (xa[i]/xa[pnts-1]);
/* Create y values */
- ya[0] = xa[0] + d_rand(-0.1, 0.5);
+ ya[0] = xa[0] + d_rand(-0.2, 0.7);
for (i = 1; i < pnts; i++)
ya[i] = ya[i-1] + d_rand(0.1,1.0) + d_rand(-0.1,0.4) + d_rand(-0.4,0.5);
diff --git a/xicc/moncurve.c b/xicc/moncurve.c
index b904420..1769ce4 100644
--- a/xicc/moncurve.c
+++ b/xicc/moncurve.c
@@ -39,11 +39,10 @@
#undef TEST_PDE /* Ckeck partial derivative calcs */
-/* Normalization factors for an average data point error squared, scale 100 */
-#define HW01 0.002 /* 0 & 1 harmonic weights */
-#define HBREAK 4 /* Harmonic that has HWBR */
-#define HWBR 0.8 /* Base weight of harmonics HBREAK up */
-#define HWINC 0.5 /* Increase in weight for each harmonic above HWBR */
+#define HW01 0.01 /* 0 & 1 harmonic weights */
+#define HBREAK 3 /* Harmonic that has HWBR */
+#define HWBR 0.5 /* Base weight of harmonics HBREAK up */
+#define HWINC 0.7 /* Increase in weight for each harmonic above HWBR */
static void mcv_del(mcv *p);
static void mcv_fit(mcv *p, int verb, int order, mcvco *d, int ndp, double smooth);
@@ -550,7 +549,7 @@ double smooth) {
w = HW01;
} else if (cx <= HBREAK) {
double bl = (cx - 1.0)/(HBREAK - 1.0);
- w = (1.0 - bl) * HW01 + bl * HWBR;
+ w = (1.0 - bl) * HW01 + bl * HWBR * smooth;
} else {
w = HWBR + (cx-HBREAK) * HWINC * smooth;
}
@@ -653,7 +652,7 @@ double smooth) {
w = HW01;
} else if (cx <= HBREAK) { /* First or second curves */
double bl = (cx - 1.0)/(HBREAK - 1.0);
- w = (1.0 - bl) * HW01 + bl * HWBR;
+ w = (1.0 - bl) * HW01 + bl * HWBR * smooth;
} else {
w = HWBR + (cx-HBREAK) * HWINC * smooth;
}
diff --git a/xicc/mpp.h b/xicc/mpp.h
index 0becaad..826c4de 100644
--- a/xicc/mpp.h
+++ b/xicc/mpp.h
@@ -27,7 +27,7 @@
/* ------------------------------------------------------------------------------ */
#define MPP_MXINKS 8 /* Would like to be ICX_MXINKS but need more dynamic allocation */
-#define MPP_MXTCORD 10 /* Maxkimum shaper harmonic orders to use */
+#define MPP_MXTCORD 10 /* Maximum shaper harmonic orders to use */
#define MPP_MXCCOMB (1 << MPP_MXINKS) /* Maximum number of primary combinations */
#define MPP_MXPARMS (MPP_MXINKS * MPP_MXTCORD + (MPP_MXINKS * MPP_MXCCOMB/2) + MPP_MXCCOMB)
/* Maximum total parameters for a band */
diff --git a/xicc/mpplu.c b/xicc/mpplu.c
index dcbd1c3..a2bb9ad 100644
--- a/xicc/mpplu.c
+++ b/xicc/mpplu.c
@@ -348,7 +348,7 @@ main(int argc, char *argv[]) {
continue;
}
/* For each input number */
- for (bp = buf-1, nbp = buf, i = 0; i < MAX_CHAN; i++) {
+ for (nbp = buf, i = 0; i < MAX_CHAN; i++) {
bp = nbp;
in[i] = strtod(bp, &nbp);
if (nbp == bp)
@@ -468,7 +468,7 @@ main(int argc, char *argv[]) {
continue;
}
/* For each input number */
- for (bp = buf-1, nbp = buf, i = 0; i < MAX_CHAN; i++) {
+ for (nbp = buf, i = 0; i < MAX_CHAN; i++) {
bp = nbp;
in[i] = strtod(bp, &nbp);
if (nbp == bp)
diff --git a/xicc/revfix.c b/xicc/revfix.c
index 59fdd0e..ee9662a 100644
--- a/xicc/revfix.c
+++ b/xicc/revfix.c
@@ -747,14 +747,16 @@ main(int argc, char *argv[]) {
/* Use helper function to do the hard work. */
if (wo->set_tables(wo,
ICM_CLUT_SET_APXLS,
- &cb, /* Context */
- icSigLabData, /* Input color space */
- icSigCmykData, /* Output color space */
- Lab_Labp, /* Linear input transform Lab->Lab' */
- NULL, NULL, /* Use default Lab' range */
- Labp_CMYKp, /* Lab' -> CMYK' transfer function */
- NULL, NULL, /* Use default CMYK' range */
- CMYKp_CMYK) != 0) /* Output transfer function, CMYK'->CMYK (NULL = deflt) */
+ &cb, /* Context */
+ icSigLabData, /* Input color space */
+ icSigCmykData, /* Output color space */
+ Lab_Labp, /* Linear input transform Lab->Lab' */
+ NULL, NULL, /* Use default Lab' range */
+ Labp_CMYKp, /* Lab' -> CMYK' transfer function */
+ NULL, NULL, /* Use default CMYK' range */
+ CMYKp_CMYK, /* Output transfer function, CMYK'->CMYK */
+ NULL, NULL /* default APXLS range */
+ ) != 0)
error("Setting 16 bit Lab->CMYK Lut failed: %d, %s",icco->errc,icco->err);
if (verb)
diff --git a/xicc/specplot.c b/xicc/specplot.c
index b2baf05..8e52726 100644
--- a/xicc/specplot.c
+++ b/xicc/specplot.c
@@ -107,7 +107,7 @@ static int do_spec(
/* Compute XYZ of illuminant */
if (icx_ill_sp2XYZ(xyz, icxOT_CIE_1931_2, NULL, icxIT_custom, 0, &tsp) != 0)
- error ("icx_sp_temp2XYZ returned error");
+ warning("icx_sp_temp2XYZ returned error");
icmXYZ2Yxy(Yxy, xyz);
icmXYZ2Lab(&icmD50, Lab, xyz);
@@ -129,11 +129,11 @@ static int do_spec(
/* Compute CCT */
if ((cct = icx_XYZ2ill_ct(cct_xyz, BBTYPE, icxOT_CIE_1931_2, NULL, xyz, NULL, 0)) < 0)
- error ("Got bad cct\n");
+ warning("Got bad cct\n");
/* Compute VCT */
if ((vct = icx_XYZ2ill_ct(vct_xyz, BBTYPE, icxOT_CIE_1931_2, NULL, xyz, NULL, 1)) < 0)
- error ("Got bad vct\n");
+ warning("Got bad vct\n");
#ifdef PLANKIAN
printf("CCT = %f, VCT = %f\n",cct, vct);
diff --git a/xicc/tiffgamut.c b/xicc/tiffgamut.c
index e3e34e8..9423eae 100644
--- a/xicc/tiffgamut.c
+++ b/xicc/tiffgamut.c
@@ -88,10 +88,11 @@ void usage(void) {
fprintf(stderr," w:x:y Adapted white point as x, y\n");
fprintf(stderr," a:adaptation Adaptation luminance in cd.m^2 (default 50.0)\n");
fprintf(stderr," b:background Background %% of image luminance (default 20)\n");
- fprintf(stderr," l:scenewhite Scene white in cd.m^2 if surround = auto (default 250)\n");
- fprintf(stderr," f:flare Flare light %% of image luminance (default 1)\n");
- fprintf(stderr," f:X:Y:Z Flare color as XYZ (default media white)\n");
- fprintf(stderr," f:x:y Flare color as x, y\n");
+ fprintf(stderr," l:imagewhite Image white in cd.m^2 if surround = auto (default 250)\n");
+ fprintf(stderr," f:flare Flare light %% of image luminance (default 0)\n");
+ fprintf(stderr," g:glare Flare light %% of ambient (default 1)\n");
+ fprintf(stderr," g:X:Y:Z Flare color as XYZ (default media white, Abs: D50)\n");
+ fprintf(stderr," g:x:y Flare color as x, y\n");
fprintf(stderr," -O outputfile Override the default output filename.\n");
exit(1);
}
@@ -344,9 +345,10 @@ main(int argc, char *argv[]) {
double vc_a = -1.0; /* Adapted luminance */
double vc_b = -1.0; /* Background % overid */
double vc_l = -1.0; /* Scene luminance override */
- double vc_f = -1.0; /* Flare % overid */
- double vc_fXYZ[3] = {-1.0, -1.0, -1.0}; /* Flare color override in XYZ */
- double vc_fxy[2] = {-1.0, -1.0}; /* Flare color override in x,y */
+ double vc_f = -1.0; /* Flare % overide */
+ double vc_g = -1.0; /* Glare % overide */
+ double vc_gXYZ[3] = {-1.0, -1.0, -1.0}; /* Glare color override in XYZ */
+ double vc_gxy[2] = {-1.0, -1.0}; /* Glare color override in x,y */
icxLuBase *luo = NULL; /* Generic lookup object */
icColorSpaceSignature ins = icSigLabData, outs; /* Type of input and output spaces */
int inn, outn; /* Number of components */
@@ -528,13 +530,17 @@ main(int argc, char *argv[]) {
usage();
vc_l = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ if (na[1] != ':')
+ usage();
+ vc_f = atof(na+2);
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc_fXYZ[0] = x; vc_fXYZ[1] = y; vc_fXYZ[2] = z;
+ vc_gXYZ[0] = x; vc_gXYZ[1] = y; vc_gXYZ[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc_fxy[0] = x; vc_fxy[1] = y;
+ vc_gxy[0] = x; vc_gxy[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
- vc_f = x;
+ vc_g = x;
} else
usage();
} else
@@ -666,19 +672,22 @@ main(int argc, char *argv[]) {
vc.Yb = vc_b/100.0;
if (vc_l >= 0.0)
vc.Lv = vc_l;
+
if (vc_f >= 0.0)
vc.Yf = vc_f/100.0;
- if (vc_fXYZ[1] > 0.0) {
+ if (vc_g >= 0.0)
+ vc.Yg = vc_g/100.0;
+ if (vc_gXYZ[1] > 0.0) {
/* Normalise it to current media white */
- vc.Fxyz[0] = vc_fXYZ[0]/vc_fXYZ[1] * vc.Fxyz[1];
- vc.Fxyz[2] = vc_fXYZ[2]/vc_fXYZ[1] * vc.Fxyz[1];
+ vc.Gxyz[0] = vc_gXYZ[0]/vc_gXYZ[1] * vc.Gxyz[1];
+ vc.Gxyz[2] = vc_gXYZ[2]/vc_gXYZ[1] * vc.Gxyz[1];
}
- if (vc_fxy[0] >= 0.0) {
- double x = vc_fxy[0];
- double y = vc_fxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ if (vc_gxy[0] >= 0.0) {
+ double x = vc_gxy[0];
+ double y = vc_gxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc.Fxyz[0] = x/y * vc.Fxyz[1];
- vc.Fxyz[2] = z/y * vc.Fxyz[1];
+ vc.Gxyz[0] = x/y * vc.Gxyz[1];
+ vc.Gxyz[2] = z/y * vc.Gxyz[1];
}
/* Get a expanded color conversion object */
@@ -726,23 +735,25 @@ main(int argc, char *argv[]) {
vc.Yb = vc_b/100.0;
if (vc_f >= 0.0)
vc.Yf = vc_f/100.0;
- if (vc_fXYZ[1] > 0.0) {
+ if (vc_g >= 0.0)
+ vc.Yg = vc_g/100.0;
+ if (vc_gXYZ[1] > 0.0) {
/* Normalise it to current media white */
- vc.Fxyz[0] = vc_fXYZ[0]/vc_fXYZ[1] * vc.Fxyz[1];
- vc.Fxyz[2] = vc_fXYZ[2]/vc_fXYZ[1] * vc.Fxyz[1];
+ vc.Gxyz[0] = vc_gXYZ[0]/vc_gXYZ[1] * vc.Gxyz[1];
+ vc.Gxyz[2] = vc_gXYZ[2]/vc_gXYZ[1] * vc.Gxyz[1];
}
- if (vc_fxy[0] >= 0.0) {
- double x = vc_fxy[0];
- double y = vc_fxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ if (vc_gxy[0] >= 0.0) {
+ double x = vc_gxy[0];
+ double y = vc_gxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc.Fxyz[0] = x/y * vc.Fxyz[1];
- vc.Fxyz[2] = z/y * vc.Fxyz[1];
+ vc.Gxyz[0] = x/y * vc.Gxyz[1];
+ vc.Gxyz[2] = z/y * vc.Gxyz[1];
}
if ((cam = new_icxcam(cam_default)) == NULL)
error("new_icxcam failed");
- cam->set_view(cam, vc.Ev, vc.Wxyz, vc.La, vc.Yb, vc.Lv, vc.Yf, vc.Fxyz,
+ cam->set_view(cam, vc.Ev, vc.Wxyz, vc.La, vc.Yb, vc.Lv, vc.Yf, vc.Yg, vc.Gxyz,
XICC_USE_HK);
}
diff --git a/xicc/tiffgmts.c b/xicc/tiffgmts.c
index 9d21d36..03f6363 100644
--- a/xicc/tiffgmts.c
+++ b/xicc/tiffgmts.c
@@ -75,9 +75,10 @@ void usage(void) {
fprintf(stderr," w:x:y Adapted white point as x, y\n");
fprintf(stderr," a:adaptation Adaptation luminance in cd.m^2 (default 50.0)\n");
fprintf(stderr," b:background Background %% of image luminance (default 20)\n");
- fprintf(stderr," f:flare Flare light %% of image luminance (default 1)\n");
- fprintf(stderr," f:X:Y:Z Flare color as XYZ (default media white)\n");
- fprintf(stderr," f:x:y Flare color as x, y\n");
+ fprintf(stderr," f:flare Flare light %% of image luminance (default 0)\n");
+ fprintf(stderr," g:glare Flare light %% of ambient (default 1)\n");
+ fprintf(stderr," g:X:Y:Z Flare color as XYZ (default media white, Abs: D50)\n");
+ fprintf(stderr," g:x:y Flare color as x, y\n");
fprintf(stderr," -V L,a,b Overide normal vector direction for span\n");
fprintf(stderr," -O outputfile Override the default output filename (locus.ts)\n");
fprintf(stderr," infile.tif File to create test value from\n");
@@ -294,9 +295,10 @@ main(int argc, char *argv[]) {
double vc_wxy[2] = {-1.0, -1.0}; /* Adapted white override in x,y */
double vc_a = -1.0; /* Adapted luminance */
double vc_b = -1.0; /* Background % overid */
- double vc_f = -1.0; /* Flare % overid */
- double vc_fXYZ[3] = {-1.0, -1.0, -1.0}; /* Flare color override in XYZ */
- double vc_fxy[2] = {-1.0, -1.0}; /* Flare color override in x,y */
+ double vc_f = -1.0; /* Flare % overide */
+ double vc_g = -1.0; /* Glare % overide */
+ double vc_gXYZ[3] = {-1.0, -1.0, -1.0}; /* Glare color override in XYZ */
+ double vc_gxy[2] = {-1.0, -1.0}; /* Glare color override in x,y */
icxLuBase *luo = NULL; /* Generic lookup object */
icColorSpaceSignature ins = icSigLabData, outs; /* Type of input and output spaces */
int inn, outn; /* Number of components */
@@ -466,13 +468,16 @@ main(int argc, char *argv[]) {
usage();
vc_b = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ vc_f = atof(na+2);
+ usage();
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc_fXYZ[0] = x; vc_fXYZ[1] = y; vc_fXYZ[2] = z;
+ vc_gXYZ[0] = x; vc_gXYZ[1] = y; vc_gXYZ[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc_fxy[0] = x; vc_fxy[1] = y;
+ vc_gxy[0] = x; vc_gxy[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
- vc_f = x;
+ vc_g = x;
} else
usage();
} else
@@ -585,17 +590,19 @@ main(int argc, char *argv[]) {
vc.Yb = vc_b/100.0;
if (vc_f >= 0.0)
vc.Yf = vc_f/100.0;
- if (vc_fXYZ[1] > 0.0) {
+ if (vc_g >= 0.0)
+ vc.Yg = vc_g/100.0;
+ if (vc_gXYZ[1] > 0.0) {
/* Normalise it to current media white */
- vc.Fxyz[0] = vc_fXYZ[0]/vc_fXYZ[1] * vc.Fxyz[1];
- vc.Fxyz[2] = vc_fXYZ[2]/vc_fXYZ[1] * vc.Fxyz[1];
+ vc.Gxyz[0] = vc_gXYZ[0]/vc_gXYZ[1] * vc.Gxyz[1];
+ vc.Gxyz[2] = vc_gXYZ[2]/vc_gXYZ[1] * vc.Gxyz[1];
}
- if (vc_fxy[0] >= 0.0) {
- double x = vc_fxy[0];
- double y = vc_fxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ if (vc_gxy[0] >= 0.0) {
+ double x = vc_gxy[0];
+ double y = vc_gxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
double z = 1.0 - x - y;
- vc.Fxyz[0] = x/y * vc.Fxyz[1];
- vc.Fxyz[2] = z/y * vc.Fxyz[1];
+ vc.Gxyz[0] = x/y * vc.Gxyz[1];
+ vc.Gxyz[2] = z/y * vc.Gxyz[1];
}
/* Get a expanded color conversion object */
diff --git a/xicc/transplot.c b/xicc/transplot.c
index e196544..d4600d9 100644
--- a/xicc/transplot.c
+++ b/xicc/transplot.c
@@ -1,7 +1,7 @@
/*
* International Color Consortium Format Library (icclib)
- * Check various aspects of CMYK device link,
+ * Check various aspects of RGB or CMYK device link,
* and RGB/CMYK profile transfer characteristics.
*
* Author: Graeme W. Gill
@@ -35,6 +35,10 @@ void usage(void) {
fprintf(stderr,"Author: Graeme W. Gill\n");
fprintf(stderr,"usage: transplot [-v] infile\n");
fprintf(stderr," -v verbose\n");
+ fprintf(stderr," -i intent p = perceptual, r = relative colorimetric,\n");
+ fprintf(stderr," s = saturation, a = absolute\n");
+ fprintf(stderr," -o order n = normal (priority: lut > matrix > monochrome)\n");
+ fprintf(stderr," r = reverse (priority: monochrome > matrix > lut)\n");
fprintf(stderr," -c -m -y -k Check Cyan and/or Magenta and/or Yellow and/or Black input\n");
fprintf(stderr," -r -g -b Check Red and/or Green and/or Blue input\n");
fprintf(stderr," -L -A -B Check L and/or a* and/or b* input\n");
@@ -57,6 +61,10 @@ main(
icc *rd_icco; /* Keep object separate */
int rv = 0;
+ /* Lookup parameters */
+ icRenderingIntent intent = icmDefaultIntent; /* Default */
+ icmLookupOrder order = icmLuOrdNorm; /* Default */
+
/* Check variables */
icmLuBase *luo;
icmLuLut *luluto; /* Lookup xLut type object */
@@ -94,6 +102,54 @@ main(
if (argv[fa][1] == 'v' || argv[fa][1] == 'V') {
verb = 1;
}
+
+ /* Intent */
+ else if (argv[fa][1] == 'i' || argv[fa][1] == 'I') {
+ fa = nfa;
+ if (na == NULL) usage();
+ switch (na[0]) {
+ case 'p':
+ intent = icPerceptual;
+ break;
+ case 'r':
+ intent = icRelativeColorimetric;
+ break;
+ case 's':
+ intent = icSaturation;
+ break;
+ case 'a':
+ intent = icAbsoluteColorimetric;
+ break;
+ /* Special function icclib intents */
+ case 'P':
+ intent = icmAbsolutePerceptual;
+ break;
+ case 'S':
+ intent = icmAbsoluteSaturation;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ /* Search order */
+ else if (argv[fa][1] == 'o' || argv[fa][1] == 'O') {
+ fa = nfa;
+ if (na == NULL) usage();
+ switch (na[0]) {
+ case 'n':
+ case 'N':
+ order = icmLuOrdNorm;
+ break;
+ case 'r':
+ case 'R':
+ order = icmLuOrdRev;
+ break;
+ default:
+ usage();
+ }
+ }
+
/* Cyan, Red */
else if (argv[fa][1] == 'c' || argv[fa][1] == 'C'
|| argv[fa][1] == 'r' || argv[fa][1] == 'R') {
@@ -153,12 +209,12 @@ main(
if (labin) {
/* Get a Device to PCS conversion object */
- if ((luo = rd_icco->get_luobj(rd_icco, icmBwd, icmDefaultIntent, icSigLabData, icmLuOrdNorm)) == NULL)
+ if ((luo = rd_icco->get_luobj(rd_icco, icmBwd, intent, icSigLabData, order)) == NULL)
error ("%d, %s",rd_icco->errc, rd_icco->err);
} else {
/* Get a PCS to Device conversion object */
- if ((luo = rd_icco->get_luobj(rd_icco, icmFwd, icmDefaultIntent, icSigLabData, icmLuOrdNorm)) == NULL) {
- if ((luo = rd_icco->get_luobj(rd_icco, icmFwd, icmDefaultIntent, icmSigDefaultData, icmLuOrdNorm)) == NULL) {
+ if ((luo = rd_icco->get_luobj(rd_icco, icmFwd, intent, icSigLabData, order)) == NULL) {
+ if ((luo = rd_icco->get_luobj(rd_icco, icmFwd, intent, icmSigDefaultData, order)) == NULL) {
error ("%d, %s",rd_icco->errc, rd_icco->err);
}
}
@@ -188,8 +244,8 @@ main(
chans[3] = 0;
}
- if (outs != icSigCmykData && outs != icSigLabData) {
- error("Expecting Lab or CMYK output space");
+ if (outs != icSigCmykData && outs != icSigLabData && outs != icSigRgbData) {
+ error("Expecting Lab or CMYK or RGB output space");
}
if (outs == icSigLabData)
diff --git a/xicc/xcal.c b/xicc/xcal.c
index 97a3086..06d343c 100644
--- a/xicc/xcal.c
+++ b/xicc/xcal.c
@@ -110,6 +110,12 @@ static int xcal_read_cgats(xcal *p, cgats *tcg, int table, char *filename) {
p->noramdac = 1;
}
+ if ((ti = tcg->find_kword(tcg, table, "TV_OUTPUT_ENCODING")) >= 0) {
+ if (strcmp(tcg->t[0].kdata[ti], "YES") == 0
+ || strcmp(tcg->t[0].kdata[ti], "yes") == 0)
+ p->tvenc = 1;
+ }
+
p->colspace = icx_colorant_comb_to_icc(p->devmask); /* 0 if none */
p->devchan = icx_noofinks(p->devmask);
ident = icx_inkmask2char(p->devmask, 1);
@@ -190,6 +196,90 @@ static int xcal_read_cgats(xcal *p, cgats *tcg, int table, char *filename) {
return 0;
}
+/* Read a calibration file from an ICC vcgt tag */
+/* Return nz if this fails */
+int xcal_read_icc(xcal *p, icc *c) {
+ icmVideoCardGamma *vg;
+ icmTextDescription *td;
+ int res, i, j;
+
+ /* See if there is a vcgt tag */
+ if ((vg = (icmVideoCardGamma *)c->read_tag(c, icSigVideoCardGammaTag)) == NULL) {
+ sprintf(p->err, "ICC profile has no vcgt");
+ return p->errc = 1;
+ }
+
+ /* What sort of device the profile is for */
+ p->devclass = c->header->deviceClass;
+ p->colspace = c->header->colorSpace;
+
+ if ((p->devmask = icx_icc_to_colorant_comb(p->colspace, p->devclass)) == 0) {
+ sprintf(p->err, "Unable to determine inkmask from ICC profile");
+ return p->errc = 1;
+ }
+ p->devchan = icx_noofinks(p->devmask);
+
+ /* Grab any descriptive information */
+ if ((td = (icmTextDescription *)c->read_tag(c, icSigDeviceMfgDescTag)) != NULL) {
+ p->xpi.deviceMfgDesc = strdup(td->desc);
+ }
+ if ((td = (icmTextDescription *)c->read_tag(c, icSigDeviceModelDescTag)) != NULL) {
+ p->xpi.modelDesc = strdup(td->desc);
+ }
+ if ((td = (icmTextDescription *)c->read_tag(c, icSigProfileDescriptionTag)) != NULL) {
+ p->xpi.profDesc = strdup(td->desc);
+ }
+ if ((td = (icmTextDescription *)c->read_tag(c, icSigCopyrightTag)) != NULL) {
+ p->xpi.copyright = strdup(td->desc);
+ }
+
+ /* Decide the lut resolution */
+ if (vg->tagType == icmVideoCardGammaFormulaType)
+ res = 2048;
+ else
+ res = vg->u.table.entryCount;
+
+ /* Read in each channels values and put them in a rspl */
+ for (j = 0; j < p->devchan; j++) {
+ datai low,high;
+ int gres[MXDI];
+ double smooth = 1.0;
+ co *dpoints;
+
+ low[0] = 0.0;
+ high[0] = 1.0;
+ gres[0] = res;
+
+ if ((p->cals[j] = new_rspl(RSPL_NOFLAGS,1, 1)) == NULL) {
+ sprintf(p->err,"new_rspl() failed");
+ return p->errc = 2;
+ }
+
+ if ((dpoints = malloc(sizeof(co) * gres[0])) == NULL) {
+ sprintf(p->err,"malloc dpoints[%d] failed",gres[0]);
+ return p->errc = 2;
+ }
+
+ /* Copy the points to our array */
+ for (i = 0; i < gres[0]; i++) {
+ dpoints[i].p[0] = i/(double)(gres[0]-1);
+ dpoints[i].v[0] = vg->lookup(vg, j, dpoints[i].p[0]);
+ }
+
+ /* Set the rspl */
+ p->cals[j]->set_rspl(p->cals[j],
+ 0,
+ (void *)dpoints, /* Read points */
+ xcal_rsplset, /* Setting function */
+ low, high, gres, /* Low, high, resolution of grid */
+ NULL, NULL /* Default data scale */
+ );
+ free(dpoints);
+ }
+
+ return 0;
+}
+
/* Read a calibration file */
/* Return nz if this fails */
static int xcal_read(xcal *p, char *filename) {
@@ -258,6 +348,13 @@ static int xcal_write_cgats(xcal *p, cgats *tcg) {
bident = icx_inkmask2char(p->devmask, 0);
tcg->add_kword(tcg, table, "COLOR_REP", ident, NULL);
+ /* Other tags */
+ if (p->noramdac)
+ tcg->add_kword(tcg, table, "VIDEO_LUT_CALIBRATION_POSSIBLE", "NO", NULL);
+
+ if (p->tvenc)
+ tcg->add_kword(tcg, table, "TV_OUTPUT_ENCODING", "YES", NULL);
+
/* Grab any descriptive information */
if (p->xpi.deviceMfgDesc != NULL)
tcg->add_kword(tcg, table, "MANUFACTURER",p->xpi.deviceMfgDesc, NULL);
@@ -483,6 +580,7 @@ xcal *new_xcal(void) {
/* Init method pointers */
p->del = xcal_del;
p->read_cgats = xcal_read_cgats;
+ p->read_icc = xcal_read_icc;
p->read = xcal_read;
p->write_cgats = xcal_write_cgats;
p->write = xcal_write;
diff --git a/xicc/xcal.h b/xicc/xcal.h
index 99f1c9c..f7c3fa9 100644
--- a/xicc/xcal.h
+++ b/xicc/xcal.h
@@ -29,6 +29,10 @@ struct _xcal {
/* Return nz if this fails (filename is for error messages) */
int (*read_cgats) (struct _xcal *p, cgats *cg, int table, char *filename);
+ /* Read a calibration file from an ICC vcgt tag */
+ /* Return nz if this fails */
+ int (*read_icc) (struct _xcal *p, icc *c);
+
/* Read a calibration file */
/* Return nz if this fails */
int (*read) (struct _xcal *p, char *filename);
@@ -41,7 +45,7 @@ struct _xcal {
/* Return nz if this fails */
int (*write)(struct _xcal *p, char *filename);
- /* Translate values through the curves curves. */
+ /* Translate values through the curves. */
void (*interp) (struct _xcal *p, double *out, double *in);
/* Translate a value backwards through the curves. */
@@ -56,6 +60,7 @@ struct _xcal {
double (*inv_interp_ch) (struct _xcal *p, int ch, double in);
int noramdac; /* Set to nz if there was no VideoLUT access */
+ int tvenc; /* nz if this cal was created using (16-235)/255 Video encoding */
/* Private: */
icProfileClassSignature devclass; /* Type of device */
diff --git a/xicc/xcam.c b/xicc/xcam.c
index 99f3c67..8e1a0cd 100644
--- a/xicc/xcam.c
+++ b/xicc/xcam.c
@@ -23,7 +23,7 @@
static void icx_cam_free(icxcam *s);
static int icx_set_view(icxcam *s, ViewingCondition Ev, double Wxyz[3],
- double La, double Yb, double Lv, double Yf, double Fxyz[3],
+ double La, double Yb, double Lv, double Yf, double Yg, double Gxyz[3],
int hk);
static int icx_XYZ_to_cam(struct _icxcam *s, double Jab[3], double XYZ[3]);
static int icx_cam_to_XYZ(struct _icxcam *s, double XYZ[3], double Jab[3]);
@@ -61,8 +61,8 @@ icxcam *new_icxcam(icxCAM which) {
}
/* Initialise methods */
- s->del = icx_cam_free;
- s->set_view = icx_set_view;
+ s->del = icx_cam_free;
+ s->set_view = icx_set_view;
s->XYZ_to_cam = icx_XYZ_to_cam;
s->cam_to_XYZ = icx_cam_to_XYZ;
s->settrace = settrace;
@@ -126,7 +126,8 @@ double Yb, /* Relative Luminance of Background to reference white */
double Lv, /* Luminance of white in the Viewing/Scene/Image field (cd/m^2) */
/* Ignored if Ev is set to other than vc_none */
double Yf, /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
-double Fxyz[3], /* The Flare white coordinates (typically the Ambient color) */
+double Yg, /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+double Gxyz[3], /* The Glare white coordinates (typically the Ambient color) */
int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
) {
s->Wxyz[0] = Wxyz[0];
@@ -136,11 +137,11 @@ int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
switch(s->tag) {
case cam_CIECAM97s3: {
cam97s3 *pp = (cam97s3 *)s->p;
- return pp->set_view(pp, Ev, Wxyz, La, Yb, Lv, Yf, Fxyz, hk);
+ return pp->set_view(pp, Ev, Wxyz, La, Yb, Lv, 0.2 * Yg, Gxyz, hk);
}
case cam_CIECAM02: {
cam02 *pp = (cam02 *)s->p;
- return pp->set_view(pp, Ev, Wxyz, La, Yb, Lv, Yf, Fxyz, hk);
+ return pp->set_view(pp, Ev, Wxyz, La, Yb, Lv, Yf, Yg, Gxyz, hk);
}
default:
break;
diff --git a/xicc/xcam.h b/xicc/xcam.h
index d4f4857..7ec6949 100644
--- a/xicc/xcam.h
+++ b/xicc/xcam.h
@@ -49,7 +49,8 @@ struct _icxcam {
double Lv, /* Luminance of white in the Viewing/Scene/Image field (cd/m^2) */
/* Ignored if Ev is set */
double Yf, /* Flare as a fraction of the reference white (range 0.0 .. 1.0) */
- double Fxyz[3], /* The Flare white coordinates (typically the Ambient color) */
+ double Yg, /* Glare as a fraction of the ambient (range 0.0 .. 1.0) */
+ double Gxyz[3], /* The Glare white coordinates (typically the Ambient color) */
int hk /* Flag, NZ to use Helmholtz-Kohlraush effect */
);
diff --git a/xicc/xcolorantslu.c b/xicc/xcolorantslu.c
index 6c537dc..601c4bd 100644
--- a/xicc/xcolorantslu.c
+++ b/xicc/xcolorantslu.c
@@ -153,7 +153,7 @@ main(int argc, char *argv[]) {
continue;
}
/* For each input number */
- for (bp = buf-1, nbp = buf, i = 0; i < MAX_CHAN; i++) {
+ for (nbp = buf, i = 0; i < MAX_CHAN; i++) {
bp = nbp;
in[i] = strtod(bp, &nbp);
if (nbp == bp)
diff --git a/xicc/xfit.c b/xicc/xfit.c
index 50916b3..d0912f9 100644
--- a/xicc/xfit.c
+++ b/xicc/xfit.c
@@ -21,8 +21,9 @@
* Need to use this for B2A tables rather than inverting
* A2B curves. Need to add grid sizing to cover just gamut range
* (including level axis gamut, but watch out for devices that
- * have values below the black point), 3x3 matrix optimization,
- * and white point to grid node mapping for B2A.
+ * have values below the black point or above the white point),
+ * 3x3 matrix optimization, and white point to grid node mapping for B2A.
+ * Currently code assumes output is always PCS ?? - would need to fix for opposite.
*
* Currently the Lab A2B output tables are adjusted for ab symetry
* to make the B2A white point land on a grid point, given that
@@ -78,6 +79,9 @@
#include "xfit.h"
#include "sort.h"
+#undef USE_XYZ_Y2LCURVE /* [Und] Use underlying L* curve for XYZ encoding */
+ /* This seems to work badly, even with high smoothness. Why ? */
+ /* It does speed up 1D lut creation though. */
#undef DEBUG /* Verbose debug information */
#undef DEBUG_PLOT /* Plot in & out curves */
@@ -110,6 +114,104 @@
#define PSHAPE_MINE 0.02 /* Minum background residual error level */
#define PSHAPE_DIST 1.0 /* Agressivness of grid distribution */
+
+/* - - - - - - - - - - - - - - - - - */
+
+/* Extra non-linearity used as base for XYZ output curves. */
+/* This makes the XYZ grid values more perceptual, and asks less */
+/* of the automatically created output curve shape. */
+/* (We assume XYZ is in 0..1 scale */
+
+/* Transfer function with offset and scale + Y2L curve */
+static double icxSTransFuncY2L(
+double *v, /* Pointer to first parameter */
+int luord, /* Number of parameters */
+double vv, /* Source of value */
+double min, /* Scale values */
+double max
+) {
+ max -= min;
+
+ vv = (vv - min)/max;
+
+#ifdef USE_XYZ_Y2LCURVE
+ if (vv > 0.008856451586)
+ vv = 1.16 * pow(vv,1.0/3.0) - 0.16;
+ else
+ vv = 9.032962896 * vv;
+#endif
+
+ vv = icxTransFunc(v, luord, vv);
+
+ vv = (vv * max) + min;
+ return vv;
+}
+
+/* Inverse Transfer function with offset and scale + Y2L */
+static double icxInvSTransFuncY2L(
+double *v, /* Pointer to first parameter */
+int luord, /* Number of parameters */
+double vv, /* Source of value */
+double min, /* Scale values */
+double max
+) {
+ max -= min;
+
+ vv = (vv - min)/max;
+ vv = icxInvTransFunc(v, luord, vv);
+
+#ifdef USE_XYZ_Y2LCURVE
+ if (vv > 0.08)
+ vv = pow((vv + 0.16)/1.16, 3.0);
+ else
+ vv = vv/9.032962896;
+#endif
+
+ vv = (vv * max) + min;
+
+ return vv;
+}
+
+/* Transfer function with offset and scale, and */
+/* partial derivative with respect to the */
+/* parameters and the input value. */
+static double icxdpdiSTransFuncY2L(
+double *v, /* Pointer to first parameter */
+double *dv, /* Return derivative wrt each parameter */
+double *pdin, /* Return derivative wrt source value */
+int luord, /* Number of parameters */
+double vv, /* Source of value */
+double min, /* Scale values */
+double max
+) {
+ int i;
+ double idv = 1.0;
+ max -= min;
+
+#ifdef USE_XYZ_Y2LCURVE
+ if (vv > 0.008856451586) {
+ vv = 1.16 * pow(vv,1.0/3.0) - 0.16;
+ idv = 1.16 / (3.0 * pow(vv, 2.0/3.0));
+ } else {
+ vv = 9.032962896 * vv;
+ idv = 9.032962896;
+ }
+#endif
+
+ vv = (vv - min)/max;
+
+ vv = icxdpdiTransFunc(v, dv, pdin, luord, vv);
+
+ *pdin *= idv; /* Account for input multiplier */
+
+ vv = (vv * max) + min;
+
+ for (i = 0; i < luord; i++) {
+ dv[i] *= max;
+ }
+ return vv;
+}
+
/* - - - - - - - - - - - - - - - - - */
#ifdef DEBUG
@@ -255,9 +357,15 @@ static void xfit_shmatsh(xfit *p, double *out, double *in) {
icxCubeInterp(p->v + p->mat_off, p->fdi, p->di, out, tin);
- for (f = 0; f < p->fdi; f++)
- out[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], out[f],
- p->out_min[f], p->out_max[f]);
+ if (p->flags & XFIT_OUT_LAB) {
+ for (f = 0; f < p->fdi; f++)
+ out[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], out[f],
+ p->out_min[f], p->out_max[f]);
+ } else {
+ for (f = 0; f < p->fdi; f++)
+ out[f] = icxSTransFuncY2L(p->v + p->out_offs[f], p->oluord[f], out[f],
+ p->out_min[f], p->out_max[f]);
+ }
}
/* - - - - - - - - - - - - - - - - - - - - */
@@ -453,10 +561,14 @@ static void xfit_invinpscurves(xfit *p, double *out, double *in) {
/* Lookup a value though an output curve */
static double xfit_outcurve(xfit *p, double in, int chan) {
double rv;
- if (p->tcomb & oc_o)
- rv = icxSTransFunc(p->v + p->out_offs[chan], p->oluord[chan], in,
- p->out_min[chan], p->out_max[chan]);
- else
+ if (p->tcomb & oc_o) {
+ if (p->flags & XFIT_OUT_LAB)
+ rv = icxSTransFunc(p->v + p->out_offs[chan], p->oluord[chan], in,
+ p->out_min[chan], p->out_max[chan]);
+ else
+ rv = icxSTransFuncY2L(p->v + p->out_offs[chan], p->oluord[chan], in,
+ p->out_min[chan], p->out_max[chan]);
+ } else
rv = in;
return rv;
}
@@ -465,22 +577,36 @@ static double xfit_outcurve(xfit *p, double in, int chan) {
static void xfit_outcurves(xfit *p, double *out, double *in) {
int f;
- for (f = 0; f < p->fdi; f++) {
- double val = in[f];
- if (p->tcomb & oc_o)
- val = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], val,
- p->out_min[f], p->out_max[f]);
- out[f] = val;
+ if (p->flags & XFIT_OUT_LAB) {
+ for (f = 0; f < p->fdi; f++) {
+ double val = in[f];
+ if (p->tcomb & oc_o)
+ val = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], val,
+ p->out_min[f], p->out_max[f]);
+ out[f] = val;
+ }
+ } else {
+ for (f = 0; f < p->fdi; f++) {
+ double val = in[f];
+ if (p->tcomb & oc_o)
+ val = icxSTransFuncY2L(p->v + p->out_offs[f], p->oluord[f], val,
+ p->out_min[f], p->out_max[f]);
+ out[f] = val;
+ }
}
}
/* Inverse Lookup a value though an output curve */
static double xfit_invoutcurve(xfit *p, double in, int chan) {
double rv;
- if (p->tcomb & oc_o)
- rv = icxInvSTransFunc(p->v + p->out_offs[chan], p->oluord[chan], in,
- p->out_min[chan], p->out_max[chan]);
- else
+ if (p->tcomb & oc_o) {
+ if (p->flags & XFIT_OUT_LAB)
+ rv = icxInvSTransFunc(p->v + p->out_offs[chan], p->oluord[chan], in,
+ p->out_min[chan], p->out_max[chan]);
+ else
+ rv = icxInvSTransFuncY2L(p->v + p->out_offs[chan], p->oluord[chan], in,
+ p->out_min[chan], p->out_max[chan]);
+ } else
rv = in;
return rv;
}
@@ -489,12 +615,22 @@ static double xfit_invoutcurve(xfit *p, double in, int chan) {
static void xfit_invoutcurves(xfit *p, double *out, double *in) {
int f;
- for (f = 0; f < p->fdi; f++) {
- double val = in[f];
- if (p->tcomb & oc_o)
- val = icxInvSTransFunc(p->v + p->out_offs[f], p->oluord[f], val,
- p->out_min[f], p->out_max[f]);
- out[f] = val;
+ if (p->flags & XFIT_OUT_LAB) {
+ for (f = 0; f < p->fdi; f++) {
+ double val = in[f];
+ if (p->tcomb & oc_o)
+ val = icxInvSTransFunc(p->v + p->out_offs[f], p->oluord[f], val,
+ p->out_min[f], p->out_max[f]);
+ out[f] = val;
+ }
+ } else {
+ for (f = 0; f < p->fdi; f++) {
+ double val = in[f];
+ if (p->tcomb & oc_o)
+ val = icxInvSTransFuncY2L(p->v + p->out_offs[f], p->oluord[f], val,
+ p->out_min[f], p->out_max[f]);
+ out[f] = val;
+ }
}
}
@@ -742,9 +878,15 @@ static double xfitfunc(void *edata, double *v) {
icxCubeInterp(p->v + p->mat_off, fdi, di, out, tin);
/* Apply output channel curves */
- for (f = 0; f < fdi; f++)
- out[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], out[f],
- p->out_min[f], p->out_max[f]);
+ for (f = 0; f < fdi; f++) {
+ if (p->flags & XFIT_OUT_LAB) {
+ out[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], out[f],
+ p->out_min[f], p->out_max[f]);
+ } else {
+ out[f] = icxSTransFuncY2L(p->v + p->out_offs[f], p->oluord[f], out[f],
+ p->out_min[f], p->out_max[f]);
+ }
+ }
/* Evaluate the error squared */
if (p->flags & XFIT_FM_INPUT) {
@@ -849,11 +991,16 @@ static double dxfitfunc(void *edata, double *dv, double *v) {
icxdpdiCubeInterp(p->v + p->mat_off, dmato_mv, dmato_tin, fdi, di, out, tin);
/* Apply output channel curves */
- for (f = 0; f < fdi; f++)
- out[f] = icxdpdiSTransFunc(p->v + p->out_offs[f],
- &dout_ov[p->out_offs[f] - p->out_off], &dout_mato[f],
- p->oluord[f], out[f], p->out_min[f], p->out_max[f]);
-
+ for (f = 0; f < fdi; f++) {
+ if (p->flags & XFIT_OUT_LAB)
+ out[f] = icxdpdiSTransFunc(p->v + p->out_offs[f],
+ &dout_ov[p->out_offs[f] - p->out_off], &dout_mato[f],
+ p->oluord[f], out[f], p->out_min[f], p->out_max[f]);
+ else
+ out[f] = icxdpdiSTransFuncY2L(p->v + p->out_offs[f],
+ &dout_ov[p->out_offs[f] - p->out_off], &dout_mato[f],
+ p->oluord[f], out[f], p->out_min[f], p->out_max[f]);
+ }
/* Convert to Delta E and compute pde's into dout_de squared */
if (p->flags & XFIT_FM_INPUT) {
@@ -1095,7 +1242,11 @@ static double symoptfunc(void *edata, double *v) {
/* Copy the parameter being tested back into xfit */
p->v[p->out_offs[ch]] = v[0];
- *out = icxSTransFunc(p->v + p->out_offs[ch], p->oluord[ch], *in,
+ if (p->flags & XFIT_OUT_LAB)
+ *out = icxSTransFunc(p->v + p->out_offs[ch], p->oluord[ch], *in,
+ p->out_min[ch], p->out_max[ch]);
+ else
+ *out = icxSTransFuncY2L(p->v + p->out_offs[ch], p->oluord[ch], *in,
p->out_min[ch], p->out_max[ch]);
rv = out[0] * out[0];
@@ -1253,10 +1404,14 @@ static void setup_piv(xfit *p) {
icxCubeInterp(p->v + p->mat_off, fdi, di, vv, vv);
/* Apply output channel curves */
- for (f = 0; f < fdi; f++)
- vv[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], vv[f],
- p->out_min[f], p->out_max[f]);
-
+ for (f = 0; f < fdi; f++) {
+ if (p->flags & XFIT_OUT_LAB)
+ vv[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], vv[f],
+ p->out_min[f], p->out_max[f]);
+ else
+ vv[f] = icxSTransFuncY2L(p->v + p->out_offs[f], p->oluord[f], vv[f],
+ p->out_min[f], p->out_max[f]);
+ }
for (e = 0; e < di; e++) {
double tt[MXDIDO];
@@ -1272,10 +1427,14 @@ static void setup_piv(xfit *p) {
icxCubeInterp(p->v + p->mat_off, fdi, di, tt, tt);
/* Apply output channel curves */
- for (f = 0; f < fdi; f++)
- tt[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], tt[f],
- p->out_min[f], p->out_max[f]);
-
+ for (f = 0; f < fdi; f++) {
+ if (p->flags & XFIT_OUT_LAB)
+ tt[f] = icxSTransFunc(p->v + p->out_offs[f], p->oluord[f], tt[f],
+ p->out_min[f], p->out_max[f]);
+ else
+ tt[f] = icxSTransFuncY2L(p->v + p->out_offs[f], p->oluord[f], tt[f],
+ p->out_min[f], p->out_max[f]);
+ }
for (f = 0; f < p->fdi; f++)
pd[f][e] = (tt[f] - vv[f])/1e-4;
@@ -1502,6 +1661,7 @@ int xfit_fit(
double out_max[MXDO], /* Output value scaling/range maximum */
double smooth, /* clut rspl smoothing factor */
double oavgdev[MXDO], /* Average output value deviation */
+ double demph, /* dark emphasis factor for cLUT grid res. */
int iord[], /* Order of input pos/shaper curve for each dimension */
int sord[], /* Order of input sub-grid shaper curve (not used) */
int oord[], /* Order of output shaper curve for each dimension */
@@ -2110,6 +2270,7 @@ dump_xfit(p);
pgp[i].v = vv;
else
pgp[i].v = pgp[i-1].v + vv;
+
}
resid->del(resid);
@@ -2120,7 +2281,10 @@ dump_xfit(p);
for (i = 0; i < NPGP; i++) {
pgp[i].v = (pgp[i].v - vo)/vs;
-//printf("~1 guide point %d: %f -> %f\n",i,pgp[i].p,pgp[i].v);
+ /* Apply any dark emphasis */
+ if (demph > 1.0) {
+ pgp[i].v = icx_powlike(pgp[i].v, 1.0/demph);
+ }
}
/* Fit the non-monotonic parameters to the guide points */
if ((posc = new_mcv_noos()) == NULL)
@@ -2237,19 +2401,13 @@ dump_xfit(p);
p->skm->lookup(p->skm, skval, p->ipoints[i].p);
xfit_abs_to_rel(p, skval, skval);
xfit_invoutcurves(p, skval, skval);
-
-//printf("~1 point %d at %f %f %f, targ %f %f %f skm %f %f %f\n",
-//i,p->ipoints[i].p[0],p->ipoints[i].p[1],p->ipoints[i].p[2],
-//p->rpoints[i].v[0],p->rpoints[i].v[1],p->rpoints[i].v[2],
-//skval[0], skval[1], skval[2]);
+//printf("~1 point %d at %f %f %f, targ %f %f %f skm %f %f %f\n", i,p->ipoints[i].p[0],p->ipoints[i].p[1],p->ipoints[i].p[2], p->rpoints[i].v[0],p->rpoints[i].v[1],p->rpoints[i].v[2], skval[0], skval[1], skval[2]);
/* Subtract it from value at this point, */
/* so rspl will fit difference to skeleton model */
for (f = 0; f < fdi; f++)
p->rpoints[i].v[f] -= skval[f];
}
-//printf("~1 point %d, w %f, %f %f %f %f -> %f %f %f\n",
-//i,p->rpoints[i].w,p->rpoints[i].p[0], p->rpoints[i].p[1], p->rpoints[i].p[2], p->rpoints[i].p[3],
-//p->rpoints[i].v[0], p->rpoints[i].v[1], p->rpoints[i].v[2]);
+//printf("~1 point %d, w %f, %f %f %f %f -> %f %f %f\n",i,p->rpoints[i].w,p->rpoints[i].p[0], p->rpoints[i].p[1], p->rpoints[i].p[2], p->rpoints[i].p[3],p->rpoints[i].v[0], p->rpoints[i].v[1], p->rpoints[i].v[2]);
}
/* Create ipos[] arrays, that hold the shaper space */
@@ -2342,6 +2500,7 @@ printf("~1 ipos[%d][%d] = %f\n",e,i,cv);
// p->clut->fit_rspl_w_df(p->clut, rsplflags, p->rpoints, p->nodp, in_min, in_max, gres,
// out_min, out_max, smooth, oavgdev, ipos, 1.0, (void *)p, skm_weak);
// } else
+ /* Normal multi-d scattered point fitting */
p->clut->fit_rspl_w(p->clut, rsplflags, p->rpoints, p->nodp, in_min, in_max, gres,
out_min, out_max, smooth, oavgdev, ipos);
#endif
diff --git a/xicc/xfit.h b/xicc/xfit.h
index f9f3233..519f071 100644
--- a/xicc/xfit.h
+++ b/xicc/xfit.h
@@ -55,8 +55,8 @@ typedef enum {
#define XFIT_OUT_WP_REL 0x0010 /* Extract the white point and make output relative */
#define XFIT_OUT_WP_REL_US 0x0030 /* Same as above but scale to avoid clipping above WP */
#define XFIT_OUT_WP_REL_C 0x0050 /* Same as above but clip any cLUT values over D50 */
-#define XFIT_CLIP_WP 0x0080 /* Clip white point to have Y <= 1.0 (conflict with above) */
-#define XFIT_OUT_LAB 0x0100 /* Output space is LAB else XYZ for reading WP */
+#define XFIT_CLIP_WP 0x0080 /* Clip white point to have Y <= 1.0 (conflict with above) */
+#define XFIT_OUT_LAB 0x0100 /* Output space is LAB else XYZ for reading WP */
#define XFIT_OUT_ZERO 0x0200 /* Adjust output curves 1 & 2 for zero */
@@ -172,6 +172,7 @@ struct _xfit {
double out_max[MXDO], /* Output value scaling/range maximum */
double smooth, /* clut rspl smoothing factor */
double oavgdev[MXDO], /* Average output value deviation */
+ double demph, /* dark emphasis factor for cLUT grid res. */
int iord[], /* Order of input positioning/shaper curve for each dimension */
int sord[], /* Order of input sub-grid shaper curve (not used) */
int oord[], /* Order of output shaper curve for each dimension */
diff --git a/xicc/xicc.c b/xicc/xicc.c
index 9b6d867..a1c4531 100644
--- a/xicc/xicc.c
+++ b/xicc/xicc.c
@@ -61,7 +61,7 @@ static icxLuBase *xicc_set_luobj(xicc *p, icmLookupFunc func, icRenderingIntent
icmLookupOrder order, int flags, int no, int nobw, cow *points,
icxMatrixModel *skm,
double dispLuminance, double wpscale, double smooth, double avgdev,
- icxViewCond *vc, icxInk *ink, xcal *cal, int quality);
+ double demph, icxViewCond *vc, icxInk *ink, xcal *cal, int quality);
static void icxLutSpaces(icxLuBase *p, icColorSpaceSignature *ins, int *inn,
icColorSpaceSignature *outs, int *outn,
icColorSpaceSignature *pcs);
@@ -929,7 +929,7 @@ icxInk *ink /* inking details (NULL for default) */
icRenderingIntent n_intent = intent; /* Native Intent to request */
icColorSpaceSignature n_pcs = icmSigDefaultData; /* Native PCS to request */
-//printf("~1 xicc_get_luobj got intent %s and pcsor %s\n",icx2str(icmRenderingIntent,intent),icx2str(icmColorSpaceSignature,pcsor));
+//printf("~1 xicc_get_luobj got intent '%s' and pcsor '%s'\n",icx2str(icmRenderingIntent,intent),icx2str(icmColorSpaceSignature,pcsor));
/* Ensure that appropriate PCS is slected for an appearance intent */
if (intent == icxAppearance
@@ -939,6 +939,7 @@ icxInk *ink /* inking details (NULL for default) */
|| intent == icxSaturationAppearance
|| intent == icxAbsSaturationAppearance) {
pcsor = icxSigJabData;
+//printf("~1 pcsor = %s\n",tag2str(pcsor));
/* Translate non-Jab intents to the equivalent appearance "intent" if pcsor == Jab. */
/* This is how we get these when the UI's don't list all the apperances intents, */
@@ -960,6 +961,7 @@ icxInk *ink /* inking details (NULL for default) */
else
intent = icxAppearance;
}
+//printf("~1 intent = %s\n",tag2str(intent));
/* Translate intent asked for into intent needed in icclib */
if (intent == icxAppearance
@@ -971,6 +973,7 @@ icxInk *ink /* inking details (NULL for default) */
else if (intent == icxSaturationAppearance
|| intent == icxAbsSaturationAppearance)
n_intent = icmAbsoluteSaturation;
+//printf("~1 n_intent = %s\n",tag2str(n_intent));
if (pcsor != icmSigDefaultData)
n_pcs = pcsor; /* There is an icclib override */
@@ -995,15 +998,16 @@ icxInk *ink /* inking details (NULL for default) */
&& (intent == icxAbsAppearance
|| intent == icxAbsPerceptualAppearance
|| intent == icxAbsSaturationAppearance)) { /* make sure its "Abs CAM" */
+//printf("~1 xicc_get_luobj using absolute apperance space with white = D50\n");
/* Set white point and flare color to D50 */
/* (Hmm. This doesn't match what happens within collink with absolute intent!!) */
vc->Wxyz[0] = icmD50.X/icmD50.Y;
vc->Wxyz[1] = icmD50.Y/icmD50.Y; // Normalise white reference to Y = 1 ?
vc->Wxyz[2] = icmD50.Z/icmD50.Y;
- vc->Fxyz[0] = icmD50.X;
- vc->Fxyz[1] = icmD50.Y;
- vc->Fxyz[2] = icmD50.Z;
+ vc->Gxyz[0] = icmD50.X;
+ vc->Gxyz[1] = icmD50.Y;
+ vc->Gxyz[2] = icmD50.Z;
}
/* Call xiccLu wrapper creation */
@@ -1054,6 +1058,7 @@ double dispLuminance, /* > 0.0 if display luminance value and is known */
double wpscale, /* > 0.0 if input white point is to be scaled */
double smooth, /* RSPL smoothing factor, -ve if raw */
double avgdev, /* reading Average Deviation as a proportion of the input range */
+double demph, /* dark emphasis factor for cLUT grid res. */
icxViewCond *vc, /* Viewing Condition (NULL if not using CAM) */
icxInk *ink, /* inking details (NULL for default) */
xcal *cal, /* Optional cal, will override any existing (not deleted with xicc)*/
@@ -1104,7 +1109,7 @@ int quality /* Quality metric, 0..3 */
case icmLutType:
/* ~~~ Should add check that it is a fwd profile ~~~ */
- xplu = set_icxLuLut(p, plu, func, intent, flags, no, nobw, points, skm, dispLuminance, wpscale, smooth, avgdev, vc, ink, quality);
+ xplu = set_icxLuLut(p, plu, func, intent, flags, no, nobw, points, skm, dispLuminance, wpscale, smooth, avgdev, demph, vc, ink, quality);
break;
default:
@@ -1217,7 +1222,8 @@ icxViewCond *vc /* Viewing parameters to return */
double Lvr = -1.0; /* Reflective device image luminance */
double Lv = -1.0; /* device image luminance */
double Yf = -1.0; /* Flare relative luminance to Lv */
- double Fxyz[3] = {-1.0, -1.0, -1.0}; /* Flare color */
+ double Yg = -1.0; /* Glare relative luminance to La */
+ double Gxyz[3] = {-1.0, -1.0, -1.0}; /* Glare color */
icTechnologySignature tsig = icMaxEnumTechnology; /* Technology Signature */
icProfileClassSignature devc = icMaxEnumClass;
int trans = -1; /* Set to 0 if not transparency, 1 if it is */
@@ -1241,7 +1247,8 @@ icxViewCond *vc /* Viewing parameters to return */
if ((ro = (icmMeasurement *)pp->read_tag(pp, icSigMeasurementTag)) != NULL
&& ro->ttype == icSigMeasurementType) {
- Yf = ro->flare;
+ Yf = 0.0 * ro->flare; // ?????
+ Yg = 1.0 * ro->flare; // ?????
/* ro->illuminant ie D50, D65, D93, A etc. */
}
}
@@ -1345,7 +1352,8 @@ icxViewCond *vc /* Viewing parameters to return */
printf("Reflective Image White Lvr = %f\n",Lvr);
printf("Device Image White Lv = %f\n",Lv);
printf("Relative Flare Yf = %f\n",Yf);
- printf("Flare color %f %f %f\n",Fxyz[0], Fxyz[1], Fxyz[2]);
+ printf("Relative Glare Yg = %f\n",Yg);
+ printf("Glare color %f %f %f\n",Gxyz[0], Gxyz[1], Gxyz[2]);
printf("Technology = %s\n",tag2str(tsig));
printf("deviceClass = %s\n",tag2str(devc));
printf("Transparency = %d\n",trans);
@@ -1357,7 +1365,8 @@ icxViewCond *vc /* Viewing parameters to return */
&& Yb >= 0.0
&& Lv >= 0.0
&& Yf >= 0.0
- && Fxyz[0] >= 0.0 && Fxyz[1] >= 0.0 && Fxyz[2] >= 0.0) {
+ && Yg >= 0.0
+ && Gxyz[0] >= 0.0 && Gxyz[1] >= 0.0 && Gxyz[2] >= 0.0) {
vc->Ev = vc_none;
vc->Wxyz[0] = Wxyz[0];
@@ -1367,9 +1376,10 @@ icxViewCond *vc /* Viewing parameters to return */
vc->Yb = Yb;
vc->Lv = Lv;
vc->Yf = Yf;
- vc->Fxyz[0] = Fxyz[0];
- vc->Fxyz[1] = Fxyz[1];
- vc->Fxyz[2] = Fxyz[2];
+ vc->Yg = Yg;
+ vc->Gxyz[0] = Gxyz[0];
+ vc->Gxyz[1] = Gxyz[1];
+ vc->Gxyz[2] = Gxyz[2];
return 0;
}
@@ -1400,9 +1410,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_average; /* Assume average viewing conditions */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.01; /* Assume 1% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1419,9 +1431,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_average; /* Assume average viewing conditions */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.005; /* Assume 0.5% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1437,8 +1451,12 @@ icxViewCond *vc /* Viewing parameters to return */
Ev = vc_average; /* Assume average viewing conditions */
if (Yf < 0.0) /* No flare figure */
Yf = 0.0; /* Assume 0% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1453,9 +1471,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_dim; /* Assume dim viewing conditions */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.01; /* Assume 1% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1472,9 +1492,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_average; /* Assume average viewing conditions */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.02; /* Assume 2% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1489,9 +1511,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_average; /* Assume average viewing conditions */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.00; /* Assume 0% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.0; /* Assume 0% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1507,9 +1531,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_dim; /* Dim environment */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.01; /* Assume 1% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
/* Assume very darkened room, no background */
@@ -1522,9 +1548,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_dark; /* Dark environment */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.01; /* Assume 1% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1549,9 +1577,11 @@ icxViewCond *vc /* Viewing parameters to return */
if (Lv < 0.0) /* No device image luminance */
Ev = vc_average; /* Assume average viewing conditions */
if (Yf < 0.0) /* No flare figure */
- Yf = 0.01; /* Assume 1% flare */
- if (Fxyz[0] < 0.0 || Fxyz[1] < 0.0 || Fxyz[2] < 0.0) /* No flare color */
- Fxyz[0] = Wxyz[0], Fxyz[1] = Wxyz[1], Fxyz[2] = Wxyz[2];
+ Yf = 0.0; /* Assume 0% flare */
+ if (Yg < 0.0) /* No glare figure */
+ Yg = 0.01; /* Assume 1% glare */
+ if (Gxyz[0] < 0.0 || Gxyz[1] < 0.0 || Gxyz[2] < 0.0) /* No flare color */
+ Gxyz[0] = Wxyz[0], Gxyz[1] = Wxyz[1], Gxyz[2] = Wxyz[2];
break;
}
@@ -1623,19 +1653,20 @@ double *wp /* Provide white point if xicc is NULL */
}
}
- /* Set a default flare color */
- vc->Fxyz[0] = vc->Wxyz[0];
- vc->Fxyz[1] = vc->Wxyz[1];
- vc->Fxyz[2] = vc->Wxyz[2];
+ /* Set a default Glare color */
+ vc->Gxyz[0] = vc->Wxyz[0];
+ vc->Gxyz[1] = vc->Wxyz[1];
+ vc->Gxyz[2] = vc->Wxyz[2];
}
/*
Typical adapting field luminances and white luminance in reflective setup:
+ (Note that displays Lv is typically brighter under the same conditions)
E = illuminance in Lux
- Lv = White luminance assuming 100% reflectance
La = Adapting field luminance in cd/m^2, assuming 20% reflectance from surround
+ Lv = White luminance assuming 100% reflectance
E La Lv Condition
11 0.7 4 Twilight
@@ -1651,6 +1682,22 @@ double *wp /* Provide white point if xicc is NULL */
10000 637 3183 Typical outdoors, full daylight
50000 3185 15915 Bright summers day
+ Display numbers:
+
+ SMPTE video standard white 100
+ SMPTE cinema standard white 55
+
+ Flare is image content dependent, and is typically 1% from factors
+ including display self illumination and observer/camera internal
+ stray light. Because image content is not static, using a 1% of white point
+ flare results quite erronious appearance modelling for predominantly
+ dark images. As a result, it is best to default to a Yf of 0%,
+ and only introduce a higher number depending on the known image content.
+
+ Glare is assumed to be from the ambient light reflecting from the display
+ and also striking the observer directly, and is (typically) defaulted
+ to 1% of ambient here.
+
*/
if (no == -1
@@ -1663,7 +1710,22 @@ double *wp /* Provide white point if xicc is NULL */
vc->La = 50.0; /* Practical to Good lighting */
vc->Lv = 250.0; /* Average viewing conditions ratio */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
+ }
+ }
+ else if (no == 2
+ || (as != NULL && stricmp(as,"pc") == 0)) {
+
+ no = 2;
+ if (vc != NULL) {
+ vc->desc = " pc - Critical print evaluation environment (ISO-3664 P1)";
+ vc->Ev = vc_average; /* Average viewing conditions */
+ vc->La = 127.0; /* 0.2 * Lv ? */
+ vc->Lv = 2000.0/3.1415; /* White of the image field */
+ vc->Yb = 0.2; /* Grey world */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 0
@@ -1672,10 +1734,12 @@ double *wp /* Provide white point if xicc is NULL */
no = 0;
if (vc != NULL) {
vc->desc = " pp - Practical Reflection Print (ISO-3664 P2)";
- vc->Ev = vc_average; /* Average viewing conditions */
- vc->La = 32.0; /* Use a practical print evaluation number */
+ vc->Ev = vc_none; /* Use explicit La/Lv */
+ vc->La = 32.0; /* 0.2 * Lv ? */
+ vc->Lv = 500.0/3.1415; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 1
@@ -1684,22 +1748,26 @@ double *wp /* Provide white point if xicc is NULL */
no = 1;
if (vc != NULL) {
vc->desc = " pe - Print evaluation environment (CIE 116-1995)";
- vc->Ev = vc_average; /* Average viewing conditions */
- vc->La = 64.0; /* Good */
+ vc->Ev = vc_none; /* Use explicit La/Lv */
+ vc->La = 30.0; /* 0.2 * Lv ? */
+ vc->Lv = 150.0; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
- else if (no == 2
- || (as != NULL && stricmp(as,"pc") == 0)) {
+ else if (no == 4
+ || (as != NULL && stricmp(as,"mb") == 0)) {
- no = 2;
+ no = 4;
if (vc != NULL) {
- vc->desc = " pc - Critical print evaluation environment (ISO-3664 P1)";
- vc->Ev = vc_average; /* Average viewing conditions */
- vc->La = 127.0; /* Critical */
+ vc->desc = " mb - Bright monitor in bright work environment";
+ vc->Ev = vc_none; /* Use explicit La/Lv */
+ vc->La = 42.0; /* Bright work environment */
+ vc->Lv = 150.0; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 3
@@ -1708,22 +1776,12 @@ double *wp /* Provide white point if xicc is NULL */
no = 3;
if (vc != NULL) {
vc->desc = " mt - Monitor in typical work environment";
- vc->Ev = vc_average; /* Average viewing conditions */
+ vc->Ev = vc_none; /* Use explicit La/Lv */
vc->La = 22.0; /* Typical work environment */
+ vc->Lv = 120.0; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.02; /* 2% flare */
- }
- }
- else if (no == 4
- || (as != NULL && stricmp(as,"mb") == 0)) {
-
- no = 4;
- if (vc != NULL) {
- vc->desc = " mb - Bright monitor in bright work environment";
- vc->Ev = vc_average; /* Average viewing conditions */
- vc->La = 42.0; /* Bright work environment */
- vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.02; /* 2% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 5
@@ -1732,10 +1790,12 @@ double *wp /* Provide white point if xicc is NULL */
no = 5;
if (vc != NULL) {
vc->desc = " md - Monitor in darkened work environment";
- vc->Ev = vc_dim; /* Dim viewing conditions */
- vc->La = 4.0; /* Darkened work environment */
+ vc->Ev = vc_none; /* Use explicit La/Lv */
+ vc->La = 10.0; /* Darkened work environment */
+ vc->Lv = 100.0; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 6
@@ -1744,10 +1804,12 @@ double *wp /* Provide white point if xicc is NULL */
no = 6;
if (vc != NULL) {
vc->desc = " jm - Projector in dim environment";
- vc->Ev = vc_dim; /* Dim viewing conditions */
+ vc->Ev = vc_none; /* Use explicit La/Lv */
vc->La = 10.0; /* Adaptation is from display */
+ vc->Lv = 80.0; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 7
@@ -1756,46 +1818,65 @@ double *wp /* Provide white point if xicc is NULL */
no = 7;
if (vc != NULL) {
vc->desc = " jd - Projector in dark environment";
- vc->Ev = vc_dark; /* Dark viewing conditions */
- vc->La = 10.0; /* Adaptation is from display */
+ vc->Ev = vc_none; /* Use explicit La/Lv */
+ vc->La = 8.0; /* Adaptation is from display */
+ vc->Lv = 80.0; /* White of the image field */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare ? */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else if (no == 8
- || (as != NULL && stricmp(as,"pcd") == 0)) {
+ || (as != NULL && stricmp(as,"tv") == 0)) {
no = 8;
if (vc != NULL) {
+ vc->desc = " tv - Television/Film Studio";
+ vc->Ev = vc_none; /* Compute from La/Lv */
+ vc->La = 0.2 * 1000.0/3.1415; /* Adative/Surround */
+ vc->Yb = 0.2; /* Grey world */
+ vc->Lv = 1000.0/3.1415; /* White of the image field */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
+ }
+ }
+ else if (no == 9
+ || (as != NULL && stricmp(as,"pcd") == 0)) {
+
+ no = 9;
+ if (vc != NULL) {
vc->desc = "pcd - Photo CD - original scene outdoors";
vc->Ev = vc_average; /* Average viewing conditions */
vc->La = 320.0; /* Typical outdoors, 1600 cd/m^2 */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.00; /* 0% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.0; /* 0% glare - assumed to be compensated ? */
}
}
- else if (no == 9
+ else if (no == 10
|| (as != NULL && stricmp(as,"ob") == 0)) {
- no = 9;
+ no = 10;
if (vc != NULL) {
vc->desc = " ob - Original scene - Bright Outdoors";
vc->Ev = vc_average; /* Average viewing conditions */
vc->La = 2000.0; /* Bright Outdoors */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.00; /* 0% flare */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.0; /* 0% glare - assumed to be compensated ? */
}
}
- else if (no == 10
+ else if (no == 11
|| (as != NULL && stricmp(as,"cx") == 0)) {
- no = 10;
+ no = 11;
if (vc != NULL) {
vc->desc = " cx - Cut Sheet Transparencies on a viewing box";
vc->Ev = vc_cut_sheet; /* Cut sheet viewing conditions */
vc->La = 53.0; /* Dim, adapted to slide ? */
vc->Yb = 0.2; /* Grey world */
- vc->Yf = 0.01; /* 1% flare ? */
+ vc->Yf = 0.0; /* 0% flare */
+ vc->Yg = 0.01; /* 1% glare */
}
}
else {
@@ -1828,7 +1909,8 @@ icxViewCond *vc
if (vc->Ev == vc_none)
printf(" Image luminance = %f cd/m^2\n",vc->Lv);
printf(" Flare to image ratio = %f\n",vc->Yf);
- printf(" Flare color = %f %f %f\n",vc->Fxyz[0], vc->Fxyz[1], vc->Fxyz[2]);
+ printf(" Glare to ambient ratio = %f\n",vc->Yg);
+ printf(" Flare color = %f %f %f\n",vc->Gxyz[0], vc->Gxyz[1], vc->Gxyz[2]);
}
@@ -1899,11 +1981,11 @@ int no, /* Enumeration selected, icxNoGMIntent for none */
char *as /* Alias string selector, NULL for none */
) {
#ifdef USE_CAM
- int colccas = 0x2; /* Use cas clipping for colorimetric style intents */
- int perccas = 0x1; /* Use cas for perceptual style intents */
+ int colccas = 0x3; /* Use abs. CAS for abs colorimetric intents */
+ int perccas = 0x2; /* Use CAS for other intents */
#else
- int colccas = 0x0; /* Use Lab for colorimetric style intents */
- int perccas = 0x0; /* Use Lab for perceptual style intents */
+ int colccas = 0x1; /* Use abs. Lab for abs colorimetric intents */
+ int perccas = 0x0; /* Use Lab for other intents */
fprintf(stderr,"!!!!!! Warning, USE_CAM is off in xicc.c !!!!!!\n");
#endif
@@ -1927,6 +2009,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 0.0;
gmi->glumbexf = 0.0;
gmi->glumknf = 0.0;
+ gmi->bph = gmm_noBPadpt; /* No BP adapation */
gmi->gamcpf = 0.0;
gmi->gamexf = 0.0;
gmi->gamcknf = 0.0;
@@ -1958,6 +2041,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 0.0;
gmi->glumbexf = 0.0;
gmi->glumknf = 0.0;
+ gmi->bph = gmm_noBPadpt; /* No BP adapation */
gmi->gamcpf = 0.0;
gmi->gamexf = 0.0;
gmi->gamcknf = 0.0;
@@ -1982,6 +2066,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 0.0;
gmi->glumbexf = 0.0;
gmi->glumknf = 0.0;
+ gmi->bph = gmm_noBPadpt; /* No BP adapation */
gmi->gamcpf = 0.0;
gmi->gamexf = 0.0;
gmi->gamcknf = 0.0;
@@ -2008,6 +2093,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 0.0; /* No compression at black end */
gmi->glumbexf = 0.0; /* No expansion at black end */
gmi->glumknf = 0.0;
+ gmi->bph = gmm_noBPadpt; /* No BP adapation */
gmi->gamcpf = 0.0;
gmi->gamexf = 0.0;
gmi->gamcknf = 0.0;
@@ -2033,6 +2119,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 1.0; /* Fully compress grey axis at black end */
gmi->glumbexf = 1.0; /* Fully expand grey axis at black end */
gmi->glumknf = 0.0; /* No knee on grey mapping */
+ gmi->bph = gmm_bendBP; /* extent and bend */
gmi->gamcpf = 0.0; /* No gamut compression */
gmi->gamexf = 0.0; /* No gamut expansion */
gmi->gamcknf = 0.0; /* No knee in gamut compress */
@@ -2060,6 +2147,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 1.0; /* Fully compress grey axis at black end */
gmi->glumbexf = 1.0; /* Fully expand grey axis at black end */
gmi->glumknf = 1.0; /* Sigma knee in grey compress/expand */
+ gmi->bph = gmm_bendBP; /* extent and bend */
gmi->gamcpf = 1.0; /* Full gamut compression */
gmi->gamexf = 0.0; /* No gamut expansion */
gmi->gamcknf = 0.8; /* High Sigma knee in gamut compress */
@@ -2073,7 +2161,7 @@ char *as /* Alias string selector, NULL for none */
/* Don't align neutral axes, but perceptually compress out of gamut */
/* and map appearance space Jab to Jab. */
- no = 5;
+ no = 6;
gmi->as = "pa";
gmi->desc = "pa - Perceptual Apperance ";
gmi->icci = icPerceptual;
@@ -2085,6 +2173,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 1.0; /* Fully compress grey axis at black end */
gmi->glumbexf = 1.0; /* Fully expand grey axis at black end */
gmi->glumknf = 1.0; /* Sigma knee in grey compress/expand */
+ gmi->bph = gmm_bendBP; /* extent and bend */
gmi->gamcpf = 1.0; /* Full gamut compression */
gmi->gamexf = 0.0; /* No gamut expansion */
gmi->gamcknf = 0.8; /* High Sigma knee in gamut compress */
@@ -2098,7 +2187,7 @@ char *as /* Alias string selector, NULL for none */
/* Align neutral axes and perceptually map white and black points, */
/* perceptually compress and expand to match gamuts and map Jab to Jab. */
- no = 6;
+ no = 7;
gmi->as = "ms";
gmi->desc = "ms - Saturation";
gmi->icci = icSaturation;
@@ -2110,6 +2199,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 1.0; /* Fully compress grey axis at black end */
gmi->glumbexf = 1.0; /* Fully expand grey axis at black end */
gmi->glumknf = 1.0; /* Sigma knee in grey compress/expand */
+ gmi->bph = gmm_bendBP; /* extent and bend */
gmi->gamcpf = 1.0; /* Full gamut compression */
gmi->gamexf = 1.0; /* Full gamut expansion */
gmi->gamcknf = 1.0; /* High Sigma knee in gamut compress/expand */
@@ -2123,7 +2213,7 @@ char *as /* Alias string selector, NULL for none */
|| (as != NULL && stricmp(as,"s") == 0)) {
/* Same as "ms" but enhance saturation */
- no = 7;
+ no = 8;
gmi->as = "s";
gmi->desc = " s - Enhanced Saturation [ICC Saturation]";
gmi->icci = icSaturation;
@@ -2135,6 +2225,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 1.0; /* Fully compress grey axis at black end */
gmi->glumbexf = 1.0; /* Fully expand grey axis at black end */
gmi->glumknf = 1.0; /* Sigma knee in grey compress/expand */
+ gmi->bph = gmm_bendBP; /* extent and bend */
gmi->gamcpf = 1.0; /* Full gamut compression */
gmi->gamexf = 1.0; /* Full gamut expansion */
gmi->gamcknf = 1.0; /* High sigma knee in gamut compress */
@@ -2147,11 +2238,11 @@ char *as /* Alias string selector, NULL for none */
|| (as != NULL && stricmp(as,"al") == 0)) {
/* Map absolute L*a*b* to L*a*b* and clip out of gamut */
- no = 8;
+ no = 9;
gmi->as = "al";
gmi->desc = "al - Absolute Colorimetric (Lab)";
gmi->icci = icAbsoluteColorimetric;
- gmi->usecas = 0x0; /* Don't use appearance space, use L*a*b* */
+ gmi->usecas = 0x1; /* Don't use appearance space, use abs. L*a*b* */
gmi->usemap = 0; /* Don't use gamut mapping */
gmi->greymf = 0.0;
gmi->glumwcpf = 0.0;
@@ -2159,6 +2250,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 0.0;
gmi->glumbexf = 0.0;
gmi->glumknf = 0.0;
+ gmi->bph = gmm_noBPadpt; /* No BP adapation */
gmi->gamcpf = 0.0;
gmi->gamexf = 0.0;
gmi->gamcknf = 0.0;
@@ -2172,11 +2264,11 @@ char *as /* Alias string selector, NULL for none */
/* Align neutral axes and linearly map white point, then */
/* map L*a*b* to L*a*b* and clip out of gamut */
- no = 3;
+ no = 10;
gmi->as = "rl";
- gmi->desc = "rl - White Point Matched Appearance (Lab)";
+ gmi->desc = "rl - White Point Matched Colorimetric (Lab)";
gmi->icci = icRelativeColorimetric;
- gmi->usecas = 0x0; /* Don't use appearance space, use L*a*b* */
+ gmi->usecas = 0x0; /* Don't use appearance space, use relative L*a*b* */
gmi->usemap = 1; /* Use gamut mapping */
gmi->greymf = 1.0; /* And linearly map white point */
gmi->glumwcpf = 1.0;
@@ -2184,6 +2276,7 @@ char *as /* Alias string selector, NULL for none */
gmi->glumbcpf = 0.0;
gmi->glumbexf = 0.0;
gmi->glumknf = 0.0;
+ gmi->bph = gmm_noBPadpt; /* No BP adapation */
gmi->gamcpf = 0.0;
gmi->gamexf = 0.0;
gmi->gamcknf = 0.0;
@@ -2210,10 +2303,12 @@ icxGMappingIntent *gmi /* Gamut Mapping parameters to return */
printf(" Closest ICC intent = '%s'\n",icm2str(icmRenderingIntent,gmi->icci));
if ((gmi->usecas & 0xff) == 0)
- printf(" Not using Color Apperance Space\n");
+ printf(" Not using Color Apperance Space - using L*a*b*\n");
else if ((gmi->usecas & 0xff) == 1)
- printf(" Using Color Apperance Space\n");
+ printf(" Not using Color Apperance Space - using Absoute L*a*b*\n");
else if ((gmi->usecas & 0xff) == 2)
+ printf(" Using Color Apperance Space\n");
+ else if ((gmi->usecas & 0xff) == 3)
printf(" Using Absolute Color Apperance Space\n");
if ((gmi->usecas & 0x100) != 0)
@@ -2229,6 +2324,13 @@ icxGMappingIntent *gmi /* Gamut Mapping parameters to return */
printf(" Grey axis black compression factor %f\n", gmi->glumbcpf);
printf(" Grey axis black expansion factor %f\n", gmi->glumbexf);
printf(" Grey axis knee factor %f\n", gmi->glumknf);
+ printf(" Black point algorithm: ");
+ switch(gmi->bph) {
+ case gmm_clipBP: printf("Neutral axis no-adapt extend and clip\n"); break;
+ case gmm_BPadpt: printf("Neutral axis fully adapt\n"); break;
+ case gmm_bendBP: printf("Neutral axis no-adapt extend and bend\n"); break;
+ case gmm_noBPadpt: printf("Neutral axis no-adapt\n"); break;
+ }
printf(" Gamut compression factor %f\n", gmi->gamcpf);
printf(" Gamut expansion factor %f\n", gmi->gamexf);
printf(" Gamut compression knee factor %f\n", gmi->gamcknf);
@@ -3581,6 +3683,164 @@ void icxdpdiMulBy3x3Parm(
out[2] = ov[2];
}
+/* ------------------------------------------- */
+/* BT.1886 support */
+
+/* Compute technical gamma from effective gamma in BT.1886 style */
+
+/* Info for optimization */
+typedef struct {
+ double thyr; /* 50% input target */
+ double roo; /* 0% input target */
+} gam_fits;
+
+/* gamma + input offset function handed to powell() */
+static double gam_fit(void *dd, double *v) {
+ gam_fits *gf = (gam_fits *)dd;
+ double gamma = v[0];
+ double a, b;
+ double rv = 0.0;
+ double tt;
+
+ if (gamma < 0.0) {
+ rv += 100.0 * -gamma;
+ gamma = 1e-4;
+ }
+
+ tt = pow(gf->roo, 1.0/gamma);
+ b = tt/(1.0 - tt); /* Offset */
+ a = pow(1.0 - tt, gamma); /* Gain */
+
+ tt = a * pow((0.5 + b), gamma);
+ tt = tt - gf->thyr;
+ rv += tt * tt;
+
+ return rv;
+}
+
+/* Given the effective gamma and the output offset Y, */
+/* return the technical gamma needed for the correct 50% response. */
+double xicc_tech_gamma(
+ double egamma, /* effective gamma needed */
+ double off /* Output offset required */
+) {
+ gam_fits gf;
+ double op[1], sa[1], rv;
+
+ if (off <= 0.0) {
+ return egamma;
+ }
+
+ gf.thyr = pow(0.5, egamma); /* Advetised 50% target */
+ gf.roo = off;
+
+ op[0] = egamma;
+ sa[0] = 0.1;
+
+ if (powell(&rv, 1, op, sa, 1e-6, 500, gam_fit, (void *)&gf, NULL, NULL) != 0)
+ warning("Computing effective gamma and input offset is inaccurate");
+
+ return op[0];
+}
+
+
+/* Set the bt1886_info to a default do nothing state */
+void bt1886_setnop(bt1886_info *p) {
+ p->ingo = 0.0;
+ p->outsc = 1.0;
+ p->outL = 0.0;
+ p->tab[0] = 0.0;
+ p->tab[1] = 0.0;
+}
+
+/* Setup the bt1886_info for the given target */
+void bt1886_setup(bt1886_info *p, double *XYZbp, double gamma) {
+ double Lab[3], bkipow;
+ p->gamma = gamma;
+
+ icmXYZ2Lab(&icmD50, Lab, XYZbp);
+
+ p->outL = Lab[0]; /* For bp blend */
+ p->tab[0] = Lab[1]; /* a* b* correction needed */
+ p->tab[1] = Lab[2];
+
+ bkipow = pow(XYZbp[1], 1.0/p->gamma);
+ p->ingo = bkipow/(1.0 - bkipow); /* non-linear Y that makes out black point */
+ p->outsc = pow(1.0 - bkipow, p->gamma); /* Scale to restore 1 -> 1 */
+}
+
+/* Apply BT.1886 black offset and gamma curve to the XYZ out of the input profile. */
+/* Do this in the colorspace defined by the input profile matrix lookup, */
+/* so it will be relative XYZ. We assume that BT.1886 does a Rec709 to gamma */
+/* viewing adjustment, irrespective of the source profile transfer curve. */
+void bt1886_apply(bt1886_info *p, icmLuMatrix *lu, double *out, double *in) {
+ int j;
+ double vv;
+
+#ifdef DEBUG
+ printf("bt1886 XYZ in %f %f %f\n", in[0],in[1],in[2]);
+#endif
+
+ lu->bwd_matrix(lu, out, in);
+
+#ifdef DEBUG
+ printf("bt1886 RGB in %f %f %f\n", out[0],out[1],out[2]);
+#endif
+
+ for (j = 0; j < 3; j++) {
+ vv = out[j];
+
+ /* Convert linear light to Rec709 transfer curve */
+ if (vv < 0.018)
+ vv = 4.5 * vv;
+ else
+ vv = 1.099 * pow(vv, 0.45) - 0.099;
+
+ /* Apply input offset & re-scale, and then gamma of 2.4/custom gamma */
+ vv = vv + p->ingo;
+
+ if (vv > 0.0)
+ vv = p->outsc * pow(vv, p->gamma);
+
+ out[j] = vv;
+ }
+
+ lu->fwd_matrix(lu, out, out);
+
+#ifdef DEBUG
+ printf("bt1886 RGB bt.1886 %f %f %f\n", out[0],out[1],out[2]);
+#endif
+
+ icmXYZ2Lab(&icmD50, out, out);
+
+#ifdef DEBUG
+ printf("bt1886 Lab after Y adj. %f %f %f\n", out[0],out[1],out[2]);
+#endif
+
+ /* Blend ab to required black point offset p->tab[] as L approaches black. */
+ vv = (out[0] - p->outL)/(100.0 - p->outL); /* 0 at bp, 1 at wp */
+ vv = 1.0 - vv;
+
+ if (vv < 0.0)
+ vv = 0.0;
+ else if (vv > 1.0)
+ vv = 1.0;
+ vv = pow(vv, 40.0);
+ out[1] += vv * p->tab[0];
+ out[2] += vv * p->tab[1];
+
+#ifdef DEBUG
+ printf("bt1886 Lab after wp adj. %f %f %f\n", out[0],out[1],out[2]);
+#endif
+
+ icmLab2XYZ(&icmD50, out, out);
+
+#ifdef DEBUG
+ printf("bt1886 XYZ out %f %f %f\n", out[0],out[1],out[2]);
+#endif
+}
+
+/* - - - - - - - - - - */
#undef stricmp
diff --git a/xicc/xicc.h b/xicc/xicc.h
index 3969ebe..2e69ef1 100644
--- a/xicc/xicc.h
+++ b/xicc/xicc.h
@@ -183,20 +183,30 @@ typedef struct {
double Wxyz[3]; /* Reference/Adapted White XYZ (Y range 0.0 .. 1.0) */
double La; /* Adapting/Surround Luminance cd/m^2 */
double Yb; /* Relative Luminance of Background to reference white */
- double Lv; /* Luminance of white in the Viewing/Scene/Image field (cd/m^2) */
+ double Lv; /* Luminance of white in the Image/Scene/Viewing field (cd/m^2) */
/* Ignored if Ev is set to other than vc_none */
double Yf; /* Flare as a fraction of the reference white (Y range 0.0 .. 1.0) */
- double Fxyz[3]; /* The Flare white coordinates (typically the Ambient color) */
- /* Will be taken from Wxyz if Fxyz == 0.0 */
+ double Yg; /* Glare as a fraction of the ambient (Y range 0.0 .. 1.0) */
+ double Gxyz[3]; /* The Glare white coordinates (ie the Ambient color) */
+ /* will be taken from Wxyz if Gxyz <= 0.0 */
char *desc; /* Possible description of this VC */
} icxViewCond;
+/* Method of black point adaptation */
+typedef enum {
+ gmm_BPadpt = 0, /* Adapt source black point to destination */
+ gmm_noBPadpt = 1, /* Don't adapt black point to destination */
+ gmm_bendBP = 2, /* Don't adapt black point, bend it to dest. at end */
+ gmm_clipBP = 3 /* Don't adapt black point, clip it to dest. at end */
+} icx_BPmap;
+
/* Structure to convey gamut mapping intent */
typedef struct {
- int usecas; /* 0x0 Use Lab space */
- /* 0x1 Use Color Appearance Space */
- /* 0x2 Use Absolute Color Appearance Space */
- /* 0x101 Use Color Appearance Space with luminence scaling */
+ int usecas; /* 0x0 Use relative Lab space */
+ /* 0x1 Use Absolute Lab Space */
+ /* 0x2 Use Color Appearance Space */
+ /* 0x3 Use Absolute Color Appearance Space */
+ /* 0x102 Use Color Appearance Space with luminence scaling */
int usemap; /* NZ if Gamut mapping should be used, else clip */
double greymf; /* Grey axis hue matching factor, 0.0 - 1.0 */
double glumwcpf; /* Grey axis luminance white compression factor, 0.0 - 1.0 */
@@ -204,6 +214,7 @@ typedef struct {
double glumbcpf; /* Grey axis luminance black compression factor, 0.0 - 1.0 */
double glumbexf; /* Grey axis luminance black expansion factor, 0.0 - 1.0 */
double glumknf; /* Grey axis luminance knee factor, 0.0 - 1.0 */
+ icx_BPmap bph; /* Method of black point adapation */
double gamcpf; /* Gamut compression factor, 0.0 - 1.0 */
double gamexf; /* Gamut expansion factor, 0.0 - 1.0 */
double gamcknf; /* Gamut compression knee factor, 0.0 - 1.0 */
@@ -294,6 +305,7 @@ struct _xicc {
double smooth, /* RSPL smoothing factor, */
/* -ve if raw */
double avgdev, /* Avge Dev. of points */
+ double demph, /* cLut dark emphasis factor */
icxViewCond *vc, /* Viewing Condition - only */
/* used if pcsor == CIECAM. */
/* or ICX_CAM_CLIP flag. */
@@ -903,6 +915,32 @@ void icxdpdiMulBy3x3Parm(
double in[3] /* Input values */
);
+/* ------------------------------------------- */
+/* BT.1886 support */
+
+/* Convert an effective gamma given an offset into a technical gamma */
+double xicc_tech_gamma(double egamma, double off);
+
+typedef struct {
+ double ingo; /* input Y gamma offset for bt1886 */
+ double outsc; /* output Y scale for bt1886 */
+ double outL; /* output black point L value */
+ double tab[2]; /* Target ab offset value at zero input for bt1886 */
+ double gamma; /* bt.1886 technical gamma to apply */
+} bt1886_info;
+
+/* Set the bt1886_info to a default do nothing state */
+void bt1886_setnop(bt1886_info *p);
+
+/* Setup the bt1886_info for the given target */
+void bt1886_setup(bt1886_info *p, double *XYZbp, double gamma);
+
+/* Apply BT.1886 black offset and gamma curve to */
+/* the XYZ out of the input profile. */
+/* Do this in the colorspace defined by the input profile matrix lookup, */
+/* so it will be relative XYZ */
+void bt1886_apply(bt1886_info *p, icmLuMatrix *lu, double *out, double *in);
+
/* - - - - - - - - - - */
#include "xcal.h"
diff --git a/xicc/xicclu.c b/xicc/xicclu.c
index aa4a452..4987e65 100644
--- a/xicc/xicclu.c
+++ b/xicc/xicclu.c
@@ -3,7 +3,8 @@
* xicc lookup/test utility
*
* This program is the analog of icclu, but allows reverse lookup
- * of transforms by making use of xicc interpolation code.
+ * of transforms by making use of xicc interpolation code, + other
+ * more advanced features.
* (Based on the old xfmlu.c)
*
* Author: Graeme W. Gill
@@ -18,6 +19,8 @@
/* TTBD:
+ Add HSV as alternative to RGB ?
+
Can -ff and -fif be made to work with device link files ?
*/
@@ -41,9 +44,9 @@
void usage(char *diag) {
int i;
- fprintf(stderr,"Translate colors through an xicc, Version %s\n",ARGYLL_VERSION_STR);
+ fprintf(stderr,"Lookup ICC or CAL colors, Version %s\n",ARGYLL_VERSION_STR);
fprintf(stderr,"Author: Graeme W. Gill, licensed under the AGPL Version 3\n");
- fprintf(stderr,"usage: xicclu [-options] profile\n");
+ fprintf(stderr,"usage: xicclu [-options] profile_or_cal\n");
if (diag != NULL)
fprintf(stderr,"Diagnostic: %s\n",diag);
fprintf(stderr," -v level Verbosity level 0 - 2 (default = 1)\n");
@@ -60,6 +63,15 @@ void usage(char *diag) {
fprintf(stderr," -p oride x = XYZ_PCS, X = XYZ * 100, l = Lab_PCS, L = LCh, y = Yxy\n");
fprintf(stderr," j = %s Appearance Jab, J = %s Appearance JCh\n",icxcam_description(cam_default),icxcam_description(cam_default));
fprintf(stderr," -s scale Scale device range 0.0 - scale rather than 0.0 - 1.0\n");
+ fprintf(stderr," -e flag Video encode device input as:\n");
+ fprintf(stderr," -E flag Video decode device output as:\n");
+ fprintf(stderr," n normal 0..1 full range RGB levels (default)\n");
+ fprintf(stderr," t (16-235)/255 \"TV\" RGB levels\n");
+ fprintf(stderr," 6 Rec601 YCbCr SD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 7 Rec709 1125/60Hz YCbCr HD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 5 Rec709 1250/50Hz YCbCr HD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," 2 Rec2020 YCbCr UHD (16-235,240)/255 \"TV\" levels\n");
+ fprintf(stderr," C Rec2020 Constant Luminance YCbCr UHD (16-235,240)/255 \"TV\" levels\n");
fprintf(stderr," -k [zhxrlv] Black value target: z = zero K,\n");
fprintf(stderr," h = 0.5 K, x = max K, r = ramp K (def.)\n");
fprintf(stderr," l = extra PCS input is portion of K locus\n");
@@ -101,10 +113,11 @@ void usage(char *diag) {
fprintf(stderr," w:x:y Adapted white point as x, y\n");
fprintf(stderr," a:adaptation Adaptation luminance in cd.m^2 (default 50.0)\n");
fprintf(stderr," b:background Background %% of image luminance (default 20)\n");
- fprintf(stderr," l:scenewhite Scene white in cd.m^2 if surround = auto (default 250)\n");
- fprintf(stderr," f:flare Flare light %% of image luminance (default 1)\n");
- fprintf(stderr," f:X:Y:Z Flare color as XYZ (default media white, Abs: D50)\n");
- fprintf(stderr," f:x:y Flare color as x, y\n");
+ fprintf(stderr," l:imagewhite Image white in cd.m^2 if surround = auto (default 250)\n");
+ fprintf(stderr," f:flare Flare light %% of image luminance (default 0)\n");
+ fprintf(stderr," g:glare Flare light %% of ambient (default 1)\n");
+ fprintf(stderr," g:X:Y:Z Flare color as XYZ (default media white, Abs: D50)\n");
+ fprintf(stderr," g:x:y Flare color as x, y\n");
fprintf(stderr,"\n");
fprintf(stderr," The colors to be translated should be fed into standard in,\n");
fprintf(stderr," one input color per line, white space separated.\n");
@@ -141,9 +154,10 @@ int
main(int argc, char *argv[]) {
int fa,nfa; /* argument we're looking at */
char prof_name[MAXNAMEL+1];
- icmFile *fp;
- icc *icco;
- xicc *xicco;
+ icmFile *fp = NULL;
+ icc *icco = NULL;
+ xicc *xicco = NULL;
+ xcal *cal = NULL; /* If .cal rather than .icm/.icc, not NULL */
int doplot = 0; /* Do grey axis plot */
double pstart[3] = { -1000.0 }; /* Plot Lab/Jab PCS start point = white */
double pend[3] = { -1000.0 }; /* Plot Lab/Jab PCS end point = black */
@@ -157,11 +171,12 @@ main(int argc, char *argv[]) {
double vc_wXYZ[3] = {-1.0, -1.0, -1.0}; /* Adapted white override in XYZ */
double vc_wxy[2] = {-1.0, -1.0}; /* Adapted white override in x,y */
double vc_a = -1.0; /* Adapted luminance */
- double vc_b = -1.0; /* Background % overid */
+ double vc_b = -1.0; /* Background % overide */
double vc_l = -1.0; /* Scene luminance override */
- double vc_f = -1.0; /* Flare % overid */
- double vc_fXYZ[3] = {-1.0, -1.0, -1.0}; /* Flare color override in XYZ */
- double vc_fxy[2] = {-1.0, -1.0}; /* Flare color override in x,y */
+ double vc_f = -1.0; /* Flare % overide */
+ double vc_g = -1.0; /* Glare % overide */
+ double vc_gXYZ[3] = {-1.0, -1.0, -1.0}; /* Glare color override in XYZ */
+ double vc_gxy[2] = {-1.0, -1.0}; /* Glare color override in x,y */
int verb = 1;
int actual = 0;
int slocwarn = 0;
@@ -172,11 +187,13 @@ main(int argc, char *argv[]) {
int repLCh = 0; /* Report LCh */
int repXYZ100 = 0; /* Scale XYZ by 10 */
double scale = 0.0; /* Device value scale factor */
+ int in_tvenc; /* 1 to use RGB Video Level encoding, 2 = Rec601, 3 = Rec709 YCbCr */
+ int out_tvenc; /* 1 to use RGB Video Level encoding, 2 = Rec601, 3 = Rec709 YCbCr */
int rv = 0;
char buf[200];
double uin[MAX_CHAN], in[MAX_CHAN], out[MAX_CHAN], uout[MAX_CHAN];
- icxLuBase *luo, *aluo = NULL;
+ icxLuBase *luo = NULL, *aluo = NULL;
icColorSpaceSignature ins, outs; /* Type of input and output spaces */
int inn, outn; /* Number of components */
icmLuAlgType alg; /* Type of lookup algorithm */
@@ -194,6 +211,8 @@ main(int argc, char *argv[]) {
double Kstle1 = 0.0, Kstpo1 = 0.0, Kenle1 = 0.0, Kenpo1 = 0.0, Kshap1 = 0.0;
int invert = 0;
+ xslpoly *chlp = NULL;
+
#ifdef SPTEST
int sptest = 0;
warning("xicc/xicclu.c !!!! special rspl gamut sest code is compiled in !!!!\n");
@@ -285,6 +304,43 @@ main(int argc, char *argv[]) {
scale = atof(na);
if (scale <= 0.0) usage("Illegal scale value");
}
+ /* Video RGB encoding */
+ else if (argv[fa][1] == 'e'
+ || argv[fa][1] == 'E') {
+ int enc;
+ if (na == NULL) usage("Video encodong flag (-e/E) needs an argument");
+ switch (na[0]) {
+ case 'n': /* Normal */
+ enc = 0;
+ break;
+ case 't': /* TV 16 .. 235 */
+ enc = 1;
+ break;
+ case '6': /* Rec601 YCbCr */
+ enc = 2;
+ break;
+ case '7': /* Rec709 1150/60/2:1 YCbCr */
+ enc = 3;
+ break;
+ case '5': /* Rec709 1250/50/2:1 YCbCr (HD) */
+ enc = 4;
+ break;
+ case '2': /* Rec2020 Non-constant Luminance YCbCr (UHD) */
+ enc = 5;
+ break;
+ case 'C': /* Rec2020 Constant Luminance YCbCr (UHD) */
+ enc = 6;
+ break;
+ default:
+ usage("Video encoding (-E) argument not recognised");
+ }
+ if (argv[fa][1] == 'e')
+ in_tvenc = enc;
+ else
+ out_tvenc = enc;
+ fa = nfa;
+ }
+
/* function */
else if (argv[fa][1] == 'f') {
fa = nfa;
@@ -375,12 +431,14 @@ main(int argc, char *argv[]) {
repYxy = 0;
repLCh = 0;
repJCh = 0;
+ repXYZ100 = 0;
break;
case 'L':
pcsor = icSigLabData;
repYxy = 0;
repLCh = 1;
repJCh = 0;
+ repXYZ100 = 0;
break;
case 'y':
case 'Y':
@@ -388,18 +446,21 @@ main(int argc, char *argv[]) {
repYxy = 1;
repLCh = 0;
repJCh = 0;
+ repXYZ100 = 0;
break;
case 'j':
pcsor = icxSigJabData;
repYxy = 0;
repLCh = 0;
repJCh = 0;
+ repXYZ100 = 0;
break;
case 'J':
pcsor = icxSigJabData;
repYxy = 0;
repLCh = 0;
repJCh = 1;
+ repXYZ100 = 0;
break;
default:
usage("Unknown parameter after flag -i");
@@ -425,7 +486,8 @@ main(int argc, char *argv[]) {
}
/* Inking rule */
- else if (argv[fa][1] == 'k') {
+ else if (argv[fa][1] == 'k'
+ || argv[fa][1] == 'K') {
fa = nfa;
if (na == NULL) usage("No parameter after flag -k");
if (argv[fa][1] == 'k')
@@ -578,18 +640,22 @@ main(int argc, char *argv[]) {
vc_b = atof(na+2);
} else if (na[0] == 'l' || na[0] == 'L') {
if (na[1] != ':')
- usage("Viewing conditions (-[cd]l) missing ':'");
+ usage("Viewing conditions (-cl) missing ':'");
vc_l = atof(na+2);
} else if (na[0] == 'f' || na[0] == 'F') {
+ if (na[1] != ':')
+ usage("Viewing conditions (-cf) missing ':'");
+ vc_f = atof(na+2);
+ } else if (na[0] == 'g' || na[0] == 'G') {
double x, y, z;
if (sscanf(na+1,":%lf:%lf:%lf",&x,&y,&z) == 3) {
- vc_fXYZ[0] = x; vc_fXYZ[1] = y; vc_fXYZ[2] = z;
+ vc_gXYZ[0] = x; vc_gXYZ[1] = y; vc_gXYZ[2] = z;
} else if (sscanf(na+1,":%lf:%lf",&x,&y) == 2) {
- vc_fxy[0] = x; vc_fxy[1] = y;
+ vc_gxy[0] = x; vc_gxy[1] = y;
} else if (sscanf(na+1,":%lf",&x) == 1) {
- vc_f = x;
+ vc_g = x;
} else
- usage("Unrecognised parameters after -cf");
+ usage("Unrecognised parameters after -cg");
} else
usage("Unrecognised parameters after -c");
}
@@ -603,17 +669,17 @@ main(int argc, char *argv[]) {
if (fa >= argc || argv[fa][0] == '-') usage("Expecting profile file name");
strncpy(prof_name,argv[fa],MAXNAMEL); prof_name[MAXNAMEL] = '\000';
- if (doplot) {
-
- /* Force PCS to be Lab or Jab */
- repJCh = 0;
- repLCh = 0;
- if (pcsor != icxSigJabData)
- pcsor = icSigLabData;
+ if (slocwarn) {
+ if ((chlp = chrom_locus_poligon(0, icxOT_CIE_1931_2, 0)) == NULL)
+ error("chrom_locus_poligon failed");
+ }
- if ((invert == 0 && func != icmBwd)
- || (invert != 0 && func != icmFwd))
- error("Must use -fb or -fif for grey axis plot");
+ if (verb > 1) {
+ icmFile *op;
+ if ((op = new_icmFileStd_fp(stdout)) == NULL)
+ error ("Can't open stdout");
+ icco->header->dump(icco->header, op, 1);
+ op->del(op);
}
/* Open up the profile for reading */
@@ -623,248 +689,275 @@ main(int argc, char *argv[]) {
if ((icco = new_icc()) == NULL)
error ("Creation of ICC object failed");
- if ((rv = icco->read(icco,fp,0)) != 0)
- error ("%d, %s",rv,icco->err);
+ if ((rv = icco->read(icco,fp,0)) == 0) { /* ICC profile */
- if (doplot) {
- if (icco->header->deviceClass != icSigInputClass
- && icco->header->deviceClass != icSigDisplayClass
- && icco->header->deviceClass != icSigOutputClass)
- error("Profile must be a device profile to plot neutral axis");
- }
+ if (doplot) {
+
+ /* Force PCS to be Lab or Jab */
+ repJCh = 0;
+ repLCh = 0;
+ if (pcsor != icxSigJabData)
+ pcsor = icSigLabData;
+
+ if ((invert == 0 && func != icmBwd)
+ || (invert != 0 && func != icmFwd))
+ error("Must use -fb or -fif for grey axis plot");
+ }
- if (verb > 1) {
- icmFile *op;
- if ((op = new_icmFileStd_fp(stdout)) == NULL)
- error ("Can't open stdout");
- icco->header->dump(icco->header, op, 1);
- op->del(op);
- }
+ if (icco->header->cmmId == str2tag("argl"))
+ icco->allowclutPoints256 = 1;
+
+ if (doplot) {
+ if (icco->header->deviceClass != icSigInputClass
+ && icco->header->deviceClass != icSigDisplayClass
+ && icco->header->deviceClass != icSigOutputClass)
+ error("Profile must be a device profile to plot neutral axis");
+ }
- /* Wrap with an expanded icc */
- if ((xicco = new_xicc(icco)) == NULL)
- error ("Creation of xicc failed");
+ /* Wrap with an expanded icc */
+ if ((xicco = new_xicc(icco)) == NULL)
+ error ("Creation of xicc failed");
- /* Set the default ink limits if not set on command line */
- icxDefaultLimits(xicco, &ink.tlimit, tlimit, &ink.klimit, klimit);
+ /* Set the default ink limits if not set on command line */
+ icxDefaultLimits(xicco, &ink.tlimit, tlimit, &ink.klimit, klimit);
- if (verb > 1) {
- if (ink.tlimit >= 0.0)
- printf("Total ink limit assumed is %3.0f%%\n",100.0 * ink.tlimit);
- if (ink.klimit >= 0.0)
- printf("Black ink limit assumed is %3.0f%%\n",100.0 * ink.klimit);
- }
+ if (verb > 1) {
+ if (ink.tlimit >= 0.0)
+ printf("Total ink limit assumed is %3.0f%%\n",100.0 * ink.tlimit);
+ if (ink.klimit >= 0.0)
+ printf("Black ink limit assumed is %3.0f%%\n",100.0 * ink.klimit);
+ }
- ink.KonlyLmin = 0; /* Use normal black as locus Lmin */
-
- ink.c.Ksmth = ICXINKDEFSMTH; /* Default curve smoothing */
- ink.c.Kskew = ICXINKDEFSKEW; /* default curve skew */
- ink.x.Ksmth = ICXINKDEFSMTH;
- ink.x.Kskew = ICXINKDEFSKEW;
-
- if (inking == 0) { /* Use minimum */
- ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
- ink.c.Kstle = 0.0;
- ink.c.Kstpo = 0.0;
- ink.c.Kenpo = 1.0;
- ink.c.Kenle = 0.0;
- ink.c.Kshap = 1.0;
- } else if (inking == 1) { /* Use 0.5 */
- ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
- ink.c.Kstle = 0.5;
- ink.c.Kstpo = 0.0;
- ink.c.Kenpo = 1.0;
- ink.c.Kenle = 0.5;
- ink.c.Kshap = 1.0;
- } else if (inking == 2) { /* Use maximum */
- ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
- ink.c.Kstle = 1.0;
- ink.c.Kstpo = 0.0;
- ink.c.Kenpo = 1.0;
- ink.c.Kenle = 1.0;
- ink.c.Kshap = 1.0;
- } else if (inking == 3) { /* Use ramp */
- ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
- ink.c.Kstle = 0.0;
- ink.c.Kstpo = 0.0;
- ink.c.Kenpo = 1.0;
- ink.c.Kenle = 1.0;
- ink.c.Kshap = 1.0;
- } else if (inking == 4) { /* Use locus */
- ink.k_rule = icxKlocus;
- } else if (inking == 5) { /* Use K target */
- ink.k_rule = icxKvalue;
- } else if (inking == 6) { /* Use specified curve */
- ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
- ink.c.Kstle = Kstle;
- ink.c.Kstpo = Kstpo;
- ink.c.Kenpo = Kenpo;
- ink.c.Kenle = Kenle;
- ink.c.Kshap = Kshap;
- } else { /* Use dual curves */
- ink.k_rule = locus ? icxKl5l : icxKl5lk; /* Locus or value target */
- ink.c.Kstle = Kstle;
- ink.c.Kstpo = Kstpo;
- ink.c.Kenpo = Kenpo;
- ink.c.Kenle = Kenle;
- ink.c.Kshap = Kshap;
- ink.x.Kstle = Kstle1;
- ink.x.Kstpo = Kstpo1;
- ink.x.Kenpo = Kenpo1;
- ink.x.Kenle = Kenle1;
- ink.x.Kshap = Kshap1;
- }
+ ink.KonlyLmin = 0; /* Use normal black as locus Lmin */
+
+ ink.c.Ksmth = ICXINKDEFSMTH; /* Default curve smoothing */
+ ink.c.Kskew = ICXINKDEFSKEW; /* default curve skew */
+ ink.x.Ksmth = ICXINKDEFSMTH;
+ ink.x.Kskew = ICXINKDEFSKEW;
+
+ if (inking == 0) { /* Use minimum */
+ ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
+ ink.c.Kstle = 0.0;
+ ink.c.Kstpo = 0.0;
+ ink.c.Kenpo = 1.0;
+ ink.c.Kenle = 0.0;
+ ink.c.Kshap = 1.0;
+ } else if (inking == 1) { /* Use 0.5 */
+ ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
+ ink.c.Kstle = 0.5;
+ ink.c.Kstpo = 0.0;
+ ink.c.Kenpo = 1.0;
+ ink.c.Kenle = 0.5;
+ ink.c.Kshap = 1.0;
+ } else if (inking == 2) { /* Use maximum */
+ ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
+ ink.c.Kstle = 1.0;
+ ink.c.Kstpo = 0.0;
+ ink.c.Kenpo = 1.0;
+ ink.c.Kenle = 1.0;
+ ink.c.Kshap = 1.0;
+ } else if (inking == 3) { /* Use ramp */
+ ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
+ ink.c.Kstle = 0.0;
+ ink.c.Kstpo = 0.0;
+ ink.c.Kenpo = 1.0;
+ ink.c.Kenle = 1.0;
+ ink.c.Kshap = 1.0;
+ } else if (inking == 4) { /* Use locus */
+ ink.k_rule = icxKlocus;
+ } else if (inking == 5) { /* Use K target */
+ ink.k_rule = icxKvalue;
+ } else if (inking == 6) { /* Use specified curve */
+ ink.k_rule = locus ? icxKluma5 : icxKluma5k; /* Locus or value target */
+ ink.c.Kstle = Kstle;
+ ink.c.Kstpo = Kstpo;
+ ink.c.Kenpo = Kenpo;
+ ink.c.Kenle = Kenle;
+ ink.c.Kshap = Kshap;
+ } else { /* Use dual curves */
+ ink.k_rule = locus ? icxKl5l : icxKl5lk; /* Locus or value target */
+ ink.c.Kstle = Kstle;
+ ink.c.Kstpo = Kstpo;
+ ink.c.Kenpo = Kenpo;
+ ink.c.Kenle = Kenle;
+ ink.c.Kshap = Kshap;
+ ink.x.Kstle = Kstle1;
+ ink.x.Kstpo = Kstpo1;
+ ink.x.Kenpo = Kenpo1;
+ ink.x.Kenle = Kenle1;
+ ink.x.Kshap = Kshap1;
+ }
- /* Setup the viewing conditions */
- if (xicc_enum_viewcond(xicco, &vc, -1, NULL, 0, NULL) == -999)
- error ("%d, %s",xicco->errc, xicco->err);
+ /* Setup the viewing conditions in case we need them */
+ if (xicc_enum_viewcond(xicco, &vc, -1, NULL, 0, NULL) == -999) {
+ if (camclip || pcsor == icxSigJabData) /* If it will be needed */
+ error("%d, %s",xicco->errc, xicco->err);
+ }
//xicc_dump_viewcond(&vc);
- if (vc_e != -1)
- if (xicc_enum_viewcond(xicco, &vc, vc_e, NULL, 0, NULL) == -999)
- error ("%d, %s",xicco->errc, xicco->err);
- if (vc_s >= 0)
- vc.Ev = vc_s;
- if (vc_wXYZ[1] > 0.0) {
- /* Normalise it to current media white */
- vc.Wxyz[0] = vc_wXYZ[0]/vc_wXYZ[1] * vc.Wxyz[1];
- vc.Wxyz[2] = vc_wXYZ[2]/vc_wXYZ[1] * vc.Wxyz[1];
- }
- if (vc_wxy[0] >= 0.0) {
- double x = vc_wxy[0];
- double y = vc_wxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
- double z = 1.0 - x - y;
- vc.Wxyz[0] = x/y * vc.Wxyz[1];
- vc.Wxyz[2] = z/y * vc.Wxyz[1];
- }
- if (vc_a >= 0.0)
- vc.La = vc_a;
- if (vc_b >= 0.0)
- vc.Yb = vc_b/100.0;
- if (vc_l >= 0.0)
- vc.Lv = vc_l;
- if (vc_f >= 0.0)
- vc.Yf = vc_f/100.0;
- if (vc_fXYZ[1] > 0.0) {
- /* Normalise it to current media white */
- vc.Fxyz[0] = vc_fXYZ[0]/vc_fXYZ[1] * vc.Fxyz[1];
- vc.Fxyz[2] = vc_fXYZ[2]/vc_fXYZ[1] * vc.Fxyz[1];
- }
- if (vc_fxy[0] >= 0.0) {
- double x = vc_fxy[0];
- double y = vc_fxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
- double z = 1.0 - x - y;
- vc.Fxyz[0] = x/y * vc.Fxyz[1];
- vc.Fxyz[2] = z/y * vc.Fxyz[1];
- }
+ if (vc_e != -1)
+ if (xicc_enum_viewcond(xicco, &vc, vc_e, NULL, 0, NULL) == -999)
+ error ("%d, %s",xicco->errc, xicco->err);
+ if (vc_s >= 0)
+ vc.Ev = vc_s;
+ if (vc_wXYZ[1] > 0.0) {
+ /* Normalise it to current media white */
+ vc.Wxyz[0] = vc_wXYZ[0]/vc_wXYZ[1] * vc.Wxyz[1];
+ vc.Wxyz[2] = vc_wXYZ[2]/vc_wXYZ[1] * vc.Wxyz[1];
+ }
+ if (vc_wxy[0] >= 0.0) {
+ double x = vc_wxy[0];
+ double y = vc_wxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ double z = 1.0 - x - y;
+ vc.Wxyz[0] = x/y * vc.Wxyz[1];
+ vc.Wxyz[2] = z/y * vc.Wxyz[1];
+ }
+ if (vc_a >= 0.0)
+ vc.La = vc_a;
+ if (vc_b >= 0.0)
+ vc.Yb = vc_b/100.0;
+ if (vc_l >= 0.0)
+ vc.Lv = vc_l;
+ if (vc_f >= 0.0)
+ vc.Yf = vc_f/100.0;
+ if (vc_g >= 0.0)
+ vc.Yg = vc_g/100.0;
+ if (vc_gXYZ[1] > 0.0) {
+ /* Normalise it to current media white */
+ vc.Gxyz[0] = vc_gXYZ[0]/vc_gXYZ[1] * vc.Gxyz[1];
+ vc.Gxyz[2] = vc_gXYZ[2]/vc_gXYZ[1] * vc.Gxyz[1];
+ }
+ if (vc_gxy[0] >= 0.0) {
+ double x = vc_gxy[0];
+ double y = vc_gxy[1]; /* If Y == 1.0, then X+Y+Z = 1/y */
+ double z = 1.0 - x - y;
+ vc.Gxyz[0] = x/y * vc.Gxyz[1];
+ vc.Gxyz[2] = z/y * vc.Gxyz[1];
+ }
//xicc_dump_viewcond(&vc);
- /* Get a expanded color conversion object */
- if ((luo = xicco->get_luobj(xicco, 0
+ /* Get a expanded color conversion object */
+ if ((luo = xicco->get_luobj(xicco, 0
#ifdef USE_NEARCLIP
- | ICX_CLIP_NEAREST
+ | ICX_CLIP_NEAREST
#endif
- | (intsep ? ICX_INT_SEPARATE : 0)
- | (merge ? ICX_MERGE_CLUT : 0)
- | (camclip ? ICX_CAM_CLIP : 0)
- | ICX_FAST_SETUP
- , func, intent, pcsor, order, &vc, &ink)) == NULL)
- error ("%d, %s",xicco->errc, xicco->err);
-
- /* Get details of conversion (Arguments may be NULL if info not needed) */
- if (invert)
- luo->spaces(luo, &outs, &outn, &ins, &inn, &alg, NULL, NULL, NULL);
- else
- luo->spaces(luo, &ins, &inn, &outs, &outn, &alg, NULL, NULL, NULL);
-
- /* If we can do check on clipped values */
- if (actual != 0) {
- if (invert == 0) {
- if (func == icmFwd || func == icmBwd) {
- if ((aluo = xicco->get_luobj(xicco, ICX_CLIP_NEAREST,
- func == icmFwd ? icmBwd : icmFwd, intent, pcsor, order, &vc, &ink)) == NULL)
- error ("%d, %s",xicco->errc, xicco->err);
+ | (intsep ? ICX_INT_SEPARATE : 0)
+ | (merge ? ICX_MERGE_CLUT : 0)
+ | (camclip ? ICX_CAM_CLIP : 0)
+ | ICX_FAST_SETUP
+ , func, intent, pcsor, order, &vc, &ink)) == NULL)
+ error ("%d, %s",xicco->errc, xicco->err);
+
+ /* Get details of conversion (Arguments may be NULL if info not needed) */
+ if (invert)
+ luo->spaces(luo, &outs, &outn, &ins, &inn, &alg, NULL, NULL, NULL);
+ else
+ luo->spaces(luo, &ins, &inn, &outs, &outn, &alg, NULL, NULL, NULL);
+
+ /* If we can do check on clipped values */
+ if (actual != 0) {
+ if (invert == 0) {
+ if (func == icmFwd || func == icmBwd) {
+ if ((aluo = xicco->get_luobj(xicco, ICX_CLIP_NEAREST,
+ func == icmFwd ? icmBwd : icmFwd, intent, pcsor, order, &vc, &ink)) == NULL)
+ error ("%d, %s",xicco->errc, xicco->err);
+ }
+ } else {
+ aluo = luo; /* We can use the same one */
}
- } else {
- aluo = luo; /* We can use the same one */
}
- }
- /* More information */
- if (verb > 1) {
- int j;
- double inmin[MAX_CHAN], inmax[MAX_CHAN];
- double outmin[MAX_CHAN], outmax[MAX_CHAN];
-
- luo->get_native_ranges(luo, inmin, inmax, outmin,outmax);
- printf("Internal input value range: ");
- for (j = 0; j < inn; j++) {
- if (j > 0)
- fprintf(stdout," %f..%f",inmin[j], inmax[j]);
- else
- fprintf(stdout,"%f..%f",inmin[j], inmax[j]);
+ /* More information */
+ if (verb > 1) {
+ int j;
+ double inmin[MAX_CHAN], inmax[MAX_CHAN];
+ double outmin[MAX_CHAN], outmax[MAX_CHAN];
+
+ luo->get_native_ranges(luo, inmin, inmax, outmin,outmax);
+ printf("Internal input value range: ");
+ for (j = 0; j < inn; j++) {
+ if (j > 0)
+ fprintf(stdout," %f..%f",inmin[j], inmax[j]);
+ else
+ fprintf(stdout,"%f..%f",inmin[j], inmax[j]);
+ }
+ printf("\nInternal output value range: ");
+ for (j = 0; j < outn; j++) {
+ if (j > 0)
+ fprintf(stdout," %f..%f",outmin[j], outmax[j]);
+ else
+ fprintf(stdout,"%f..%f",outmin[j], outmax[j]);
+ }
+
+ luo->get_ranges(luo, inmin, inmax, outmin,outmax);
+ printf("\nInput value range: ");
+ for (j = 0; j < inn; j++) {
+ if (j > 0)
+ fprintf(stdout," %f..%f",inmin[j], inmax[j]);
+ else
+ fprintf(stdout,"%f..%f",inmin[j], inmax[j]);
+ }
+ printf("\nOutput value range: ");
+ for (j = 0; j < outn; j++) {
+ if (j > 0)
+ fprintf(stdout," %f..%f",outmin[j], outmax[j]);
+ else
+ fprintf(stdout,"%f..%f",outmin[j], outmax[j]);
+ }
+ printf("\n");
}
- printf("\nInternal output value range: ");
- for (j = 0; j < outn; j++) {
- if (j > 0)
- fprintf(stdout," %f..%f",outmin[j], outmax[j]);
- else
- fprintf(stdout,"%f..%f",outmin[j], outmax[j]);
+
+ if (repYxy) { /* report Yxy rather than XYZ */
+ if (ins == icSigXYZData)
+ ins = icSigYxyData;
+ if (outs == icSigXYZData)
+ outs = icSigYxyData;
}
- luo->get_ranges(luo, inmin, inmax, outmin,outmax);
- printf("\nInput value range: ");
- for (j = 0; j < inn; j++) {
- if (j > 0)
- fprintf(stdout," %f..%f",inmin[j], inmax[j]);
- else
- fprintf(stdout,"%f..%f",inmin[j], inmax[j]);
+ if (repJCh) { /* report JCh rather than Jab */
+ if (ins == icxSigJabData)
+ ins = icxSigJChData;
+ if (outs == icxSigJabData)
+ outs = icxSigJChData;
}
- printf("\nOutput value range: ");
- for (j = 0; j < outn; j++) {
- if (j > 0)
- fprintf(stdout," %f..%f",outmin[j], outmax[j]);
- else
- fprintf(stdout,"%f..%f",outmin[j], outmax[j]);
+ if (repLCh) { /* report LCh rather than Lab */
+ if (ins == icSigLabData)
+ ins = icxSigLChData;
+ if (outs == icSigLabData)
+ outs = icxSigLChData;
}
- printf("\n");
- }
- if (repYxy) { /* report Yxy rather than XYZ */
- if (ins == icSigXYZData)
- ins = icSigYxyData;
- if (outs == icSigXYZData)
- outs = icSigYxyData;
- }
+#ifdef SPTEST
+ if (sptest) {
+ icxLuLut *clu;
+ double cent[3] = { 50.0, 0.0, 0.0 };
- if (repJCh) { /* report JCh rather than Jab */
- if (ins == icxSigJabData)
- ins = icxSigJChData;
- if (outs == icxSigJabData)
- outs = icxSigJChData;
- }
- if (repLCh) { /* report LCh rather than Lab */
- if (ins == icSigLabData)
- ins = icxSigLChData;
- if (outs == icSigLabData)
- outs = icxSigLChData;
- }
+ if (luo->plu->ttype != icmLutType)
+ error("Special test only works on CLUT profiles");
-#ifdef SPTEST
- if (sptest) {
- icxLuLut *clu;
- double cent[3] = { 50.0, 0.0, 0.0 };
+ clu = (icxLuLut *)luo;
+
+ clu->clutTable->comp_gamut(clu->clutTable, cent, NULL, spoutf, clu, spioutf, clu);
+ rspl_gam_plot(clu->clutTable, "sp_test.wrl", sptest-1);
+ exit(0);
+ }
+#endif
+
+ } else { /* See if it's a .cal */
+ fp->del(fp);
+ fp = NULL;
- if (luo->plu->ttype != icmLutType)
- error("Special test only works on CLUT profiles");
+ if ((cal = new_xcal()) == NULL)
+ error("new_xcal failed");
- clu = (icxLuLut *)luo;
+ if ((cal->read(cal, prof_name)) != 0) {
+ error ("File '%s' is not an ICC or .cal file",prof_name);
+ }
- clu->clutTable->comp_gamut(clu->clutTable, cent, NULL, spoutf, clu, spioutf, clu);
- rspl_gam_plot(clu->clutTable, "sp_test.wrl", sptest-1);
- exit(0);
+ /* Get details of conversion (Arguments may be NULL if info not needed) */
+ outs = ins = cal->colspace;
+ outn = inn = cal->devchan;
}
-#endif
if (doplot) {
int i, j;
@@ -872,43 +965,64 @@ main(int argc, char *argv[]) {
double yy[6][XRES];
double start[3], end[3];
- /* Plot from white to black by default */
- luo->efv_wh_bk_points(luo, start, end, NULL);
+ if (cal != NULL) {
+ for (i = 0; i < XRES; i++) {
+ double ival = (double)i/(XRES-1.0);
- if (pstart[0] == -1000.0)
- icmCpy3(pstart, start);
+ for (j = 0; j < inn; j++)
+ in[j] = ival;
- if (pend[0] == -1000.0)
- icmCpy3(pend, end);
+ /* Do the conversion */
+ if (func == icmBwd || invert) {
+ if ((rv = cal->inv_interp(cal, out, in)) != 0)
+ error ("%d, %s",cal->errc,cal->err);
+ } else {
+ cal->interp(cal, out, in);
+ }
- if (verb) {
- printf("Plotting from white %f %f %f to black %f %f %f\n",
- pstart[0], pstart[1], pstart[2], pend[0], pend[1], pend[2]);
- }
- for (i = 0; i < XRES; i++) {
- double ival = (double)i/(XRES-1.0);
+ xx[i] = 100.0 * ival;
+ for (j = 0; j < outn; j++)
+ yy[j][i] = 100.0 * out[j];
+ }
+ } else {
+ /* Plot from white to black by default */
+ luo->efv_wh_bk_points(luo, start, end, NULL);
+
+ if (pstart[0] == -1000.0)
+ icmCpy3(pstart, start);
+
+ if (pend[0] == -1000.0)
+ icmCpy3(pend, end);
- /* Input is always Jab or Lab */
- in[0] = ival * pend[0] + (1.0 - ival) * pstart[0];
- in[1] = ival * pend[1] + (1.0 - ival) * pstart[1];
- in[2] = ival * pend[2] + (1.0 - ival) * pstart[2];
+ if (verb) {
+ printf("Plotting from white %f %f %f to black %f %f %f\n",
+ pstart[0], pstart[1], pstart[2], pend[0], pend[1], pend[2]);
+ }
+ for (i = 0; i < XRES; i++) {
+ double ival = (double)i/(XRES-1.0);
+
+ /* Input is always Jab or Lab */
+ in[0] = ival * pend[0] + (1.0 - ival) * pstart[0];
+ in[1] = ival * pend[1] + (1.0 - ival) * pstart[1];
+ in[2] = ival * pend[2] + (1.0 - ival) * pstart[2];
//in[1] = in[2] = 0.0;
- /* Do the conversion */
- if (invert) {
- if ((rv = luo->inv_lookup(luo, out, in)) > 1)
- error ("%d, %s",xicco->errc,xicco->err);
+ /* Do the conversion */
+ if (invert) {
+ if ((rv = luo->inv_lookup(luo, out, in)) > 1)
+ error ("%d, %s",xicco->errc,xicco->err);
//printf("~1 %f: %f %f %f -> %f %f %f %f\n", ival, in[0], in[1], in[2], out[0], out[1], out[2], out[3]);
- } else {
- if ((rv = luo->lookup(luo, out, in)) > 1)
- error ("%d, %s",xicco->errc,xicco->err);
- }
+ } else {
+ if ((rv = luo->lookup(luo, out, in)) > 1)
+ error ("%d, %s",xicco->errc,xicco->err);
+ }
- xx[i] = 100.0 * ival;
- for (j = 0; j < outn; j++)
- yy[j][i] = 100.0 * out[j];
- }
+ xx[i] = 100.0 * ival;
+ for (j = 0; j < outn; j++)
+ yy[j][i] = 100.0 * out[j];
+ }
//fflush(stdout);
+ }
/* plot order: Black Red Green Blue Yellow Purple */
if (outs == icSigRgbData) {
@@ -941,7 +1055,6 @@ main(int argc, char *argv[]) {
}
}
-
} else {
if (slocwarn && outs != icSigXYZData
@@ -966,7 +1079,7 @@ main(int argc, char *argv[]) {
continue;
}
/* For each input number */
- for (bp = buf-1, nbp = buf, i = 0; i < MAX_CHAN; i++) {
+ for (nbp = buf, i = 0; i < MAX_CHAN; i++) {
bp = nbp;
uout[i] = out[i] = in[i] = uin[i] = strtod(bp, &nbp);
if (nbp == bp)
@@ -976,8 +1089,7 @@ main(int argc, char *argv[]) {
break;
/* If device data and scale */
- if(scale > 0.0
- && ins != icxSigJabData
+ if( ins != icxSigJabData
&& ins != icxSigJChData
&& ins != icSigXYZData
&& ins != icSigLabData
@@ -987,8 +1099,29 @@ main(int argc, char *argv[]) {
&& ins != icSigYxyData
&& ins != icSigHsvData
&& ins != icSigHlsData) {
- for (i = 0; i < MAX_CHAN; i++) {
- in[i] /= scale;
+ if (scale > 0.0) {
+ for (i = 0; i < MAX_CHAN; i++)
+ in[i] /= scale;
+ }
+ if (inn == 3 && in_tvenc != 0) {
+ if (in_tvenc == 1) { /* Video 16-235 range */
+ icmRGB_2_VidRGB(in, in);
+ } else if (in_tvenc == 2) { /* Rec601 YCbCr */
+ icmRec601_RGBd_2_YPbPr(in, in);
+ icmRecXXX_YPbPr_2_YCbCr(in, in);
+ } else if (in_tvenc == 3) { /* Rec709 YCbCr */
+ icmRec709_RGBd_2_YPbPr(in, in);
+ icmRecXXX_YPbPr_2_YCbCr(in, in);
+ } else if (out_tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ icmRec709_50_RGBd_2_YPbPr(in, in);
+ icmRecXXX_YPbPr_2_YCbCr(in, in);
+ } else if (out_tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRec2020_NCL_RGBd_2_YPbPr(in, in);
+ icmRecXXX_YPbPr_2_YCbCr(in, in);
+ } else if (out_tvenc == 6) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRec2020_CL_RGBd_2_YPbPr(in, in);
+ icmRecXXX_YPbPr_2_YCbCr(in, in);
+ }
}
}
@@ -999,7 +1132,7 @@ main(int argc, char *argv[]) {
}
if (repYxy && ins == icSigYxyData) {
- icmXYZ2Yxy(in, in);
+ icmYxy2XYZ(in, in);
}
/* JCh -> Jab & LCh -> Lab */
@@ -1012,14 +1145,25 @@ main(int argc, char *argv[]) {
}
/* Do conversion */
- if (invert) {
- for (j = 0; j < MAX_CHAN; j++)
- out[j] = in[j]; /* Carry any auxiliary value to out for lookup */
- if ((rv = luo->inv_lookup(luo, out, in)) > 1)
- error ("%d, %s",xicco->errc,xicco->err);
- } else {
- if ((rv = luo->lookup(luo, out, in)) > 1)
- error ("%d, %s",xicco->errc,xicco->err);
+ if (cal != NULL) { /* .cal */
+ if (func == icmBwd || invert) {
+ if ((rv = cal->inv_interp(cal, out, in)) != 0)
+ error ("%d, %s",cal->errc,cal->err);
+ } else {
+ cal->interp(cal, out, in);
+ rv = 0;
+ }
+
+ } else { /* ICC */
+ if (invert) {
+ for (j = 0; j < MAX_CHAN; j++)
+ out[j] = in[j]; /* Carry any auxiliary value to out for lookup */
+ if ((rv = luo->inv_lookup(luo, out, in)) > 1)
+ error ("%d, %s",xicco->errc,xicco->err);
+ } else {
+ if ((rv = luo->lookup(luo, out, in)) > 1)
+ error ("%d, %s",xicco->errc,xicco->err);
+ }
}
if (slocwarn) {
@@ -1030,7 +1174,7 @@ main(int argc, char *argv[]) {
else
icmCpy3(xyz, out);
- outsloc = icx_outside_spec_locus(xyz, icxOT_CIE_1931_2);
+ outsloc = icx_outside_spec_locus(chlp, xyz);
}
/* Copy conversion out value so that we can create user values */
@@ -1044,7 +1188,7 @@ main(int argc, char *argv[]) {
}
if (repYxy && outs == icSigYxyData) {
- icmXYZ2Yxy(out, out);
+ icmXYZ2Yxy(uout, uout);
}
/* Jab -> JCh and Lab -> LCh */
@@ -1058,8 +1202,7 @@ main(int argc, char *argv[]) {
}
/* If device data and scale */
- if(scale > 0.0
- && outs != icxSigJabData
+ if( outs != icxSigJabData
&& outs != icxSigJChData
&& outs != icSigXYZData
&& outs != icSigLabData
@@ -1069,8 +1212,29 @@ main(int argc, char *argv[]) {
&& outs != icSigYxyData
&& outs != icSigHsvData
&& outs != icSigHlsData) {
- for (i = 0; i < MAX_CHAN; i++) {
- uout[i] *= scale;
+ if (outn == 3 && out_tvenc != 0) {
+ if (out_tvenc == 1) { /* Video 16-235 range */
+ icmVidRGB_2_RGB(uout, uout);
+ } else if (out_tvenc == 2) { /* Rec601 YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(uout, uout);
+ icmRec601_YPbPr_2_RGBd(uout, uout);
+ } else if (out_tvenc == 3) { /* Rec709 1150/60/2:1 YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(uout, uout);
+ icmRec709_YPbPr_2_RGBd(uout, uout);
+ } else if (out_tvenc == 4) { /* Rec709 1250/50/2:1 YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(uout, uout);
+ icmRec709_50_YPbPr_2_RGBd(uout, uout);
+ } else if (out_tvenc == 5) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(uout, uout);
+ icmRec2020_NCL_YPbPr_2_RGBd(uout, uout);
+ } else if (out_tvenc == 6) { /* Rec2020 Non-constant Luminance YCbCr */
+ icmRecXXX_YCbCr_2_YPbPr(uout, uout);
+ icmRec2020_CL_YPbPr_2_RGBd(uout, uout);
+ }
+ }
+ if (scale > 0.0) {
+ for (i = 0; i < MAX_CHAN; i++)
+ uout[i] *= scale;
}
}
@@ -1082,8 +1246,11 @@ main(int argc, char *argv[]) {
else
fprintf(stdout,"%f",uin[j]);
}
- printf(" [%s] -> %s -> ", icx2str(icmColorSpaceSignature, ins),
- icm2str(icmLuAlg, alg));
+ if (cal != NULL)
+ printf(" [%s] -> ", icx2str(icmColorSpaceSignature, ins));
+ else
+ printf(" [%s] -> %s -> ", icx2str(icmColorSpaceSignature, ins),
+ icm2str(icmLuAlg, alg));
}
for (j = 0; j < outn; j++) {
@@ -1138,11 +1305,16 @@ main(int argc, char *argv[]) {
/* Done with lookup object */
if (aluo != NULL && aluo != luo)
luo->del(aluo);
- luo->del(luo);
-
- xicco->del(xicco); /* Expansion wrapper */
- icco->del(icco); /* Icc */
- fp->del(fp);
+ if (luo != NULL)
+ luo->del(luo);
+ if (cal != NULL)
+ cal->del(cal);
+ if (xicco != NULL)
+ xicco->del(xicco); /* Expansion wrapper */
+ if (icco != NULL)
+ icco->del(icco); /* Icc */
+ if (fp != NULL)
+ fp->del(fp);
return 0;
}
diff --git a/xicc/xlut.c b/xicc/xlut.c
index 21c286e..bbad934 100644
--- a/xicc/xlut.c
+++ b/xicc/xlut.c
@@ -56,8 +56,8 @@
do anything useful though, the chromatic adapation tag would
have to be used for absolute intent.
This may be the way of improving compatibility with other systems,
- but would break compatibility with existing Argyll profiles,
- unless special measures are taken:
+ and is needed for V4, but would break compatibility with existing
+ Argyll profiles, unless special measures are taken:
ie.
@@ -65,7 +65,7 @@
Create Bradford chromatic adapation matrix and store it in tag
Adapt all the readings using Bradford
Create white point and store it in tag (white point will be D50)
- Adapt all the readings to the white point using wrong Von-Kries (no change)
+ Adapt all the readings to the white point using wrong Von-Kries (== NOOP)
Store relative colorimetric cLUT
Set version >= 2.4
@@ -154,12 +154,16 @@
#undef DISABLE_KCURVE_FILTER /* [Undef] don't filter the Kcurve */
#undef REPORT_LOCUS_SEGMENTS /* [Undef[ Examine how many segments there are in aux inversion */
+#define XYZ_EXTRA_SMOOTH 20.0 /* Extra smoothing factor for XYZ profiles */
#define SHP_SMOOTH 1.0 /* Input shaper curve smoothing */
#define OUT_SMOOTH1 1.0 /* Output shaper curve smoothing for L*, X,Y,Z */
#define OUT_SMOOTH2 1.0 /* Output shaper curve smoothing for a*, b* */
#define CAMCLIPTRANS 1.0 /* [1.0] Cam clipping transition region Delta E */
-#define USECAMCLIPSPLINE /* [def] use spline blend */
+ /* Should this be smaller ? */
+#undef USECAMCLIPSPLINE /* [Und] use spline blend between PCS and Jab */
+
+#define CCJSCALE 2.0 /* [2.0] Amount to emphasize J delta E in in computing clip */
/*
* TTBD:
@@ -1322,6 +1326,7 @@ double *in /* Function input values to invert (== clut output' values) */
if (crv && clipd != NULL) {
+
/* Compute the clip DE */
for (cdist = 0.0, f = 0; f < fdi; f++) {
double tt;
@@ -1329,6 +1334,7 @@ double *in /* Function input values to invert (== clut output' values) */
cdist += tt * tt;
}
cdist = sqrt(cdist);
+ DBR(("Targ PCS %f %f %f Clipped %f %f %f cdist %f\n",tin[0],tin[1],tin[2],pp[0].v[0],pp[0].v[1],pp[0].v[2],cdist))
}
nsoln &= RSPL_NOSOLNS; /* Get number of solutions */
@@ -1368,6 +1374,7 @@ double *in /* Function input values to invert (== clut output' values) */
for (f = 0; f < fdi; f++) /* Transfer CAM targ */
cpp.v[f] = tin[f];
+ cpp.v[0] *= CCJSCALE;
/* Make sure that the auxiliar value is initialized, */
/* even though it shouldn't have any effect, since should clipp. */
@@ -1376,7 +1383,6 @@ double *in /* Function input values to invert (== clut output' values) */
cpp.p[e] = 0.5;
}
}
-
if (p->clutTable->di > fdi) { /* ie. CMYK->Lab, there will be ambiguity */
nsoln = p->cclutTable->rev_interp(
@@ -1404,12 +1410,14 @@ double *in /* Function input values to invert (== clut output' values) */
}
/* Compute the CAM clip distances */
+ cpp.v[0] /= CCJSCALE;
for (cdist = 0.0, f = 0; f < fdi; f++) {
double tt;
tt = cpp.v[f] - tin[f];
cdist += tt * tt;
}
cdist = sqrt(cdist);
+ DBR(("Targ CAM %f %f %f Clipped %f %f %f cdist %f\n",tin[0],tin[1],tin[2],cpp.v[0],cpp.v[1],cpp.v[2],cdist))
/* Use magic number to set blend distance, and compute a blend factor. */
/* Blend over 1 delta E, otherwise the Lab & CAM02 divergence can result */
@@ -1425,20 +1433,21 @@ double *in /* Function input values to invert (== clut output' values) */
/* Blend between solution values for PCS and CAM clip result. */
/* We're hoping that the solutions are close, and expect them to be */
/* that way when we're close to the gamut surface (since the cell */
- /* vertex values should be exact, irrespective of which space they're */
- /* in), but weird things could happen away from the surface. Weird */
- /* things can happen anyway with "clip to nearest", since this is not */
+ /* vertex values should be exact, irrespective of which interpolation */
+ /* space they're in), but weird things could happen away from the surface. */
+ /* Weird things can happen anyway with "clip to nearest", since this is not */
/* guaranteed to be a smooth function, depending on the gamut surface */
/* geometry, without taking some precaution such as clipping to a */
/* convex hull "wrapper" to create a clip vector, which we're not */
/* current doing. */
DBR(("Clip blend between device:\n"))
- DBR(("Lab: %f %f %f and\n",pp[0].p[0], pp[0].p[1], pp[0].p[2]))
- DBR(("Jab: %f %f %f\n",cpp.p[0], cpp.p[1], cpp.p[2]))
+ DBR(("Lab: %s & ",icmPdv(p->clutTable->di, pp[0].p)))
+ DBR(("Jab: %s ",icmPdv(p->clutTable->di, cpp.p)))
for (e = 0; e < p->clutTable->di; e++) {
out[e] = (1.0 - bf) * pp[0].p[e] + bf * cpp.p[e];
}
+ DBR((" = %s\n",icmPdv(p->clutTable->di, out)))
/* Not CAM clip case */
} else {
@@ -1459,6 +1468,7 @@ double *in /* Function input values to invert (== clut output' values) */
for (i = 0; i < nsoln; i++) {
double ss;
+ DBR(("Soln %d: %s\n",i, icmPdv(p->clutTable->di, pp[i].p)))
for (ss = 0.0, e = 0; e < p->clutTable->di; e++) {
double tt;
tt = pp[i].p[e] - p->licent[e];
@@ -1469,6 +1479,16 @@ double *in /* Function input values to invert (== clut output' values) */
}
}
}
+#ifndef NEVER
+ // ~~99 average them
+ for (i = 1; i < nsoln; i++) {
+ for (e = 0; e < p->clutTable->di; e++)
+ pp[0].p[e] += pp[i].p[e];
+ }
+ for (e = 0; e < p->clutTable->di; e++)
+ pp[0].p[e] /= (double)nsoln;
+ bsoln = 0;
+#endif
//printf("~1 chose %d\n",bsoln);
i = bsoln;
}
@@ -2289,8 +2309,8 @@ fprintf(stderr,"~1 Internal optimised 4D separations not yet implemented!\n");
else
xicc_enum_viewcond(xicp, &p->vc, -1, NULL, 0, NULL); /* Use a default */
p->cam = new_icxcam(cam_default);
- p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, p->vc.Yf,
- p->vc.Fxyz, XICC_USE_HK);
+ p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv,
+ p->vc.Yf, p->vc.Yg, p->vc.Gxyz, XICC_USE_HK);
} else {
p->cam = NULL;
}
@@ -2477,10 +2497,12 @@ icxLuLut_clut_camclip_func(
luluto->output(luluto, out, out);
luluto->out_abs(luluto, out, out);
p->cam->XYZ_to_cam(p->cam, out, out);
+ out[0] *= CCJSCALE;
}
/* Initialise the additional CAM space clut rspl, used to compute */
/* reverse lookup CAM clipping results when the camclip flag is set. */
+/* We scale J by CCJSCALE, to give a more L* preserving clip direction */
/* return error code. */
static int
icxLuLut_init_clut_camclip(
@@ -2490,7 +2512,7 @@ icxLuLut *p) {
/* Setup so clut contains transform to CAM Jab */
/* (camclip is only used in fwd or invfwd direction lookup) */
double cmin[3], cmax[3];
- cmin[0] = 0.0; cmax[0] = 100.0; /* Nominal Jab output ranges */
+ cmin[0] = 0.0; cmax[0] = CCJSCALE * 100.0; /* Nominal Jab output ranges */
cmin[1] = -128.0; cmax[1] = 128.0;
cmin[2] = -128.0; cmax[2] = 128.0;
@@ -2835,6 +2857,7 @@ double dispLuminance, /* > 0.0 if display luminance value and is kno
double wpscale, /* > 0.0 if white point is to be scaled */
double smooth, /* RSPL smoothing factor, -ve if raw */
double avgdev, /* reading Average Deviation as a prop. of the input range */
+double demph, /* dark emphasis factor for cLUT grid res. */
icxViewCond *vc, /* Viewing Condition (NULL if not using CAM) */
icxInk *ink, /* inking details (NULL for default) */
int quality /* Quality metric, 0..3 */
@@ -2906,15 +2929,18 @@ int quality /* Quality metric, 0..3 */
/* (This is for rspl scattered data fitting smoothness adjustment) */
/* (This could do with more tuning) */
- /* For some unknown reason XYZ seems masively under-smoothed, so bump it up */
+ /* XYZ display models are under-smoothed, because the mapping is typically */
+ /* very "straight", and the lack of tension reduces any noise reduction effect. */
+ /* !!! This probably means that we should switch to 3rd order smoothness criteria !! */
+ /* We apply an arbitrary correction here */
if (p->pcs == icSigXYZData) {
- oavgdev[0] = 1.0 * 0.60 * avgdev;
- oavgdev[1] = 1.0 * 1.00 * avgdev;
- oavgdev[2] = 1.0 * 0.60 * avgdev;
+ oavgdev[0] = XYZ_EXTRA_SMOOTH * 0.70 * avgdev;
+ oavgdev[1] = XYZ_EXTRA_SMOOTH * 1.00 * avgdev;
+ oavgdev[2] = XYZ_EXTRA_SMOOTH * 0.70 * avgdev;
} else if (p->pcs == icSigLabData) {
oavgdev[0] = 1.00 * avgdev;
- oavgdev[1] = 0.60 * avgdev;
- oavgdev[2] = 0.60 * avgdev;
+ oavgdev[1] = 0.70 * avgdev;
+ oavgdev[2] = 0.70 * avgdev;
} else { /* Hmmm */
for (f = 0; f < p->outputChan; f++)
oavgdev[f] = avgdev;
@@ -3348,7 +3374,7 @@ int quality /* Quality metric, 0..3 */
if (xf->fit(xf, xfflags, p->inputChan, p->outputChan,
rsplflags, wp, dwhite, wpscale, dgwhite,
ipoints, nodp, skm, in_min, in_max, gres, out_min, out_max,
- smooth, oavgdev, iord, sord, oord, shp_smooth, out_smooth, tcomb,
+ smooth, oavgdev, demph, iord, sord, oord, shp_smooth, out_smooth, tcomb,
(void *)p, xfit_to_de2, xfit_to_dde2) != 0) {
p->pp->errc = 2;
sprintf(p->pp->err,"xfit fitting failed");
@@ -3821,7 +3847,8 @@ int quality /* Quality metric, 0..3 */
NULL, NULL, /* Use default Maximum range of Dev' values */
set_clut, /* Dev' -> PCS' transfer function */
NULL, NULL, /* Use default Maximum range of PCS' values */
- set_output /* Linear output transform PCS'->PCS */
+ set_output, /* Linear output transform PCS'->PCS */
+ NULL, NULL /* No APXLS */
) != 0)
error("Setting 16 bit %s->%s Lut failed: %d, %s",
icm2str(icmColorSpaceSignature, h->colorSpace),
@@ -3843,8 +3870,8 @@ int quality /* Quality metric, 0..3 */
else
xicc_enum_viewcond(xicp, &p->vc, -1, NULL, 0, NULL); /* Use a default */
p->cam = new_icxcam(cam_default);
- p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, p->vc.Yf,
- p->vc.Fxyz, XICC_USE_HK);
+ p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv,
+ p->vc.Yf, p->vc.Yg, p->vc.Gxyz, XICC_USE_HK);
if (flags & ICX_VERBOSE)
printf("Done A to B table creation\n");
diff --git a/xicc/xlutfix.c b/xicc/xlutfix.c
index 6497688..a0c0e4e 100644
--- a/xicc/xlutfix.c
+++ b/xicc/xlutfix.c
@@ -368,7 +368,8 @@ void (*outfunc)(void *cbctx, double *out, double *in)
inmin, inmax,
xif_set_clut,
clutmin, clutmax,
- xif_set_output);
+ xif_set_output,
+ NULL, NULL);
return rv;
}
@@ -540,7 +541,8 @@ printf("~1 doing the first pass\n");
inmin, inmax,
xif_set_clut,
clutmin, clutmax,
- xif_set_output);
+ xif_set_output,
+ NULL, NULL);
#if defined(SAVE_TRACE) || defined(USE_TRACE)
fclose(xcs.tf);
@@ -594,7 +596,8 @@ printf("~1 updatding the icc\n");
inmin, inmax,
xif_set_clut,
clutmin, clutmax,
- xif_set_output);
+ xif_set_output,
+ NULL, NULL);
free(xcs.fhi);
free(xcs.g);
diff --git a/xicc/xmatrix.c b/xicc/xmatrix.c
index a194314..53db237 100644
--- a/xicc/xmatrix.c
+++ b/xicc/xmatrix.c
@@ -42,9 +42,9 @@
#define XSHAPE_OFFG 0.1 /* Input offset weights when ord 0 is gamma */
#define XSHAPE_OFFS 1.0 /* Input offset weights when ord 0 is shaper */
-#define XSHAPE_HW01 0.002 /* 0 & 1 harmonic weights */
-#define XSHAPE_HBREAK 4 /* Harmonic that has HWBR */
-#define XSHAPE_HWBR 0.8 /* Base weight of harmonics HBREAK up */
+#define XSHAPE_HW01 0.01 /* 0 & 1 harmonic weights */
+#define XSHAPE_HBREAK 3 /* Harmonic that has HWBR */
+#define XSHAPE_HWBR 0.5 /* Base weight of harmonics HBREAK up */
#define XSHAPE_HWINC 0.5 /* Increase in weight for each harmonic above HWBR */
#define XSHAPE_GAMTHR 0.01 /* Input threshold for linear slope below gamma power */
@@ -309,8 +309,8 @@ int dir /* 0 = fwd, 1 = bwd */
else
xicc_enum_viewcond(xicp, &p->vc, -1, NULL, 0, NULL); /* Use a default */
p->cam = new_icxcam(cam_default);
- p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv, p->vc.Yf,
- p->vc.Fxyz, XICC_USE_HK);
+ p->cam->set_view(p->cam, p->vc.Ev, p->vc.Wxyz, p->vc.La, p->vc.Yb, p->vc.Lv,
+ p->vc.Yf, p->vc.Yg, p->vc.Gxyz, XICC_USE_HK);
} else {
p->cam = NULL;
}
@@ -560,7 +560,6 @@ double *v /* Pointer to parameters */
tt = v[11 + f];
if (f == 0 && p->shape0gam)
tt -= 1.0; /* default is linear */
- tt *= tt;
/* Weigh to suppress ripples */
if (f <= 1) { /* Use XSHAPE_HW01 */
w = XSHAPE_HW01;
@@ -568,15 +567,15 @@ double *v /* Pointer to parameters */
double bl = (f - 1.0)/(XSHAPE_HBREAK - 1.0);
w = (1.0 - bl) * XSHAPE_HW01 + bl * XSHAPE_HWBR * p->smooth;
} else { /* Use XSHAPE_HWBR * smooth */
- w = XSHAPE_HWBR + (f-XSHAPE_HBREAK) * XSHAPE_HWINC;
- w *= p->smooth;
+ w = XSHAPE_HWBR + (f-XSHAPE_HBREAK) * XSHAPE_HWINC * p->smooth;
}
+ tt *= tt;
tparam += w * tt;
}
return XSHAPE_MAG * tparam;
}
- /* Input ffset value */
+ /* Input offset value */
if (p->shape0gam)
w = XSHAPE_OFFG;
else
@@ -603,7 +602,6 @@ double *v /* Pointer to parameters */
w = (1.0 - bl) * XSHAPE_HW01 + bl * XSHAPE_HWBR * p->smooth;
} else {
w = XSHAPE_HWBR + (f-XSHAPE_HBREAK) * XSHAPE_HWINC * p->smooth;
- w *= p->smooth;
}
for (g = 0; g < 3; g++) {
tt = v[15 + 3 * f + g];
@@ -863,6 +861,10 @@ double scale /* Scale device values */
os->v[3] = 0.2; os->v[4] = 0.8; os->v[5] = 0.1;
os->v[6] = 0.02; os->v[7] = 0.15; os->v[8] = 1.3;
+ /* We try and take a homomorphic approach here, in an attempt */
+ /* to avoid getting trapped at a local minimum when a full */
+ /* set of shaper parameters are in play. */
+
/* Do a first pass just setting the matrix values */
os->isLinear = 1;
os->isGamma = 1;
@@ -889,17 +891,43 @@ double scale /* Scale device values */
#endif /* NEVER */
/* Now optimize again with shaper or gamma curves */
- if (!isLinear || isGamma) {
+ if (!isLinear) {
+ double scgamma;
/* Start from linear, which is what was assumed for the matrix fit, */
- /* and fit first with a single shared curve. */
+ /* and fit with a single shared gamma curve. */
os->isShTRC = 1;
- if (isGamma) { /* Just gamma curve */
- os->isLinear = 0;
- os->isGamma = 1;
- os->optdim = 10;
- os->v[9] = 1.0; /* Linear */
- } else { /* Creating input curves */
+ os->isLinear = 0;
+ os->isGamma = 1;
+ os->optdim = 10;
+ os->v[9] = 1.0; /* Linear */
+
+ /* Set search area to starting values */
+ for (j = 0; j < os->optdim; j++)
+ os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */
+
+ if (os->verb)
+ printf("Creating matrix and single gamma curve...\n");
+
+ if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits,
+ mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0)
+ warning("Powell failed to converge, residual error = %f",rerr);
+
+ scgamma = os->v[9];
+ if (isShTRC && !isGamma) {
+
+#ifndef NEVER
+ if (os->verb) {
+ printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]);
+ printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]);
+ printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]);
+ printf("Gamma = %f\n",os->v[9]);
+ }
+#endif /* NEVER */
+
+ /* Do final optimisation using full curve capability */
+ /* and fit first with a single shared curve. */
+ os->isShTRC = 1;
os->isLinear = 0;
os->isGamma = 0;
os->optdim = 9 + 2 + os->norders; /* Matrix, offset + orders */
@@ -911,71 +939,96 @@ double scale /* Scale device values */
os->v[11] = 0.0; /* 0th Harmonic */
for (i = 12; i < os->optdim; i++)
os->v[i] = 0.0; /* Higher orders */
- }
- /* Set search area to starting values */
- for (j = 0; j < os->optdim; j++)
- os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */
+ /* Set search area to starting values */
+ for (j = 0; j < os->optdim; j++)
+ os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */
- if (os->verb)
- printf("Creating matrix and single curve...\n");
+ if (os->verb)
+ printf("Creating matrix and single shaper curve...\n");
- if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits,
- mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0)
- warning("Powell failed to converge, residual error = %f",rerr);
+ if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits,
+ mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0)
+ warning("Powell failed to converge, residual error = %f",rerr);
+
+ scgamma = os->v[9];
+
+ }
+
+ /* For multiple curves, continue fitting */
+ if (!isShTRC) {
+ double mcgamma[3];
#ifndef NEVER
- if (os->verb) {
- printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]);
- printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]);
- printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]);
- if (isGamma) { /* Creating input curves */
+ if (os->verb) {
+ printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]);
+ printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]);
+ printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]);
printf("Gamma = %f\n",os->v[9]);
- } else { /* Creating input curves */
- printf("Input offset = %f\n",os->v[9]);
- printf("Output offset = %f\n",os->v[10]);
- for (j = 0; j < os->norders; j++) {
- if (shape0gam && j == 0)
- printf("gamma = %f\n", os->v[11 + j]);
- else
- printf("%d harmonics = %f\n",j, os->v[11 + j]);
- }
}
- }
#endif /* NEVER */
- /* Now do the final optimisation with all curves */
- if (!isShTRC) {
+ /* Fit matrix + multi gamma curves */
os->isShTRC = 0;
- if (isGamma) { /* Just gamma curves */
- os->isLinear = 0;
- os->isGamma = 1;
- os->optdim = 12;
- os->v[9] = os->v[10] = os->v[11] = 1.0; /* Linear */
- } else { /* Creating input curves */
- os->isLinear = 0;
- os->isGamma = 0;
- os->optdim = 9 + 6 + 3 * os->norders; /* Matrix, offset + orders */
- os->v[9] = os->v[10] = os->v[11] = 0.0; /* Input offset */
- os->v[12] = os->v[13] = os->v[14] = 0.0; /* Output offset */
- if (shape0gam)
- os->v[15] = os->v[16] = os->v[17] = 1.0; /* Gamma */
- else
- os->v[15] = os->v[16] = os->v[17] = 0.0; /* 0th Harmonic */
- for (i = 18; i < os->optdim; i++)
- os->v[i] = 0.0; /* Higher orders */
- }
+ os->isLinear = 0;
+ os->isGamma = 1;
+ os->optdim = 12;
+ os->v[9] = os->v[10] = os->v[11] = scgamma; /* Single curve value */
/* Set search area to starting values */
for (j = 0; j < os->optdim; j++)
os->sa[j] = 0.2; /* Matrix, Gamma, Offsets, harmonics */
if (os->verb)
- printf("Creating matrix and curves...\n");
+ printf("Creating matrix and gamma curves...\n");
if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits,
mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0)
warning("Powell failed to converge, residual error = %f",rerr);
+
+
+ mcgamma[0] = os->v[9];
+ mcgamma[1] = os->v[10];
+ mcgamma[2] = os->v[11];
+
+ if (!isGamma) {
+
+#ifndef NEVER
+ if (os->verb) {
+ printf("Matrix = %f %f %f\n",os->v[0], os->v[1], os->v[2]);
+ printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]);
+ printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]);
+ printf("Gamma = %f %f %f\n",os->v[9], os->v[10], os->v[11]);
+ }
+#endif /* NEVER */
+
+ /* Do final curves */
+ os->isShTRC = 0;
+ os->isLinear = 0;
+ os->isGamma = 0;
+ os->optdim = 9 + 6 + 3 * os->norders; /* Matrix, offset + orders */
+ os->v[9] = os->v[10] = os->v[11] = 0.0; /* Input offset */
+ os->v[12] = os->v[13] = os->v[14] = 0.0; /* Output offset */
+ if (shape0gam) {
+ os->v[15] = mcgamma[0];
+ os->v[16] = mcgamma[1];
+ os->v[17] = mcgamma[2];
+ } else
+ os->v[15] = os->v[16] = os->v[17] = 0.0; /* 0th Harmonic */
+ for (i = 18; i < os->optdim; i++)
+ os->v[i] = 0.0; /* Higher orders */
+
+ /* Set search area to starting values */
+ for (j = 0; j < os->optdim; j++)
+ os->sa[j] = 0.1; /* Matrix, Gamma, Offsets, harmonics */
+
+ if (os->verb)
+ printf("Creating matrix and curves...\n");
+
+ if (powell(&rerr, os->optdim, os->v, os->sa, stopon, maxits,
+ mxoptfunc, (void *)os, mxprogfunc, (void *)os) != 0)
+ warning("Powell failed to converge, residual error = %f",rerr);
+ }
}
}
if (os->clipprims) { /* Clip -ve primaries */
@@ -991,7 +1044,7 @@ double scale /* Scale device values */
printf(" %f %f %f\n",os->v[3], os->v[4], os->v[5]);
printf(" %f %f %f\n",os->v[6], os->v[7], os->v[8]);
if (!isLinear) { /* Creating input curves */
- if (isGamma) { /* Creating input curves */
+ if (os->isGamma) { /* Creating input curves */
if (isShTRC)
printf("Gamma = %f\n",os->v[9]);
else
@@ -1531,7 +1584,7 @@ double smooth /* Curve smoothing, nominally 1.0 */
}
/* If we are going to auto scale the WP to avoid clipping */
- /* values above the WP: (not important for matrix profiles ?) */
+ /* values above the WP: (not so important for matrix profiles ?) */
if ((p->flags & ICX_SET_WHITE_US) == ICX_SET_WHITE_US) {
double tw[3], bw[3];
icmXYZNumber _wp;
@@ -1813,12 +1866,28 @@ double smooth /* Curve smoothing, nominally 1.0 */
/* Matrix values */
{
icmXYZArray *wor, *wog, *wob;
+ double mat[3][3];
wor = pmlu->redColrnt;
wog = pmlu->greenColrnt;
wob = pmlu->blueColrnt;
- wor->data[0].X = os.v[0]; wor->data[0].Y = os.v[3]; wor->data[0].Z = os.v[6];
- wog->data[0].X = os.v[1]; wog->data[0].Y = os.v[4]; wog->data[0].Z = os.v[7];
- wob->data[0].X = os.v[2]; wob->data[0].Y = os.v[5]; wob->data[0].Z = os.v[8];
+
+ /* Copy to mat[RGB][XYZ] */
+ mat[0][0] = os.v[0];
+ mat[0][1] = os.v[3];
+ mat[0][2] = os.v[6];
+ mat[1][0] = os.v[1];
+ mat[1][1] = os.v[4];
+ mat[1][2] = os.v[7];
+ mat[2][0] = os.v[2];
+ mat[2][1] = os.v[5];
+ mat[2][2] = os.v[8];
+
+ /* Make sure rounding doesn't wreck white point */
+ quantizeRGBprimsS15Fixed16(mat);
+
+ wor->data[0].X = mat[0][0]; wor->data[0].Y = mat[0][1]; wor->data[0].Z = mat[0][2];
+ wog->data[0].X = mat[1][0]; wog->data[0].Y = mat[1][1]; wog->data[0].Z = mat[1][2];
+ wob->data[0].X = mat[2][0]; wob->data[0].Y = mat[2][1]; wob->data[0].Z = mat[2][2];
/* Load into pmlu matrix and inverse ??? */
}
diff --git a/xicc/xmono.c b/xicc/xmono.c
index f0ee04f..fe9c55e 100644
--- a/xicc/xmono.c
+++ b/xicc/xmono.c
@@ -261,7 +261,7 @@ int dir /* 0 = fwd, 1 = bwd */
if (pcsor == icxSigJabData) {
p->vc = *vc; /* Copy the structure */
p->cam = new_icxcam(cam_default);
- p->cam->set_view(p->cam, vc->Ev, vc->Wxyz, vc->La, vc->Yb, vc->Lv, vc->Yf, vc->Fxyz,
+ p->cam->set_view(p->cam, vc->Ev, vc->Wxyz, vc->La, vc->Yb, vc->Lv, vc->Yf, vc->Yg, vc->Gxyz,
XICC_USE_HK);
} else
p->cam = NULL;
diff --git a/xicc/xspect.c b/xicc/xspect.c
index a372d60..cc0ce85 100644
--- a/xicc/xspect.c
+++ b/xicc/xspect.c
@@ -23,16 +23,7 @@
/*
* TTBD:
*
- * If needed by ISO 13655-1009:
- * fwa_convert() function takes two illuminants:
- * first one is the measurement illumination to correct to,
- * the second is the assumed illumination spectrum for XYZ conversion.
- * so we compute the spectral reflectance as if the instrument had
- * one sort of practical illuminant (and taking into account FWA),
- * and then convert to D50 equivalent.
- * Need to bypass FWA if inst illum == simulated inst. illum.
- * Need to modify tools to allow optional param to -f which is
- * the simulated instrument illum, then make -i have -M0, -M1, -M2 options.
+ * Should add some more modern standard CMFs - see <http://www.cvrl.org/>
*
* [Does this make any sense though ? That is what's happening
* for a standard A illuminant instrument emitting D50 XYZ values,
@@ -52,6 +43,7 @@
#else
# include "numsup.h"
#endif
+#include "conv.h"
#include "xspect.h"
#define CLAMP_XYZ /* [def] Clamp XYZ to be >= 0.0 */
@@ -279,8 +271,9 @@ static int daylight_il(xspect *sp, double ct) {
double xd, yd;
double m1, m2;
- if (ct < 1000.0 || ct > 35000.0) /* Actually, accuracy is guaranteed from only 4000 - 25000 */
+ if (ct < 4000.0 || ct > 25000.0) { /* Only accurate down to 4000 */
return 1;
+ }
/* Compute chromaticity coordinates */
if (ct < 7000.0) {
@@ -306,6 +299,8 @@ static int daylight_il(xspect *sp, double ct) {
return 0;
}
+#endif /* !SALONEINSTLIB */
+
/* General temperature Planckian (black body) spectra */
/* Fill in the given xspect with the specified Planckian illuminant */
/* Return nz if temperature is out of range */
@@ -317,7 +312,6 @@ static int planckian_il(xspect *sp, double ct) {
return 1;
/* Set out targets */
-// sp->spec_n = 107; /* 5nm */
sp->spec_n = 531; /* 1nm */
sp->spec_wl_short = 300.0;
sp->spec_wl_long = 830;
@@ -337,6 +331,8 @@ static int planckian_il(xspect *sp, double ct) {
return 0;
}
+#ifndef SALONEINSTLIB
+
/* CIE F5 */
/* Fluorescent, Standard, 6350K, CRI 72 */
static xspect il_F5 = {
@@ -364,7 +360,7 @@ static xspect il_F5 = {
/* Fluorescent, Wide band 5000K, CRI 95 */
static xspect il_F8 = {
107, 300.0, 830.0, /* 109 bands from 300 to 830 nm in 5nm steps */
- 20.0, /* Arbitrary scale factor */
+ 30.0, /* Arbitrary scale factor */
{
/* 300 */ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
/* 340 */ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
@@ -388,7 +384,7 @@ static xspect il_F8 = {
/* Fluorescent, Narrow band 5000K, CRI 81 */
static xspect il_F10 = {
107, 300.0, 830.0, /* 109 bands from 300 to 830 nm in 5nm steps */
- 20.0, /* Arbitrary scale factor */
+ 30.0, /* Arbitrary scale factor */
{
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
@@ -503,28 +499,16 @@ double temp /* Optional temperature in degrees kelvin, for Dtemp and Ptemp *
return 0;
case icxIT_Dtemp:
return daylight_il(sp, temp);
+#endif
case icxIT_Ptemp:
return planckian_il(sp, temp);
-#endif
}
return 1;
}
-/* ------------- */
-
-/* Spectral locus poligon cache */
-typedef struct {
- int n; /* Number of spectral vertexes, 0 if uninit */
- double xmin, xmax, ymin, ymax; /* Boundint box */
- double tx[3], ty[3]; /* Fast inner triangle test, RGB */
- double be[3][3]; /* baricentric equations of triangle */
-// double eed[3]; /* Distance of triangle points to 0.3, 0.3 */
- double x[XSPECT_MAX_BANDS]; /* x value of vertex */
- double y[XSPECT_MAX_BANDS]; /* y value of vertex */
-} xslpoly;
/* ------------- */
-/* Observer Data and locus poligon cache */
+/* Observer Data */
/* Standard CIE 1931 2 degree */
static xspect ob_CIE_1931_2[3] = {
@@ -833,8 +817,6 @@ static xspect ob_CIE_1931_2[3] = {
}
};
-static xslpoly poly_CIE_1931_2 = { 0 };
-
/* Standard CIE 1964 10 degree */
static xspect ob_CIE_1964_10[3] = {
{
@@ -1142,8 +1124,6 @@ static xspect ob_CIE_1964_10[3] = {
}
};
-static xslpoly poly_CIE_1964_10 = { 0 };
-
#ifndef SALONEINSTLIB
/* Standard CIE 1964 10 degree observer, */
/* adjusted for compatibility with 2 degree observer. */
@@ -1454,8 +1434,6 @@ static xspect ob_CIE_1964_10c[3] = {
}
};
-static xslpoly poly_CIE_1964_10c = { 0 };
-
/* Judd & Voss 1978 2 degree */
static xspect ob_Judd_Voss_2[3] = {
{
@@ -1532,8 +1510,6 @@ static xspect ob_Judd_Voss_2[3] = {
}
};
-static xslpoly poly_Judd_Voss_2 = { 0 };
-
/* Stiles & Burch 1955 2 degree, */
/* rotated to align with 1931 XYZ space, */
@@ -1601,8 +1577,6 @@ static xspect ob_Stiles_Burch_2[3] = {
}
};
-static xslpoly poly_Stiles_Burch_2 = { 0 };
-
/* Shaw & Fairchild 1997 2 degree observer. */
/* From Mark Shaw's Masters thesis: */
/* "Evaluating the 1931 CIE Color Matching Functions" */
@@ -1666,8 +1640,898 @@ static xspect ob_Shaw_Fairchild_2[3] = {
}
};
-static xslpoly poly_Shaw_Fairchild_2 = { 0 };
+#ifdef NEVER
+CIE TC 1-36 proposed
+2-deg XYZ CMFs transformed from the CIE (2006) 2-deg LMS cone fundamentals
+
+390 3.769647E-03 4.146161E-04 1.847260E-02
+391 4.532416E-03 5.028333E-04 2.221101E-02
+392 5.446553E-03 6.084991E-04 2.669819E-02
+393 6.538868E-03 7.344436E-04 3.206937E-02
+394 7.839699E-03 8.837389E-04 3.847832E-02
+395 9.382967E-03 1.059646E-03 4.609784E-02
+396 1.120608E-02 1.265532E-03 5.511953E-02
+397 1.334965E-02 1.504753E-03 6.575257E-02
+398 1.585690E-02 1.780493E-03 7.822113E-02
+399 1.877286E-02 2.095572E-03 9.276013E-02
+400 2.214302E-02 2.452194E-03 1.096090E-01
+401 2.601285E-02 2.852216E-03 1.290077E-01
+402 3.043036E-02 3.299115E-03 1.512047E-01
+403 3.544325E-02 3.797466E-03 1.764441E-01
+404 4.109640E-02 4.352768E-03 2.049517E-01
+405 4.742986E-02 4.971717E-03 2.369246E-01
+406 5.447394E-02 5.661014E-03 2.725123E-01
+407 6.223612E-02 6.421615E-03 3.117820E-01
+408 7.070048E-02 7.250312E-03 3.547064E-01
+409 7.982513E-02 8.140173E-03 4.011473E-01
+410 8.953803E-02 9.079860E-03 4.508369E-01
+411 9.974848E-02 1.005608E-02 5.034164E-01
+412 1.104019E-01 1.106456E-02 5.586361E-01
+413 1.214566E-01 1.210522E-02 6.162734E-01
+414 1.328741E-01 1.318014E-02 6.760982E-01
+415 1.446214E-01 1.429377E-02 7.378822E-01
+416 1.566468E-01 1.545004E-02 8.013019E-01
+417 1.687901E-01 1.664093E-02 8.655573E-01
+418 1.808328E-01 1.785302E-02 9.295791E-01
+419 1.925216E-01 1.907018E-02 9.921293E-01
+420 2.035729E-01 2.027369E-02 1.051821E+00
+421 2.137531E-01 2.144805E-02 1.107509E+00
+422 2.231348E-01 2.260041E-02 1.159527E+00
+423 2.319245E-01 2.374789E-02 1.208869E+00
+424 2.403892E-01 2.491247E-02 1.256834E+00
+425 2.488523E-01 2.612106E-02 1.305008E+00
+426 2.575896E-01 2.739923E-02 1.354758E+00
+427 2.664991E-01 2.874993E-02 1.405594E+00
+428 2.753532E-01 3.016909E-02 1.456414E+00
+429 2.838921E-01 3.165145E-02 1.505960E+00
+430 2.918246E-01 3.319038E-02 1.552826E+00
+431 2.989200E-01 3.477912E-02 1.595902E+00
+432 3.052993E-01 3.641495E-02 1.635768E+00
+433 3.112031E-01 3.809569E-02 1.673573E+00
+434 3.169047E-01 3.981843E-02 1.710604E+00
+435 3.227087E-01 4.157940E-02 1.748280E+00
+436 3.288194E-01 4.337098E-02 1.787504E+00
+437 3.349242E-01 4.517180E-02 1.826609E+00
+438 3.405452E-01 4.695420E-02 1.863108E+00
+439 3.451688E-01 4.868718E-02 1.894332E+00
+440 3.482554E-01 5.033657E-02 1.917479E+00
+441 3.494153E-01 5.187611E-02 1.930529E+00
+442 3.489075E-01 5.332218E-02 1.934819E+00
+443 3.471746E-01 5.470603E-02 1.932650E+00
+444 3.446705E-01 5.606335E-02 1.926395E+00
+445 3.418483E-01 5.743393E-02 1.918437E+00
+446 3.390240E-01 5.885107E-02 1.910430E+00
+447 3.359926E-01 6.030809E-02 1.901224E+00
+448 3.324276E-01 6.178644E-02 1.889000E+00
+449 3.280157E-01 6.326570E-02 1.871996E+00
+450 3.224637E-01 6.472352E-02 1.848545E+00
+451 3.156225E-01 6.614749E-02 1.817792E+00
+452 3.078201E-01 6.757256E-02 1.781627E+00
+453 2.994771E-01 6.904928E-02 1.742514E+00
+454 2.909776E-01 7.063280E-02 1.702749E+00
+455 2.826646E-01 7.238339E-02 1.664439E+00
+456 2.747962E-01 7.435960E-02 1.629207E+00
+457 2.674312E-01 7.659383E-02 1.597360E+00
+458 2.605847E-01 7.911436E-02 1.568896E+00
+459 2.542749E-01 8.195345E-02 1.543823E+00
+460 2.485254E-01 8.514816E-02 1.522157E+00
+461 2.433039E-01 8.872657E-02 1.503611E+00
+462 2.383414E-01 9.266008E-02 1.486673E+00
+463 2.333253E-01 9.689723E-02 1.469595E+00
+464 2.279619E-01 1.013746E-01 1.450709E+00
+465 2.219781E-01 1.060145E-01 1.428440E+00
+466 2.151735E-01 1.107377E-01 1.401587E+00
+467 2.075619E-01 1.155111E-01 1.370094E+00
+468 1.992183E-01 1.203122E-01 1.334220E+00
+469 1.902290E-01 1.251161E-01 1.294275E+00
+470 1.806905E-01 1.298957E-01 1.250610E+00
+471 1.707154E-01 1.346299E-01 1.203696E+00
+472 1.604471E-01 1.393309E-01 1.154316E+00
+473 1.500244E-01 1.440235E-01 1.103284E+00
+474 1.395705E-01 1.487372E-01 1.051347E+00
+475 1.291920E-01 1.535066E-01 9.991789E-01
+476 1.189859E-01 1.583644E-01 9.473958E-01
+477 1.090615E-01 1.633199E-01 8.966222E-01
+478 9.951424E-02 1.683761E-01 8.473981E-01
+479 9.041850E-02 1.735365E-01 8.001576E-01
+480 8.182895E-02 1.788048E-01 7.552379E-01
+481 7.376817E-02 1.841819E-01 7.127879E-01
+482 6.619477E-02 1.896559E-01 6.725198E-01
+483 5.906380E-02 1.952101E-01 6.340976E-01
+484 5.234242E-02 2.008259E-01 5.972433E-01
+485 4.600865E-02 2.064828E-01 5.617313E-01
+486 4.006154E-02 2.121826E-01 5.274921E-01
+487 3.454373E-02 2.180279E-01 4.948809E-01
+488 2.949091E-02 2.241586E-01 4.642586E-01
+489 2.492140E-02 2.307302E-01 4.358841E-01
+490 2.083981E-02 2.379160E-01 4.099313E-01
+491 1.723591E-02 2.458706E-01 3.864261E-01
+492 1.407924E-02 2.546023E-01 3.650566E-01
+493 1.134516E-02 2.640760E-01 3.454812E-01
+494 9.019658E-03 2.742490E-01 3.274095E-01
+495 7.097731E-03 2.850680E-01 3.105939E-01
+496 5.571145E-03 2.964837E-01 2.948102E-01
+497 4.394566E-03 3.085010E-01 2.798194E-01
+498 3.516303E-03 3.211393E-01 2.654100E-01
+499 2.887638E-03 3.344175E-01 2.514084E-01
+500 2.461588E-03 3.483536E-01 2.376753E-01
+501 2.206348E-03 3.629601E-01 2.241211E-01
+502 2.149559E-03 3.782275E-01 2.107484E-01
+503 2.337091E-03 3.941359E-01 1.975839E-01
+504 2.818931E-03 4.106582E-01 1.846574E-01
+505 3.649178E-03 4.277595E-01 1.720018E-01
+506 4.891359E-03 4.453993E-01 1.596918E-01
+507 6.629364E-03 4.635396E-01 1.479415E-01
+508 8.942902E-03 4.821376E-01 1.369428E-01
+509 1.190224E-02 5.011430E-01 1.268279E-01
+510 1.556989E-02 5.204972E-01 1.176796E-01
+511 1.997668E-02 5.401387E-01 1.094970E-01
+512 2.504698E-02 5.600208E-01 1.020943E-01
+513 3.067530E-02 5.800972E-01 9.527993E-02
+514 3.674999E-02 6.003172E-01 8.890075E-02
+515 4.315171E-02 6.206256E-01 8.283548E-02
+516 4.978584E-02 6.409398E-01 7.700982E-02
+517 5.668554E-02 6.610772E-01 7.144001E-02
+518 6.391651E-02 6.808134E-01 6.615436E-02
+519 7.154352E-02 6.999044E-01 6.117199E-02
+520 7.962917E-02 7.180890E-01 5.650407E-02
+521 8.821473E-02 7.351593E-01 5.215121E-02
+522 9.726978E-02 7.511821E-01 4.809566E-02
+523 1.067504E-01 7.663143E-01 4.431720E-02
+524 1.166192E-01 7.807352E-01 4.079734E-02
+525 1.268468E-01 7.946448E-01 3.751912E-02
+526 1.374060E-01 8.082074E-01 3.446846E-02
+527 1.482471E-01 8.213817E-01 3.163764E-02
+528 1.593076E-01 8.340701E-01 2.901901E-02
+529 1.705181E-01 8.461711E-01 2.660364E-02
+530 1.818026E-01 8.575799E-01 2.438164E-02
+531 1.931090E-01 8.682408E-01 2.234097E-02
+532 2.045085E-01 8.783061E-01 2.046415E-02
+533 2.161166E-01 8.879907E-01 1.873456E-02
+534 2.280650E-01 8.975211E-01 1.713788E-02
+535 2.405015E-01 9.071347E-01 1.566174E-02
+536 2.535441E-01 9.169947E-01 1.429644E-02
+537 2.671300E-01 9.269295E-01 1.303702E-02
+538 2.811351E-01 9.366731E-01 1.187897E-02
+539 2.954164E-01 9.459482E-01 1.081725E-02
+540 3.098117E-01 9.544675E-01 9.846470E-03
+541 3.241678E-01 9.619834E-01 8.960687E-03
+542 3.384319E-01 9.684390E-01 8.152811E-03
+543 3.525786E-01 9.738289E-01 7.416025E-03
+544 3.665839E-01 9.781519E-01 6.744115E-03
+545 3.804244E-01 9.814106E-01 6.131421E-03
+546 3.940988E-01 9.836669E-01 5.572778E-03
+547 4.076972E-01 9.852081E-01 5.063463E-03
+548 4.213484E-01 9.863813E-01 4.599169E-03
+549 4.352003E-01 9.875357E-01 4.175971E-03
+550 4.494206E-01 9.890228E-01 3.790291E-03
+551 4.641616E-01 9.910811E-01 3.438952E-03
+552 4.794395E-01 9.934913E-01 3.119341E-03
+553 4.952180E-01 9.959172E-01 2.829038E-03
+554 5.114395E-01 9.980205E-01 2.565722E-03
+555 5.280233E-01 9.994608E-01 2.327186E-03
+556 5.448696E-01 9.999930E-01 2.111280E-03
+557 5.618898E-01 9.997557E-01 1.915766E-03
+558 5.790137E-01 9.989839E-01 1.738589E-03
+559 5.961882E-01 9.979123E-01 1.577920E-03
+560 6.133784E-01 9.967737E-01 1.432128E-03
+561 6.305897E-01 9.957356E-01 1.299781E-03
+562 6.479223E-01 9.947115E-01 1.179667E-03
+563 6.654866E-01 9.935534E-01 1.070694E-03
+564 6.833782E-01 9.921156E-01 9.718623E-04
+565 7.016774E-01 9.902549E-01 8.822531E-04
+566 7.204110E-01 9.878596E-01 8.010231E-04
+567 7.394495E-01 9.849324E-01 7.273884E-04
+568 7.586285E-01 9.815036E-01 6.606347E-04
+569 7.777885E-01 9.776035E-01 6.001146E-04
+570 7.967750E-01 9.732611E-01 5.452416E-04
+571 8.154530E-01 9.684764E-01 4.954847E-04
+572 8.337389E-01 9.631369E-01 4.503642E-04
+573 8.515493E-01 9.571062E-01 4.094455E-04
+574 8.687862E-01 9.502540E-01 3.723345E-04
+575 8.853376E-01 9.424569E-01 3.386739E-04
+576 9.011588E-01 9.336897E-01 3.081396E-04
+577 9.165278E-01 9.242893E-01 2.804370E-04
+578 9.318245E-01 9.146707E-01 2.552996E-04
+579 9.474524E-01 9.052333E-01 2.324859E-04
+580 9.638388E-01 8.963613E-01 2.117772E-04
+581 9.812596E-01 8.883069E-01 1.929758E-04
+582 9.992953E-01 8.808462E-01 1.759024E-04
+583 1.017343E+00 8.736445E-01 1.603947E-04
+584 1.034790E+00 8.663755E-01 1.463059E-04
+585 1.051011E+00 8.587203E-01 1.335031E-04
+586 1.065522E+00 8.504295E-01 1.218660E-04
+587 1.078421E+00 8.415047E-01 1.112857E-04
+588 1.089944E+00 8.320109E-01 1.016634E-04
+589 1.100320E+00 8.220154E-01 9.291003E-05
+590 1.109767E+00 8.115868E-01 8.494468E-05
+591 1.118438E+00 8.007874E-01 7.769425E-05
+592 1.126266E+00 7.896515E-01 7.109247E-05
+593 1.133138E+00 7.782053E-01 6.507936E-05
+594 1.138952E+00 7.664733E-01 5.960061E-05
+595 1.143620E+00 7.544785E-01 5.460706E-05
+596 1.147095E+00 7.422473E-01 5.005417E-05
+597 1.149464E+00 7.298229E-01 4.590157E-05
+598 1.150838E+00 7.172525E-01 4.211268E-05
+599 1.151326E+00 7.045818E-01 3.865437E-05
+600 1.151033E+00 6.918553E-01 3.549661E-05
+601 1.150002E+00 6.791009E-01 3.261220E-05
+602 1.148061E+00 6.662846E-01 2.997643E-05
+603 1.144998E+00 6.533595E-01 2.756693E-05
+604 1.140622E+00 6.402807E-01 2.536339E-05
+605 1.134757E+00 6.270066E-01 2.334738E-05
+606 1.127298E+00 6.135148E-01 2.150221E-05
+607 1.118342E+00 5.998494E-01 1.981268E-05
+608 1.108033E+00 5.860682E-01 1.826500E-05
+609 1.096515E+00 5.722261E-01 1.684667E-05
+610 1.083928E+00 5.583746E-01 1.554631E-05
+611 1.070387E+00 5.445535E-01 1.435360E-05
+612 1.055934E+00 5.307673E-01 1.325915E-05
+613 1.040592E+00 5.170130E-01 1.225443E-05
+614 1.024385E+00 5.032889E-01 1.133169E-05
+615 1.007344E+00 4.895950E-01 1.048387E-05
+616 9.895268E-01 4.759442E-01 0.000000E+00
+617 9.711213E-01 4.623958E-01 0.000000E+00
+618 9.523257E-01 4.490154E-01 0.000000E+00
+619 9.333248E-01 4.358622E-01 0.000000E+00
+620 9.142877E-01 4.229897E-01 0.000000E+00
+621 8.952798E-01 4.104152E-01 0.000000E+00
+622 8.760157E-01 3.980356E-01 0.000000E+00
+623 8.561607E-01 3.857300E-01 0.000000E+00
+624 8.354235E-01 3.733907E-01 0.000000E+00
+625 8.135565E-01 3.609245E-01 0.000000E+00
+626 7.904565E-01 3.482860E-01 0.000000E+00
+627 7.664364E-01 3.355702E-01 0.000000E+00
+628 7.418777E-01 3.228963E-01 0.000000E+00
+629 7.171219E-01 3.103704E-01 0.000000E+00
+630 6.924717E-01 2.980865E-01 0.000000E+00
+631 6.681600E-01 2.861160E-01 0.000000E+00
+632 6.442697E-01 2.744822E-01 0.000000E+00
+633 6.208450E-01 2.631953E-01 0.000000E+00
+634 5.979243E-01 2.522628E-01 0.000000E+00
+635 5.755410E-01 2.416902E-01 0.000000E+00
+636 5.537296E-01 2.314809E-01 0.000000E+00
+637 5.325412E-01 2.216378E-01 0.000000E+00
+638 5.120218E-01 2.121622E-01 0.000000E+00
+639 4.922070E-01 2.030542E-01 0.000000E+00
+640 4.731224E-01 1.943124E-01 0.000000E+00
+641 4.547417E-01 1.859227E-01 0.000000E+00
+642 4.368719E-01 1.778274E-01 0.000000E+00
+643 4.193121E-01 1.699654E-01 0.000000E+00
+644 4.018980E-01 1.622841E-01 0.000000E+00
+645 3.844986E-01 1.547397E-01 0.000000E+00
+646 3.670592E-01 1.473081E-01 0.000000E+00
+647 3.497167E-01 1.400169E-01 0.000000E+00
+648 3.326305E-01 1.329013E-01 0.000000E+00
+649 3.159341E-01 1.259913E-01 0.000000E+00
+650 2.997374E-01 1.193120E-01 0.000000E+00
+651 2.841189E-01 1.128820E-01 0.000000E+00
+652 2.691053E-01 1.067113E-01 0.000000E+00
+653 2.547077E-01 1.008052E-01 0.000000E+00
+654 2.409319E-01 9.516653E-02 0.000000E+00
+655 2.277792E-01 8.979594E-02 0.000000E+00
+656 2.152431E-01 8.469044E-02 0.000000E+00
+657 2.033010E-01 7.984009E-02 0.000000E+00
+658 1.919276E-01 7.523372E-02 0.000000E+00
+659 1.810987E-01 7.086061E-02 0.000000E+00
+660 1.707914E-01 6.671045E-02 0.000000E+00
+661 1.609842E-01 6.277360E-02 0.000000E+00
+662 1.516577E-01 5.904179E-02 0.000000E+00
+663 1.427936E-01 5.550703E-02 0.000000E+00
+664 1.343737E-01 5.216139E-02 0.000000E+00
+665 1.263808E-01 4.899699E-02 0.000000E+00
+666 1.187979E-01 4.600578E-02 0.000000E+00
+667 1.116088E-01 4.317885E-02 0.000000E+00
+668 1.047975E-01 4.050755E-02 0.000000E+00
+669 9.834835E-02 3.798376E-02 0.000000E+00
+670 9.224597E-02 3.559982E-02 0.000000E+00
+671 8.647506E-02 3.334856E-02 0.000000E+00
+672 8.101986E-02 3.122332E-02 0.000000E+00
+673 7.586514E-02 2.921780E-02 0.000000E+00
+674 7.099633E-02 2.732601E-02 0.000000E+00
+675 6.639960E-02 2.554223E-02 0.000000E+00
+676 6.206225E-02 2.386121E-02 0.000000E+00
+677 5.797409E-02 2.227859E-02 0.000000E+00
+678 5.412533E-02 2.079020E-02 0.000000E+00
+679 5.050600E-02 1.939185E-02 0.000000E+00
+680 4.710606E-02 1.807939E-02 0.000000E+00
+681 4.391411E-02 1.684817E-02 0.000000E+00
+682 4.091411E-02 1.569188E-02 0.000000E+00
+683 3.809067E-02 1.460446E-02 0.000000E+00
+684 3.543034E-02 1.358062E-02 0.000000E+00
+685 3.292138E-02 1.261573E-02 0.000000E+00
+686 3.055672E-02 1.170696E-02 0.000000E+00
+687 2.834146E-02 1.085608E-02 0.000000E+00
+688 2.628033E-02 1.006476E-02 0.000000E+00
+689 2.437465E-02 9.333376E-03 0.000000E+00
+690 2.262306E-02 8.661284E-03 0.000000E+00
+691 2.101935E-02 8.046048E-03 0.000000E+00
+692 1.954647E-02 7.481130E-03 0.000000E+00
+693 1.818727E-02 6.959987E-03 0.000000E+00
+694 1.692727E-02 6.477070E-03 0.000000E+00
+695 1.575417E-02 6.027677E-03 0.000000E+00
+696 1.465854E-02 5.608169E-03 0.000000E+00
+697 1.363571E-02 5.216691E-03 0.000000E+00
+698 1.268205E-02 4.851785E-03 0.000000E+00
+699 1.179394E-02 4.512008E-03 0.000000E+00
+700 1.096778E-02 4.195941E-03 0.000000E+00
+701 1.019964E-02 3.902057E-03 0.000000E+00
+702 9.484317E-03 3.628371E-03 0.000000E+00
+703 8.816851E-03 3.373005E-03 0.000000E+00
+704 8.192921E-03 3.134315E-03 0.000000E+00
+705 7.608750E-03 2.910864E-03 0.000000E+00
+706 7.061391E-03 2.701528E-03 0.000000E+00
+707 6.549509E-03 2.505796E-03 0.000000E+00
+708 6.071970E-03 2.323231E-03 0.000000E+00
+709 5.627476E-03 2.153333E-03 0.000000E+00
+710 5.214608E-03 1.995557E-03 0.000000E+00
+711 4.831848E-03 1.849316E-03 0.000000E+00
+712 4.477579E-03 1.713976E-03 0.000000E+00
+713 4.150166E-03 1.588899E-03 0.000000E+00
+714 3.847988E-03 1.473453E-03 0.000000E+00
+715 3.569452E-03 1.367022E-03 0.000000E+00
+716 3.312857E-03 1.268954E-03 0.000000E+00
+717 3.076022E-03 1.178421E-03 0.000000E+00
+718 2.856894E-03 1.094644E-03 0.000000E+00
+719 2.653681E-03 1.016943E-03 0.000000E+00
+720 2.464821E-03 9.447269E-04 0.000000E+00
+721 2.289060E-03 8.775171E-04 0.000000E+00
+722 2.125694E-03 8.150438E-04 0.000000E+00
+723 1.974121E-03 7.570755E-04 0.000000E+00
+724 1.833723E-03 7.033755E-04 0.000000E+00
+725 1.703876E-03 6.537050E-04 0.000000E+00
+726 1.583904E-03 6.078048E-04 0.000000E+00
+727 1.472939E-03 5.653435E-04 0.000000E+00
+728 1.370151E-03 5.260046E-04 0.000000E+00
+729 1.274803E-03 4.895061E-04 0.000000E+00
+730 1.186238E-03 4.555970E-04 0.000000E+00
+731 1.103871E-03 4.240548E-04 0.000000E+00
+732 1.027194E-03 3.946860E-04 0.000000E+00
+733 9.557493E-04 3.673178E-04 0.000000E+00
+734 8.891262E-04 3.417941E-04 0.000000E+00
+735 8.269535E-04 3.179738E-04 0.000000E+00
+736 7.689351E-04 2.957441E-04 0.000000E+00
+737 7.149425E-04 2.750558E-04 0.000000E+00
+738 6.648590E-04 2.558640E-04 0.000000E+00
+739 6.185421E-04 2.381142E-04 0.000000E+00
+740 5.758303E-04 2.217445E-04 0.000000E+00
+741 5.365046E-04 2.066711E-04 0.000000E+00
+742 5.001842E-04 1.927474E-04 0.000000E+00
+743 4.665005E-04 1.798315E-04 0.000000E+00
+744 4.351386E-04 1.678023E-04 0.000000E+00
+745 4.058303E-04 1.565566E-04 0.000000E+00
+746 3.783733E-04 1.460168E-04 0.000000E+00
+747 3.526892E-04 1.361535E-04 0.000000E+00
+748 3.287199E-04 1.269451E-04 0.000000E+00
+749 3.063998E-04 1.183671E-04 0.000000E+00
+750 2.856577E-04 1.103928E-04 0.000000E+00
+751 2.664108E-04 1.029908E-04 0.000000E+00
+752 2.485462E-04 9.611836E-05 0.000000E+00
+753 2.319529E-04 8.973323E-05 0.000000E+00
+754 2.165300E-04 8.379694E-05 0.000000E+00
+755 2.021853E-04 7.827442E-05 0.000000E+00
+756 1.888338E-04 7.313312E-05 0.000000E+00
+757 1.763935E-04 6.834142E-05 0.000000E+00
+758 1.647895E-04 6.387035E-05 0.000000E+00
+759 1.539542E-04 5.969389E-05 0.000000E+00
+760 1.438270E-04 5.578862E-05 0.000000E+00
+761 1.343572E-04 5.213509E-05 0.000000E+00
+762 1.255141E-04 4.872179E-05 0.000000E+00
+763 1.172706E-04 4.553845E-05 0.000000E+00
+764 1.095983E-04 4.257443E-05 0.000000E+00
+765 1.024685E-04 3.981884E-05 0.000000E+00
+766 9.584715E-05 3.725877E-05 0.000000E+00
+767 8.968316E-05 3.487467E-05 0.000000E+00
+768 8.392734E-05 3.264765E-05 0.000000E+00
+769 7.853708E-05 3.056140E-05 0.000000E+00
+770 7.347551E-05 2.860175E-05 0.000000E+00
+771 6.871576E-05 2.675841E-05 0.000000E+00
+772 6.425257E-05 2.502943E-05 0.000000E+00
+773 6.008292E-05 2.341373E-05 0.000000E+00
+774 5.620098E-05 2.190914E-05 0.000000E+00
+775 5.259870E-05 2.051259E-05 0.000000E+00
+776 4.926279E-05 1.921902E-05 0.000000E+00
+777 4.616623E-05 1.801796E-05 0.000000E+00
+778 4.328212E-05 1.689899E-05 0.000000E+00
+779 4.058715E-05 1.585309E-05 0.000000E+00
+780 3.806114E-05 1.487243E-05 0.000000E+00
+781 3.568818E-05 1.395085E-05 0.000000E+00
+782 3.346023E-05 1.308528E-05 0.000000E+00
+783 3.137090E-05 1.227327E-05 0.000000E+00
+784 2.941371E-05 1.151233E-05 0.000000E+00
+785 2.758222E-05 1.080001E-05 0.000000E+00
+786 2.586951E-05 1.013364E-05 0.000000E+00
+787 2.426701E-05 9.509919E-06 0.000000E+00
+788 2.276639E-05 8.925630E-06 0.000000E+00
+789 2.136009E-05 8.377852E-06 0.000000E+00
+790 2.004122E-05 7.863920E-06 0.000000E+00
+791 1.880380E-05 7.381539E-06 0.000000E+00
+792 1.764358E-05 6.929096E-06 0.000000E+00
+793 1.655671E-05 6.505136E-06 0.000000E+00
+794 1.553939E-05 6.108221E-06 0.000000E+00
+795 1.458792E-05 5.736935E-06 0.000000E+00
+796 1.369853E-05 5.389831E-06 0.000000E+00
+797 1.286705E-05 5.065269E-06 0.000000E+00
+798 1.208947E-05 4.761667E-06 0.000000E+00
+799 1.136207E-05 4.477561E-06 0.000000E+00
+800 1.068141E-05 4.211597E-06 0.000000E+00
+801 1.004411E-05 3.962457E-06 0.000000E+00
+802 9.446399E-06 3.728674E-06 0.000000E+00
+803 8.884754E-06 3.508881E-06 0.000000E+00
+804 8.356050E-06 3.301868E-06 0.000000E+00
+805 7.857521E-06 3.106561E-06 0.000000E+00
+806 7.386996E-06 2.922119E-06 0.000000E+00
+807 6.943576E-06 2.748208E-06 0.000000E+00
+808 6.526548E-06 2.584560E-06 0.000000E+00
+809 6.135087E-06 2.430867E-06 0.000000E+00
+810 5.768284E-06 2.286786E-06 0.000000E+00
+811 5.425069E-06 2.151905E-06 0.000000E+00
+812 5.103974E-06 2.025656E-06 0.000000E+00
+813 4.803525E-06 1.907464E-06 0.000000E+00
+814 4.522350E-06 1.796794E-06 0.000000E+00
+815 4.259166E-06 1.693147E-06 0.000000E+00
+816 4.012715E-06 1.596032E-06 0.000000E+00
+817 3.781597E-06 1.504903E-06 0.000000E+00
+818 3.564496E-06 1.419245E-06 0.000000E+00
+819 3.360236E-06 1.338600E-06 0.000000E+00
+820 3.167765E-06 1.262556E-06 0.000000E+00
+821 2.986206E-06 1.190771E-06 0.000000E+00
+822 2.814999E-06 1.123031E-06 0.000000E+00
+823 2.653663E-06 1.059151E-06 0.000000E+00
+824 2.501725E-06 9.989507E-07 0.000000E+00
+825 2.358723E-06 9.422514E-07 0.000000E+00
+826 2.224206E-06 8.888804E-07 0.000000E+00
+827 2.097737E-06 8.386690E-07 0.000000E+00
+828 1.978894E-06 7.914539E-07 0.000000E+00
+829 1.867268E-06 7.470770E-07 0.000000E+00
+830 1.762465E-06 7.053860E-07 0.000000E+00
+
+CIE TC 1-36 proposed
+10-deg XYZ CMFs transformed from the CIE (2006) 2-deg LMS cone fundamentals
+
+390 2.952420E-03 4.076779E-04 1.318752E-02
+391 3.577275E-03 4.977769E-04 1.597879E-02
+392 4.332146E-03 6.064754E-04 1.935758E-02
+393 5.241609E-03 7.370040E-04 2.343758E-02
+394 6.333902E-03 8.929388E-04 2.835021E-02
+395 7.641137E-03 1.078166E-03 3.424588E-02
+396 9.199401E-03 1.296816E-03 4.129467E-02
+397 1.104869E-02 1.553159E-03 4.968641E-02
+398 1.323262E-02 1.851463E-03 5.962964E-02
+399 1.579791E-02 2.195795E-03 7.134926E-02
+400 1.879338E-02 2.589775E-03 8.508254E-02
+401 2.226949E-02 3.036799E-03 1.010753E-01
+402 2.627978E-02 3.541926E-03 1.195838E-01
+403 3.087862E-02 4.111422E-03 1.408647E-01
+404 3.611890E-02 4.752618E-03 1.651644E-01
+405 4.204986E-02 5.474207E-03 1.927065E-01
+406 4.871256E-02 6.285034E-03 2.236782E-01
+407 5.612868E-02 7.188068E-03 2.582109E-01
+408 6.429866E-02 8.181786E-03 2.963632E-01
+409 7.319818E-02 9.260417E-03 3.381018E-01
+410 8.277331E-02 1.041303E-02 3.832822E-01
+411 9.295327E-02 1.162642E-02 4.316884E-01
+412 1.037137E-01 1.289884E-02 4.832440E-01
+413 1.150520E-01 1.423442E-02 5.379345E-01
+414 1.269771E-01 1.564080E-02 5.957740E-01
+415 1.395127E-01 1.712968E-02 6.568187E-01
+416 1.526661E-01 1.871265E-02 7.210459E-01
+417 1.663054E-01 2.038394E-02 7.878635E-01
+418 1.802197E-01 2.212935E-02 8.563391E-01
+419 1.941448E-01 2.392985E-02 9.253017E-01
+420 2.077647E-01 2.576133E-02 9.933444E-01
+421 2.207911E-01 2.760156E-02 1.059178E+00
+422 2.332355E-01 2.945513E-02 1.122832E+00
+423 2.452462E-01 3.133884E-02 1.184947E+00
+424 2.570397E-01 3.327575E-02 1.246476E+00
+425 2.688989E-01 3.529554E-02 1.308674E+00
+426 2.810677E-01 3.742705E-02 1.372628E+00
+427 2.933967E-01 3.967137E-02 1.437661E+00
+428 3.055933E-01 4.201998E-02 1.502449E+00
+429 3.173165E-01 4.446166E-02 1.565456E+00
+430 3.281798E-01 4.698226E-02 1.624940E+00
+431 3.378678E-01 4.956742E-02 1.679488E+00
+432 3.465097E-01 5.221219E-02 1.729668E+00
+433 3.543953E-01 5.491387E-02 1.776755E+00
+434 3.618655E-01 5.766919E-02 1.822228E+00
+435 3.693084E-01 6.047429E-02 1.867751E+00
+436 3.770107E-01 6.332195E-02 1.914504E+00
+437 3.846850E-01 6.619271E-02 1.961055E+00
+438 3.918591E-01 6.906185E-02 2.005136E+00
+439 3.980192E-01 7.190190E-02 2.044296E+00
+440 4.026189E-01 7.468288E-02 2.075946E+00
+441 4.052637E-01 7.738452E-02 2.098231E+00
+442 4.062482E-01 8.003601E-02 2.112591E+00
+443 4.060660E-01 8.268524E-02 2.121427E+00
+444 4.052283E-01 8.538745E-02 2.127239E+00
+445 4.042529E-01 8.820537E-02 2.132574E+00
+446 4.034808E-01 9.118925E-02 2.139093E+00
+447 4.025362E-01 9.431041E-02 2.144815E+00
+448 4.008675E-01 9.751346E-02 2.146832E+00
+449 3.979327E-01 1.007349E-01 2.142250E+00
+450 3.932139E-01 1.039030E-01 2.128264E+00
+451 3.864108E-01 1.069639E-01 2.103205E+00
+452 3.779513E-01 1.099676E-01 2.069388E+00
+453 3.684176E-01 1.129992E-01 2.030030E+00
+454 3.583473E-01 1.161541E-01 1.988178E+00
+455 3.482214E-01 1.195389E-01 1.946651E+00
+456 3.383830E-01 1.232503E-01 1.907521E+00
+457 3.288309E-01 1.273047E-01 1.870689E+00
+458 3.194977E-01 1.316964E-01 1.835578E+00
+459 3.103345E-01 1.364178E-01 1.801657E+00
+460 3.013112E-01 1.414586E-01 1.768440E+00
+461 2.923754E-01 1.468003E-01 1.735338E+00
+462 2.833273E-01 1.524002E-01 1.701254E+00
+463 2.739463E-01 1.582021E-01 1.665053E+00
+464 2.640352E-01 1.641400E-01 1.625712E+00
+465 2.534221E-01 1.701373E-01 1.582342E+00
+466 2.420135E-01 1.761233E-01 1.534439E+00
+467 2.299346E-01 1.820896E-01 1.482544E+00
+468 2.173617E-01 1.880463E-01 1.427438E+00
+469 2.044672E-01 1.940065E-01 1.369876E+00
+470 1.914176E-01 1.999859E-01 1.310576E+00
+471 1.783672E-01 2.060054E-01 1.250226E+00
+472 1.654407E-01 2.120981E-01 1.189511E+00
+473 1.527391E-01 2.183041E-01 1.129050E+00
+474 1.403439E-01 2.246686E-01 1.069379E+00
+475 1.283167E-01 2.312426E-01 1.010952E+00
+476 1.167124E-01 2.380741E-01 9.541809E-01
+477 1.056121E-01 2.451798E-01 8.995253E-01
+478 9.508569E-02 2.525682E-01 8.473720E-01
+479 8.518206E-02 2.602479E-01 7.980093E-01
+480 7.593120E-02 2.682271E-01 7.516389E-01
+481 6.733159E-02 2.765005E-01 7.082645E-01
+482 5.932018E-02 2.850035E-01 6.673867E-01
+483 5.184106E-02 2.936475E-01 6.284798E-01
+484 4.486119E-02 3.023319E-01 5.911174E-01
+485 3.836770E-02 3.109438E-01 5.549619E-01
+486 3.237296E-02 3.194105E-01 5.198843E-01
+487 2.692095E-02 3.278683E-01 4.862772E-01
+488 2.204070E-02 3.365263E-01 4.545497E-01
+489 1.773951E-02 3.456176E-01 4.249955E-01
+490 1.400745E-02 3.554018E-01 3.978114E-01
+491 1.082291E-02 3.660893E-01 3.730218E-01
+492 8.168996E-03 3.775857E-01 3.502618E-01
+493 6.044623E-03 3.896960E-01 3.291407E-01
+494 4.462638E-03 4.021947E-01 3.093356E-01
+495 3.446810E-03 4.148227E-01 2.905816E-01
+496 3.009513E-03 4.273539E-01 2.726773E-01
+497 3.090744E-03 4.398206E-01 2.555143E-01
+498 3.611221E-03 4.523360E-01 2.390188E-01
+499 4.491435E-03 4.650298E-01 2.231335E-01
+500 5.652072E-03 4.780482E-01 2.078158E-01
+501 7.035322E-03 4.915173E-01 1.930407E-01
+502 8.669631E-03 5.054224E-01 1.788089E-01
+503 1.060755E-02 5.197057E-01 1.651287E-01
+504 1.290468E-02 5.343012E-01 1.520103E-01
+505 1.561956E-02 5.491344E-01 1.394643E-01
+506 1.881640E-02 5.641302E-01 1.275353E-01
+507 2.256923E-02 5.792416E-01 1.163771E-01
+508 2.694456E-02 5.944264E-01 1.061161E-01
+509 3.199910E-02 6.096388E-01 9.682266E-02
+510 3.778185E-02 6.248296E-01 8.852389E-02
+511 4.430635E-02 6.399656E-01 8.118263E-02
+512 5.146516E-02 6.550943E-01 7.463132E-02
+513 5.912224E-02 6.702903E-01 6.870644E-02
+514 6.714220E-02 6.856375E-01 6.327834E-02
+515 7.538941E-02 7.012292E-01 5.824484E-02
+516 8.376697E-02 7.171103E-01 5.353812E-02
+517 9.233581E-02 7.330917E-01 4.914863E-02
+518 1.011940E-01 7.489041E-01 4.507511E-02
+519 1.104362E-01 7.642530E-01 4.131175E-02
+520 1.201511E-01 7.788199E-01 3.784916E-02
+521 1.303960E-01 7.923410E-01 3.467234E-02
+522 1.411310E-01 8.048510E-01 3.175471E-02
+523 1.522944E-01 8.164747E-01 2.907029E-02
+524 1.638288E-01 8.273520E-01 2.659651E-02
+525 1.756832E-01 8.376358E-01 2.431375E-02
+526 1.878114E-01 8.474653E-01 2.220677E-02
+527 2.001621E-01 8.568868E-01 2.026852E-02
+528 2.126822E-01 8.659242E-01 1.849246E-02
+529 2.253199E-01 8.746041E-01 1.687084E-02
+530 2.380254E-01 8.829552E-01 1.539505E-02
+531 2.507787E-01 8.910274E-01 1.405450E-02
+532 2.636778E-01 8.989495E-01 1.283354E-02
+533 2.768607E-01 9.068753E-01 1.171754E-02
+534 2.904792E-01 9.149652E-01 1.069415E-02
+535 3.046991E-01 9.233858E-01 9.753000E-03
+536 3.196485E-01 9.322325E-01 8.886096E-03
+537 3.352447E-01 9.412862E-01 8.089323E-03
+538 3.513290E-01 9.502378E-01 7.359131E-03
+539 3.677148E-01 9.587647E-01 6.691736E-03
+540 3.841856E-01 9.665325E-01 6.083223E-03
+541 4.005312E-01 9.732504E-01 5.529423E-03
+542 4.166669E-01 9.788415E-01 5.025504E-03
+543 4.325420E-01 9.832867E-01 4.566879E-03
+544 4.481063E-01 9.865720E-01 4.149405E-03
+545 4.633109E-01 9.886887E-01 3.769336E-03
+546 4.781440E-01 9.897056E-01 3.423302E-03
+547 4.927483E-01 9.899849E-01 3.108313E-03
+548 5.073315E-01 9.899624E-01 2.821650E-03
+549 5.221315E-01 9.900731E-01 2.560830E-03
+550 5.374170E-01 9.907500E-01 2.323578E-03
+551 5.534217E-01 9.922826E-01 2.107847E-03
+552 5.701242E-01 9.943837E-01 1.911867E-03
+553 5.874093E-01 9.966221E-01 1.734006E-03
+554 6.051269E-01 9.985649E-01 1.572736E-03
+555 6.230892E-01 9.997775E-01 1.426627E-03
+556 6.410999E-01 9.999440E-01 1.294325E-03
+557 6.590659E-01 9.992200E-01 1.174475E-03
+558 6.769436E-01 9.978793E-01 1.065842E-03
+559 6.947143E-01 9.961934E-01 9.673215E-04
+560 7.123849E-01 9.944304E-01 8.779264E-04
+561 7.299978E-01 9.927831E-01 7.967847E-04
+562 7.476478E-01 9.911578E-01 7.231502E-04
+563 7.654250E-01 9.893925E-01 6.563501E-04
+564 7.834009E-01 9.873288E-01 5.957678E-04
+565 8.016277E-01 9.848127E-01 5.408385E-04
+566 8.201041E-01 9.817253E-01 4.910441E-04
+567 8.386843E-01 9.780714E-01 4.459046E-04
+568 8.571936E-01 9.738860E-01 4.049826E-04
+569 8.754652E-01 9.692028E-01 3.678818E-04
+570 8.933408E-01 9.640545E-01 3.342429E-04
+571 9.106772E-01 9.584409E-01 3.037407E-04
+572 9.273554E-01 9.522379E-01 2.760809E-04
+573 9.432502E-01 9.452968E-01 2.509970E-04
+574 9.582244E-01 9.374773E-01 2.282474E-04
+575 9.721304E-01 9.286495E-01 2.076129E-04
+576 9.849237E-01 9.187953E-01 1.888948E-04
+577 9.970067E-01 9.083014E-01 1.719127E-04
+578 1.008907E+00 8.976352E-01 1.565030E-04
+579 1.021163E+00 8.872401E-01 1.425177E-04
+580 1.034327E+00 8.775360E-01 1.298230E-04
+581 1.048753E+00 8.687920E-01 1.182974E-04
+582 1.063937E+00 8.607474E-01 1.078310E-04
+583 1.079166E+00 8.530233E-01 9.832455E-05
+584 1.093723E+00 8.452535E-01 8.968787E-05
+585 1.106886E+00 8.370838E-01 8.183954E-05
+586 1.118106E+00 8.282409E-01 7.470582E-05
+587 1.127493E+00 8.187320E-01 6.821991E-05
+588 1.135317E+00 8.086352E-01 6.232132E-05
+589 1.141838E+00 7.980296E-01 5.695534E-05
+590 1.147304E+00 7.869950E-01 5.207245E-05
+591 1.151897E+00 7.756040E-01 4.762781E-05
+592 1.155582E+00 7.638996E-01 4.358082E-05
+593 1.158284E+00 7.519157E-01 3.989468E-05
+594 1.159934E+00 7.396832E-01 3.653612E-05
+595 1.160477E+00 7.272309E-01 3.347499E-05
+596 1.159890E+00 7.145878E-01 3.068400E-05
+597 1.158259E+00 7.017926E-01 2.813839E-05
+598 1.155692E+00 6.888866E-01 2.581574E-05
+599 1.152293E+00 6.759103E-01 2.369574E-05
+600 1.148163E+00 6.629035E-01 2.175998E-05
+601 1.143345E+00 6.498911E-01 1.999179E-05
+602 1.137685E+00 6.368410E-01 1.837603E-05
+603 1.130993E+00 6.237092E-01 1.689896E-05
+604 1.123097E+00 6.104541E-01 1.554815E-05
+605 1.113846E+00 5.970375E-01 1.431231E-05
+606 1.103152E+00 5.834395E-01 1.318119E-05
+607 1.091121E+00 5.697044E-01 1.214548E-05
+608 1.077902E+00 5.558892E-01 1.119673E-05
+609 1.063644E+00 5.420475E-01 1.032727E-05
+610 1.048485E+00 5.282296E-01 9.530130E-06
+611 1.032546E+00 5.144746E-01 8.798979E-06
+612 1.015870E+00 5.007881E-01 8.128065E-06
+613 9.984859E-01 4.871687E-01 7.512160E-06
+614 9.804227E-01 4.736160E-01 6.946506E-06
+615 9.617111E-01 4.601308E-01 6.426776E-06
+616 9.424119E-01 4.467260E-01 0.000000E+00
+617 9.227049E-01 4.334589E-01 0.000000E+00
+618 9.027804E-01 4.203919E-01 0.000000E+00
+619 8.828123E-01 4.075810E-01 0.000000E+00
+620 8.629581E-01 3.950755E-01 0.000000E+00
+621 8.432731E-01 3.828894E-01 0.000000E+00
+622 8.234742E-01 3.709190E-01 0.000000E+00
+623 8.032342E-01 3.590447E-01 0.000000E+00
+624 7.822715E-01 3.471615E-01 0.000000E+00
+625 7.603498E-01 3.351794E-01 0.000000E+00
+626 7.373739E-01 3.230562E-01 0.000000E+00
+627 7.136470E-01 3.108859E-01 0.000000E+00
+628 6.895336E-01 2.987840E-01 0.000000E+00
+629 6.653567E-01 2.868527E-01 0.000000E+00
+630 6.413984E-01 2.751807E-01 0.000000E+00
+631 6.178723E-01 2.638343E-01 0.000000E+00
+632 5.948484E-01 2.528330E-01 0.000000E+00
+633 5.723600E-01 2.421835E-01 0.000000E+00
+634 5.504353E-01 2.318904E-01 0.000000E+00
+635 5.290979E-01 2.219564E-01 0.000000E+00
+636 5.083728E-01 2.123826E-01 0.000000E+00
+637 4.883006E-01 2.031698E-01 0.000000E+00
+638 4.689171E-01 1.943179E-01 0.000000E+00
+639 4.502486E-01 1.858250E-01 0.000000E+00
+640 4.323126E-01 1.776882E-01 0.000000E+00
+641 4.150790E-01 1.698926E-01 0.000000E+00
+642 3.983657E-01 1.623822E-01 0.000000E+00
+643 3.819846E-01 1.550986E-01 0.000000E+00
+644 3.657821E-01 1.479918E-01 0.000000E+00
+645 3.496358E-01 1.410203E-01 0.000000E+00
+646 3.334937E-01 1.341614E-01 0.000000E+00
+647 3.174776E-01 1.274401E-01 0.000000E+00
+648 3.017298E-01 1.208887E-01 0.000000E+00
+649 2.863684E-01 1.145345E-01 0.000000E+00
+650 2.714900E-01 1.083996E-01 0.000000E+00
+651 2.571632E-01 1.025007E-01 0.000000E+00
+652 2.434102E-01 9.684588E-02 0.000000E+00
+653 2.302389E-01 9.143944E-02 0.000000E+00
+654 2.176527E-01 8.628318E-02 0.000000E+00
+655 2.056507E-01 8.137687E-02 0.000000E+00
+656 1.942251E-01 7.671708E-02 0.000000E+00
+657 1.833530E-01 7.229404E-02 0.000000E+00
+658 1.730097E-01 6.809696E-02 0.000000E+00
+659 1.631716E-01 6.411549E-02 0.000000E+00
+660 1.538163E-01 6.033976E-02 0.000000E+00
+661 1.449230E-01 5.676054E-02 0.000000E+00
+662 1.364729E-01 5.336992E-02 0.000000E+00
+663 1.284483E-01 5.016027E-02 0.000000E+00
+664 1.208320E-01 4.712405E-02 0.000000E+00
+665 1.136072E-01 4.425383E-02 0.000000E+00
+666 1.067579E-01 4.154205E-02 0.000000E+00
+667 1.002685E-01 3.898042E-02 0.000000E+00
+668 9.412394E-02 3.656091E-02 0.000000E+00
+669 8.830929E-02 3.427597E-02 0.000000E+00
+670 8.281010E-02 3.211852E-02 0.000000E+00
+671 7.761208E-02 3.008192E-02 0.000000E+00
+672 7.270064E-02 2.816001E-02 0.000000E+00
+673 6.806167E-02 2.634698E-02 0.000000E+00
+674 6.368176E-02 2.463731E-02 0.000000E+00
+675 5.954815E-02 2.302574E-02 0.000000E+00
+676 5.564917E-02 2.150743E-02 0.000000E+00
+677 5.197543E-02 2.007838E-02 0.000000E+00
+678 4.851788E-02 1.873474E-02 0.000000E+00
+679 4.526737E-02 1.747269E-02 0.000000E+00
+680 4.221473E-02 1.628841E-02 0.000000E+00
+681 3.934954E-02 1.517767E-02 0.000000E+00
+682 3.665730E-02 1.413473E-02 0.000000E+00
+683 3.412407E-02 1.315408E-02 0.000000E+00
+684 3.173768E-02 1.223092E-02 0.000000E+00
+685 2.948752E-02 1.136106E-02 0.000000E+00
+686 2.736717E-02 1.054190E-02 0.000000E+00
+687 2.538113E-02 9.775050E-03 0.000000E+00
+688 2.353356E-02 9.061962E-03 0.000000E+00
+689 2.182558E-02 8.402962E-03 0.000000E+00
+690 2.025590E-02 7.797457E-03 0.000000E+00
+691 1.881892E-02 7.243230E-03 0.000000E+00
+692 1.749930E-02 6.734381E-03 0.000000E+00
+693 1.628167E-02 6.265001E-03 0.000000E+00
+694 1.515301E-02 5.830085E-03 0.000000E+00
+695 1.410230E-02 5.425391E-03 0.000000E+00
+696 1.312106E-02 5.047634E-03 0.000000E+00
+697 1.220509E-02 4.695140E-03 0.000000E+00
+698 1.135114E-02 4.366592E-03 0.000000E+00
+699 1.055593E-02 4.060685E-03 0.000000E+00
+700 9.816228E-03 3.776140E-03 0.000000E+00
+701 9.128517E-03 3.511578E-03 0.000000E+00
+702 8.488116E-03 3.265211E-03 0.000000E+00
+703 7.890589E-03 3.035344E-03 0.000000E+00
+704 7.332061E-03 2.820496E-03 0.000000E+00
+705 6.809147E-03 2.619372E-03 0.000000E+00
+706 6.319204E-03 2.430960E-03 0.000000E+00
+707 5.861036E-03 2.254796E-03 0.000000E+00
+708 5.433624E-03 2.090489E-03 0.000000E+00
+709 5.035802E-03 1.937586E-03 0.000000E+00
+710 4.666298E-03 1.795595E-03 0.000000E+00
+711 4.323750E-03 1.663989E-03 0.000000E+00
+712 4.006709E-03 1.542195E-03 0.000000E+00
+713 3.713708E-03 1.429639E-03 0.000000E+00
+714 3.443294E-03 1.325752E-03 0.000000E+00
+715 3.194041E-03 1.229980E-03 0.000000E+00
+716 2.964424E-03 1.141734E-03 0.000000E+00
+717 2.752492E-03 1.060269E-03 0.000000E+00
+718 2.556406E-03 9.848854E-04 0.000000E+00
+719 2.374564E-03 9.149703E-04 0.000000E+00
+720 2.205568E-03 8.499903E-04 0.000000E+00
+721 2.048294E-03 7.895158E-04 0.000000E+00
+722 1.902113E-03 7.333038E-04 0.000000E+00
+723 1.766485E-03 6.811458E-04 0.000000E+00
+724 1.640857E-03 6.328287E-04 0.000000E+00
+725 1.524672E-03 5.881375E-04 0.000000E+00
+726 1.417322E-03 5.468389E-04 0.000000E+00
+727 1.318031E-03 5.086349E-04 0.000000E+00
+728 1.226059E-03 4.732403E-04 0.000000E+00
+729 1.140743E-03 4.404016E-04 0.000000E+00
+730 1.061495E-03 4.098928E-04 0.000000E+00
+731 9.877949E-04 3.815137E-04 0.000000E+00
+732 9.191847E-04 3.550902E-04 0.000000E+00
+733 8.552568E-04 3.304668E-04 0.000000E+00
+734 7.956433E-04 3.075030E-04 0.000000E+00
+735 7.400120E-04 2.860718E-04 0.000000E+00
+736 6.880980E-04 2.660718E-04 0.000000E+00
+737 6.397864E-04 2.474586E-04 0.000000E+00
+738 5.949726E-04 2.301919E-04 0.000000E+00
+739 5.535291E-04 2.142225E-04 0.000000E+00
+740 5.153113E-04 1.994949E-04 0.000000E+00
+741 4.801234E-04 1.859336E-04 0.000000E+00
+742 4.476245E-04 1.734067E-04 0.000000E+00
+743 4.174846E-04 1.617865E-04 0.000000E+00
+744 3.894221E-04 1.509641E-04 0.000000E+00
+745 3.631969E-04 1.408466E-04 0.000000E+00
+746 3.386279E-04 1.313642E-04 0.000000E+00
+747 3.156452E-04 1.224905E-04 0.000000E+00
+748 2.941966E-04 1.142060E-04 0.000000E+00
+749 2.742235E-04 1.064886E-04 0.000000E+00
+750 2.556624E-04 9.931439E-05 0.000000E+00
+751 2.384390E-04 9.265512E-05 0.000000E+00
+752 2.224525E-04 8.647225E-05 0.000000E+00
+753 2.076036E-04 8.072780E-05 0.000000E+00
+754 1.938018E-04 7.538716E-05 0.000000E+00
+755 1.809649E-04 7.041878E-05 0.000000E+00
+756 1.690167E-04 6.579338E-05 0.000000E+00
+757 1.578839E-04 6.148250E-05 0.000000E+00
+758 1.474993E-04 5.746008E-05 0.000000E+00
+759 1.378026E-04 5.370272E-05 0.000000E+00
+760 1.287394E-04 5.018934E-05 0.000000E+00
+761 1.202644E-04 4.690245E-05 0.000000E+00
+762 1.123502E-04 4.383167E-05 0.000000E+00
+763 1.049725E-04 4.096780E-05 0.000000E+00
+764 9.810596E-05 3.830123E-05 0.000000E+00
+765 9.172477E-05 3.582218E-05 0.000000E+00
+766 8.579861E-05 3.351903E-05 0.000000E+00
+767 8.028174E-05 3.137419E-05 0.000000E+00
+768 7.513013E-05 2.937068E-05 0.000000E+00
+769 7.030565E-05 2.749380E-05 0.000000E+00
+770 6.577532E-05 2.573083E-05 0.000000E+00
+771 6.151508E-05 2.407249E-05 0.000000E+00
+772 5.752025E-05 2.251704E-05 0.000000E+00
+773 5.378813E-05 2.106350E-05 0.000000E+00
+774 5.031350E-05 1.970991E-05 0.000000E+00
+775 4.708916E-05 1.845353E-05 0.000000E+00
+776 4.410322E-05 1.728979E-05 0.000000E+00
+777 4.133150E-05 1.620928E-05 0.000000E+00
+778 3.874992E-05 1.520262E-05 0.000000E+00
+779 3.633762E-05 1.426169E-05 0.000000E+00
+780 3.407653E-05 1.337946E-05 0.000000E+00
+781 3.195242E-05 1.255038E-05 0.000000E+00
+782 2.995808E-05 1.177169E-05 0.000000E+00
+783 2.808781E-05 1.104118E-05 0.000000E+00
+784 2.633581E-05 1.035662E-05 0.000000E+00
+785 2.469630E-05 9.715798E-06 0.000000E+00
+786 2.316311E-05 9.116316E-06 0.000000E+00
+787 2.172855E-05 8.555201E-06 0.000000E+00
+788 2.038519E-05 8.029561E-06 0.000000E+00
+789 1.912625E-05 7.536768E-06 0.000000E+00
+790 1.794555E-05 7.074424E-06 0.000000E+00
+791 1.683776E-05 6.640464E-06 0.000000E+00
+792 1.579907E-05 6.233437E-06 0.000000E+00
+793 1.482604E-05 5.852035E-06 0.000000E+00
+794 1.391527E-05 5.494963E-06 0.000000E+00
+795 1.306345E-05 5.160948E-06 0.000000E+00
+796 1.226720E-05 4.848687E-06 0.000000E+00
+797 1.152279E-05 4.556705E-06 0.000000E+00
+798 1.082663E-05 4.283580E-06 0.000000E+00
+799 1.017540E-05 4.027993E-06 0.000000E+00
+800 9.565993E-06 3.788729E-06 0.000000E+00
+801 8.995405E-06 3.564599E-06 0.000000E+00
+802 8.460253E-06 3.354285E-06 0.000000E+00
+803 7.957382E-06 3.156557E-06 0.000000E+00
+804 7.483997E-06 2.970326E-06 0.000000E+00
+805 7.037621E-06 2.794625E-06 0.000000E+00
+806 6.616311E-06 2.628701E-06 0.000000E+00
+807 6.219265E-06 2.472248E-06 0.000000E+00
+808 5.845844E-06 2.325030E-06 0.000000E+00
+809 5.495311E-06 2.186768E-06 0.000000E+00
+810 5.166853E-06 2.057152E-06 0.000000E+00
+811 4.859511E-06 1.935813E-06 0.000000E+00
+812 4.571973E-06 1.822239E-06 0.000000E+00
+813 4.302920E-06 1.715914E-06 0.000000E+00
+814 4.051121E-06 1.616355E-06 0.000000E+00
+815 3.815429E-06 1.523114E-06 0.000000E+00
+816 3.594719E-06 1.435750E-06 0.000000E+00
+817 3.387736E-06 1.353771E-06 0.000000E+00
+818 3.193301E-06 1.276714E-06 0.000000E+00
+819 3.010363E-06 1.204166E-06 0.000000E+00
+820 2.837980E-06 1.135758E-06 0.000000E+00
+821 2.675365E-06 1.071181E-06 0.000000E+00
+822 2.522020E-06 1.010243E-06 0.000000E+00
+823 2.377511E-06 9.527779E-07 0.000000E+00
+824 2.241417E-06 8.986224E-07 0.000000E+00
+825 2.113325E-06 8.476168E-07 0.000000E+00
+826 1.992830E-06 7.996052E-07 0.000000E+00
+827 1.879542E-06 7.544361E-07 0.000000E+00
+828 1.773083E-06 7.119624E-07 0.000000E+00
+829 1.673086E-06 6.720421E-07 0.000000E+00
+830 1.579199E-06 6.345380E-07 0.000000E+00
+#endif /* NEVER */
#endif /* !SALONEINSTLIB */
/* Return pointers to three xpsects with a standard observer weighting curves */
@@ -1745,36 +2609,6 @@ char *standardObserverDescription(icxObserverType obType) {
return "Unknown observer";
}
-/* Return a pointer to the spectral locus poligon */
-/* return NULL on failure. */
-static xslpoly *spectral_locus_poligon(
-icxObserverType obType /* Type of observer */
-) {
- switch (obType) {
- case icxOT_custom:
- return NULL;
- case icxOT_none:
- return NULL;
- case icxOT_default:
- case icxOT_CIE_1931_2:
- return &poly_CIE_1931_2;
- case icxOT_CIE_1964_10:
- return &poly_CIE_1964_10;
-#ifndef SALONEINSTLIB
- case icxOT_Stiles_Burch_2:
- return &poly_Stiles_Burch_2;
- case icxOT_Judd_Voss_2:
- return &poly_Judd_Voss_2;
- case icxOT_CIE_1964_10c:
- return &poly_CIE_1964_10c;
- case icxOT_Shaw_Fairchild_2:
- return &poly_Shaw_Fairchild_2;
-#endif /* !SALONEINSTLIB */
- default:
- return NULL;
- }
-}
-
#ifndef SALONEINSTLIB
/* ----------------------------------- */
@@ -2135,6 +2969,8 @@ int write_nxspect(char *fname, xspect *sp, int nspec, int type) {
sprintf(buf,"%f", sp->norm);
ocg->add_kword(ocg, 0, "SPECTRAL_NORM",buf, NULL);
+ /* Should we adda A COORD field for "CMF" and an INDEX field for "SPECT" ? */
+
/* Generate fields for spectral values */
for (i = 0; i < sp->spec_n; i++) {
int nm;
@@ -2172,6 +3008,7 @@ int write_nxspect(char *fname, xspect *sp, int nspec, int type) {
/* Up to nspec will be restored starting at offset off.. */
/* The number restored from the file will be written to *nret */
/* type: 0 = any, mask: 1 = SPECT, 2 = CMF, 4 = ccss */
+/* (Note that not all ccss information is read. Use ccss->read_ccss() for this. */
/* Return NZ on error */
/* (Would be nice to return an error message!) */
int read_nxspect(xspect *sp, char *fname, int *nret, int off, int nspec, int type) {
@@ -2454,6 +3291,44 @@ static int getval_raw_xspec_lin(xspect *sp, double *rv, double wl) {
return rc;
}
+/* Get a raw linearly interpolated spectrum value x 3. */
+/* Return NZ if value is valid, Z and last valid value */
+/* if outside the range */
+/* NOTE: Returned value isn't normalised by sp->norm */
+static int getval_raw_xspec3_lin(xspect *sp, double *rv, double wl) {
+ int i, rc = 1;
+ double f, w;
+
+ if (wl < sp[0].spec_wl_short) {
+ wl = sp[0].spec_wl_short;
+ rc = 0;
+ }
+
+ if (wl > sp[0].spec_wl_long) {
+ wl = sp[0].spec_wl_long;
+ rc = 0;
+ }
+
+ /* Compute fraction 0.0 - 1.0 out of known spectrum */
+ f = (wl - sp[0].spec_wl_short) / (sp[0].spec_wl_long - sp[0].spec_wl_short);
+ f *= (sp[0].spec_n - 1.0);
+ i = (int)floor(f); /* Base grid coordinate */
+
+ if (i < 0) /* Limit to valid cube base index range */
+ i = 0;
+ else if (i > (sp[0].spec_n - 2))
+ i = (sp[0].spec_n - 2);
+
+ w = f - (double)i; /* Interpolation weighting factor */
+
+ /* Compute interpolated value */
+ rv[0] = (1.0 - w) * sp[0].spec[i] + w * sp[0].spec[i+1];
+ rv[1] = (1.0 - w) * sp[1].spec[i] + w * sp[1].spec[i+1];
+ rv[2] = (1.0 - w) * sp[2].spec[i] + w * sp[2].spec[i+1];
+
+ return rc;
+}
+
#ifdef NEVER /* Nearest neighbor resampler, for testing */
/* Get a raw nearest-neighbor interpolated spectrum value. */
/* Return NZ if value is valid, Z and last valid value */
@@ -2587,6 +3462,7 @@ void xspect2xspect(xspect *dst, xspect *targ, xspect *src) {
/* Given an emission spectrum, set the UV output to the given level. */
/* The shape of the UV is taken from FWA1_stim, and the level is */
/* with respect to the Y of the input spectrum. */
+/* The output range is extended to accomodate the UV wavelengths */
void xsp_setUV(xspect *out, xspect *in, double uvlevel) {
int i, xs, xe;
double ww, avg;
@@ -2594,7 +3470,7 @@ void xsp_setUV(xspect *out, xspect *in, double uvlevel) {
cin = *in;
- /* Compute the average of the input spetrum */
+ /* Compute the average of the input spectrum */
for (avg = 0.0, i = 0; i < cin.spec_n; i++)
avg += cin.spec[i];
avg /= cin.spec_n;
@@ -2618,6 +3494,9 @@ void xsp_setUV(xspect *out, xspect *in, double uvlevel) {
getval_raw_xspec_lin(&cin, &inv, ww);
getval_raw_xspec_lin(&FWA1_stim, &uvv, ww);
+ /* Input illuminant with no Uv */
+ out->spec[i] = inv;
+
/* Taper measured illum out */
bl = (ww - FWA1_stim.spec_wl_short)/(FWA1_stim.spec_wl_long - FWA1_stim.spec_wl_short);
bl = bl < 0.0 ? 0.0 : (bl > 1.0 ? 1.0 : bl);
@@ -3735,8 +4614,9 @@ xspect *in /* Spectrum to be converted */
/* are used, also consistent with CIE and ANSI CGATS recommendations. */
out[j] = 0.0;
for (ww = p->observer[j].spec_wl_short; ww <= p->observer[j].spec_wl_long; ww += 1.0) {
- double I, O, S;
- getval_xspec(&p->illuminant, &I, ww);
+ double I = 1.0, O, S;
+ if (!p->isemis)
+ getval_xspec(&p->illuminant, &I, ww);
getval_xspec(&p->observer[j], &O, ww);
getval_xspec(in, &S, ww);
if (j == 1)
@@ -3788,7 +4668,7 @@ icxIllumeType ilType, /* Illuminant */
xspect *custIllum, /* Optional custom illuminant */
icxObserverType obType, /* Observer */
xspect custObserver[3], /* Optional custom observer */
-icColorSpaceSignature rcs, /* Return color space, icSigXYZData or icSigLabData */
+icColorSpaceSignature rcs, /* Return color space, icSigXYZData or D50 icSigLabData */
/* ** Must be icSigXYZData if SALONEINSTLIB ** */
icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */
) {
@@ -3924,9 +4804,10 @@ icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */
#ifndef SALONEINSTLIB
+
/* -------------------------------------------------------- */
-/* Return the spectrum locus rangefor the given observer */
+/* Return the spectrum locus range for the given observer */
/* return 0 on sucecss, nz if observer not known */
int icx_spectrum_locus_range(double *min_wl, double *max_wl, icxObserverType obType) {
xspect *sp[3];
@@ -3947,7 +4828,7 @@ int icx_spectrum_locus_range(double *min_wl, double *max_wl, icxObserverType obT
int icx_spectrum_locus(double xyz[3], double wl, icxObserverType obType) {
xspect *sp[3];
- DBGF((DBGA,"icx_spectrum_locus got obs %d wl %f\n",obType, wl));
+ DBGF((DBGA,"icx_chrom_locus got obs %d wl %f\n",obType, wl));
if (standardObserver(sp, obType))
return 1;
@@ -3966,113 +4847,1033 @@ int icx_spectrum_locus(double xyz[3], double wl, icxObserverType obType) {
return 0;
}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Pre-calculated spectral locuses of Daylight and Plankian at 5 Mired intervals */
+/* These aren't actually spectrum, they are XYZ values */
+/* indexed by temperature in Mired */
+
+static xspect illoc_Daylight_CIE_1931_2[3] = {
+ {
+ 69, 60.000000, 400.000000,
+ 1.0,
+ {
+ 0.970635, 0.968292, 0.966045, 0.963906, 0.961884,
+ 0.959990, 0.958232, 0.956618, 0.955155, 0.953850,
+ 0.952710, 0.951740, 0.950945, 0.950330, 0.949899,
+ 0.949656, 0.949604, 0.949747, 0.950085, 0.950619,
+ 0.951352, 0.952283, 0.953413, 0.954741, 0.956265,
+ 0.957984, 0.959896, 0.961999, 0.964289, 0.966764,
+ 0.969419, 0.972251, 0.975254, 0.978425, 0.981759,
+ 0.985248, 0.988889, 0.992674, 0.996597, 1.000651,
+ 1.004828, 1.009121, 1.013522, 1.018021, 1.022611,
+ 1.027281, 1.032021, 1.036822, 1.041673, 1.046562,
+ 1.051478, 1.056409, 1.061342, 1.066265, 1.071163,
+ 1.076024, 1.080834, 1.085577, 1.090239, 1.094805,
+ 1.099259, 1.103586, 1.107771, 1.111796, 1.115647,
+ 1.119306, 1.122759, 1.125989, 1.128981
+ }
+ },
+ {
+ 69, 60.000000, 400.000000,
+ 1.0,
+ {
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000
+ }
+ },
+ {
+ 69, 60.000000, 400.000000,
+ 1.0,
+ {
+ 1.787622, 1.747661, 1.707659, 1.667701, 1.627864,
+ 1.588223, 1.548842, 1.509780, 1.471093, 1.432827,
+ 1.395026, 1.357727, 1.320965, 1.284767, 1.249158,
+ 1.214160, 1.179790, 1.146125, 1.113225, 1.081024,
+ 1.049542, 1.018793, 0.988790, 0.959541, 0.931050,
+ 0.903320, 0.876351, 0.850140, 0.824684, 0.799977,
+ 0.776012, 0.752780, 0.730272, 0.708479, 0.687390,
+ 0.666992, 0.647275, 0.628227, 0.609834, 0.592085,
+ 0.574967, 0.558466, 0.542572, 0.527270, 0.512549,
+ 0.498396, 0.484799, 0.471746, 0.459226, 0.447227,
+ 0.435739, 0.424749, 0.414250, 0.404229, 0.394677,
+ 0.385586, 0.376946, 0.368749, 0.360986, 0.353651,
+ 0.346735, 0.340234, 0.334139, 0.328447, 0.323151,
+ 0.318248, 0.313734, 0.309607, 0.305862
+ }
+ }
+};
+
+static xspect illoc_Plankian_CIE_1931_2[3] = {
+ {
+ 189, 60.000000, 1000.000000,
+ 1.0,
+ {
+ 0.990017, 0.987458, 0.985018, 0.982708, 0.980540,
+ 0.978522, 0.976663, 0.974970, 0.973449, 0.972105,
+ 0.970942, 0.969965, 0.969174, 0.968572, 0.968159,
+ 0.967936, 0.967902, 0.968056, 0.968396, 0.968922,
+ 0.969629, 0.970517, 0.971581, 0.972819, 0.974227,
+ 0.975803, 0.977542, 0.979441, 0.981495, 0.983702,
+ 0.986058, 0.988559, 0.991200, 0.993979, 0.996891,
+ 0.999934, 1.003102, 1.006394, 1.009804, 1.013331,
+ 1.016970, 1.020718, 1.024572, 1.028529, 1.032586,
+ 1.036739, 1.040986, 1.045325, 1.049751, 1.054263,
+ 1.058857, 1.063532, 1.068285, 1.073113, 1.078013,
+ 1.082985, 1.088024, 1.093130, 1.098299, 1.103530,
+ 1.108822, 1.114170, 1.119575, 1.125034, 1.130544,
+ 1.136105, 1.141715, 1.147371, 1.153072, 1.158817,
+ 1.164604, 1.170431, 1.176297, 1.182201, 1.188140,
+ 1.194115, 1.200122, 1.206161, 1.212231, 1.218329,
+ 1.224456, 1.230610, 1.236790, 1.242994, 1.249221,
+ 1.255470, 1.261741, 1.268032, 1.274342, 1.280670,
+ 1.287015, 1.293376, 1.299753, 1.306144, 1.312548,
+ 1.318965, 1.325393, 1.331833, 1.338282, 1.344741,
+ 1.351208, 1.357683, 1.364165, 1.370653, 1.377146,
+ 1.383645, 1.390147, 1.396654, 1.403162, 1.409674,
+ 1.416186, 1.422700, 1.429214, 1.435728, 1.442241,
+ 1.448753, 1.455263, 1.461771, 1.468275, 1.474777,
+ 1.481274, 1.487767, 1.494255, 1.500738, 1.507215,
+ 1.513686, 1.520150, 1.526607, 1.533057, 1.539498,
+ 1.545932, 1.552356, 1.558772, 1.565178, 1.571574,
+ 1.577960, 1.584336, 1.590701, 1.597054, 1.603397,
+ 1.609727, 1.616045, 1.622351, 1.628644, 1.634924,
+ 1.641190, 1.647444, 1.653683, 1.659908, 1.666119,
+ 1.672315, 1.678497, 1.684663, 1.690814, 1.696949,
+ 1.703069, 1.709173, 1.715260, 1.721331, 1.727386,
+ 1.733423, 1.739444, 1.745447, 1.751433, 1.757402,
+ 1.763353, 1.769286, 1.775201, 1.781098, 1.786976,
+ 1.792836, 1.798677, 1.804500, 1.810304, 1.816088,
+ 1.821853, 1.827600, 1.833326, 1.839033, 1.844721,
+ 1.850388, 1.856036, 1.861664, 1.867272, 1.872859,
+ 1.878426, 1.883973, 1.889500, 1.895006
+ }
+ },
+ {
+ 189, 60.000000, 1000.000000,
+ 1.0,
+ {
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000
+ }
+ },
+ {
+ 189, 60.000000, 1000.000000,
+ 1.0,
+ {
+ 1.807443, 1.767939, 1.728424, 1.688977, 1.649677,
+ 1.610595, 1.571797, 1.533345, 1.495294, 1.457694,
+ 1.420591, 1.384023, 1.348026, 1.312628, 1.277856,
+ 1.243731, 1.210269, 1.177483, 1.145385, 1.113980,
+ 1.083273, 1.053267, 1.023960, 0.995350, 0.967433,
+ 0.940204, 0.913655, 0.887779, 0.862566, 0.838007,
+ 0.814090, 0.790805, 0.768140, 0.746084, 0.724623,
+ 0.703745, 0.683438, 0.663689, 0.644486, 0.625814,
+ 0.607663, 0.590019, 0.572870, 0.556203, 0.540006,
+ 0.524267, 0.508975, 0.494117, 0.479683, 0.465661,
+ 0.452040, 0.438809, 0.425958, 0.413476, 0.401354,
+ 0.389581, 0.378149, 0.367047, 0.356266, 0.345798,
+ 0.335634, 0.325764, 0.316182, 0.306879, 0.297847,
+ 0.289078, 0.280566, 0.272302, 0.264279, 0.256492,
+ 0.248932, 0.241594, 0.234472, 0.227558, 0.220848,
+ 0.214334, 0.208013, 0.201877, 0.195922, 0.190142,
+ 0.184533, 0.179089, 0.173806, 0.168679, 0.163703,
+ 0.158875, 0.154189, 0.149641, 0.145229, 0.140947,
+ 0.136792, 0.132760, 0.128847, 0.125050, 0.121366,
+ 0.117792, 0.114323, 0.110958, 0.107692, 0.104523,
+ 0.101449, 0.098466, 0.095571, 0.092763, 0.090038,
+ 0.087394, 0.084829, 0.082340, 0.079926, 0.077583,
+ 0.075310, 0.073104, 0.070964, 0.068888, 0.066874,
+ 0.064919, 0.063023, 0.061184, 0.059399, 0.057667,
+ 0.055987, 0.054357, 0.052775, 0.051240, 0.049752,
+ 0.048307, 0.046906, 0.045546, 0.044226, 0.042946,
+ 0.041704, 0.040499, 0.039330, 0.038195, 0.037095,
+ 0.036027, 0.034990, 0.033985, 0.033009, 0.032062,
+ 0.031144, 0.030252, 0.029387, 0.028548, 0.027734,
+ 0.026943, 0.026177, 0.025432, 0.024710, 0.024009,
+ 0.023329, 0.022669, 0.022029, 0.021407, 0.020804,
+ 0.020219, 0.019651, 0.019099, 0.018564, 0.018044,
+ 0.017540, 0.017051, 0.016576, 0.016115, 0.015668,
+ 0.015233, 0.014811, 0.014402, 0.014005, 0.013619,
+ 0.013245, 0.012881, 0.012528, 0.012186, 0.011853,
+ 0.011530, 0.011217, 0.010912, 0.010617, 0.010329,
+ 0.010051, 0.009780, 0.009517, 0.009262, 0.009014,
+ 0.008773, 0.008540, 0.008313, 0.008092
+ }
+ }
+};
+
+static xspect illoc_Daylight_CIE_1964_10[3] = {
+ {
+ 69, 60.000000, 400.000000,
+ 1.0,
+ {
+ 0.949535, 0.948408, 0.947363, 0.946408, 0.945551,
+ 0.944800, 0.944161, 0.943639, 0.943243, 0.942976,
+ 0.942844, 0.942853, 0.943006, 0.943308, 0.943763,
+ 0.944374, 0.945146, 0.946079, 0.947174, 0.948434,
+ 0.949861, 0.951455, 0.953217, 0.955146, 0.957242,
+ 0.959504, 0.961930, 0.964519, 0.967268, 0.970175,
+ 0.973237, 0.976450, 0.979812, 0.983317, 0.986963,
+ 0.990743, 0.994653, 0.998688, 1.002842, 1.007108,
+ 1.011480, 1.015951, 1.020514, 1.025161, 1.029883,
+ 1.034672, 1.039519, 1.044415, 1.049348, 1.054309,
+ 1.059288, 1.064271, 1.069249, 1.074207, 1.079135,
+ 1.084018, 1.088844, 1.093597, 1.098265, 1.102832,
+ 1.107284, 1.111605, 1.115781, 1.119796, 1.123634,
+ 1.127280, 1.130718, 1.133933, 1.136910
+ }
+ },
+ {
+ 69, 60.000000, 400.000000,
+ 1.0,
+ {
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000
+ }
+ },
+ {
+ 69, 60.000000, 400.000000,
+ 1.0,
+ {
+ 1.736104, 1.699156, 1.662051, 1.624867, 1.587679,
+ 1.550555, 1.513559, 1.476750, 1.440182, 1.403904,
+ 1.367961, 1.332394, 1.297239, 1.262528, 1.228292,
+ 1.194555, 1.161341, 1.128728, 1.096782, 1.065445,
+ 1.034742, 1.004693, 0.975315, 0.946623, 0.918626,
+ 0.891332, 0.864747, 0.838873, 0.813712, 0.789262,
+ 0.765521, 0.742485, 0.720149, 0.698506, 0.677549,
+ 0.657271, 0.637662, 0.618713, 0.600415, 0.582756,
+ 0.565728, 0.549318, 0.533516, 0.518310, 0.503690,
+ 0.489644, 0.476161, 0.463230, 0.450839, 0.438977,
+ 0.427633, 0.416797, 0.406457, 0.396605, 0.387228,
+ 0.378318, 0.369864, 0.361858, 0.354290, 0.347151,
+ 0.340434, 0.334131, 0.328233, 0.322735, 0.317629,
+ 0.312911, 0.308575, 0.304616, 0.301031
+ }
+ }
+};
+
+static xspect illoc_Plankian_CIE_1964_10[3] = {
+ {
+ 189, 60.000000, 1000.000000,
+ 1.0,
+ {
+ 0.974241, 0.972539, 0.970952, 0.969490, 0.968163,
+ 0.966977, 0.965941, 0.965060, 0.964340, 0.963785,
+ 0.963398, 0.963183, 0.963140, 0.963272, 0.963578,
+ 0.964058, 0.964713, 0.965540, 0.966539, 0.967707,
+ 0.969041, 0.970540, 0.972201, 0.974020, 0.975994,
+ 0.978121, 0.980396, 0.982816, 0.985378, 0.988077,
+ 0.990911, 0.993876, 0.996967, 1.000182, 1.003517,
+ 1.006968, 1.010533, 1.014206, 1.017986, 1.021868,
+ 1.025851, 1.029929, 1.034101, 1.038362, 1.042711,
+ 1.047144, 1.051659, 1.056252, 1.060921, 1.065663,
+ 1.070476, 1.075357, 1.080304, 1.085314, 1.090384,
+ 1.095514, 1.100699, 1.105939, 1.111231, 1.116573,
+ 1.121962, 1.127398, 1.132878, 1.138400, 1.143962,
+ 1.149564, 1.155202, 1.160875, 1.166582, 1.172320,
+ 1.178090, 1.183888, 1.189713, 1.195565, 1.201441,
+ 1.207340, 1.213262, 1.219204, 1.225165, 1.231144,
+ 1.237140, 1.243152, 1.249179, 1.255219, 1.261272,
+ 1.267336, 1.273410, 1.279494, 1.285586, 1.291686,
+ 1.297792, 1.303903, 1.310020, 1.316140, 1.322264,
+ 1.328390, 1.334517, 1.340646, 1.346774, 1.352902,
+ 1.359028, 1.365152, 1.371274, 1.377392, 1.383506,
+ 1.389615, 1.395720, 1.401819, 1.407911, 1.413996,
+ 1.420075, 1.426145, 1.432207, 1.438260, 1.444304,
+ 1.450337, 1.456361, 1.462374, 1.468376, 1.474367,
+ 1.480346, 1.486312, 1.492266, 1.498207, 1.504134,
+ 1.510048, 1.515948, 1.521834, 1.527705, 1.533561,
+ 1.539402, 1.545228, 1.551037, 1.556831, 1.562609,
+ 1.568370, 1.574114, 1.579842, 1.585552, 1.591245,
+ 1.596920, 1.602578, 1.608217, 1.613839, 1.619442,
+ 1.625026, 1.630592, 1.636139, 1.641668, 1.647177,
+ 1.652666, 1.658137, 1.663587, 1.669019, 1.674430,
+ 1.679822, 1.685193, 1.690544, 1.695876, 1.701187,
+ 1.706477, 1.711747, 1.716997, 1.722226, 1.727434,
+ 1.732621, 1.737788, 1.742934, 1.748058, 1.753162,
+ 1.758245, 1.763306, 1.768347, 1.773366, 1.778364,
+ 1.783341, 1.788296, 1.793230, 1.798143, 1.803034,
+ 1.807904, 1.812753, 1.817580, 1.822386, 1.827170,
+ 1.831933, 1.836674, 1.841394, 1.846092
+ }
+ },
+ {
+ 189, 60.000000, 1000.000000,
+ 1.0,
+ {
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 1.000000
+ }
+ },
+ {
+ 189, 60.000000, 1000.000000,
+ 1.0,
+ {
+ 1.775958, 1.738417, 1.700795, 1.663169, 1.625615,
+ 1.588201, 1.550992, 1.514049, 1.477427, 1.441177,
+ 1.405344, 1.369969, 1.335088, 1.300732, 1.266930,
+ 1.233704, 1.201074, 1.169056, 1.137662, 1.106903,
+ 1.076786, 1.047315, 1.018493, 0.990321, 0.962796,
+ 0.935916, 0.909677, 0.884073, 0.859098, 0.834744,
+ 0.811003, 0.787866, 0.765323, 0.743365, 0.721980,
+ 0.701159, 0.680891, 0.661164, 0.641968, 0.623290,
+ 0.605120, 0.587446, 0.570257, 0.553542, 0.537290,
+ 0.521489, 0.506129, 0.491199, 0.476688, 0.462586,
+ 0.448883, 0.435567, 0.422630, 0.410062, 0.397852,
+ 0.385993, 0.374473, 0.363285, 0.352420, 0.341868,
+ 0.331622, 0.321672, 0.312013, 0.302634, 0.293529,
+ 0.284689, 0.276109, 0.267780, 0.259696, 0.251849,
+ 0.244234, 0.236843, 0.229670, 0.222710, 0.215956,
+ 0.209402, 0.203043, 0.196873, 0.190887, 0.185079,
+ 0.179445, 0.173979, 0.168676, 0.163533, 0.158544,
+ 0.153704, 0.149010, 0.144457, 0.140042, 0.135759,
+ 0.131606, 0.127578, 0.123672, 0.119884, 0.116210,
+ 0.112648, 0.109194, 0.105845, 0.102598, 0.099449,
+ 0.096397, 0.093437, 0.090567, 0.087785, 0.085088,
+ 0.082473, 0.079938, 0.077480, 0.075098, 0.072788,
+ 0.070550, 0.068380, 0.066276, 0.064237, 0.062260,
+ 0.060345, 0.058488, 0.056688, 0.054943, 0.053252,
+ 0.051613, 0.050025, 0.048485, 0.046993, 0.045547,
+ 0.044145, 0.042787, 0.041470, 0.040194, 0.038958,
+ 0.037760, 0.036598, 0.035473, 0.034382, 0.033325,
+ 0.032300, 0.031308, 0.030346, 0.029413, 0.028510,
+ 0.027634, 0.026786, 0.025963, 0.025166, 0.024394,
+ 0.023646, 0.022921, 0.022218, 0.021537, 0.020877,
+ 0.020237, 0.019618, 0.019017, 0.018435, 0.017871,
+ 0.017324, 0.016795, 0.016281, 0.015784, 0.015302,
+ 0.014835, 0.014382, 0.013943, 0.013518, 0.013106,
+ 0.012706, 0.012319, 0.011944, 0.011581, 0.011228,
+ 0.010887, 0.010556, 0.010235, 0.009925, 0.009623,
+ 0.009331, 0.009048, 0.008774, 0.008508, 0.008251,
+ 0.008001, 0.007759, 0.007524, 0.007297, 0.007077,
+ 0.006863, 0.006656, 0.006455, 0.006261
+ }
+ }
+};
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Fast but slightly less accurate CCT support */
+
+/* Context for optimiser callback */
+typedef struct {
+ xspect *iloc; /* Locus to match to */
+ double xyz[3]; /* Target XYZ */
+ icmXYZNumber XYZ; /* Target as XYZ number for DE wp */
+ xsp2cie *conv; /* Means of converting spectrum to XYZ */
+ int viscct; /* nz to use visual best match color temperature */
+} cct2ctx;
+
+static double cct2_func(void *fdata, double tp[]) {
+ cct2ctx *x = (cct2ctx *)fdata;
+ double xyz[3]; /* Current value */
+ double lab1[3], lab2[3];
+ xspect sp;
+ double rv = 0.0;
+ icmXYZNumber *wp = &x->XYZ;
+
+ /* Get XYZ for given temp in Mired. */
+ /* Will clip to limits of locus */
+ getval_raw_xspec3_lin(x->iloc, xyz, tp[0]);
+
+ xyz[0] /= xyz[1];
+ xyz[2] /= xyz[1];
+ xyz[1] /= xyz[1];
+
+ /* Compute the color difference to the target */
+ if (x->viscct) {
+ /* Use modern CIEDE2000 color difference - gives a better visual match */
+ icmXYZ2Lab(wp, lab1, x->xyz);
+ icmXYZ2Lab(wp, lab2, xyz);
+ rv = icmCIE2Ksq(lab1, lab2);
+ } else {
+ /* Use original CIE 1960 UCS space color difference */
+ icmXYZ21960UCS(lab1, x->xyz);
+ icmXYZ21960UCS(lab2, xyz);
+ rv = icmLabDEsq(lab1, lab2);
+ }
+
+//a1logd(g_log, 1, " cct2_func returning %f for temp = %f\n",rv,1e6/tp[0]);
+//DBGF((DBGA,"returning %f for temp = %f\n",rv,tp[0]));
+ return rv;
+
+}
+
+/* Given a choice of temperature dependent illuminant (icxIT_Dtemp or icxIT_Ptemp), */
+/* return the closest correlated color temperature to the XYZ. */
+/* An observer type can be chosen for interpretting the spectrum of the input and */
+/* the illuminant. */
+/* Return -1.0 on erorr */
+double icx_XYZ2ill_ct2(
+double txyz[3], /* If not NULL, return the XYZ of the locus temperature */
+icxIllumeType ilType, /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */
+icxObserverType obType, /* Observer, CIE_1931_2 or CIE_1964_10 */
+double xyz[3], /* Input XYZ value */
+int viscct /* nz to use visual CIEDE2000, 0 to use CCT CIE 1960 UCS. */
+) {
+ cct2ctx x; /* Context for callback */
+ double cp[1], s[1];
+ double rv;
+ int i;
+ double tc, ber, bct = 0.0;
+
+ x.viscct = viscct;
+
+ if (ilType != icxIT_Dtemp && ilType != icxIT_Ptemp)
+ return -1.0;
+ if (obType != icxOT_CIE_1931_2 && obType != icxOT_CIE_1964_10)
+ return -1.0;
+
+ /* Locus to use */
+ if (obType == icxOT_CIE_1931_2) {
+ if (ilType == icxIT_Dtemp) {
+ x.iloc = illoc_Daylight_CIE_1931_2;
+ } else {
+ x.iloc = illoc_Plankian_CIE_1931_2;
+ }
+ } else {
+ if (ilType == icxIT_Dtemp) {
+ x.iloc = illoc_Daylight_CIE_1964_10;
+ } else {
+ x.iloc = illoc_Plankian_CIE_1964_10;
+ }
+ }
+
+ icmAry2Ary(x.xyz, xyz);
+
+ /* Normalise target */
+ x.xyz[0] /= x.xyz[1];
+ x.xyz[2] /= x.xyz[1];
+ x.xyz[1] /= x.xyz[1];
+
+ /* Convert to XYZ number for DE wp */
+ icmAry2XYZ(x.XYZ, x.xyz);
+
+ /* Do some start samples, to avoid getting trapped in local minima */
+ for (ber = 1e9, i = 0; i < 6; i++) {
+ double er;
+ tc = x.iloc[0].spec_wl_short
+ + i/(6-1.0) * (x.iloc[0].spec_wl_long - x.iloc[0].spec_wl_short);
+ if ((er = cct2_func((void *)&x, &tc)) < ber) {
+ ber = er;
+ bct = tc;
+ }
+//a1logd(g_log, 1, " starting tc = %f, err = %f\n",1e6/tc,er);
+//DBGF((DBGA,"tc = %f, er = %f\n",1e6/tc,er));
+ }
+ cp[0] = bct;
+ s[0] = 20.0;
+
+ /* Locate the CCT in Mired */
+ if (powell(&rv, 1, cp, s, 0.01, 1000, cct2_func, (void *)&x, NULL, NULL) != 0) {
+ x.conv->del(x.conv);
+ return -1.0;
+ }
+
+ if(txyz != NULL) {
+ /* Return the closest value on the locus */
+ getval_raw_xspec3_lin(x.iloc, txyz, cp[0]);
+ txyz[0] /= txyz[1];
+ txyz[2] /= txyz[1];
+ txyz[1] /= txyz[1];
+ }
+
+//a1logd(g_log, 1, " returning %f with error %f delta E94 %f\n",1e6/cp[0],sqrt(rv));
+//DBGF((DBGA,"returning %f with error %f delta E94 %f\n",cp[0],sqrt(rv)));
+ return 1e6/cp[0];
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Spectral and illuminant chromaticity locus support */
+
+/* All the nomenclature is for spectral locus, */
+/* but we use the same mechanism for a Daylight or */
+/* Plankian illuminant locus, substituting temp/Mired for wavelength/nm */
+
+/* Chromaticity locus poligon vertex */
+typedef struct {
+ double xy[2]; /* xy, u'v' value */
+ double xy_n[2]; /* xy, u'v' inwards normal direction */
+ double dist; /* Accumulated distance */
+ double rgb[3]; /* Representative color at this point */
+} xslvtx;
+
+/* Vertex bounding box */
+typedef struct {
+ int ix; /* Starting index of vertex */
+ int n; /* Number of vertexes in box */
+ double xmin;
+ double ymin;
+ double xmax;
+ double ymax;
+} xslbbx;
+
+#define SLOC_BBXN 19 /* 19 vertexes per bounding box */
+
+/* Chromaticity locus poligon cache */
+struct _xslpoly {
+ int sp; /* 0 = Spectral Locus, 1 = Daylight, 2 = Plankian */
+ icxObserverType obType; /* Type of observer */
+ int uv; /* 0 = xy, 1 = u'v' space */
+ int n; /* Number of vertexes, 0 if uninit */
+ double wl_short; /* First reading wavelength in nm (shortest)/ smallest Mired */
+ double wl_long; /* Last reading wavelength in nm (longest)/ largest Mired */
+ double xmin, xmax, ymin, ymax; /* xy Boundint box */
+ double tx[3], ty[3]; /* xy Fast inner triangle test, RGB (spectral locus) */
+ double be[3][3]; /* xy baricentric equations of triangle (spectral locus) */
+// double eed[3]; /* xy Distance of triangle points to 0.3, 0.3 (spectral locus) */
+ xslvtx v[XSPECT_MAX_BANDS]; /* vertex values */
+ int nbb; /* Number of bounding boxes */
+ xslbbx bb[XSPECT_MAX_BANDS/SLOC_BBXN + 1]; /* Bounding boxes */
+ double d_max; /* Maximum distance */
+ double rv[XSPECT_MAX_BANDS]; /* distance to wl reverse lookup */
+};
+
/* Init a xslpoly */
/* Return nz on error */
-static int icx_init_locus_poly(icxObserverType obType) {
- xslpoly *poly;
+static int icx_init_locus_poly(
+ xslpoly *p
+) {
+// static CRITICAL_SECTION lock = { NULL, -1 };
+ static amutex_static(lock);
- if ((poly = spectral_locus_poligon(obType)) == NULL)
- return 1;
+// InitializeCriticalSection(&(lock));
+
+ /* Prevent threads trying to multiply initialise the xslpoly */
+// EnterCriticalSection(&(lock));
+ amutex_lock(lock);
- /* Initialise (should have a mutex!) */
- if (poly->n == 0) {
- int i, j, c;
+ if (p->n == 0) {
+ int i0, in;
+ double wl_short, wl_long;
+ int ii, i, j, c;
double Yxy[3];
double xyz[3];
xspect *sp[3];
-double tt[3][3];
-
- if (standardObserver(sp, obType))
- return 3;
-
- poly->n = sp[0]->spec_n;
- poly->xmin = poly->ymin = 1e6;
- poly->xmax = poly->ymax = -1e6;
-
- for (i = 0; i < poly->n; i++) {
- xyz[0] = sp[0]->spec[i];
- xyz[1] = sp[1]->spec[i];
- xyz[2] = sp[2]->spec[i];
-
- icmXYZ2Yxy(Yxy, xyz);
-
- poly->x[i] = Yxy[1];
- poly->y[i] = Yxy[2];
- if (poly->x[i] < poly->xmin)
- poly->xmin = poly->x[i];
- if (poly->x[i] > poly->xmax)
- poly->xmax = poly->x[i];
- if (poly->y[i] < poly->ymin)
- poly->ymin = poly->y[i];
- if (poly->y[i] > poly->ymax)
- poly->ymax = poly->y[i];
+ double tt[3][3];
+ double dist = 0.0;
+
+ if (standardObserver(sp, p->obType)) {
+ amutex_unlock(lock);
+ return 1;
+ }
+
+ if (p->sp == 0) { /* If spectral locus */
+ i0 = 0;
+ in = sp[0]->spec_n;
+ wl_short = sp[0]->spec_wl_short;
+ wl_long = sp[0]->spec_wl_long;
+
+ /* Limit the range to 400 - 700, as the locus is not well behaved outside that */
+ if (wl_short < 400.0) {
+ i0 = (int)ceil(XSPECT_DIX(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, 400.0));
+ wl_short = XSPECT_WL(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, i0);
+ }
+ if (wl_long > 700.0) {
+ in = (int)ceil(XSPECT_DIX(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, 700.0));
+ wl_long = XSPECT_WL(sp[0]->spec_wl_short, sp[0]->spec_wl_long, sp[0]->spec_n, in);
+ in++;
+ }
+
+ p->n = in - i0;
+ p->wl_short = wl_short;
+ p->wl_long = wl_long;
+ p->xmin = p->ymin = 1e6;
+ p->xmax = p->ymax = -1e6;
+
+ /* Compute xy, and accumulated distance along locus */
+ for (ii = 0, i = i0; i < in; i++, ii++) {
+ double wl = XSPECT_WL(p->wl_short, p->wl_long, p->n, ii);
+
+ xyz[0] = sp[0]->spec[i];
+ xyz[1] = sp[1]->spec[i];
+ xyz[2] = sp[2]->spec[i];
+
+ if (p->uv == 0)
+ icmXYZ2Yxy(Yxy, xyz);
+ else
+ icmXYZ21976UCS(Yxy, xyz);
+ p->v[ii].xy[0] = Yxy[1];
+ p->v[ii].xy[1] = Yxy[2];
+
+ if (ii == 0) {
+ p->v[ii].dist = 0.0;
+ } else {
+ double d0, d1;
+ d0 = p->v[ii].xy[0] - p->v[ii-1].xy[0];
+ d1 = p->v[ii].xy[1] - p->v[ii-1].xy[1];
+ dist += sqrt(d0 * d0 + d1 * d1);
+ p->v[ii].dist = dist;
+ }
+
+ /* Compute a display color */
+ icx_wl2RGB_ds(p->v[ii].rgb, wl, 0.1);
+
+//a1logd(g_log, 1, " [%d] = %f %f, dist %f\n",i,p->v[ii].xy[0],p->v[ii].xy[1],p->v[ii].dist);
+ if (Yxy[1] < p->xmin)
+ p->xmin = Yxy[1];
+ if (Yxy[1] > p->xmax)
+ p->xmax = Yxy[1];
+ if (Yxy[2] < p->ymin)
+ p->ymin = Yxy[2];
+ if (Yxy[2] > p->ymax)
+ p->ymax = Yxy[2];
+ }
+
+ } else { /* Daylight or Plankian locus */
+ xspect *iloc;
+ icxIllumeType ilType = p->sp == 1 ? icxIT_Dtemp : icxIT_Ptemp;
+
+ if (p->obType == icxOT_CIE_1931_2) {
+ if (ilType == icxIT_Dtemp) {
+ iloc = illoc_Daylight_CIE_1931_2;
+ } else {
+ iloc = illoc_Plankian_CIE_1931_2;
+ }
+ } else {
+ if (ilType == icxIT_Dtemp) {
+ iloc = illoc_Daylight_CIE_1964_10;
+ } else {
+ iloc = illoc_Plankian_CIE_1964_10;
+ }
+ }
+
+ i0 = 0;
+ in = iloc[0].spec_n;
+ wl_short = iloc[0].spec_wl_short;
+ wl_long = iloc[0].spec_wl_long;
+
+ p->n = in - i0;
+ p->wl_short = wl_short;
+ p->wl_long = wl_long;
+ p->xmin = p->ymin = 1e6;
+ p->xmax = p->ymax = -1e6;
+
+ /* Compute xy/u'v', and accumulated distance along locus */
+ for (ii = 0, i = i0; i < in; i++, ii++) {
+ double xyz[3];
+ double temp;
+
+ xyz[0] = iloc[0].spec[i];
+ xyz[1] = iloc[1].spec[i];
+ xyz[2] = iloc[2].spec[i];
+
+ if (p->uv == 0)
+ icmXYZ2Yxy(Yxy, xyz);
+ else
+ icmXYZ21976UCS(Yxy, xyz);
+ p->v[ii].xy[0] = Yxy[1];
+ p->v[ii].xy[1] = Yxy[2];
+
+ if (ii == 0) {
+ p->v[ii].dist = 0.0;
+ } else {
+ double d0, d1;
+ d0 = p->v[ii].xy[0] - p->v[ii-1].xy[0];
+ d1 = p->v[ii].xy[1] - p->v[ii-1].xy[1];
+ dist += sqrt(d0 * d0 + d1 * d1);
+ p->v[ii].dist = dist;
+ }
+
+ /* Compute a display color */
+ icx_XYZ2RGB_ds(p->v[ii].rgb, xyz, 0.1);
+
+//a1logd(g_log, 1, " [%d] Mired %f = %f %f, dist %f\n",i,XSPECT_WL(wl_short, wl_long, in, i),p->v[ii].xy[0],p->v[ii].xy[1],p->v[ii].dist);
+ if (Yxy[1] < p->xmin)
+ p->xmin = Yxy[1];
+ if (Yxy[1] > p->xmax)
+ p->xmax = Yxy[1];
+ if (Yxy[2] < p->ymin)
+ p->ymin = Yxy[2];
+ if (Yxy[2] > p->ymax)
+ p->ymax = Yxy[2];
+ }
}
- /* Select 3 points for inner triangle in RGB order */
- poly->tx[0] = poly->x[poly->n - 1];
- poly->ty[0] = poly->y[poly->n - 1];
-
- xyz[0] = value_xspect(sp[0], 517.0);
- xyz[1] = value_xspect(sp[1], 517.0);
- xyz[2] = value_xspect(sp[2], 517.0);
- icmXYZ2Yxy(Yxy, xyz);
- poly->tx[1] = Yxy[1];
- poly->ty[1] = Yxy[2];
-
- poly->tx[2] = poly->x[0];
- poly->ty[2] = poly->y[0];
-
- /* Compute distance from triangles to 0.3, 0.3 */
-// for (i = 0; i < 3; i++) {
-// poly->eed[i] = sqrt((poly->tx[i] - 0.3) * (poly->tx[i] - 0.3)
-// + (poly->ty[i] - 0.3) * (poly->ty[i] - 0.3));
-// }
-
- /* Compute baricentric equations */
- for (i = 0; i < 3; i++) {
- tt[0][i] = poly->tx[i];
- tt[1][i] = poly->ty[i];
- tt[2][i] = 1.0;
+ /* Compute bounding boxes */
+ for (i = ii = 0; i < p->n;) {
+ int m;
+ p->bb[ii].ix = i;
+ p->bb[ii].xmin = p->bb[ii].ymin = 1e6;
+ p->bb[ii].xmax = p->bb[ii].ymax = -1e6;
+ for (m = 0; m < SLOC_BBXN && i < p->n; i++, m++) {
+ if (p->v[i].xy[0] < p->bb[ii].xmin)
+ p->bb[ii].xmin = p->v[i].xy[0];
+ if (p->v[i].xy[1] < p->bb[ii].ymin)
+ p->bb[ii].ymin = p->v[i].xy[1];
+ if (p->v[i].xy[0] > p->bb[ii].xmax)
+ p->bb[ii].xmax = p->v[i].xy[0];
+ if (p->v[i].xy[1] > p->bb[ii].ymax)
+ p->bb[ii].ymax = p->v[i].xy[1];
+ }
+ p->bb[ii++].n = m;
}
- if (icmInverse3x3(poly->be, tt))
- error("icx_init_locus_poly: Matrix inversion failed");
+ p->nbb = ii;
- /* Compute baricentric of 0.3 0.3 */
- /* (Not currently used. How to move center to 0.3 0.3 ?? */
-// for (i = 0; i < 3; i++)
-// poly->eed[i] = poly->be[i][0] * 0.3 + poly->be[i][1] * 0.3 + poly->be[i][2];
+//for (i = 0; i < p->nbb; i++)
+//a1logd(g_log, 1,"bb %d: n = %d, bb %f %f %f %f",i,p->bb[i].n, p->bb[i].xmin,p->bb[i].xmax,p->bb[i].ymin,p->bb[i].ymax);
+
+ /* Compute reverse lookup of distance to wavelength/temp */
+ {
+ p->d_max = p->v[p->n-1].dist;
+
+//a1logd(g_log, 1,"d_max = %f\n",p->d_max);
+
+ p->rv[0] = 0.0;
+ for (i = 1; i < XSPECT_MAX_BANDS; i++)
+ p->rv[i] = -1.0;
+
+ /* Create search start points */
+ for (i = 0; i < p->n; i++) {
+ int ix;
+ ix = (int)floor(XSPECT_DIX(0.0, p->d_max, XSPECT_MAX_BANDS, p->v[i].dist));
+ if (p->rv[ix] < 0.0 || (double)i < p->rv[ix]) {
+ p->rv[ix] = (double)i;
+//a1logd(g_log, 1,"ix %d dist %f start ix %d\n",ix,p->v[i].dist,i);
+ }
+ }
+
+ /* Go through start points and create interpolated points */
+ for (i = XSPECT_MAX_BANDS-2; i > 0; i--) {
+ double d, wl0, d0, wl1, d1, bl, wl;
+ int j, ix;
+
+ d = XSPECT_WL(0.0, p->d_max, XSPECT_MAX_BANDS, i); /* Distance of this cell */
+
+ /* Find a search start point - skip any empty slots */
+ for (j = i; j >= 0; j--) {
+ ix = (int)p->rv[j];
+ if (ix >= 0)
+ break;
+ }
+ if (j < 0)
+ ix = 0;
+
+ for (; ix >= 0; ix--) {
+ d0 = p->v[ix].dist;
+ if (d0 <= d)
+ break;
+ }
+ if (ix < 0)
+ ix = 0;
+ wl0 = XSPECT_WL(wl_short, wl_long, p->n, ix);
+
+ /* Locate the fwd point after this entries distance */
+ for (j = ix+1; j < p->n; j++) {
+ d1 = p->v[j].dist;
+ if (d1 >= d)
+ break;
+ }
+ if (j >= p->n) {
+ d1 = p->d_max;
+ j--;
+ if (ix == j) {
+ ix--;
+ wl0 = XSPECT_WL(wl_short, wl_long, p->n, ix);
+ d0 = p->v[ix].dist;
+ }
+ }
+ wl1 = XSPECT_WL(wl_short, wl_long, p->n, j);
+
+ /* Linearly interpolate for this entries distance */
+ bl = (d - d0)/(d1 - d0);
+//a1logd(g_log, 1,"rv ix %d, d %f, bl %f, ixs %d - %d, ds %f - %f, wls %f - %f\n",i,d,bl, ix,j,d0,d1,wl0,wl1);
+ wl = (1.0 - bl) * wl0 + bl * wl1;
+ p->rv[i] = wl;
+ }
+ p->rv[0] = wl_short;
+ p->rv[XSPECT_MAX_BANDS-1] = wl_long;
+
+//for (i = 0; i < XSPECT_MAX_BANDS; i++)
+// a1logd(g_log, 1,"rv %d = %f\n",i,p->rv[i]);
+ }
+
+ /* Compute outward normals, and delta wl/delta dist */
+ for (i = 0; i < p->n; i++) {
+ int span = 1;
+ double pn[2], mm;
+
+ if (i < 50) /* Hack to straighten up 400nm */
+ span = 20;
+
+ i0 = i - span;
+ in = i + span;
+ if (i0 < 0) {
+ i0 = 0;
+ in = i0 + 2 * span;
+ }
+ if (in > (p->n-1)) {
+ in = (p->n-1);
+ i0 = in - 2 * span;
+ }
+ pn[0] = p->v[in].xy[1] - p->v[i0].xy[1];
+ pn[1] = -(p->v[in].xy[0] - p->v[i0].xy[0]);
+
+// a1logd(g_log, 1,"i0 = %d, in = %d\n",i0, in);
+// a1logd(g_log, 1,"i0 %d = %f %f\n",i0,p->v[i0].xy[0],p->v[i0].xy[1]);
+// a1logd(g_log, 1,"in %d = %f %f\n",in,p->v[in].xy[0],p->v[i0].xy[1]);
+// a1logd(g_log, 1,"pn = %f %f\n",pn[0],pn[1]);
+
+ mm = sqrt(pn[0] * pn[0] + pn[1] * pn[1]);
+ pn[0] /= mm;
+ pn[1] /= mm;
+
+ p->v[i].xy_n[0] = pn[0];
+ p->v[i].xy_n[1] = pn[1];
+ }
+
+#ifdef NEVER
+ /* Compute v2 sub sampled values */
+#endif
+
+ if (p->sp == 0) { /* If spectral locus */
+ /* Select 3 points for inner triangle in RGB order */
+ p->tx[0] = p->v[p->n - 1].xy[0];
+ p->ty[0] = p->v[p->n - 1].xy[1];
+
+ xyz[0] = value_xspect(sp[0], 517.0);
+ xyz[1] = value_xspect(sp[1], 517.0);
+ xyz[2] = value_xspect(sp[2], 517.0);
+ if (p->uv == 0)
+ icmXYZ2Yxy(Yxy, xyz);
+ else
+ icmXYZ21976UCS(Yxy, xyz);
+ p->tx[1] = Yxy[1];
+ p->ty[1] = Yxy[2];
+
+ p->tx[2] = p->v[0].xy[0];
+ p->ty[2] = p->v[0].xy[1];
+
+ /* Compute distance from triangles to 0.3, 0.3 */
+// for (i = 0; i < 3; i++) {
+// p->eed[i] = sqrt((p->tx[i] - 0.3) * (p->tx[i] - 0.3)
+// + (p->ty[i] - 0.3) * (p->ty[i] - 0.3));
+// }
+
+ /* Compute baricentric equations */
+ for (i = 0; i < 3; i++) {
+ tt[0][i] = p->tx[i];
+ tt[1][i] = p->ty[i];
+ tt[2][i] = 1.0;
+ }
+ if (icmInverse3x3(p->be, tt)) {
+ a1loge(g_log, 2, "icx_init_locus_poly: Matrix inversion failed");
+ amutex_unlock(lock);
+ return 2;
+ }
+
+ /* Compute baricentric of 0.3 0.3 */
+ /* (Not currently used. How to move center to 0.3 0.3 ?? */
+// for (i = 0; i < 3; i++)
+// p->eed[i] = p->be[i][0] * 0.3 + p->be[i][1] * 0.3 + p->be[i][2];
+ }
}
+ amutex_unlock(lock);
return 0;
}
+/* Spectral locus */
+static xslpoly splo_CIE_1931_2_xy = { 0, icxOT_CIE_1931_2, 0, 0 };
+static xslpoly splo_CIE_1931_2_uv = { 0, icxOT_CIE_1931_2, 1, 0 };
+static xslpoly splo_CIE_1964_10_xy = { 0, icxOT_CIE_1964_10, 0, 0 };
+static xslpoly splo_CIE_1964_10_uv = { 0, icxOT_CIE_1964_10, 1, 0 };
+static xslpoly splo_Stiles_Burch_2_xy = { 0, icxOT_Stiles_Burch_2, 0, 0 };
+static xslpoly splo_Stiles_Burch_2_uv = { 0, icxOT_Stiles_Burch_2, 1, 0 };
+static xslpoly splo_Judd_Voss_2_xy = { 0, icxOT_Judd_Voss_2, 0, 0 };
+static xslpoly splo_Judd_Voss_2_uv = { 0, icxOT_Judd_Voss_2, 1, 0 };
+static xslpoly splo_CIE_1964_10c_xy = { 0, icxOT_CIE_1964_10c, 0, 0 };
+static xslpoly splo_CIE_1964_10c_uv = { 0, icxOT_CIE_1964_10c, 1, 0 };
+static xslpoly splo_Shaw_Fairchild_2_xy = { 0, icxOT_Shaw_Fairchild_2, 0, 0 };
+static xslpoly splo_Shaw_Fairchild_2_uv = { 0, icxOT_Shaw_Fairchild_2, 1, 0 };
+
+/* Illuminant locus */
+static xslpoly illo_D_CIE_1931_2_xy = { 1, icxOT_CIE_1931_2, 0, 0 };
+static xslpoly illo_D_CIE_1931_2_uv = { 1, icxOT_CIE_1931_2, 1, 0 };
+static xslpoly illo_D_CIE_1964_10_xy = { 1, icxOT_CIE_1964_10, 0, 0 };
+static xslpoly illo_D_CIE_1964_10_uv = { 1, icxOT_CIE_1964_10, 1, 0 };
+static xslpoly illo_P_CIE_1931_2_xy = { 2, icxOT_CIE_1931_2, 0, 0 };
+static xslpoly illo_P_CIE_1931_2_uv = { 2, icxOT_CIE_1931_2, 1, 0 };
+static xslpoly illo_P_CIE_1964_10_xy = { 2, icxOT_CIE_1964_10, 0, 0 };
+static xslpoly illo_P_CIE_1964_10_uv = { 2, icxOT_CIE_1964_10, 1, 0 };
+
+/* Return a pointer to the chromaticity locus poligon */
+/* return NULL on failure. */
+xslpoly *chrom_locus_poligon(
+icxLocusType loty, /* Locus type, 1 = spectral, 2 = Daylight, 3 = Plankian */
+icxObserverType obType, /* Type of observer */
+int uv /* 0 = xy, 1 = u'v' space */
+) {
+ xslpoly *rv = NULL;
+
+ if (loty == icxLT_none)
+ return NULL;
+
+ switch (obType) {
+ case icxOT_default:
+ case icxOT_CIE_1931_2:
+ if (uv == 0) {
+ if (loty == icxLT_spectral)
+ rv = &splo_CIE_1931_2_xy;
+ else if (loty == icxLT_daylight)
+ rv = &illo_D_CIE_1931_2_xy;
+ else if (loty == icxLT_plankian)
+ rv = &illo_P_CIE_1931_2_xy;
+ } else {
+ if (loty == icxLT_spectral)
+ rv = &splo_CIE_1931_2_uv;
+ else if (loty == icxLT_daylight)
+ rv = &illo_D_CIE_1931_2_uv;
+ else if (loty == icxLT_plankian)
+ rv = &illo_P_CIE_1931_2_uv;
+ }
+ break;
+ case icxOT_CIE_1964_10:
+ if (uv == 0) {
+ if (loty == icxLT_spectral)
+ rv = &splo_CIE_1964_10_xy;
+ else if (loty == icxLT_daylight)
+ rv = &illo_D_CIE_1964_10_xy;
+ else if (loty == icxLT_plankian)
+ rv = &illo_P_CIE_1964_10_xy;
+ } else {
+ if (loty == icxLT_spectral)
+ rv = &splo_CIE_1964_10_uv;
+ else if (loty == icxLT_daylight)
+ rv = &illo_D_CIE_1964_10_uv;
+ else if (loty == icxLT_plankian)
+ rv = &illo_P_CIE_1964_10_uv;
+ }
+ break;
+ default:
+ rv = NULL;
+ }
+ if (rv == NULL)
+ return rv;
+
+
+ if (rv->n == 0 && icx_init_locus_poly(rv))
+ return NULL;
+
+ return rv;
+}
+
+
/* Determine whether the given XYZ is outside the spectrum locus */
/* Return 0 if within locus */
/* Return 1 if outside locus */
-/* Return 2 if unknown (bad observer) */
-int icx_outside_spec_locus(double xyz[3], icxObserverType obType) {
+int icx_outside_spec_locus(xslpoly *p, double xyz[3]) {
int i, j, c;
xslpoly *poly;
double Yxy[3];
- if ((poly = spectral_locus_poligon(obType)) == NULL)
- return 2;
-
- /* Init poly if needed */
- if (poly->n == 0 && icx_init_locus_poly(obType))
- return 2;
-
icmXYZ2Yxy(Yxy, xyz);
/* Quick test - bounding box */
- if (Yxy[1] < poly->xmin || Yxy[1] > poly->xmax
- || Yxy[2] < poly->ymin || Yxy[2] > poly->ymax)
+ if (Yxy[1] < p->xmin || Yxy[1] > p->xmax
+ || Yxy[2] < p->ymin || Yxy[2] > p->ymax)
return 1;
/* Quick test - inner triangle */
for (c = 1, i = 0, j = 3-1; i < 3; j = i++) {
- if ( ((poly->ty[i] > Yxy[2]) != (poly->ty[j] > Yxy[2]))
- && (Yxy[1] < (poly->tx[j] - poly->tx[i]) * (Yxy[2] - poly->ty[i])
- / (poly->ty[j] - poly->ty[i]) + poly->tx[i]) )
+ if ( ((p->ty[i] > Yxy[2]) != (p->ty[j] > Yxy[2]))
+ && (Yxy[1] < (p->tx[j] - p->tx[i]) * (Yxy[2] - p->ty[i])
+ / (p->ty[j] - p->ty[i]) + p->tx[i]) )
c = !c;
}
if (c == 0)
@@ -4080,91 +5881,52 @@ int icx_outside_spec_locus(double xyz[3], icxObserverType obType) {
/* Do point in poligon test */
/* (This could be speeded up in many ways) */
- for (c = 1, i = 0, j = poly->n-1; i < poly->n; j = i++) {
- if ( ((poly->y[i] > Yxy[2]) != (poly->y[j] > Yxy[2]))
- && (Yxy[1] < (poly->x[j] - poly->x[i]) * (Yxy[2] - poly->y[i])
- / (poly->y[j] - poly->y[i]) + poly->x[i]) )
+ for (c = 1, i = 0, j = p->n-1; i < p->n; j = i++) {
+ if ( ((p->v[i].xy[1] > Yxy[2]) != (p->v[j].xy[1] > Yxy[2]))
+ && (Yxy[1] < (p->v[j].xy[0] - p->v[i].xy[0]) * (Yxy[2] - p->v[i].xy[1])
+ / (p->v[j].xy[1] - p->v[i].xy[1]) + p->v[i].xy[0]) )
c = !c;
}
return c;
}
-/* Return an aproximate RGB value for coloring within the spectrum locus */
-void icx_spec_locus_color(double rgb[3], double xyz[3], icxObserverType obType) {
- int i, j;
- xslpoly *poly;
- double Yxy[3];
- double dtt[3]; /* Distances to triangle points */
- double v[3];
- double max;
-
- if ((poly = spectral_locus_poligon(obType)) == NULL)
- return;
-
- /* Init poly if needed */
- if (poly->n == 0 && icx_init_locus_poly(obType))
- return;
-
- icmXYZ2Yxy(Yxy, xyz);
-
- /* Compute the baricentric coord for the input point, */
- for (max = -1e6, i = 0; i < 3; i++) {
- v[i] = poly->be[i][0] * Yxy[1] + poly->be[i][1] * Yxy[2] + poly->be[i][2];
- if (v[i] < 0.0)
- v[i] = 0.0;
- else if (v[i] > 1.0)
- v[i] = 1.0;
-
- /* Normalise to put wp at 0.3 0.3 */
- // ~~99
-
- v[i] = pow(v[i], 1.0/2.2);
-
- if (v[i] > max)
- max = v[i];
- }
-
- for (i = 0; i < 3; i++) {
- rgb[i] = v[i]/max;
- }
-}
-
/* -------------------------------------------------------- */
+
/* Status T log10 weightings */
-/* CMYV */
+/* CMY + ISO V */
static xspect denT[4] = {
{
44, 340.0, 770.0, /* 44 bands from 340 to 770 nm in 10nm steps */
1.0, /* Log10 Scale factor */
{
- 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.500, 1.778, 2.653, 4.477,
+ -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, 0.500, 1.778, 2.653, 4.477,
5.000, 4.929, 4.740, 4.398, 4.000,
3.699, 3.176, 2.699, 2.477, 2.176,
- 1.699, 1.000, 0.500, 0.000, 0.000,
- 0.000, 0.000, 0.000
+ 1.699, 1.000, 0.500, -10.0, -10.0,
+ -10.0, -10.0, -10.0
}
},
{
44, 340.0, 770.0, /* 44 bands from 340 to 770 nm in 10nm steps */
1.0, /* Log10 Scale factor */
{
- 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.500, 3.000, 3.699,
+ -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, 0.500, 3.000, 3.699,
4.447, 4.833, 4.964, 5.000, 4.944,
4.820, 4.623, 4.342, 3.954, 3.398,
- 2.845, 1.954, 1.000, 0.500, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000
+ 2.845, 1.954, 1.000, 0.500, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0
}
},
{
@@ -4176,19 +5938,19 @@ static xspect denT[4] = {
3.778, 4.230, 4.602, 4.778, 4.914,
4.973, 5.000, 4.987, 4.929, 4.813,
4.602, 4.255, 3.699, 2.301, 1.602,
- 0.500, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
- 0.000, 0.000, 0.000
+ 0.500, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
+ -10.0, -10.0, -10.0
}
},
{
44, 340.0, 770.0, /* 44 bands from 340 to 770 nm in 10nm steps */
1.0, /* Log10 Scale factor */
{
- 0.000,
- 0.000, 0.000, 0.000, 0.000, 0.000,
+ -10.0,
+ -10.0, -10.0, -10.0, -10.0, -10.0,
0.500, 1.332, 1.914, 2.447, 2.881,
3.090, 3.346, 3.582, 3.818, 4.041,
4.276, 4.513, 4.702, 4.825, 4.905,
@@ -4201,6 +5963,7 @@ static xspect denT[4] = {
}
};
+
/* Given a reflectance or transmition spectral product, (Relative */
/* to the scale factor), return status T CMYV log10 density values */
void xsp_Tdensity(
@@ -4226,10 +5989,10 @@ xspect *in /* Spectral product to be converted */
out[j] += S * W;
}
out[j] /= sum; /* Normalise */
- if (out[j] < 0.00001)
- out[j] = 0.00001; /* Just to be sure we don't get silly values */
- else if (out[j] > 1.0)
- out[j] = 1.0;
+ if (out[j] < 1e-8)
+ out[j] = 1e-8; /* Just to be sure we don't get silly values */
+ else if (out[j] > 2.0)
+ out[j] = 2.0;
out[j] = -log10(out[j]); /* Convert to density */
}
@@ -4294,17 +6057,17 @@ double *in /* Input XYZ values */
}
}
-/* Given an XYZ value, */
-/* return approximate sRGB values */
+/* Given an XYZ value, return sRGB values. */
+/* This is a little slow if wp used */
void icx_XYZ2sRGB(
-double *out, /* Return aproximate CMYV log10 density */
+double *out, /* Return approximate sRGB values */
double *wp, /* Input XYZ white point (may be NULL) */
double *in /* Input XYZ values */
) {
int i, j;
double XYZ[3];
- double d65[3] = { 0.950543, 1.0, 1.089303 };
- double mat[3][3] = {
+ double d65[3] = { 0.950543, 1.0, 1.089303 }; /* D65 */
+ double mat[3][3] = { /* sRGB absolute XYZ->RGB ? */
{ 3.2406, -1.5372, -0.4986 },
{ -0.9689, 1.8758, 0.0415 },
{ 0.0557, -0.2040, 1.0570 }
@@ -4312,8 +6075,13 @@ double *in /* Input XYZ values */
/* Do a simple Von Kries between input white point and D65 */
if (wp != NULL) {
- for (j = 0; j < 3; j++)
- XYZ[j] = d65[j] * in[j]/wp[j];
+ icmXYZNumber dst, src;
+ double vkmat[3][3];
+
+ icmAry2XYZ(src, wp);
+ icmAry2XYZ(dst, d65);
+ icmChromAdaptMatrix(ICM_CAM_BRADFORD | ICM_CAM_BRADFORD, dst, src, vkmat);
+ icmMulBy3x3(XYZ, vkmat, in);
} else {
for (j = 0; j < 3; j++)
XYZ[j] = in[j];
@@ -4341,6 +6109,87 @@ double *in /* Input XYZ values */
}
}
+/* Given an XYZ value, return approximate RGB value */
+/* Desaurate to white by the given amount */
+void icx_XYZ2RGB_ds(
+double *out, /* Return approximate sRGB values */
+double *in, /* Input XYZ */
+double desat /* 0.0 = full saturation, 1.0 = white */
+) {
+ int i, j;
+ double mat[3][3] = { /* XYZ to D65 sRGB */
+ { 1.490715, -0.075680, -0.313279 }, /* Triangle that occupies spectrum locus */
+ { -0.492678, 1.364383, 0.095391 },
+ { 0.049610, -0.137386, 1.001080 }
+ };
+ double white[3] = { 1.0, 1.0, 1.0 } ;
+ double max;
+
+ /* Normalize */
+ in[0] /= in[1];
+ in[2] /= in[1];
+ in[1] = 1.0;
+
+//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: norm XYZ %f %f %f\n", in[0], in[1], in[2]);
+
+ /* Convert to sRGB cromaticities */
+ for (i = 0; i < 3; i++) {
+ out[i] = 0.0;
+ for (j = 0; j < 3; j++) {
+ out[i] += in[j] * mat[i][j];
+ }
+ }
+//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: raw RGB %f %f %f\n", out[0], out[1], out[2]);
+
+ /* Clip */
+ max = -1e6;
+ for (i = 0; i < 3; i++) {
+ if (out[i] > max)
+ max = out[i];
+ }
+ for (i = 0; i < 3; i++) {
+ out[i] /= max;
+ if (out[i] < 0.0)
+ out[i] = 0.0;
+ }
+//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: clip RGB %f %f %f\n", out[0], out[1], out[2]);
+
+ /* Desaturate */
+ icmBlend3(out, out, white, desat);
+
+//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: desat RGB %f %f %f\n", out[0], out[1], out[2]);
+
+ /* Apply gamma */
+ for (j = 0; j < 3; j++) {
+ if (out[j] <= (0.03928/12.92)) {
+ out[j] *= 12.92;
+ if (out[j] < 0.0)
+ out[j] = 0.0;
+ } else {
+ out[j] = pow(out[j], 1.0/2.4) * 1.055 - 0.055;
+ if (out[j] > 1.0)
+ out[j] = 1.0;
+ }
+ }
+
+//a1logd(g_log, 1,"icx_XYZ2sRGB_ds: final RGB %f %f %f\n", out[0], out[1], out[2]);
+}
+
+/* Given a wavelengthm return approximate RGB value */
+/* Desaurate to white by the given amount */
+void icx_wl2RGB_ds(
+double *out, /* Return approximate sRGB values */
+double wl, /* Input wavelength in nm */
+double desat /* 0.0 = full saturation, 1.0 = white */
+) {
+ double XYZ[3];
+
+ icx_spectrum_locus(XYZ, wl, icxOT_CIE_1931_2);
+//a1logd(g_log, 1,"cx_wl2sRGB_ds: wl %f -> XYZ %f %f %f\n",wl, XYZ[0], XYZ[1], XYZ[2]);
+
+ icx_XYZ2RGB_ds(out, XYZ, desat);
+}
+
/* ------------------- */
#ifdef NEVER /* Deprecated */
@@ -4348,11 +6197,16 @@ double *in /* Input XYZ values */
/* Given a daylight color temperature in degrees K, */
/* return the corresponding XYZ value (standard 2 degree observer) */
void icx_DTEMP2XYZ(
-double *out, /* Return XYZ value with Y == 1 */
+double *out, /* Return XYZ value with Y == 1, -1 on error */
double ct /* Input temperature in degrees K */
) {
double Yxy[3];
+ if (ct < 2500.0 || ct > 25000.0) { /* Only accurate down to 4000 */
+ out[0] = out[1] = out[2] = -1.0;
+ return;
+ }
+
//DBGF((DBGA,"computing temperature %f\n",ct));
/* Compute chromaticity coordinates */
if (ct < 7000.0) {
@@ -4465,7 +6319,6 @@ static double cct_func(void *fdata, double tp[]) {
/* return the closest correlated color temperature to the given spectrum or XYZ. */
/* An observer type can be chosen for interpretting the spectrum of the input and */
/* the illuminant. */
-/* Note we can use CIEDE2000, rather than the traditional L*u*v* 2/3 space for CCT */
/* Return -1 on erorr */
double icx_XYZ2ill_ct(
double txyz[3], /* If not NULL, return the XYZ of the locus temperature */
@@ -4705,6 +6558,137 @@ xspect *sample /* Illuminant sample to compute CRI of */
return cri;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/* Compute Australian Radiation Protection and Nuclear Safety Agency (ARPANSA) */
+/* Exposure to Ultraviolet Radiation exposure limits from a spectrum in mw/m-2/nm. */
+/* To be accurate, the spectrum must capture any significant */
+/* exposure wavelengths between 180 - 400 nm */
+
+/* Raw RSE from Table 1 of "Radiation Protection Series No. 12 December 2006" */
+struct {
+ double wl; /* Wavelength */
+ double rse; /* Relative Spectral Effectiveness */
+} raw_rse[57] = {
+ { 180.0, 0.012 },
+ { 190.0, 0.019 },
+ { 200.0, 0.030 },
+ { 205.0, 0.051 },
+ { 210.0, 0.075 },
+ { 215.0, 0.095 },
+ { 220.0, 0.120 },
+ { 225.0, 0.150 },
+ { 230.0, 0.190 },
+ { 235.0, 0.240 },
+ { 240.0, 0.300 },
+ { 245.0, 0.360 },
+ { 250.0, 0.430 },
+ { 254.0, 0.500 },
+ { 255.0, 0.520 },
+ { 260.0, 0.650 },
+ { 265.0, 0.810 },
+ { 270.0, 1.000 },
+ { 275.0, 0.960 },
+ { 280.0, 0.880 },
+ { 285.0, 0.770 },
+ { 290.0, 0.640 },
+ { 295.0, 0.540 },
+ { 297.0, 0.460 },
+ { 300.0, 0.300 },
+ { 303.0, 0.120 },
+ { 305.0, 0.060 },
+ { 308.0, 0.026 },
+ { 310.0, 0.015 },
+ { 313.0, 0.006 },
+ { 315.0, 0.003 },
+ { 316.0, 0.0024 },
+ { 317.0, 0.0020 },
+ { 318.0, 0.0016 },
+ { 319.0, 0.0012 },
+ { 320.0, 0.0010 },
+ { 322.0, 0.00067 },
+ { 323.0, 0.00054 },
+ { 325.0, 0.00050 },
+ { 328.0, 0.00044 },
+ { 330.0, 0.00041 },
+ { 333.0, 0.00037 },
+ { 335.0, 0.00034 },
+ { 340.0, 0.00028 },
+ { 345.0, 0.00024 },
+ { 350.0, 0.00020 },
+ { 355.0, 0.00016 },
+ { 360.0, 0.00013 },
+ { 365.0, 0.00011 },
+ { 370.0, 0.000093 },
+ { 375.0, 0.000077 },
+ { 380.0, 0.000064 },
+ { 385.0, 0.000053 },
+ { 390.0, 0.000044 },
+ { 395.0, 0.000036 },
+ { 400.0, 0.000030 }
+};
+
+/* Compute 1nm sampling rse from raw table using linear interpolation */
+static void compute_rse(xspect *dst) {
+ int i;
+
+ dst->spec_n = 221;
+ dst->spec_wl_short = 180.0;
+ dst->spec_wl_long = 400.0;
+ dst->norm = 1.0;
+
+ /* Linearly interpolate between each raw point */
+ for (i = 0; i < (57-1); i++) {
+ int j, n, ix;
+
+ n = (int)(raw_rse[i+1].wl - raw_rse[i].wl + 0.5);
+ for (j = 0; j <= n; j++) {
+ double bl = j/(double)n;
+ double wl = raw_rse[i].wl + j;
+
+ ix = XSPECT_XIX(dst, wl);
+ dst->spec[ix] = (1.0 - bl) * raw_rse[i].rse + bl * raw_rse[i+1].rse;
+
+//a1logd(g_log, 1,"UV rse ix %d wl %f rse = %f\n",ix,wl,dst->spec[ix]);
+ }
+ }
+}
+
+xspect ARPANSA_rse = { 0 };
+
+/* Return the maximum 24 hour exposure in seconds. */
+/* Maximum return value is 8 hours */
+/* Returns -1.0 if the source sample doesn't go down to at least 350 nm */
+double icx_ARPANSA_UV_exp(
+xspect *sample /* Illuminant sample to compute UV_exp of */
+) {
+ double wl_short, wl_long;
+ double effwpsm; /* Effective Watt/m^2 */
+ double wl;
+ double secs;
+ if (ARPANSA_rse.spec_n == 0)
+ compute_rse(&ARPANSA_rse);
+
+ wl_short = ARPANSA_rse.spec_wl_short;
+ wl_long = ARPANSA_rse.spec_wl_long;
+
+ if (sample->spec_wl_short > wl_short)
+ wl_short = sample->spec_wl_short;
+
+ if (wl_short > 350.0)
+ return -1.0;
+
+ effwpsm = 0.0;
+ for (wl = wl_short; wl <= (wl_long + 1e-6); wl++)
+ effwpsm += value_xspect(sample, wl) * value_xspect(&ARPANSA_rse, wl);
+
+ effwpsm /= 1000.0; /* Convert to W from mW */
+
+ secs = 30.0/effwpsm;
+
+ if (secs > (8 * 60 * 60)) /* Limit to 8 hours */
+ secs = 8 * 60 * 60;
+
+ return secs;
+}
#endif /* !SALONEINSTLIB */
diff --git a/xicc/xspect.h b/xicc/xspect.h
index caca8b2..e3adc1f 100644
--- a/xicc/xspect.h
+++ b/xicc/xspect.h
@@ -82,7 +82,7 @@ typedef struct {
/* Given a wavelength and address of an xspect, compute the nearest index */
#define XSPECT_XIX(PXSP, WL) \
-((int)floor(XSPECT_DIX(PXSP, WL) + 0.5))
+((int)floor(XSPECT_XDIX(PXSP, WL) + 0.5))
#ifndef SALONEINSTLIB
@@ -137,8 +137,8 @@ typedef enum {
icxIT_F10 = 11, /* Fluorescent Narrow Band 5000K, CRI 81 */
icxIT_Spectrocam = 12, /* Spectrocam Xenon Lamp */
icxIT_Dtemp = 13, /* Daylight at specified temperature */
- icxIT_Ptemp = 14 /* Planckian at specified temperature */
#endif /* !SALONEINSTLIB*/
+ icxIT_Ptemp = 14 /* Planckian at specified temperature */
} icxIllumeType;
/* Fill in an xpsect with a standard illuminant spectrum */
@@ -146,7 +146,7 @@ typedef enum {
int standardIlluminant(
xspect *sp, /* Xspect to fill in */
icxIllumeType ilType, /* Type of illuminant */
-double temp); /* Optional temperature in degrees kelvin, for Dtemp and Ptemp */
+double temp); /* Optional temperature in degrees kelvin, For Dtemp and Ptemp */
/* Given an emission spectrum, set the UV output to the given level. */
/* The shape of the UV is taken from FWA1_stim, and the level is */
@@ -176,6 +176,7 @@ int standardObserver(xspect *sp[3], icxObserverType obType);
/* Return a string describing the standard observer */
char *standardObserverDescription(icxObserverType obType);
+
/* Clamping state */
typedef enum {
icxNoClamp = 0, /* Don't clamp XYZ/Lab to +ve */
@@ -287,12 +288,27 @@ xsp2cie *new_xsp2cie(
icxObserverType obType, /* Observer */
xspect custObserver[3],
- icColorSpaceSignature rcs, /* Return color space, icSigXYZData or icSigLabData */
+ icColorSpaceSignature rcs, /* Return color space, icSigXYZData or D50 icSigLabData */
/* ** Must be icSigXYZData if SALONEINSTLIB ** */
icxClamping clamp /* NZ to clamp XYZ/Lab to be +ve */
);
#ifndef SALONEINSTLIB
+
+/* --------------------------- */
+/* Given a choice of temperature dependent illuminant (icxIT_Dtemp or icxIT_Ptemp), */
+/* return the closest correlated color temperature to the XYZ. */
+/* An observer type can be chosen for interpretting the spectrum of the input and */
+/* the illuminant. */
+/* Return -1.0 on erorr */
+double icx_XYZ2ill_ct2(
+double txyz[3], /* If not NULL, return the XYZ of the locus temperature */
+icxIllumeType ilType, /* Type of illuminant, icxIT_Dtemp or icxIT_Ptemp */
+icxObserverType obType, /* Observer, CIE_1931_2 or CIE_1964_10 */
+double xyz[3], /* Input XYZ value */
+int viscct /* nz to use visual CIEDE2000, 0 to use CCT CIE 1960 UCS. */
+);
+
/* --------------------------- */
/* Spectrum locus */
@@ -301,19 +317,32 @@ xsp2cie *new_xsp2cie(
int icx_spectrum_locus_range(double *min_wl, double *max_wl, icxObserverType obType);
/* Return an XYZ that is on the spectrum locus for the given observer. */
-/* wl is the input wavelength in the range icx_spectrum_locus_range(), */
+/* wl is the input wavelength in the range icx_chrom_locus_range(), */
/* and return clipped result if outside this range. */
/* Return nz if observer unknown. */
int icx_spectrum_locus(double xyz[3], double in, icxObserverType obType);
-/* Determine whether the given XYZ is outside the spectrum locus */
+/* - - - - - - - - - - - - - - */
+/* Chromaticity locus support */
+
+typedef struct _xslpoly xslpoly;
+
+typedef enum {
+ icxLT_none = 0,
+ icxLT_spectral = 1,
+ icxLT_daylight = 2,
+ icxLT_plankian = 3
+} icxLocusType;
+
+/* Return a pointer to the chromaticity locus object */
+/* return NULL on failure. */
+xslpoly *chrom_locus_poligon(icxLocusType locus_type, icxObserverType obType, int cspace);
+
+
+/* Determine whether the given XYZ is outside the chromaticity locus */
/* Return 0 if within locus */
/* Return 1 if outside locus */
-/* Return 2 if unknown (bad observer) */
-int icx_outside_spec_locus(double xyz[3], icxObserverType obType);
-
-/* Return an aproximate RGB value for coloring within the spectrum locus */
-void icx_spec_locus_color(double rgb[3], double xyz[3], icxObserverType obType);
+int icx_outside_spec_locus(xslpoly *p, double xyz[3]);
/* --------------------------- */
/* Density and other functions */
@@ -346,6 +375,21 @@ double *wp, /* Input XYZ white point (may be NULL) */
double *in /* Input XYZ values */
);
+/* Given an XYZ value, return approximate RGB value */
+/* Desaurate to white by the given amount */
+void icx_XYZ2RGB_ds(
+double *out, /* Return approximate sRGB values */
+double *in, /* Input XYZ */
+double desat /* 0.0 = full saturation, 1.0 = white */
+);
+
+/* Given a wavelengthm return approximate RGB value */
+/* Desaurate to white by the given amount */
+void icx_wl2RGB_ds(
+double *out, /* Return approximate sRGB values */
+double wl, /* Input wavelength in nm */
+double desat /* 0.0 = full saturation, 1.0 = white */
+);
/* Given an illuminant definition and an observer model, return */
@@ -356,7 +400,7 @@ double xyz[3], /* Return XYZ value with Y == 1 */
icxObserverType obType, /* Observer */
xspect custObserver[3], /* Optional custom observer */
icxIllumeType ilType, /* Type of illuminant */
-double ct, /* Input temperature in degrees K */
+double temp, /* Input temperature in degrees K */
xspect *custIllum); /* Optional custom illuminant */
@@ -364,7 +408,6 @@ xspect *custIllum); /* Optional custom illuminant */
/* return the closest correlated color temperature to the given spectrum or XYZ. */
/* An observer type can be chosen for interpretting the spectrum of the input and */
/* the illuminant. */
-/* Note we're using CICDE94, rather than the traditional L*u*v* 2/3 space for CCT */
/* Return -1 on erorr */
double icx_XYZ2ill_ct(
double txyz[3], /* If not NULL, return the XYZ of the black body temperature */
@@ -383,6 +426,15 @@ double icx_CIE1995_CRI(
int *invalid, /* if not NULL, set to nz if invalid */
xspect *sample /* Illuminant sample to compute CRI of */
);
+
+
+/* Return the maximum 24 hour exposure in seconds. */
+/* Limit is 8 hours */
+/* Returns -1 if the source sample doesn't go down to at least 350 nm */
+double icx_ARPANSA_UV_exp(
+xspect *sample /* Illuminant sample to compute UV_exp of */
+);
+
#endif /* !SALONEINSTLIB*/
#ifdef __cplusplus
diff --git a/ziparch.sh b/ziparch.sh
index d4496ca..44f3382 100644
--- a/ziparch.sh
+++ b/ziparch.sh
@@ -9,6 +9,10 @@ rm -rf _zipdir
mkdir _zipdir
NOTFOUND=
+# Split on lines, not spaces
+OIFS="$IFS"
+IFS='
+'
for i in `cat adirs bdirs`
do
echo
@@ -35,9 +39,9 @@ do
fi
fi
- if [ ! -e ${i}/${j} ] ; then
+ if [ ! -e "${i}/${j}" ] ; then
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Can't find file ${i}/${j} !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
- NOTFOUND="$NOTFOUND ${i}/${j}"
+ NOTFOUND=$NOTFOUND ${i}/${j}
else
dos2unix ${i}/${j}
cp ${i}/${j} _zipdir/${i}/${j}
@@ -72,7 +76,7 @@ do
if [ ! -e ${i}/${j} ] ; then
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Can't find file ${i}/${j} !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
- NOTFOUND="$NOTFOUND ${i}/${j}"
+ NOTFOUND=$NOTFOUND ${i}/${j}
else
dos2unix ${i}/${j}
cp ${i}/${j} _zipdir/${i}/${j}
@@ -94,3 +98,5 @@ if [ "X$NOTFOUND" != "X" ] ; then
echo "!!!!!! Didn't find $NOTFOUND !!!!!!"
fi
echo "Finished Complete Argyll source archive argyll.zip... "
+
+IFS="$OIFS"