home *** CD-ROM | disk | FTP | other *** search
- % Copyright (C) 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_cspace.ps,v 1.5.2.1 2003/12/12 22:07:58 giles Exp $
- % basic colorspace mechanism
-
- %
- % This new implementation of color spaces extends the color space
- % formalism to all PostScript levels. Level specific features and
- % operators continue to be accessible only in the appropriate level,
- % but the colorspace concept and associated mechanisms are used
- % throughout.
- %
- % The color space mechanism is built around two dictionaries:
- %
- % .cspace_util
- % A dictionary in global VM that is accessible in userdict only
- % during initialization. This dictionary is intended for various
- % utility procedures that are used in implementing the individual
- % color spaces.
- %
- % colorspacedict
- % A dictionary of methods for each color space type. The keys
- % in this dictionary are color space type names (e.g.: /DeviceGray,
- % /Separation, etc.), and the values are dictionaries of methods.
- % The set of methods is the same for each color space type, and
- % provides a complete implementation for the corresponding color
- % space type. This dictionary is in global VM.
- %
- % The information specific to a color space type is created in a file
- % for that type or group of types (e.g.: gs_csdev.ps, gs_csindx.ps,
- % etc.). These files will generally adhere to the template:
- %
- % .currentglobal true .setglobal
- % <level-specific dictionary> begin
- % ...
- % .cspace_util begin
- % colorspacedict
- % /<color space type name>
- % mark
- % /cs_validate
- % {
- % ...
- % }
- % bind
- % ...
- % .dicttomark
- % put
- % end % .cspace_util
- % end ... % level-specific dictionary
- % .setglobal
- %
- % The methods associated with a color space are listed below (along with
- % their stack handling), followed by descriptions.
- %
- % - cs_potential_indexed_base <bool>
- %
- % - cs_potential_pattern_base <bool>
- %
- % - cs_potential_alternate <bool>
- %
- % - cs_potential_icc_alternate <bool>
- %
- %
- % <name | array> cs_get_ncomps <int>
- %
- % <name | array> cs_get_range <range_array>
- %
- % <name | array> cs_get_default_color <c1> ... <cn>
- %
- %
- % <c1> ... <cn> <name | array> cs_get_currentgray <gray>
- %
- % <c1> ... <cn> <name | array> cs_get_currentrgb <red> <green> <blue>
- %
- % <c1> ... <cn> <name | array> cs_get_currentcmyk
- % <cyan> <magenta> <yellow> <black>
- %
- %
- % <name | array> cs_validate <name | array>
- %
- % <name1 | array1> cs_substitute <name1 | array1> <array2>
- %
- % <name1 | array1> <array2> cs_prepare <name1 | array1> <array2>
- %
- % <name | array> cs_install -
- %
- %
- % <c1> ... <cn> <array> cs_verify_color <c1> ... <cn>
- %
- % <array> cs_complete_color -
- %
- %
- % cs_potential_indexed_base, cs_potential_pattern_base,
- % cs_potential_alternate, cs_potential_icc_alternate
- % These are booleans rather than procedures. They indicate if the color
- % space can be a base space of an Indexed color space (anything except
- % Indexed and Pattern), a Pattern color space (anything except Pattern),
- % the alternative color space of a Separation or DeviceN color space, or
- % the alternative color space of an ICCBased color space. The two
- % parameters are distinct only because of a Ghostscript-specific
- % implementation problem; in principle, there is nothing special about
- % ICCBased color spaces in this regard.
- %
- % cs_get_ncomps
- % Return the number of color components for the color spaces. For Pattern
- % color spaces, the value is -1 if there is no base space, or -(n + 1) if
- % the base space has n components.
- %
- % cs_get_range
- % Return the input Range array appropriate for this color space. This is
- % defined for all color spaces, though it is of interest primarily for
- % CIEBased and ICCBased color spaces. For Indexed color spaces this is
- % [ 0 hival ], where hival is the maximum support index value. For all
- % other non-CIEBased, non-ICCBased color spaces, the range is an array
- % of ncomps elements, all of which are [ 0 1 ], where ncomps is the
- % number of color space components.
- %
- % cs_get_default_color
- % Generates the default color for the current color space. Under normal
- % circumstances this is done internally. It is provided in PostScript
- % only to support an optimization that doesn't change the current color
- % space more often than necessary.
- %
- % cs_get_currentgray, cs_get_currentrgb, cs_get_currentcmyk
- % These procedures are used to implement the currentgray, currentrgb,
- % and currentcmyk operators (which are pseudo-operators in the current
- % implementation).
- %
- % cs_validate
- % Validate the operand color space. Because color spaces are extensively
- % manipulated in PostScript in this implementation, error handling can
- % become burdensome. To make the code somewhat simpler, it is useful to
- % be able to validate a color space prior to manipulation, so as to
- % ensure that errors are not discovered in awkward places.
- %
- % cs_substitute
- % Substitute a device-independent color space for device specific color
- % space. This applies directly to the device-specific color spaces
- % (DeviceGray, DeviceRGB, DeviceCMYK), and indirectly when these color
- % spaces are used as base/alternative color spaces. The mechanism for
- % color substitution is included in all language levels, though it may
- % only be accessed for Language Level 3.
- %
- % The substituted color space is the topmost of the operands pushed.
- % this may or may not be the same as the original color space, which
- % is immediately below it on the operand stack. If the two differ,
- % the substituted space will always be in local VM (and will be
- % writable).
- %
- % Substitution is applied recursively to the base/alternate color
- % space of ICCBased, Indexed, Separation, DeviceN, or Pattern
- % color spaces. Because Ghostscript currently requires that any
- % base or alternative color space be the current color space when
- % the enclosing color space is set, this substitution effectively
- % occurs twice: once in the original color space, and once when the
- % base/alternative color space is made the current color space.
- % We retain the first substitution as we would eventually like to
- % remove the restriction on making the base/alternative color space
- % the current color space.
- %
- % cs_prepare
- % Perform any operations required on the color space for installation.
- % This method exists primarily to allow conversion of PostScript
- % procedures to functions for CIEBased color spaces. Two operands are
- % provided: the original and the substituted color space. If the two
- % differ and the latter is writable, required modifications can
- % be made "in place". Otherwise, a new instance of the second color
- % space must be built.
- %
- % Currently, cs_prepare is not explicitly recursive. Because
- % Ghostscript requires a base/alternate color space to be installed
- % as the current color space prior to installing the enclosing color
- % space, the cs_prepare method will implicitly be called recursively.
- % The reason for not making this explicit is that color space
- % preparation may involve a considerable amount of work, which could
- % be avoided if, for example, an alternative color space will not
- % be used because the enclosing Separation/DeviceN color space is
- % supported in native mode by the process color model. We would
- % eventually like to remove the need to prepare color spaces that
- % will not be used.
- %
- % cs_install
- % This method actually installs the color space in the graphic state.
- % Only the substituted/prepared space (which may be the same as the
- % original space) is passed as an operand; the original space is handled
- % directly by the .setcolorspace operator.
- %
- % The provision of a separate method for this tasks reflects the
- % historical implementation of color spaces in the Ghostscript
- % interpreter. This implementation provides a unique operator for each
- % color space type.
- %
- % cs_prepare_color
- % Modify a set of color operands as required by a color space. This
- % is used primarily to verify the color operands, as this is most
- % conveniently done in PostScript.
- %
- % cs_complete_setcolor
- % This method is invoked immediately after a (successful) invocation
- % of setcolor. Ii is provided as a separate method for compatibility
- % with Adobe implementations. These implementations invoke the lookup
- % (Indexed) or tint procedure each time setcolor is invoked (only if
- % the alternative color space is used in the case of the tint
- % transform). Because Ghostscript may convert these procedures to
- % functions (or pre-sample them), the procedures may not always be
- % called when expected. There are applications that depend on this
- % behavior (e.g.: Adobe PhotoShop 5+), so this method provides a way
- % to emulate it.
- %
- % In principle, a cs_complete_setcolor procedure for an Indexed color
- % space whose base space should invoke cs_complete_setcolor on its
- % base space. Currently we don't do this, because it has not been
- % shown to be necessary. It would be simple to add if it is every
- % needed.
- %
- % All of these methods are procedures.
- %
- % For each of these methods, there is a procedure in .cspace_util with
- % a dot ('.') prefix that will invoke the appropriate procedure for the
- % operand array.
- %
-
- .currentglobal true .setglobal
- userdict /.cspace_util 80 dict put
- .cspace_util begin
-
- %
- % Colorspacedict is initially in .cspace_util; it is copied to level2dict
- % in the Level 2 initialization code to retain compatibility with
- % earlier implementations.
- %
- /colorspacedict 20 dict def
-
-
- %
- % <obj> make_array1 <array>
- %
- % procedure for conditionally converting a named color space to a
- % 1-element array. Since names are always global, the array will be
- % as well.
- %
- /make_array1
- {
- dup type /nametype eq
- { currentglobal true setglobal exch 1 array astore exch setglobal }
- if
- }
- bind def
-
- %
- % <name|array> .get_cspace_type name
- %
- % Provide generic routine for retrieving the color space type.
- %
- /.get_cspace_type
- {
- dup type dup /arraytype eq exch /packedarraytype eq or
- { 0 get }
- if
- }
- bind def
-
- %
- % <name|array> .get_method_dict <dict>
- %
- % Get the method dictionary for a specific color space. Note that the
- % color space is left on the stack.
- %
- /.get_method_dict
- { //colorspacedict exch //.get_cspace_type exec get }
- bind def
-
- %
- % <name|array> <proc_name> .get_method <name|array> <proc | bool>
- %
- % Get the named method for the operand color space.
- %
- /.get_method
- { exch //.get_method_dict exec exch get }
- bind def
-
-
- %
- % <name_array> .cs_potential_indexed_base <bool>
- % <name_array> .cs_potential_pattern_base <bool>
- % <name_array> .cs_potential_alternate <bool>
- % <name_array> .cs_potential_icc_alternate <bool>
- % <name | array> .cs_get_ncomps <int>
- % <name | array> .cs_get_range <range_array>
- % <name | array> .cs_get_default_color <c1> ... <cn>
- % <c1> ... <cn> <name | array> .cs_get_currentgray <gray>
- % <c1> ... <cn> <name | array> .cs_get_currentrgb <r> <g> <b>
- % <c1> ... <cn> <name | array> .cs_get_currentcmyk <c> <m> <y> <k>
- % <name | array> .cs_validate <name | array>
- % <name1 | array1> .cs_substitute <name1 | array1> <array2>
- % <name1 | array1> <array2> .cs_prepare <name1 | array1> <array2>
- % <name | array> .cs_install -
- % <c1> ... <cn> <array> .cs_prepare_color <c1> ... <cn>
- % <array> .cs_complete_setcolor -
- %
- % These procedures provide access to the corresponding methods of the
- % operand color space.
- %
- /.cs_potential_indexed_base
- { /cs_potential_indexed_base //.get_method exec }
- bind def
-
- /.cs_potential_pattern_base
- { /cs_potential_pattern_base //.get_method exec }
- bind def
-
- /.cs_potential_alternate
- { /cs_potential_alternate //.get_method exec }
- bind def
-
- /.cs_potential_icc_alternate
- { /cs_potential_icc_alternate //.get_method exec }
- bind def
-
- /.cs_get_ncomps
- { dup /cs_get_ncomps //.get_method exec exec }
- bind def
-
- /.cs_get_range
- { dup /cs_get_range //.get_method exec exec }
- bind def
-
- /.cs_get_default_color
- { dup /cs_get_default_color //.get_method exec exec }
- bind def
-
- /.cs_get_currentgray
- { dup /cs_get_currentgray //.get_method exec exec }
- bind def
-
- /.cs_get_currentrgb
- { dup /cs_get_currentrgb //.get_method exec exec }
- bind def
-
- /.cs_get_currentcmyk
- { dup /cs_get_currentcmyk //.get_method exec exec }
- bind def
-
- /.cs_validate
- { dup /cs_validate //.get_method exec exec }
- bind def
-
- /.cs_substitute
- { dup /cs_substitute //.get_method exec exec }
- bind def
-
- /.cs_prepare
- { dup /cs_prepare //.get_method exec exec }
- bind def
-
- /.cs_install
- { dup /cs_install //.get_method exec exec }
- bind def
-
- /.cs_prepare_color
- { dup /cs_prepare_color //.get_method exec exec }
- bind def
-
- /.cs_complete_setcolor
- { dup /cs_complete_setcolor //.get_method exec exec }
- bind def
-
-
- %
- % Make sure we have an interpreter color space before redefining
- % setcolorspace. The interpreter internal code only sets the effective
- % color space; the interpreters color spaces begins as a null object.
- %
- % NB: This should come prior to the redefinition of setcolorspace, and
- % must use an array operand.
- %
- [ /DeviceGray ] setcolorspace
-
-
- %
- % <c1> ... <cn> setcolor -
- %
- % As with setcolorspace, setcolor is initially placed in .cspace_util,
- % and is copied to level2dict by the Level 2 initialization code. The
- % internal definition of setcolor is removed from systemdict as soon
- % as this procedure is defined.
- %
- /setcolor
- {
- {
- currentcolorspace //.cs_prepare_color exec //setcolor
- currentcolorspace //.cs_complete_setcolor exec
- }
- stopped
- { //.cspace_util /setcolor get $error /errorname get signalerror }
- if
- }
- bind odef
-
- systemdict /setcolor .undef
-
-
- %
- % <name|array> <bool> _setcolorspace -
- % <name|array> _setcolorspace_nosub -
- %
- % <name|array> setcolorspace -
- % <name|array> forcesetcolorspace -
- %
- % setcolorspace is initially placed in .cspace_util. It is copied to
- % level2dict by the Level 2 initialization code. The internal
- % setcolorspace operator is removed from systemdict as soon as this
- % procedure is defined.
- %
- % Because some jobs, in particular PDF jobs, repeatedly set the same
- % color space, this procedure will check if the operand and current
- % color spaces are the same. The check is absolute for parameterless
- % color spaces, conservative for others. For PostScript, this
- % optimization can only be employed if color space substitution is
- % disabled, as otherwise there is no way to account for possible changes
- % in the /Default* instances of the ColorSpace resource category. For PDF
- % jobs, resource category instances can only be changed at very specific
- % times (typically page boundaries), so the "operand color space is the
- % same as current color space" optimization may be used even if color
- % space substitution is in effect. The optimization is also highly
- % desirable in such cases, as it greatly improves performance.
- %
- % In certain situations, it is critical that a color space be set,
- % even if it is the same as the current color space. This is the case
- % when a CIEBased color space is used as a base or alternative color
- % space, due to some long-standing problems with the graphics libraries
- % handling of sampled information from the procedures in CIE color
- % spaces and the color rendering dictionary. The forcesetcolorspace
- % operator is provided for those situations.
- %
- % Note also that, if the current color space is not reset, at least
- % the current color must be reset to its default value.
- %
- % Another problem arises in the case of ICCBased color spaces. These
- % color spaces may be used to substitute for a DeviceGray/DeviceRGB/
- % DeviceCMYK color space, and may themselves require such a color
- % space as an alternate. Obviously, when this is the case the normal
- % setcolorspace mechanism would encounter and infinite loop if the
- % alternate colro space needed to be used. For this particular case,
- % the special _setcolorspace_nosub is provided, which suppresses
- % color space substitution. This routine does not bother to check if
- % the operand and current color space are the same.
- %
- /_setcolorspace
- {
- {
- % see if the operand space is the same as the current space
- currentcolorspace dup length 1 eq
- {
- 0 get
- 2 index dup type dup /arraytype eq exch /packedarraytype eq or
- {
- dup length 1 eq
- { 0 get }
- if
- }
- if
- }
- { 2 index }
- ifelse
- eq and dup
- {
- %
- % If PDFfile is defined on the dictionary stack, this is a
- % PDF job. No additional check is required in this case (see
- % comment above).
- %
- /PDFfile where
- { pop }
- { .getuseciecolor not and } % check that UseCIEColor is off
- ifelse
- }
- if
- { //.cs_get_default_color exec setcolor }
- {
- //.cs_validate exec
- //.cs_substitute exec
- //.cs_prepare exec
- //.cs_install exec
- //make_array1 exec //setcolorspace
- }
- ifelse
- }
- stopped
- { //.cspace_util /setcolorspace get $error /errorname get signalerror }
- if
- }
- bind def
-
- /_setcolorspace_nosub
- {
- {
- //.cs_validate exec
- dup
- //.cs_prepare exec
- //.cs_install exec
- //make_array1 exec //setcolorspace
- }
- stopped
- { //.cspace_util /setcolorspace get $error /errorname get signalerror }
- if
- }
- bind def
-
- /setcolorspace { //true //_setcolorspace exec } bind odef
- /forcesetcolorspace { //false //_setcolorspace exec } bind odef
-
- %
- % - initgraphics -
- %
- % The initgraphics operator must be redefined create a real color space.
- % Previously this was unnecessary, as .currentcolorspace could return
- % an integer.
- %
- %
- /initgraphics
- { initgraphics { /DeviceGray } cvlit forcesetcolorspace }
- .bind systemdict begin odef end
-
- systemdict /setcolorspace .undef
-
-
- %
- % <gray> setgray -
- %
- % <r> <g> <b> setrgbcolor -
- %
- % <c> <m> <y> <b> setcmykcolor -
- %
- % The Level 1 color setting operators. setcmykcolor is created only if
- % setcolorscreen is present. These operators are always defined in
- % systemdict.
- %
- /setgray
- {
- { { /DeviceGray } cvlit //setcolorspace //setcolor }
- stopped
- { /setgray load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
-
- /setrgbcolor
- {
- { { /DeviceRGB } cvlit //setcolorspace //setcolor }
- stopped
- { /setrgbcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
-
- /setcolorscreen where
- {
- pop
- /setcmykcolor
- {
- { { /DeviceCMYK } cvlit //setcolorspace //setcolor }
- stopped
- { /setcmykcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
- }
- if
-
-
- %
- % - currentgray <gray>
- %
- % - currentrgbcolor <r> <g> <b>
- %
- % - currentcmykcolor <c> <m> <y> <k>
- %
- % Return the current color, mapped to a DeviceGray, DeviceRGB, or
- % DeviceCMYK color space. The latter is only created if setcolorscreen
- % is present.
- /currentgray
- { currentcolor currentcolorspace //.cs_get_currentgray exec }
- bind systemdict begin odef end
-
- /currentrgbcolor
- { currentcolor currentcolorspace //.cs_get_currentrgb exec }
- bind systemdict begin odef end
-
- /setcolorscreen where
- {
- pop
- /currentcmykcolor
- { currentcolor currentcolorspace //.cs_get_currentcmyk exec }
- bind systemdict begin odef end
- }
- if
-
-
-
- %
- % Add some generically useful structures and procedures to .cspace_util.
- %
-
- %
- % Some common errors. The command for these errors will normally be
- % overwritten by the invoking operator. We cannot "load" the secolorspace
- % or setcolor operators, as they are not present in Level 1 systems.
- %
- /setcspace_typecheck
- { /setcolorspace cvx /typecheck signalerror }
- bind def
-
- /setcspace_rangecheck
- { /setcolorspace cvx /rangecheck signalerror }
- bind def
-
- /setcspace_invalidaccess
- { /setcolorspace cvx /invalidaccess signalerror }
- bind def
-
- /setcspace_undefined
- { /setcolorspace cvx /undefined signalerror }
- bind def
-
- /setcolor_typecheck
- { /setcolor cvx /typecheck signalerror }
- bind def
-
- /setcolor_invalidaccess
- { /setcolor cvx /invalidaccess signalerror }
- bind def
-
-
- %
- % <obj> check_array <obj>
- %
- % Check that an object is an array. Currently we don't check for
- % readability, as a failing get or length operator should generate
- % the appropriate invalidaccess error.
- /check_array
- {
- dup type dup /arraytype ne exch /packedarraytype ne and
- { /setcolorspace cvx /typecheck signalerror }
- if
- }
- bind def
-
-
- % pre-defined procedures for cs_ncomps and cs_get_range
- /ncomps_1 { pop 1 } bind def
- /ncomps_3 { pop 3 } bind def
- /ncomps_4 { pop 4 } bind def
-
- /dflt_range_4 [ 0 1 0 1 0 1 0 1 ] readonly def
- /dflt_range_3 dflt_range_4 0 6 getinterval def
- /dflt_range_1 dflt_range_4 0 2 getinterval def
-
- % <obj> get_range_[1|3|4] <range>
- /get_range_1 { pop //dflt_range_1 } bind def
- /get_range_3 { pop //dflt_range_3 } bind def
- /get_range_4 { pop //dflt_range_4 } bind def
-
-
- %
- % <c1> ... <cn> <name | array> <n>
- % check_num_stack
- % <c1> ... <cn> <array | array>
- %
- % <c1> <array> validate_color_1 <c1>
- % <c1> <c2> <c3> <arraY> validate_color_3 <c1> <c2> <c3>
- % <c1> <c2> <c3> <c4> <arraY> validate_color_4 <c1> <c2> <c3> <c4>
- %
- % check_num_stack verifies that the stack consists of a color space array and
- % n numbers. This is used by most of the cs_prepare_color procedures. The
- % validate_color_[1|3|4] procedures can be used as the cs_prepare_color
- % procedure for Device specific, CIEBased, and Indexed color spaces.
- %
- % Note that the pseudo-operator that (indirectly) invokes this routine will
- % handle resetting the stacks.
- %
- /check_num_stack
- {
- dup 2 add copy exch pop
- {
- type dup /integertype ne exch /realtype ne and
- //setcolor_typecheck
- if
- }
- repeat
- pop % remove the extra op_count
- }
- bind def
-
- % <c1> <array> validate_1 <c1>
- /validate_1 { 1 //check_num_stack exec pop } bind def
-
- % <c1> <c2> <c3> <array> validate_3 <c1> <c2> <c3>
- /validate_3 { 3 //check_num_stack exec pop } bind def
-
- % <c1> <c2> <c3> <c4> <array> validate_4 <c1> <c2> <c3> <c4>
- /validate_4 { 4 //check_num_stack exec pop } bind def
-
-
- %
- % <obj> pop_1 -
- %
- % This is a procedure form of pop. It may be used where a procedure is
- % expected, but the function of the procedure is the same as the pop
- % operator.
- /pop_1 { pop } bind def
-
- %
- % <obj> dup_1 <obj> <obj>
- %
- % An analog to pop_1, this one for dup.
- %
- /dup_1 { dup } bind def
-
- %
- % <obj1> ... <objn> <n> clear_n_objs -
- %
- % Clear n objects from the operand stack.
- %
- /clear_n_objs { //pop_1 repeat } bind def
-
- %
- % <obj1> ... <objn> <array> clear_setcolor_operands -
- %
- % Clear the setcolor operands for a color space.
- %
- /clear_setcolor_operands
- { //.cs_get_ncomps exec //clear_n_objs exec }
- bind def
-
- %
- % Return 1, 3, or 4 zeros. These routines are used primarily for the
- % CIEBased color spaces, for which currentgray and currentrgb
- % should return 0 for all components, and currentcmyk should return
- % 0 0 0 1.0 (this varies from Adobe's documentation but is consistent
- % with their impelementations).
- %
- /no_currentgray { //.cs_get_ncomps exec //clear_n_objs exec 0 } bind def
- /no_currentrgb { //.cs_get_ncomps exec //clear_n_objs exec 0 0 0 } bind def
- /no_currentcmyk { //.cs_get_ncomps exec //clear_n_objs exec 0 0 0 1.0 } bind def
-
-
- %
- % <num> bound_0_1 <num>
- %
- % Bound a number to the range [0, 1]
- %
- /bound_0_1
- {
- dup 0 lt
- { pop 0 }
- {
- dup 1 gt
- { pop 1 }
- if
- }
- ifelse
- }
- bind def
-
-
- %
- % Provide pseudo-operators for sethsbcolor and currenthsbcolor. These are
- % alternate versions of the setrgbcolor and currentrgbcolor operators, which
- % make use of a hue/staturation/brightness color description.
- %
-
- %
- % <num_1> ... <num_n> n max_n <num>
- % <num_1> ... <num_n> n min_n <num>
- %
- % Find the maximum and minum of 3 color component intensities.
- %
- /max_n
- {
- 1 sub
- { 2 copy lt { exch } if pop }
- repeat
- }
- bind def
-
- /min_n
- {
- 1 sub
- { 2 copy gt { exch } if pop }
- repeat
- }
- bind def
-
-
- %
- % <r> <g> <b> .rgb_2_hsb <h> <s> <br>
- % <h> <s> <br> .hsb_2_rgb <r> <g> <b>
- %
- % Convert between RGB and HSB colors, using the hexcone approach (see
- % Rogers, David, "Procedureal Elements For Computer Graphics",
- % (McGraw-Hill, 1985), pp. 402 - 3).
- %
- % The rgb ==> hsb calculation is:
- %
- % br = max(r, g, b)
- %
- % if (br == 0)
- % h = 0, s = 0;
- % else {
- % v = min(r, g, b)
- % diff = br - v;
- % sat = diff / br;
- % if (r == br)
- % h = (g - b) / (6 * diff) + (b > g ? 1 : 0);
- % else if (g == br)
- % h = 1/3 + (b - r) / (6 * diff);
- % else /* b == br */
- % h = 2/3 + (r - g) / (6 * diff);
- % }
- %
- % The hsb ==> rgb conversion is:
- %
- % mn = (1 - s) * br, md = 6 * s * br;
- %
- % switch ((int)floor(6 * h)) {
- % case 0: /* r >= g >= b */
- % r = br;
- % g = mn + h * md;
- % b = mn;
- % break;
- %
- % case 1: /* g >= r >= b */
- % r = mn + md * (1/3 - h);
- % g = br;
- % b = mn;
- % break;
- %
- % case 2: /* g >= b >= r */
- % r = mn;
- % g = br;
- % b = mn + (h - 1/3) * md;
- % break;
- %
- % case 3: /* b >= g >= r */
- % r = mn;
- % g = mn + (2/3 - h) * md;
- % b = br;
- % break;
- %
- % case 4: /* b >= r >= g */
- % r = mn + (h - 2/3) * md;
- % g = mn;
- % b = br;
- % break;
- %
- % case 5: /* r >= b >= g */
- % r = br;
- % g = mn;
- % b = mn + (1 - h) * md;
- % break;
- %
- % case 6: /* We have wrapped around the hexcone. Thus this case is
- % the same as case 0 with h = 0 */
- % h = 0;
- % r = br;
- % g = mn + h * md = mn;
- % b = mn;
- % break;
- % }
- %
- /.rgb_2_hsb
- {
- % find the largest and smallest components
- 3 copy 3 //max_n exec dup 5 1 roll
- dup 0 eq
- { pop pop pop pop 0 0 }
- {
- 4 copy pop 3 //min_n exec 1 index exch sub
- dup 2 index div 7 1 roll
- dup 0 eq
- { 5 { pop } repeat 0 3 1 roll }
- {
- 6 mul 5 1 roll
- 2 copy eq % blue == brightness
- { pop pop sub exch div .666667 add }
- {
- 2 index eq % green == brightness
- { exch pop exch sub exch div .3333333 add }
- {
- % red == brightness
- sub exch pop exch div
- dup 0 lt
- { 1 add }
- if
- }
- ifelse
- }
- ifelse
- 3 1 roll
- }
- ifelse
- }
- ifelse
- }
- bind def
-
-
- /.hsb_2_rgb
- {
- 3 { 0 max 1 min 3 1 roll } repeat
- 1 2 index sub 1 index mul % (1 - s) * br
- 3 -1 roll 2 index mul 6 mul % 6 * s * br
- 4 -1 roll % stack: <br> <(1 - s) * br> <6 * s * br> <h>
-
- % array of procedures for the 7 hue cases
- {
- % 0 ==> r >= g >= b
- { mul 1 index add exch }
-
- % 1 ==> g >= r >= b
- { 0.333333 exch sub mul 1 index add 3 1 roll }
-
- % 2 ==> g >= b >= r
- { 0.333333 sub mul 1 index add 3 1 roll exch 3 -1 roll }
-
- % 3 ==> b >= g >= r
- { 0.666667 exch sub mul 1 index add 3 -1 roll }
-
- % 4 ==> b >= r >= g
- { 0.666667 sub mul 1 index add 3 1 roll exch }
-
- % 5 ==> r >= b >= g
- { 1 exch sub mul 1 index add }
-
- % 6 ==> r = br, g = b = mn
- % Case 6 is the same as case 0 with h = 0. This also simplifies
- % the calculations.
- { pop pop dup }
- }
- 1 index 6 mul cvi % (int)(6 * h)
- get exec
- }
- bind def
-
-
- %
- % <hue> <saturation> <brightness sethsbcolor -
- %
- % - currenthsbcolor <hue> <saturation> <brightness>
- %
- /sethsbcolor
- {
- { //.hsb_2_rgb exec setrgbcolor }
- stopped
- { /sethsbcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
-
- /currenthsbcolor
- {
- { currentrgbcolor //.rgb_2_hsb exec }
- stopped
- { /currenthsbcolor load $error /errorname get signalerror }
- if
- }
- bind systemdict begin odef end
-
- end % .cspace_util
- .setglobal
-