diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2012-02-13 08:46:29 -0800 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2012-03-15 11:54:22 +0000 |
commit | 2eb8cc7f7731dbc4ea020778d434b2282944b097 (patch) | |
tree | 620a4a56fcf8273cf47bcb6ad5d36d17d223f475 /gs/psi | |
parent | b10a176816c5bc6b71906378a952a17c54dbb849 (diff) |
C portion for making use of output intent ICC profile.
This commit puts into place the c-code for making use of an
ICC profile stream from the PDF interpreter for setting of the
output intent. This is done through the use of zset_outputintent.
This function will make the various settings of the icc profiles
in the device and in the icc manager based upon the process model
of the target device and the icc profile of the output intent. It
will be up to the interpreter to make the call to .set_outputintent
with the proper output intent ICCBased dictionary on the top of the
stack. This should be done in the interpreter after the device has
been set up and all the default ICC profiles are in place. The
interpreter should make the call if we have specified -dUsePDFX3Profile.
The first output intent that is present in the file should be used,
unless someone specifies a different intent through the use of
–dOutputIntent=x . In this case, the x+1 output intent (if it
exists) will be used. Note that if the particular output intent does
not include an ICC profile entry (DestOutputProfile), then the output
intent will not be used. In this case, we will eventually want to
specify what the OutputConditionIdentifier was for that particular
intent if it was missing the DestOutputProfile.
Diffstat (limited to 'gs/psi')
-rw-r--r-- | gs/psi/int.mak | 2 | ||||
-rw-r--r-- | gs/psi/zicc.c | 139 |
2 files changed, 139 insertions, 2 deletions
diff --git a/gs/psi/int.mak b/gs/psi/int.mak index fc2728e9f..16676f01c 100644 --- a/gs/psi/int.mak +++ b/gs/psi/int.mak @@ -1715,7 +1715,7 @@ $(PSOBJ)zicc.$(OBJ) : $(PSSRC)zicc.c $(OP) $(math__h) $(memory__h)\ $(gsstruct_h) $(gxcspace_h) $(stream_h) $(files_h) $(gscolor2_h)\ $(gsicc_h) $(estack_h) $(idict_h) $(idparam_h) $(igstate_h)\ $(icie_h) $(ialloc_h) $(zicc_h) $(gsicc_manage_h) $(GX) $(gxistate_h)\ - $(gsicc_create_h) $(gsicc_profilecache_h) + $(gsicc_create_h) $(gsicc_profilecache_h) $(gxdevice_h) $(gsicc_cache_h) $(PSCC) $(PSO_)zicc.$(OBJ) $(C_) $(PSSRC)zicc.c # ---------------- Support for %disk IODevices ---------------- # diff --git a/gs/psi/zicc.c b/gs/psi/zicc.c index 8da0af7ae..cec8e5f06 100644 --- a/gs/psi/zicc.c +++ b/gs/psi/zicc.c @@ -36,6 +36,8 @@ #include "gxistate.h" #include "gsicc_create.h" #include "gsicc_profilecache.h" +#include "gxdevice.h" /* for output intent setting */ +#include "gsicc_cache.h" int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff) { @@ -217,6 +219,140 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff) } /* + * <dict> .set_outputintent - + * + * Set and use the specified output intent. + * + */ +static int +zset_outputintent(i_ctx_t * i_ctx_p) +{ + os_ptr op = osp; + int code = 0; + gx_device *dev = gs_currentdevice(igs); + gs_imager_state *pis = (gs_imager_state *)igs; + cmm_dev_profile_t *dev_profile; + stream * s = 0L; + ref * pnval; + ref * pstrmval; + int ncomps, dev_comps; + cmm_profile_t *picc_profile; + int expected = 0; + gs_color_space_index index; + gsicc_manager_t *icc_manager = pis->icc_manager; + cmm_profile_t *source_profile = NULL; + + /* Get the device structure */ + code = dev_proc(dev, get_profile)(dev, &dev_profile); + if (dev_profile == NULL) { + code = gsicc_init_device_profile_struct(dev, NULL, 0); + code = dev_proc(dev, get_profile)(dev, &dev_profile); + } + if (dev_profile->oi_profile != NULL) { + return 0; /* Allow only one setting of this object */ + } + code = dict_find_string(op, "N", &pnval); + if (code < 0) + return code; + ncomps = pnval->value.intval; + + /* verify the DataSource entry. Creat profile from stream */ + if (dict_find_string(op, "DataSource", &pstrmval) <= 0) + return_error(e_undefined); + check_read_file(i_ctx_p, s, pstrmval); + + picc_profile = gsicc_profile_new(s, gs_state_memory(igs), NULL, 0); + picc_profile->num_comps = ncomps; + picc_profile->profile_handle = + gsicc_get_profile_handle_buffer(picc_profile->buffer, + picc_profile->buffer_size); + if (picc_profile->profile_handle == NULL) { + rc_decrement(picc_profile,"zset_outputintent"); + return -1; + } + picc_profile->data_cs = gscms_get_profile_data_space(picc_profile->profile_handle); + switch (picc_profile->data_cs) { + case gsCIEXYZ: + case gsCIELAB: + case gsRGB: + expected = 3; + source_profile = icc_manager->default_rgb; + break; + case gsGRAY: + expected = 1; + source_profile = icc_manager->default_gray; + break; + case gsCMYK: + expected = 4; + source_profile = icc_manager->default_cmyk; + break; + case gsNCHANNEL: + expected = 0; + break; + case gsNAMED: + case gsUNDEFINED: + break; + } + if (expected && ncomps != expected) { + rc_decrement(picc_profile,"zset_outputintent"); + return_error(e_rangecheck); + } + gsicc_init_hash_cs(picc_profile, pis); + + /* All is well with the profile. Lets set the stuff that needs to be set */ + dev_profile->oi_profile = picc_profile; + picc_profile->name = (char *) gs_alloc_bytes(dev->memory, + MAX_DEFAULT_ICC_LENGTH, + "zset_outputintent"); + strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE)); + picc_profile->name[strlen(OI_PROFILE)] = 0; + picc_profile->name_length = strlen(OI_PROFILE); + + /* If the output device has a different number of componenets, then we are + going to set the output intent as the proofing profile, unless the + proofing profile has already been set. + + If the device has the same number of components (and color model) then as + the profile we will use this as the output profile, unless someone has + explicitly set the output profile. + + Finally, we will use the output intent profile for the default profile + of the proper Device profile in the icc manager, again, unless someone + has explicitly set this default profile. */ + + dev_comps = dev_profile->device_profile[0]->num_comps; + index = gsicc_get_default_type(dev_profile->device_profile[0]); + if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) { + /* The OI profile is the same type as the profile for the device and a + "default" profile for the device was not externally set. So we go + ahead and use the OI profile as the device profile. Care needs to be + taken here to keep from screwing up any device parameters. We will + use a keyword of OIProfile for the user/device parameter to indicate + its usage. Also, note conflicts if one is setting object dependent + color management */ + rc_assign(dev_profile->device_profile[0], picc_profile, + "zset_outputintent"); + } else { + if (dev_profile->proof_profile == NULL) { + /* This means that we should use the OI profile as the proofing + profile.*/ + dev_profile->proof_profile = picc_profile; + rc_increment(picc_profile); + } + } + /* Now the source colors. See which source color space needs to use the + output intent ICC profile */ + index = gsicc_get_default_type(source_profile); + if (index < gs_color_space_index_DevicePixel) { + /* source_profile is currently the default. Set it to the OI profile */ + rc_assign(source_profile, picc_profile, "zset_outputintent"); + } + /* Remove the output intent dict from the stack */ + pop(1); + return code; +} + +/* * <dict> .seticcspace - * * Create an ICCBased color space and set it to be the current color space. @@ -402,6 +538,7 @@ seticc_cal(i_ctx_t * i_ctx_p, float *white, float *black, float *gamma, const op_def zicc_ll3_op_defs[] = { op_def_begin_ll3(), - { "1.seticcspace", zseticcspace }, + { "1.seticcspace", zseticcspace }, + { "1.set_outputintent", zset_outputintent }, op_def_end(0) }; |