<?xml version="1.0"?>
<!DOCTYPE riscos-prm PUBLIC "-//Gerph//DTD PRM documentation 1.03//EN"
                            "http://gerph.org/dtd/103/prm.dtd">

<riscos-prm>
<chapter title="ColourMap">

<section title="Introduction and Overview">
<p>
The ColourMap module provides an interface for constructing combinations of colour
mapping functions, as used by SpriteExtend, DrawFile and others. These functions
allow colours within images to be manipulated to affect their rendering.
</p>
<p>
Typical uses for colour mapping include highlighting or fading graphical elements,
as used within the Window Manager. The colour mapping is performed through a colour
mapping descriptor -- a function pointer and workspace pair which are used to
translate colours. The ColourMap module provides descriptors for commonly used
colour operations, allowing clients to perform mappings without needing to provide
their own implementations.
</p>
<p>
Multiple colour mapping operations may be chained together: each operation in the
chain is applied in turn to produce the final result.
</p>
</section>

<section title="Technical Details">

<subsection title="Sequence of operations">
<p>
The normal sequence of operations to create and use a colour mapping descriptor is:
</p>
<p>
<list type='ordered'>
 <item>Call <reference type='swi' name='ColourMap_Start'/>, passing R1 = 0, to read
       the initial size of the workspace required.</item>
 <item>Allocate a workspace block of at least the size returned.</item>
 <item>Call <reference type='swi' name='ColourMap_Start'/> again, passing the workspace
       pointer and its size in R1 and R2, to initialise the workspace.</item>
 <item>Call <reference type='swi' name='ColourMap_ApplyMapping'/> with the desired
       mapping type and parameters.</item>
 <item>If an error occurs and R2 is returned as a negative value, the workspace was too
       small. Reallocate the workspace to the size indicated (negated), reinitialise it
       with <reference type='swi' name='ColourMap_Start'/>, and re-apply all mappings.
       If R2 is positive on error, the error relates to the mapping itself.</item>
 <item>Repeat calling <reference type='swi' name='ColourMap_ApplyMapping'/> to add
       further mappings, as needed.</item>
 <item>Call <reference type='swi' name='ColourMap_End'/> to obtain a colour mapping
       descriptor suitable for use with DrawFile, SpriteExtend, or other clients.</item>
 <item>Release the workspace once colour mapping is no longer required.</item>
</list>
</p>
</subsection>

<subsection title="Workspace properties">
<p>
The workspace block is provided by the client. Its required size can be determined by
calling <reference type='swi' name='ColourMap_Start'/> with R1 = 0. Providing a larger
workspace than the minimum will reduce the likelihood of reallocation requests being
returned from subsequent <reference type='swi' name='ColourMap_ApplyMapping'/> calls.
</p>
<p>
During the construction phase (between <reference type='swi' name='ColourMap_Start'/>
and <reference type='swi' name='ColourMap_End'/>), the workspace may be freely relocated
in memory by the client, as the ColourMap module holds no direct references to it during
this phase. However, once <reference type='swi' name='ColourMap_End'/> has been called,
the workspace must remain at a fixed address. The descriptor returned contains a direct
pointer into the workspace; relocating the workspace after this point will invalidate the
descriptor.
</p>
<p>
If the workspace must be moved after <reference type='swi' name='ColourMap_End'/> has
been called, call <reference type='swi' name='ColourMap_End'/> again at the new location
to obtain a fresh, valid descriptor.
</p>
<p>
The client may release the workspace memory once the colour mappings it provides are no
longer required. The ColourMap module holds no references to the workspace after use.
Multiple independent clients may use the ColourMap module simultaneously.
</p>
<p>
If the ColourMap module is killed or reinitialised, any descriptors previously returned
by <reference type='swi' name='ColourMap_End'/> may become invalid.
</p>
<p>
The workspace requirement for any given set of mappings remains constant regardless of
the parameters supplied to those mappings. This allows clients to reuse workspace blocks
for similar mappings without relocation.
</p>
<p>
The workspace format may change between versions of the module. Workspace blocks must
not be stored in persistent storage, such as data files or embedded within applications.
</p>
<p>
No executable code is placed within the workspace, so it may be located outside the
26-bit executable address range.
</p>
</subsection>

<subsection title="Workspace format">
<p>
The internal layout of the workspace is shown below. Clients should treat the workspace
as opaque and must not modify it directly.
</p>
<p>
<offset-table>
 <offset number="0">Magic word (&hex;9072340E), used to validate the workspace</offset>
 <offset number="4">Size of workspace currently used, in bytes</offset>
 <offset number="8">Colour mapping descriptor: workspace pointer (or 0 if not yet valid)</offset>
 <offset number="12">Colour mapping descriptor: function pointer (or 0 if not yet valid)</offset>
 <offset number="16">First mapping entry (see below); further entries follow contiguously</offset>
</offset-table>
</p>
<p>
Each mapping entry within the workspace has the following layout:
</p>
<p>
<offset-table>
 <offset number="0">Mapping type (a <reference type='subsection' name='Mapping types'/> value), or -1 to mark the end of the list</offset>
 <offset number="4">Size of the mapping's workspace data, in bytes</offset>
 <offset number="8">Function pointer for this mapping (filled in by <reference type='swi' name='ColourMap_End'/>)</offset>
 <offset number="12">Mapping-specific workspace data</offset>
</offset-table>
</p>
</subsection>

<subsection title="Colour mapping descriptor">
<p>
The colour mapping descriptor is a two-word block returned by
<reference type='swi' name='ColourMap_End'/>. It may be passed directly to interfaces
such as SpriteExtend and DrawFile which accept a colour mapping descriptor pointer.
</p>
<p>
<offset-table>
 <offset number="0">Pointer to the workspace for this mapping</offset>
 <offset number="4">Pointer to the function that applies this mapping</offset>
</offset-table>
</p>
<p>
The descriptor is valid only while the workspace remains at its current address and the
ColourMap module remains loaded.
</p>
</subsection>

<subsection title="Mapping types">
<p>
The following mapping types are recognised by ColourMap_ApplyMapping. The type value is
supplied in bits 0-7 of R0.
</p>
<p>
<value-table head-number="Type" head-value="Description">
 <value number="0"><reference type='swi' name='ColourMap_ApplyMapping' reason='0' use-description='yes'/></value>
 <value number="1"><reference type='swi' name='ColourMap_ApplyMapping' reason='1' use-description='yes'/></value>
 <value number="2"><reference type='swi' name='ColourMap_ApplyMapping' reason='2' use-description='yes'/></value>
 <value number="3"><reference type='swi' name='ColourMap_ApplyMapping' reason='3' use-description='yes'/></value>
 <value number="4"><reference type='swi' name='ColourMap_ApplyMapping' reason='4' use-description='yes'/></value>
 <value number="5"><reference type='swi' name='ColourMap_ApplyMapping' reason='5' use-description='yes'/></value>
 <value number="6"><reference type='swi' name='ColourMap_ApplyMapping' reason='6' use-description='yes'/></value>
 <value number="7"><reference type='swi' name='ColourMap_ApplyMapping' reason='7' use-description='yes'/></value>
 <value number="8"><reference type='swi' name='ColourMap_ApplyMapping' reason='8' use-description='yes'/></value>
</value-table>
</p>
</subsection>

<subsection title="Colour format">
<p>
Colours supplied to ColourMap SWIs and returned by them use the RISC OS 32-bit colour
word format:
</p>
<p>
<offset-table>
 <offset number="0">Blue component (bits 24-31 of word, i.e. bits 7-0 at byte offset 3)</offset>
 <offset number="1">Green component</offset>
 <offset number="2">Red component</offset>
 <offset number="3">Always 0 (unused)</offset>
</offset-table>
</p>
<p>
In hexadecimal notation this is written as &hex;BBGGRR00.
</p>
</subsection>

</section>


<section title="SWI calls">

<!-- ColourMap_Start -->
<swi-definition name="ColourMap_Start"
                number="567C0"
                description="Initialise a ColourMap workspace block, or read the minimum workspace size"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">
<entry>
 <register-use number="0">Flags (reserved, must be 0)</register-use>
 <register-use number="1">Pointer to the workspace block, or 0 to read the minimum required size</register-use>
 <register-use number="2">Size of the workspace block, in bytes (ignored if R1 = 0)</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">If called with R1 = 0: minimum workspace size required (positive).
                          If called with a workspace pointer: size of workspace used (positive).</register-use>
</exit>

<use>
<p>
This SWI initialises a block of memory for use as a ColourMap workspace, or returns
the minimum size required for such a block.
</p>
<p>
When called with R1 = 0, the minimum workspace size is returned in R2. This is the size
needed to hold the standard mapping header and at least one instance of the most common
mapping (blend to colour). Allocating a larger workspace will reduce the chance of
reallocation being requested by subsequent
<reference type='swi' name='ColourMap_ApplyMapping'/> calls.
</p>
<p>
When called with R1 pointing to an allocated block, the workspace is initialised ready
for mappings to be added. If the workspace is too small, an
<reference type='error' name='ColourMap_NotEnoughWorkspace'/> error is returned and R2
is set to the negative of the size required.
</p>
</use>

<related>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
 <reference type='swi' name='ColourMap_End'/>
</related>
</swi-definition>


<!-- ColourMap_ApplyMapping overview -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                description="Add a colour mapping operation to the workspace"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">
<entry>
 <register-use number="0">
  <p>Flags and mapping type:</p>
  <p>
  <bitfield-table>
   <bit number="0-7" name="Type">
    Mapping type:
    <value-table head-number="Type" head-value="Mapping">
     <value number="0"><reference type='swi' name='ColourMap_ApplyMapping' reason='0' use-description='yes'/></value>
     <value number="1"><reference type='swi' name='ColourMap_ApplyMapping' reason='1' use-description='yes'/></value>
     <value number="2"><reference type='swi' name='ColourMap_ApplyMapping' reason='2' use-description='yes'/></value>
     <value number="3"><reference type='swi' name='ColourMap_ApplyMapping' reason='3' use-description='yes'/></value>
     <value number="4"><reference type='swi' name='ColourMap_ApplyMapping' reason='4' use-description='yes'/></value>
     <value number="5"><reference type='swi' name='ColourMap_ApplyMapping' reason='5' use-description='yes'/></value>
     <value number="6"><reference type='swi' name='ColourMap_ApplyMapping' reason='6' use-description='yes'/></value>
     <value number="7"><reference type='swi' name='ColourMap_ApplyMapping' reason='7' use-description='yes'/></value>
     <value number="8"><reference type='swi' name='ColourMap_ApplyMapping' reason='8' use-description='yes'/></value>
    </value-table>
   </bit>
   <bit number="8-31" state="reserved">Reserved; must be 0</bit>
  </bitfield-table>
  </p>
 </register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">Dependent on mapping type (see below)</register-use>
 <register-use number="4">Dependent on mapping type (see below)</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">If workspace was too small: negative value giving the required workspace size.
                          Otherwise preserved.</register-use>
</exit>

<use>
<p>
This SWI appends a colour mapping operation to those already held in the workspace.
Mappings are applied in the order they were added when
<reference type='swi' name='ColourMap_End'/> constructs the final descriptor.
</p>
<p>
If the workspace is too small to accommodate the new mapping, a
<reference type='error' name='ColourMap_NotEnoughWorkspace'/> error is returned and R2
is set to the negative of the total workspace size required. The client should
reallocate the workspace to that size, reinitialise it with
<reference type='swi' name='ColourMap_Start'/>, and re-apply all mappings.
</p>
<p>
See the per-reason entries below for the specific register usage and behaviour of each
mapping type.
</p>
</use>

<related>
 <reference type='swi' name='ColourMap_Start'/>
 <reference type='swi' name='ColourMap_End'/>
</related>
</swi-definition>

<!-- Reason 0: Blend -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="0"
                reasonname="Blend"
                description="Blend the colour towards a target colour">
<entry>
 <register-use number="0">0 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">Target colour (&hex;BBGGRR00)</register-use>
 <register-use number="4">Blend factor: 0 for fully source colour, &hex;FF for fully target colour</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
Each colour component (red, green and blue) is blended linearly between the source pixel
colour and the target colour according to the blend factor. A factor of 0 leaves the
source colour unchanged; a factor of &hex;FF replaces the source colour entirely with
the target colour.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='4'/>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='5'/>
</related>
</swi-definition>

<!-- Reason 1: User -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="1"
                reasonname="User"
                description="Apply a user-supplied colour mapping descriptor">
<entry>
 <register-use number="0">1 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">Pointer to a colour mapping descriptor; a copy is taken</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
Chains a standard colour mapping descriptor into the mapping sequence. A copy of the
descriptor is taken at the time of the call, so the original descriptor need not remain
valid after the call returns. This allows multiple mapping functions to be composed
together.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_End'/>
</related>
</swi-definition>

<!-- Reason 2: Identity -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="2"
                reasonname="Identity"
                description="Apply no transformation (identity mapping)">
<entry>
 <register-use number="0">2 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
The identity mapping passes colours through unchanged. This is rarely useful in
practice but is provided for completeness.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
</related>
</swi-definition>

<!-- Reason 3: Invert -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="3"
                reasonname="Invert"
                description="Invert each colour component">
<entry>
 <register-use number="0">3 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
Each colour component is replaced by its bitwise complement, giving a photographic
negative effect. A component value of 0 becomes &hex;FF, and vice versa.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
</related>
</swi-definition>

<!-- Reason 4: Monochrome -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="4"
                reasonname="Monochrome"
                description="Convert colour to greyscale">
<entry>
 <register-use number="0">4 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
The colour is converted to a luminance-weighted greyscale using the standard
coefficients for red, green and blue. The result is a neutral grey with equal red,
green and blue components.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='5'/>
</related>
</swi-definition>

<!-- Reason 5: MonoScale -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="5"
                reasonname="MonoScale"
                description="Convert colour to greyscale and scale to a colour range">
<entry>
 <register-use number="0">5 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">'Black' colour: the output colour corresponding to a luminance of 0 (&hex;BBGGRR00)</register-use>
 <register-use number="4">'White' colour: the output colour corresponding to a luminance of &hex;FF (&hex;BBGGRR00)</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
The colour is first converted to a greyscale luminance value (0-255) using the
same method as <reference type='swi' name='ColourMap_ApplyMapping' reason='4'/>.
Each component of the output colour is then linearly interpolated between the
corresponding component of the 'black' colour and the 'white' colour according to the
luminance. This allows, for example, converting an image to a blue-scale (setting the
'black' colour to dark blue and the 'white' colour to light blue).
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='4'/>
</related>
</swi-definition>

<!-- Reason 6: Gamma -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="6"
                reasonname="Gamma"
                description="Apply gamma correction to each colour component">
<entry>
 <register-use number="0">6 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">Gamma level &times; 256 (valid range 0-1024, representing 0.0-4.0)</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
Applies gamma correction to each colour component. The correction maps the linear
component values through a logarithmic curve whose shape is determined by the gamma
level. The correction is stored as a 256-entry lookup table in the workspace.
</p>
<p>
A gamma level of 256 (1.0) produces no change. Values below 256 darken the image;
values above 256 lighten it.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='7'/>
</related>
</swi-definition>

<!-- Reason 7: Contrast -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="7"
                reasonname="Contrast"
                description="Increase or decrease the contrast of the image">
<entry>
 <register-use number="0">7 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">Contrast factor &times; 256 (valid range 0-1024, representing 0.0-4.0)</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
Adjusts the contrast of each colour component using a lookup table. A factor of 256
(1.0) leaves the image unchanged. Factors above 256 expand the range of component
values, increasing contrast; factors below 256 compress the range, decreasing contrast.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='6'/>
</related>
</swi-definition>

<!-- Reason 8: Brightness -->
<swi-definition name="ColourMap_ApplyMapping"
                number="567C1"
                reason="8"
                reasonname="Brightness"
                description="Add a fixed offset to each colour component">
<entry>
 <register-use number="0">8 (mapping type)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
 <register-use number="3">Value to add to each component (-256 to +256)</register-use>
</entry>
<exit>
 <register-use number="0" state="preserved"/>
 <register-use number="1" state="preserved"/>
 <register-use number="2">Negative required workspace size on out-of-memory error; otherwise preserved</register-use>
</exit>
<use>
<p>
Adds the given value to each of the red, green and blue components independently,
brightening or darkening the image uniformly. Component values are clamped to the
range 0-255.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='6'/>
 <reference type='swi' name='ColourMap_ApplyMapping' reason='7'/>
</related>
</swi-definition>


<!-- ColourMap_End -->
<swi-definition name="ColourMap_End"
                number="567C2"
                description="Obtain the colour mapping descriptor from the workspace"
                irqs="undefined"
                fiqs="enabled"
                processor-mode="SVC"
                re-entrant="no">
<entry>
 <register-use number="0">Flags (reserved, must be 0)</register-use>
 <register-use number="1">Pointer to the workspace block</register-use>
 <register-use number="2">Size of the workspace block, in bytes</register-use>
</entry>
<exit>
 <register-use number="0">Pointer to the colour mapping descriptor, or 0 if no mappings are held in the workspace</register-use>
 <register-use number="1" state="preserved"/>
 <register-use number="2" state="preserved"/>
</exit>

<use>
<p>
This SWI constructs and returns a colour mapping descriptor representing all the
mappings currently held in the workspace. The descriptor may be passed directly to
interfaces such as SpriteExtend or DrawFile that accept colour mapping descriptors.
</p>
<p>
If no mappings have been added to the workspace, 0 is returned in R0 to indicate that
no colour mapping is needed.
</p>
<p>
Once this call has been made, the workspace must not be relocated or modified. If the
workspace is moved or further mappings are applied, this SWI must be called again to
obtain a new valid descriptor.
</p>
<p>
The returned descriptor points into the workspace. The descriptor becomes invalid if
the workspace is freed or the ColourMap module is killed.
</p>
</use>

<related>
 <reference type='swi' name='ColourMap_Start'/>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
</related>
</swi-definition>

</section>


<section title="Error messages">
<p>
The ColourMap module uses error base &hex;81AC00.
</p>

<error-definition name="ColourMap_NotEnoughWorkspace"
                  number="81AC00"
                  description="Not enough memory in the ColourMap workspace">
<use>
<p>
Returned by <reference type='swi' name='ColourMap_Start'/> or
<reference type='swi' name='ColourMap_ApplyMapping'/> when the workspace provided is
too small. R2 is set to the negative of the workspace size required, allowing the
client to reallocate the workspace and retry.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_Start'/>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
</related>
</error-definition>

<error-definition name="ColourMap_WorkspaceCorrupt"
                  number="81AC01"
                  description="ColourMap workspace corrupt">
<use>
<p>
Returned when the workspace block supplied to a SWI does not contain a valid magic
number, or when the reported workspace size is inconsistent with the block. This
typically indicates that the wrong pointer or size was supplied, or that the workspace
was overwritten by the client.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
 <reference type='swi' name='ColourMap_End'/>
</related>
</error-definition>

<error-definition name="ColourMap_BadFlags"
                  number="81AC02"
                  description="Reserved bits set in flags to ColourMap module">
<use>
<p>
Returned when any reserved flag bits (bits 8-31 of R0 for
<reference type='swi' name='ColourMap_ApplyMapping'/>, or any bits in R0 for
<reference type='swi' name='ColourMap_Start'/>) are set to non-zero values.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_Start'/>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
</related>
</error-definition>

<error-definition name="ColourMap_BadMappingType"
                  number="81AC03"
                  description="Mapping type not recognised by the ColourMap module">
<use>
<p>
Returned by <reference type='swi' name='ColourMap_ApplyMapping'/> when the mapping
type supplied in bits 0-7 of R0 is not one of the types supported by the
module.
</p>
</use>
<related>
 <reference type='swi' name='ColourMap_ApplyMapping'/>
</related>
</error-definition>

</section>


<section title="Examples">
<p>
The following example in C illustrates the typical usage sequence to create a
descriptor that blends towards a red colour at 50% and then desaturates the result
to greyscale.
</p>
<p>
<extended-example type='c'>
#include "modhead.h" /* For SWI definitions */

_kernel_oserror *apply_blend_and_mono(void **desc_out)
{
    _kernel_swi_regs r;
    _kernel_oserror *err;
    char *workspace = NULL;
    int wssize;

    /* Step 1: query the minimum workspace size */
    r.r[0] = 0;
    r.r[1] = 0;
    r.r[2] = 0;
    err = _kernel_swi(ColourMap_Start, &amp;r, &amp;r);
    if (err) return err;
    wssize = -r.r[2]; /* returned as negative on size query */

    /* Step 2: allocate the workspace */
    workspace = malloc(wssize);
    if (!workspace) return /* out of memory error */;

retry:
    /* Step 3: initialise the workspace */
    r.r[0] = 0;
    r.r[1] = (int)workspace;
    r.r[2] = wssize;
    err = _kernel_swi(ColourMap_Start, &amp;r, &amp;r);
    if (err) goto fail;

    /* Step 4: apply a 50% blend towards red (&amp;000000FF = red in BBGGRR00) */
    r.r[0] = 0; /* type = Blend */
    r.r[1] = (int)workspace;
    r.r[2] = wssize;
    r.r[3] = 0x000000FF; /* red */
    r.r[4] = 0x80;       /* 50% blend */
    err = _kernel_swi(ColourMap_ApplyMapping, &amp;r, &amp;r);
    if (err)
    {
        if (r.r[2] &lt; 0)
        {
            /* workspace too small: grow and retry */
            wssize = -r.r[2];
            free(workspace);
            workspace = malloc(wssize);
            if (!workspace) return /* out of memory error */;
            goto retry;
        }
        goto fail;
    }

    /* Step 5: apply a monochrome conversion */
    r.r[0] = 4; /* type = Monochrome */
    r.r[1] = (int)workspace;
    r.r[2] = wssize;
    err = _kernel_swi(ColourMap_ApplyMapping, &amp;r, &amp;r);
    if (err) goto fail;

    /* Step 6: obtain the colour mapping descriptor */
    r.r[0] = 0;
    r.r[1] = (int)workspace;
    r.r[2] = wssize;
    err = _kernel_swi(ColourMap_End, &amp;r, &amp;r);
    if (err) goto fail;

    *desc_out = (void *)r.r[0];
    return NULL;

fail:
    free(workspace);
    return err;
}
</extended-example>
</p>
</section>

</chapter>

<meta>
 <maintainer>
  <email name="Gerph" address="gerph@gerph.org"/>
 </maintainer>
 <disclaimer>
  <p>
   &copy; Justin Fletcher. MIT licence.
  </p>
 </disclaimer>
 <history>
  <revision number="1" author="JF" date="16 Jan 2003" title="Initial version">
   <change>Initial documentation for the ColourMap module.</change>
  </revision>
  <revision number="2" author="Gerph" date="20 May 2026" title="PRM-in-XML conversion">
   <change>Converted documentation from plain text to PRM-in-XML format.</change>
  </revision>
 </history>
 <related>
  <reference type='link' href='?' name='SpriteExtend'/>
  <reference type='link' href='?' name='DrawFile'/>
 </related>
</meta>
</riscos-prm>
