Device Settings

From ColourWiki

All variable parts of the colour processing chain must be taken into account, to achieve predictable results. As a consequence colour profiles as colour only transformations are not enough to describe completely the path colours has to go. For instance downloading a printer profile and separating an image does not ensure the according driver settings are selected correctly or even the appropriate driver was used. Even the driver and its version is often not included and not standardised to access machine readable. To overcome that information hole for monitors, Apple introduced the vcgt tag to describe the according hardware state in the graphics card gamma table. This is a single step and maybe enough for just this task.

In the following proposal, I will draw sketchy, what I think is needed to make the task complete, and apply to other areas too.



Table of contents

Informations Incorporated

  • device identification
    • device type, manufacturer, model, serial number, country, device options
AB & Co Ltd., printer model CD-1234, EF photo ink, GH gloss paper, #1234-5678
  • driver names and their versions to verify integrity
nv/nvidia, Gutenprint/HPIJS, DCraw versions
The driver names used must be unique to later lookup and find the appropriate profile. If one application use Gutenprint and an other gimp-print chances are high to not find the according profile. Of course some kind of registering probably with a enumeration type would help here. With a good maintained database this should work fine.
The driver must be able to tell: down to what driver version he is colour compatible for a certain device.
  • device settings (as provided, colour relevant ones should be query able by a device driver API)
expl. PPD, scan parameters, VCGT
    • fixing colour sensible driver settings in a GUI to exclude wrong user interaction is a precondition to form a calibration
PPD with removed choices, VCGT + fixed monitor settings, DCraw called with specified options
  • device colour characterisation (a ICC profile belonging to the above outlined calibration)
    • the profile must belong to the device/driver/settings/version mix
    • priority among selected profiles (generic profile - low, self calibrated - high) can be a profile property
    • fuzzy device/driver settings match outlined by Graeme here (http://lists.freedesktop.org/archives/openicc/2005q2/000313.html)
  • distribute by combining above information
    • packing all informations into one piece
embed into ICC profile, register in a local or remote hardware db, xml configuration

Advantages

  • select an profile and the system/application selects the correct driver and knows about needed settings
  • change settings and the system can tell if an profile is available
  • email a complete settings file, no further information is needed to setup
  • use the same settings in all applications, they are globally available through the profiles themselves

Scenario

(X example, similar to print, scan, digicams):

  • obtain monitor settings informations
  • set/reset monitor settings from software (xcalib/ddccontrol,...)
  • interface to get/set settings from Oyranos to drivers
  • extract ICC information easily
  • alert for expired configuration

Image:Device_profiles_01.pngas Inkscape SVG (http://www.oyranos.org/wiki/images/d/da/Device_profiles_01.svg)

Driver

Image:Device profiles 03.png

The big question is, where are driver properties are agreed upon between two applications. The device part will be handled by Oyranos, thats clear. The device configuration backends handle especially the device property to Oyranos DB key mapping. Does it make sense to facilitate a driver backend API to do the same for various drivers? Logical? No, devices access and drivers overlap so much, that it is not useful to split them.

/* possible sequence to get a device profile - unimplemented */
oyDevice_s * device = 0;
oyProfile_s * profile = 0;

oyDeviceGet( "config", "camera.dcraw", "absorber-2.0", 0, &device );
oyDeviceSetDriverContext( device, (void*) driver_context_pointer, (const char*) "string.dcraw.xml", (size_t)0 );
oyDeviceGetProfile( device, &profile );

Profiling

Image:Device profiles 04.png

Implementation Details

  • easy accessible text format to store and handle driver informations (key/value pairs) in the Oyranos DB

Image:Device profiles 02.png

  • driver identifier (which every application can either understand or reject the whole profile)
  • possibly allow data blobs too, to allow compressed content
  • Graeme Gill suggested to use an magic number to identify the blob.
  • additional part within this format to store CMM specific thing (expire date, ...)
  • combine with ICC profiles
  • add device settings information to an existing ICC profile
    • use a internal dedicated ICC profile tag
      • possibly hard to circumvent license issues
      • best to identify, without breaking ICC standards
      • allow profilers do handle themselves (by an small library)
      • need possibility to add that information after profiling, because the device informations may not be available at profiling time or the profiler is simply not aware of our demand
    • check and correct the size tag in ICC profiles and append the device settings text behind. The profile size would be the offset to that data.
      • profile readers and CMMs would handle as usual
      • non standard
      • someone else can use the same approach, which would make such data useless
      • give the modified a proper extension to identify; ?? ICG for instance (InterColorprofileGathering) ??
    • prepend the text and define an offset to the ICC profile data
      • breaks existing CMMs and profile readers
      • clear to handle, to be covered by an specification
      • forces a switch first
  • the driver version should be editable (ICC Examin?), so a older drivers can be still used
  • fuzzy matching should be possible see here
    • oyConfig_Check_f // should help with that

Oyranos API suggestion

/** The following function includes all information to create and return the device 
    settings tag */
int           oyProfile_AddDeviceSettings     ( const char* device_manufacturer, // used for the 'dmnd' tag
                                                const char* device_name,         // used for the 'dmdd' tag
                                                const char* device_serial,       // 
                                                const char* driver_name,         // just for information
                                                const char* driver_signature,    // to choose the driver
                                                const char* driver_version,      // to choose the driver
                                                struct tm * calibration_time,    // used for the 'calt' tag
                                                                                 // needs <time.h>
                                                void*       configuration_data_block,
                                                size_t      config_block_size,
                                                oyProfile_s* profile,            // profile to embed into )
return: error status
/** a function to extract the device settings tag from a existing profile */
oyDeviceSettings_s* oyIccDeviceSettingsDataGet( oyProfile_s* profile,
                                                size_t*     data_size )

For the oyDeviceSettings_s structure see the proposal below.

TODO: proof the available options (ICC, XML...), choose, publish a specification and procedure suggestion, implement in Oyranos

Specification

Device Settings in ICC Revision History
v0.1 2006-08-28 - 09-04 Kai-Uwe Behrmann © 2006
v0.2 2006-09-06 Kai-Uwe Behrmann © 2006 Thanks for suggestions and revisions to Graeme Gill, Hal V. Engel, Robert L Krawitz and Gerhard Fuernkranz.

TODO (v0.3):

  • The Priority field should be limited to one profiler. Otherwise its value is object for concurency, which is not desireable.
  • change the name to 'drvS' to tell its dedication is about driver settings not device resolving
    • remove the device resolving and hint to use the 'pddt' tag instead
  • rename the Device Settings in ICC to Driver Settings in ICC

Specific Considerations

Printing

The proclaimed

wget http://localhost:631/profiles/sRGB.icc

is not working in CUPS(v1.2), as pointed out by Hal V. Engel and confimed (http://www.cups.org/str.php?L2894) by Mike Sweet.

A path to send a user selected local device profile to a remote print host is unclear, at least to me.

The limitation of one CUPS profile directory, e.g. "/usr/share/cups/profiles", is too restsictive, even with linking to other directories. The cupsICCProfile attribute should therefore allow for absolute locations, not just relative to a CUPS profile directory. The CUPS_DATADIR seems not a appropriate mechanism.

CUPS passes data from the data directory, e.g. the web documentation pages. It is possible to link the CUPS profile directory to that and the above mentioned wget http://localhost:631/profiles/sRGB.icc should work. Open is, how to know the data_root path. Much related is Till Kampeter's support request for by default exposing ICC profiles from PPDs on the CUPS web server (http://www.cups.org/str.php?L2896).


A print job should reflect the users local settings in regards of rendering intent selection, editing space and so on. How are profiles, rendering intents and other settings passed from a printing application to backends, e.g. the *toraster family. Do the RPI's need to parse the PPD in order to read the cupsICCProfile PPD attribute? How copy localy stored profiles to remote printing hosts?

Linux will switch to PDF (http://www.linuxfoundation.org/en/OpenPrinting/PDF_as_Standard_Print_Job_Format) as standard format for printing. The advantage of Ghostscript would be to obtain PDF colour management (https://www.linuxfoundation.org/en/OpenPrinting/Color_Management) right from the beginning.

Issues:


Desireable APIs for Oyranos:

  • obtain a profile by giving Oyranos a static PPD (one without all open choices stripped).
  • obtain a list of profile/static_PPD combinations for a specific print queue.


Camera Raw Developing

  • DNG (http://www.adobe.com/products/dng)

...

Scanning


Configuration

Module Protocol

Oyranos core <-> device module protocol

Implementation Overview

Oyranos implements devices as oyConfig_s objects.

A 'oyConfig_s' object holds a set of options comming from a device backend and possibly from the Oyranos DataBase (Oyranos DB).

Options which are relevant for inclusion into the Oyranos DB must be build of text strings. These are the oyConfig_s::backend_core options.

The device options represent both device attributes and driver settings in one object.

The device backend is implemented in Oyranos with the oyCMMapi8_s structure. This structure must be included in a module and be pointed to from a oyCMMInfo_s structure like all modules.

Tables

Options marked with "in:" are passed through a oyOptions_s argument to the module. Outgoing options are passed through the device(s) created by the modules and are assigned as follows:

[c] - oyConfig_s::backend_core - identification stuff as strings

[d] - oyConfig_s::data - additional data

[b] - oyConfig_s::db - only for Oyranos core and thus tabu for modules

Required options are marked with a [r].

The "device_name" option shall only be considered in oyConfig_s::oyConfigs_FromPattern. In oyConfig_s::oyConfigs_Modify the oyConfig_s's devices should have already that property in their backend_core part.

"list" call
Property Modules Informations Data format
"command"="list" oyX1, SANE, CUPS, oyRE in[r]: call for detected device(s) in: string
"device_name" oyX1, SANE, CUPS
oyRE
device ID in: select a single device; out[r]: device ID
any meaning for oyRE?
in(oyConfigs_FromPattern)/out[c]: string
"oyNAME_NAME" oyX1, SANE, CUPS, oyRE in: call for lightweight informations
out: short UI description
in/out[d]: string
"icc_profile" oyX1, CUPS out: the ICC profile accessible through the device driver in: string; out[d]: oyProfile_s or
a empty "icc_profile" option of oyVAL_STRUCT, if ICC profiles are supported by the device but in the actual search not found.
"display_name" oyX1 in: select a X11 display and get all connected devices; "device_name" has priority in(oyConfigs_FromPattern): string
"device_rectangle" oyX1 out[r]: the device rectangle in pixels in: string
out[d]: oyRectangle_s
"supported_devices" oyRE out: one manufacturer in the first line, remaining lines each for one model in: string
out[d]: strings
"device_context" oyX1,
SANE,
CUPS,
oyRE
out: not required
"SANE_Device"
"ppd_file_t*"
"libraw_output_params_t*"
out[d]: string
device handles SANE,
CUPS, oyRE
version + SANE_Device + SANE_Handle
out: device handle caching
out[c]: oyCMMptr_s or oyOption_SetFromData() but no string(s)

Note: If a "manufacturer" or a "model" option appear in a device after the "list" call, the device is considered ready for a Oyranos DB query. Thus all options which normally appear after a "properties" call should be included together with "manufacturer" or "model" options.


"properties" call
Property Modules Informations Data format
"command"="properties" oyX1, SANE, CUPS, oyRE in[r]: call for even expensive informations
in: string
"device_name" oyX1, SANE, CUPS, oyRE in: select a single device;
out: ID of each device, e.g. <manufacturer>-<model>
in(oyConfigs_FromPattern)/out[c]: string
"display_name" oyX1 in: select a X11 display and get all connected devices; "device_name" has priority in(oyConfigs_FromPattern): string
"manufacturer" oyX1, SANE, CUPS, oyRE out[r]: device manufacturer out[c]: string
"model" oyX1, SANE, CUPS, oyRE out[r]: device model out[c]: string
"serial" oyX1, SANE, CUPS, oyRE out: device serial number out[c]: string
"system_port" oyX1,
SANE,
CUPS,
oyRE
out: X11 screen number
out: scsi/usb/parallel port?
out: print queue?
out: RAW file name?
out[c]: string
"host" oyX1,
SANE,
CUPS,
oyRE
out: X11 server host name
out: possible?t
out: print host possible?
out: "local" host?
out[c]: string
"display_geometry" oyX1 out[r]: X11 screen geometry as in "device_rectangle" out[c]: string
"edid" oyX1 out: monitor EDID block in: string
out[d]: use oyOption_SetFromData(); users - oyOption_GetData()
"device_context" oyX1,
SANE,
CUPS,
oyRE
in: not required
SANE_Device
ppd_file_t*?
libraw_output_params_t*
in: add with oyOption_SetFromData()
device handles SANE, CUPS, oyRE in: abreviation to talk with drivers in[c]: oyOption_GetData()
device settings oyX1,
SANE,
CUPS,
oyRE
out[r]: "display_geometry" ...
...
static colour related PPD attributes
libraw options
out[c]: string


"setup" call
Property Modules Informations Data format
"command"="setup" oyX1,
SANE,
CUPS,
oyRE
in[r]: call for uploading a ICC profile through the device driver
do nothing
set a cupsICCProfile attribute in a given PPD and write out to file
do nothing
in: string
"device_name" oyX1, SANE, CUPS in[r]: select a single device in(oyConfigs_FromPattern): string
"profile_name" oyX1, SANE, CUPS in[r]: the local accessible ICC profile file name in: string
"config_file" CUPS in: a PPD configuration file (ppd_file_t*) to modify or nothing; out: (ppd_file_t*) in: oyOption_GetData(); out[d]: oyOption_SetFromData()?
device handles SANE, CUPS, oyRE in: abreviation to talk with drivers in[c]: oyOption_GetData()


"unset" call
Property Modules Informations Data format
"command"="unset" oyX1,
SANE,
CUPS,
oyRE
in[r]: unloading the _ICC_PROFILE_xxx atom
do nothing
remove a cupsICCProfile attribute in a given PPD
do nothing
in: string
"device_name" oyX1, SANE, CUPS in[r]: select a single device in(oyConfigs_FromPattern): string
"profile_name" oyX1, SANE, CUPS in[r]: the local accessible ICC profile file name in: string
"config_file" CUPS in: a PPD configuration file (ppd_file_t*) to modify or nothing; out: (ppd_file_t*) in: oyOption_GetData(); out[d]: oyOption_SetFromData()?
device handles SANE, CUPS, oyRE in: abreviation to talk with drivers in[c]: oyOption_GetData()


"help" call
Property Modules Informations Data format
"command"="help" oyX1, SANE, CUPS, oyRE in[r]: show help text through the modules local oyMessage_f in: string

Calling a device module without any command or a unknown command shall issue a message through the modules local oyMessage_f. The message shall contain infos about, describing calls and their properties and the expected results. Otherwise adhering to the above protocol will enshure a base level of interoperability with users like KM.

How to create a useful "device_name" (ID)?

it should be unique in that the module can distinguish each device and understand to build a device context. This is important for the case when no device context pointer/handle is passed from the user. How that is defined is up to the module writer. Even though, a string, one which makes sense in KM, would be much appreciated. e.g. in oyX1 it is "device_name"=":0.1" or "device_name"="far-away.org:10.0". The modules XOpenDisplay() can directly use these strings and the module can create a context and talk to the device. For SANE you have choosen "pnm:0", "pnm:1" and here locally I see "plustek:libusb:003:002". The last is unfortunedly subject to change with a new usb port or after newly plugging in. But that seems accepable.


Handling device contexts

The "device_context" option can be set from the module during the "list" call into a device. The user can then see, which specific information is accepted by the module. The module has implicitely to assume, that the user has no background about the called device class, and to initialise a device by its own. In case the user has already a context and passes this one to Oyranos, the module needs to extract the colour related device settings from this and pass the device settings as string to Oyranos. Oyranos will then be able to search for a according ICC profile.

It is important for Oyranos, the module and the user to agree who is responsible for the driver contexts. oyOption_SetFromData() is useful to pass a pointer through a oyOption_s. The size argument can be set to zero to avoid freeing the pointer through Oyranos. In case the module provides a context, e.g. in "list" then that needs to be released through driver functions. Oyranos has the oyCMMptr_s struct defined in oyranos_cmm.h which can be used: [1] (http://www.oyranos.org/doc_alpha/structoyCMMptr__s.html).

Multiple Configurations per "device_name"

For backends its possible to resolve one "device_name" option to multiple driver configurations. Such backends are best implemented in that they resolve the oyConfig_s objects right from the beginning, e.g. the "list" call. Otherwise the oyConfig_s devices are not uniquely defined. On a practical example, a CUPS device would be uniquely defined, if all colour related and to be included PPD entries are included in the oyConfig_s::backend_core options as strings.

Users can subsummarise such devices in that they look at the registration, manufacturer, model and serial number strings. However they should make clear that each device consists as well of the driver settings.

Further Reading

The above protocol is to be implemented in Oyranos device modules. See: [2] (http://www.oyranos.org/doc_alpha/extending_oyranos.html#write_device_modules)

References