summaryrefslogtreecommitdiff
path: root/psi/zicc.c
diff options
context:
space:
mode:
authorRay Johnston <ray.johnston@artifex.com>2018-11-14 16:56:43 -0800
committerRay Johnston <ray.johnston@artifex.com>2018-11-28 13:26:33 -0800
commitf0ca2c929171a025e846a2eddd51f767e04c8e23 (patch)
tree62a6956649c7fa56bbf5c749d20c34e7976dfc2d /psi/zicc.c
parent34bb42a7bcd649675d618a62c9f8a3a673598787 (diff)
downloadghostpdl-f0ca2c929171a025e846a2eddd51f767e04c8e23.tar.gz
Bug 695813. Reduce memory usage for ICC profiles. Example AIX361DC_Save.pdf
The same ICC profiles and colorspace were used many times (in the example the cited PDF_1.7_ATS file) which could result in memory usage growth and performance impact associated with loading the same profile many times. There was a icc_profile_cache in the gstate, but it was not being used for ICCBased colorspaces, only for CIEBased* spaces. Adding logic to cache ICCBased colorspaces and change ICCBased space to be in stable memory so it can exist in the cache. This results in a reduction of the RAM needed for the cited file from 1.0Gb down to 44Mb and reduced the parse time from 29.4s down to 24.4s (overall time from 94.5s to 91.3s) for ppmraw 600 dpi. Note that this optimization results in many fewer CS/cs operations being emitted by pdfwrite, but this also can result in text being emitted as TJ operations (glyphs with positioning) which can result in single pixel shifts in glyphs. Sometimes this looks better, sometimes not, but the reduction in size/complexity of the resulting PDF is worth it.
Diffstat (limited to 'psi/zicc.c')
-rw-r--r--psi/zicc.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/psi/zicc.c b/psi/zicc.c
index dbd2562c7..f9c7b1ec5 100644
--- a/psi/zicc.c
+++ b/psi/zicc.c
@@ -47,6 +47,7 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
int code, k;
gs_color_space * pcs;
ref * pstrmval;
+ ref * phashval = NULL;
stream * s = 0L;
cmm_profile_t *picc_profile = NULL;
int i, expected = 0;
@@ -58,13 +59,27 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
GSICC_STANDARD_PROFILES_KEYS
};
+ /* If we are override ICC mode, we won't use the profile */
+ if (!gs_currentoverrideicc(igs) &&
+ dict_find_string(ICCdict, ".hash", &phashval) == 1 &&
+ r_has_type(phashval, t_integer)) {
+ pcs = gsicc_find_cs(phashval->value.intval, igs);
+ if (pcs != NULL) {
+ /* Set the color space. We are done. */
+ code = gs_setcolorspace(igs, pcs);
+ /* Remove the ICC dict from the stack */
+ pop(1);
+ return code;
+ }
+ }
+
/* verify the DataSource entry */
if (dict_find_string(ICCdict, "DataSource", &pstrmval) <= 0)
return_error(gs_error_undefined);
check_read_file(i_ctx_p, s, pstrmval);
/* build the color space object */
- code = gs_cspace_build_ICC(&pcs, NULL, gs_gstate_memory(igs));
+ code = gs_cspace_build_ICC(&pcs, NULL, gs_gstate_memory(igs)->stable_memory);
if (code < 0)
return gs_rethrow(code, "building color space object");
/* For now, dump the profile into a buffer
@@ -198,18 +213,27 @@ int seticc(i_ctx_t * i_ctx_p, int ncomps, ref *ICCdict, float *range_buff)
}
/* Have one increment from the color space. Having these tied
together is not really correct. Need to fix that. ToDo. MJV */
- rc_adjust(picc_profile, -2, "seticc");
+ rc_adjust(picc_profile, -2, "seticc"); /* NB: May free the profile and set picc_profile to 0 */
rc_increment(pcs->cmm_icc_profile_data);
}
- /* Set the color space. We are done. No joint cache here... */
+ /* Set the color space. We are done. */
code = gs_setcolorspace(igs, pcs);
/* The context has taken a reference to the colorspace. We no longer need
* ours, so drop it. */
rc_decrement_only(pcs, "seticc");
- /* In this case, we already have a ref count of 2 on the icc profile
- one for when it was created and one for when it was set. We really
- only want one here so adjust */
- rc_decrement(picc_profile,"seticc");
+ if (picc_profile != NULL) {
+ /* In this case, we already have a ref count of 2 on the icc profile
+ one for when it was created and one for when it was set. We really
+ only want one here so adjust */
+ rc_decrement(picc_profile,"seticc");
+ if (code >= 0) {
+ /* Save this colorspace in the iccprofile_cache */
+ gsicc_add_cs(igs, pcs, picc_profile->hashcode);
+ /* should be an integer, but if for some reason it isn't, don't update */
+ if (phashval && r_has_type(phashval, t_integer))
+ phashval->value.intval = picc_profile->hashcode;
+ }
+ }
/* Remove the ICC dict from the stack */
pop(1);
return code;