% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. % % This software is provided AS-IS with no warranty, either express or % implied. % % This software is distributed under license and may not be copied, % modified or distributed except as expressly authorized under the terms % of the license contained in the file LICENSE in this distribution. % % For more information about licensing, please refer to % http://www.ghostscript.com/licensing/. For information on % commercial licensing, go to http://www.artifex.com/licensing/ or % contact Artifex Software, Inc., 101 Lucas Valley Road #110, % San Rafael, CA 94903, U.S.A., +1(415)492-9861. % $Id: gs_icc.ps,v 1.10 2003/07/14 19:32:17 ray Exp $ % ICCBased color space method dictionaries. % This assumes gs_ciecs2.ps has already been processed. % % Note that the substitution procedure in this routine will dynamically % check for support of ICCBased color space. If such support is not % provided, the alternative color space will be used. % % The validation routine in dictionary (cs_validate) performs a more % extensive validation than is done for other color spaces, because % .seticcspace does less checking than most other color space setting % operators. % .currentglobal true .setglobal .cspace_util begin % % A dictionary for mapping the number of components of an ICCBased color % space to the appropriate alternative color space. This is used only % if an alternative color space is not specifically provided. % /icc_comp_map_dict mark 1 /DeviceGray 3 /DeviceRGB 4 /DeviceCMYK .dicttomark def % % get_icc_alternative_space % % Get the alternative color space for an ICCBased color space. % /get_icc_alternative_space { 1 get dup /Alternate .knownget { exch pop } { /N get //icc_comp_map_dict exch get } ifelse } bind def colorspacedict /ICCBased mark /cs_potential_indexed_base true /cs_potential_pattern_base true /cs_potential_alternate true /cs_potential_icc_alternate false /cs_get_ncomps { 1 get /N get } bind /cs_get_range { 1 get dup /Range .knownget { exch pop } { /N get 2 mul //dflt_range_4 exch 0 exch getinterval } ifelse } bind /cs_get_default_color { 1 get /N get { 0 } repeat } bind % % For generating a gray, RGB, or CMYK equivalent color, we will % assume that the alternative color space provides reasonable % mapping. /cs_get_currentgray { //get_icc_alternative_space exec //.cs_get_currentgray exec } bind /cs_get_currentrgb { //get_icc_alternative_space exec //.cs_get_currentrgb exec } bind /cs_get_currentcmyk { //get_icc_alternative_space exec //.cs_get_currentcmyk exec } bind % a lot of validation is done by the cs_validate method /cs_validate { //check_cie_cspace exec dup 1 get dup /N get dup type /integertype ne //setcspace_typecheck if //icc_comp_map_dict exch known not //setcspace_rangecheck if dup /DataSource get dup type dup /stringtype ne exch /filetype ne and //setcspace_typecheck if rcheck not //setcspace_invalidaccess if dup /Range .knownget { //check_array exec { type dup /integertype ne exch /realtype ne and //setcspace_typecheck if } forall } if /Alternate .knownget { //.cs_validate exec //.cs_potential_icc_alternate exec not //setcspace_rangecheck if } if } bind % substitute the Alternate space, if appropriate /cs_substitute { % % A design problem in the Ghostscript graphic library color % space code prevents an ICCBased color space from having an % ICCBased alternative color space. This situation actually % arises fairly frequently in PDF, as an ICCBased color space % is used as the substitute color for a Device{Gray|RGB|CMYK} % color space, which in turn are used as the alternative color % space to another (or possibly even the same) ICCBased color % space. % % This situation causes no fundamental problems, as % Ghostscript nominally supports ICCBased color spaces, so the % Alternate color space is not used. Where this is not true % (primarily because the NOCIE option is selected), the code % would (except for the design flaw noted above) select the % Alternate of the Alternate color space. % % The code below works around this problem by suprressing % color space substitution for alternative color spaces if % the substituting space is an ICCBased color space. % dup //get_icc_alternative_space exec //.cs_substitute exec 2 copy eq 1 index //.cs_potential_icc_alternate exec not or { pop pop dup } { % retain just the new Alternate space exch pop % build all new structures in local VM .currentglobal 3 1 roll //false .setglobal % copy the original ICCBased color space array 1 index dup length array copy % copy the ICCBased dictionary dup 1 2 copy get dup length dict copy % insert the new alterante color space dup /Alternate 7 -1 roll put % insert the new dictionary into the arra put % restore the VM mode 3 -1 roll .setglobal } ifelse } bind % % The current implementation of ICCBased color spaces requires the % DataSource to be a file. % /cs_prepare { % make DataSource a file dup 1 get /DataSource get type /stringtype eq { % build all new structures in local VM .currentglobal exch //false .setglobal % check if we need to copy the color space and dictionary 2 copy eq { dup length array copy dup 1 2 copy get dup length dict copy put } if % fetch DataSource, setting up stack for multiple puts dup 1 2 copy get dup /DataSource 2 copy get % convert the string into a file /ReusableStreamDecode filter % put the file into the dictioary, the dictionary into the array put put % restore the VM mode exch .setglobal } if } bind % % Install the current color space. % % The current Ghostscript color space implementation requires that % color spaces that provide a base or alternative color space set % that base/alternative color space to be the current color space % before attempting to set the original color space. This can cause % difficulty if an ICCBased color space is being used as a substitute % color space for a device-specific color space, and uses that same % device-specific color space as an alternative space. For this % reason, a special _setcolorspace_nosub operator is provided. % /cs_install { % set the alternative color space to be the current color space dup //get_icc_alternative_space exec //_setcolorspace_nosub exec % check for native support /.seticcspace where { pop //false } { //true } ifelse NOCIE or //pop_1 % do nothing { % Acrobat Reader silently ignores errors with ICC profiles % and uses the alternate color space -- do the same. mark exch 1 get { .seticcspace } .internalstopped cleartomark } ifelse } bind % for now, the alternative spaces for an ICCBased color space do % not require special preparation /cs_prepare_color { dup 1 get /N get //check_num_stack exec pop } bind /cs_complete_setcolor //pop_1 .dicttomark put end % .cspace_util NOPSICC { (%END PSICC) .skipeof } if % Now set up ICC profile loading for PostScript %%BeginICCProfile sections. systemdict begin /.ProcessICCcomment { % file comment -- file comment dup (%%BeginICCProfile) anchorsearch { pop pop DEBUG { (.ProcessICCcomment found %%BeginICCProfile) print flush } if % load an ICC profile defined as comments (hex encoded). % Ends with %%End at the start of a line. Read the data into % a bytestring to allow seeking. This string can be used as a % seekable ReusableStreamDecode filter source by the ICC logic. % % Since .bigstring needs to know the size, we first read an array of % strings each 64000 max length. % % stack: --file-- (%%BeginICCProfile: ...) 1 index 0 (%%EndICCProfile) /SubFileDecode filter [ { counttomark 1 add index 64000 string readhexstring not { exit } if } loop ] exch closefile 0 1 index { length add } forall .bigstring exch 0 exch { % stack: --file-- (%%BeginICCProfile: ...) --bytestring-- cur_index --string-- 2 copy length add % calculate next string start point 3 1 roll 3 index 3 1 roll putinterval } forall pop % discard length of bytestring % make a seekable -file- out of the bytestring mark /AsyncRead true .dicttomark /ReusableStreamDecode filter % stack: --file-- (%%BeginICCProfile: ...) --icc_subfile-- /DeviceCMYK setcolorspace << /DataSource 3 -1 roll /N 4 % Try CMYK first >> { .seticcspace } stopped { /DeviceRGB setcolorspace dup /N 3 put { .seticcspace } stopped { /DeviceGray setcolorspace dup /N 1 put { .seticcspace } stopped { % last choice QUIET not { ( *** Unable to load ICC profile from PostScript DSC comments ***) = flush } if pop } if } if } if } { pop % Not interested in this DSC comment } ifelse } bind def % Merge ProcessICCcomment with existing handler /.ProcessICCcomment load /exec load currentuserparams /ProcessDSCComment get dup null eq {pop {pop pop}} if /exec load 4 array astore cvx readonly << /ProcessDSCComment 3 -1 roll >> setuserparams end % systemdict %END PSICC .setglobal