summaryrefslogtreecommitdiff
path: root/gs/psi
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2012-02-13 08:46:29 -0800
committerChris Liddell <chris.liddell@artifex.com>2012-03-15 11:54:22 +0000
commit2eb8cc7f7731dbc4ea020778d434b2282944b097 (patch)
tree620a4a56fcf8273cf47bcb6ad5d36d17d223f475 /gs/psi
parentb10a176816c5bc6b71906378a952a17c54dbb849 (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.mak2
-rw-r--r--gs/psi/zicc.c139
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)
};