Introduction and Overview
A number of graphics formats are supported natively by RISC OS. JPEG, DrawFiles and Sprites are directly renderable, and PNGs are supported through a number of conversion calls. Each of these formats, however, is rendered using slightly different calls. The ImageFileRender module simplifies rendering these (and potentially other third party) image files.
All graphics formats have two things in common :
- They cover a region (even empty files must say what space they cover).
- They have a resolution at which they are drawn.
The region they cover is known as the 'bounding box'. For many graphics formats, this will be aligned with the origin - for example a bitmap graphic. For others, this bounding box may be elsewhere in the image - for example vector formats such as DrawFiles.
The resolution at which they have been drawn describes how accurately the images is stored. Usually this is stored in 'dots per inch' (DPI) along with the image itself. Screen resolution is usually - this depends on the eigenfactors for the screen mode in use - treated as 90 DPI. Some formats may use much more accurate internal representations than this; for example DrawFiles are stored at 2048 DPI.
For the purposes of rendering the image file, we ignore the colour depth because the rendering process will generate its results in the most accurate manner possible for output depth.
Images may be rendered using a number of transformation types, allowing them to be rendered to fit a region, to a scale, or using a more general transformation.
Within each image file there may be a number of individual images. These can be accessed by a sequence number which indicates their logical location within the file. The images may be related - as would be the case with frames of an animation - or they may be unrelated - as would be the case with a collection of resources.
When accessing images, additional information may be provided to the renderer which may perform specific operation on the image. This extra data is specific to the renderer and cannot be handled generically.
Technical Details
Sequence numbers
Graphics files may contain multiple logical images which may either be frames of an animation, alternate versions, or other image resources. These images are accessed through a sequence number which must be supplied to all images. A sequence number of 0 will render the 'default' image within the file. This may be the first image in some formats, the last in others, or some arbitrary image. A sequence number higher than that of the last image should be treated as the last image. A sequence number of 1 indicates the first image should be processed.
Rendering quality
Image files may contain data which is more accurate than can be represented by the display. This is usually the case for bitmap images at high colour depths and almost always the case for bitmap images. In order to allow some control over the quality of the rendered image (and usually the rendering speed) a 'quality' parameter can be provided to the renderer. This is a value from 1 to a renderer specific limit (with a maximum of 15) and will be bounded to the maximum that the renderer supports. Thus, if the highest quality is required, a value of 15 should be supplied. If the lowest quality is required, a value of 1 should be supplied. In the majority of cases, however, the 'default' will be required. This is a value which the renderer feels is suitable for most operations and does not require excessive processing to complete. To request the default quality, a value of 0 should be specified as the quality.
Transformation types
Graphics files may be transformed in a number of ways. This allows us to provide a simpler interface for rendering based on the requirements of the application. At present, there are three transformation types provided by the module:
Value | Meaning |
---|---|
0 | Render to fit |
1 | Render scaled |
2 | Render transformed |
For all rendering types an x and y origin are supplied from which all operations will be based. This allows the same details to be used for the fit, scale or transform regardless of the images location on the screen.
Render to fit
When rendering to fit, a width and height must be supplied by the application. The image file will be scaled to fit within this region. In addition, a border and angle may be provided to specify an area around the image which should be left clear, and to specify the angle through which the image should be rotated.
Rotation is performed anti-clockwise. The centre of the rotation is not strictly relevant to this operation because the image is always scaled to fit the width and height supplied.
The 'fit' block has the following structure:
Offset | Contents |
---|---|
0 | width (in OS units) |
4 | height (in OS units) |
8 | border (to apply to all edges) |
12 | angle (in degrees clockwise, as a 16.16 fixed point value) |
As the shape is scaled to fit the size specified, the point about which rotation occurs is not important. It can be considered to be the centre of the image.
Render scaled
When rendering scaled, a pair of multiplication and division factors should be supplied which describe the scale at which the image should be rendered. The scale block is a standard RISC OS scale block (as used by SpriteExtend)
The scaling block has the following structure :
Offset | Contents |
---|---|
0 | X multiplication factor |
4 | Y multiplication factor |
8 | X division factor |
12 | Y division factor |
Render transformed
Rendering images through a transformation matrix is the most flexible method of rendering that the ImageFileRender module provides. Transformation matrices are provided in standard RISC OS tranformation blocks (as used by SpriteExtend, Draw, DrawFile and others).
The transformation has the following structure:
Offset | Contents |
---|---|
0 | m00 |
4 | m10 |
8 | m01 |
12 | m11 |
16 | m20 |
20 | m21 |
where the matrix is constructed:
{ m00, m01, 0 }
{ m10, m11, 0 }
{ m20, m21, 1 }
m00, m01, m10, and m11 are 16.16 fixed point values.
m20 and m21 are 24.8 fixed point values.
Arbitrary transformations
Not all image formats support arbitrary transformations. Because of this, certain formats will be unable to render when a complex transformation is in use. A typical example of such limitations is that of JPEGs. The internal renderer can only render JPEGs as a scaled object. If rotation, or other complex transformations are applied to files which are not capable of those transformations, an error will be returned.
Clipping
All images will be clipped to the standard graphics rectangles. If an image must not pass outside a region, a graphics window should be used. This can be set through a VDU 24 sequence.
Image file origins
Whilst most images are based at the origin, some images will have a bounding box which are not. When the image is rendered 'to fit', the image origin is implicitly ignored. When scaling and transforming however, the origin is maintained and will be scaled with the image itself. Because this can make manipulating such images more complex, this origin offset can be negated by the ImageFileRender module. In this mode, the image can be treated as if it does not have any offset from the origin.
Colour mapping
In order to provide highlighting and other colour manipulation on the image, the ImageFileRender module can use colour mapping functions (as used by SpriteExtend, DrawFile, and ColourTrans). These allow the colours in the image to be manipulated to provide effects such as highlighting or shading.
Extensions for more complex colour mapping
The operations that can be provided in a generic manner by the ImageFileRender module do not cover the full range of operations that might be applied to every image file format. Because of this, extension data may be provided which is specific to the renderer in use. Because each renderer may provide specific data to enable it to render images, and there may be multiple providers of rendering facilities, a 'magic' identifier is allocated to each renderer. This is ensures the the renderer is not given data in a form which it does not understand.
Where a magic identifier is supplied and a suitable renderer is available, it will be used. If no suitable renderer can be found, the last registered renderer will be used. This ensures that the where extension data is used it is passed to the appropriate renderer, and falls back to using the most recent renderer installed.
The extension data block must be word aligned, and the first word contains the magic identifier for the render that it is intended for. The remainder of the extension data block is specific to the renderer in use.
The magic identifier may be any 32bit value, but we recommend that these are registered with RISCOS Ltd to ensure that there are no duplicated identifiers. At present, allocations are of the form &6699ccii, where cc indicates the company or individual producing the renderer, and ii is some image format number at the company or individual's discretion.
Sprite file extensions
When rendering sprite files, by default the first sprite is rendered from the file. This covers the majority of the situations that it will be required, but where different sprites are required, the extension block describes which to use. The identifier for the RISCOS Ltd sprite renderer is &66990101. The named sprite will only be used when the sequence number is left as 'default'.
Offset | Contents |
---|---|
0 | &66990101 |
4 | Sprite name, up to 12 characters |
Renderers
Custom renderers
Custom renderers may be registered with the ImageFileRender module. These renderers can provided additional rendering facilities for third party filetypes, or provide additional facilities over those of the standard renderers.
Renderers have four components:
- A routine which calculates the bounding box and resolution of an image
- A routine which renders an image
- A routine which declares fonts in a document (may be omitted)
- A routine which returns information about an image
In addition, they provide a number of informational fields which describe the renderer's capabilities:
- The filetype that the renderer applies to
- The name of the renderer (including the version and author)
- A flags word that describes the renderers capabilities
- The renderers 'magic' identifier (or 0 if it provides no special operations)
Renderer name
The renderer name provides details about the renderer in order that diagnostics may be performed and information about the installed renderers is available. The renderer name consists of three, tab (ASCII 9) separated, fields:
- The renderer name
- The version number in the form x.xx
- The authors (or publishers) name
Renderer flags
Not all renderers have the same capabilities, as stated earlier. The flags provide details to ImageFileRender of the capabilities of the renderer. This is a bit field, structured:
Bit(s) | Meaning | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
0-1 | Renderer transformation capabilities:
These bits should be set to the capabilities of the renderer. Attempts to render files of which the capabilities word indicates are not possible by the renderer will be faulted by ImageFileRender module. | |||||||||||
2 |
Renderer supports colour mapping. This bit should be set if the renderer can perform colour mapping. If unset, attempts to use colour mapping on this file type will be faulted by ImageFileRender. | |||||||||||
3 |
Renderer can draw irregular shapes so must be called to calculate bounding boxes. This bit should be set if transforming a shape using a complex matrix (eg skew or rotate) may result in a different bounding box than that which would be generated for a rectangular area. If unset, the renderer will be called to calculate the bounds of an identity transform only. ImageFileRender will perform the remainder of the calculations. If a renderer can only render rectangular areas then leaving this bit clear simplifies the implementation. | |||||||||||
4-7 |
Maximum number of 'quality' levels supported (1-15). The highest quality level which is supported by the renderer. If the quality level requested by a client exceeds this, the renderer will be called with this value. | |||||||||||
8-11 |
Default 'quality' level to use (1-15). Where quality settings are omitted (ie when 'default' quality is selected) the default quality will be passed to the renderer. A value of 0 means that quality levels are ignored. |
Service calls
R0 | = | API version (102 at present) |
R1 | = | &80D40 |
This service is issued after the ImageFileRender module has initialised. Renderers should register themselves with the module.
R0 | = | API version (102 at present) |
R1 | = | &80D41 |
This service is issued as the ImageFileRender module finalises to notify clients that it is no longer providing rendering facilities.
R0 | = | API version (102 at present) |
R1 | = | &80D42 |
R2 | = | Filetype affected |
This service is issued when a renderer registers or deregisters with the ImageFileRender module. Clients which have cached details of other renderers should re-read any renderer values necessary after checking whether the filetype matches those which they are interested in.
SWI calls
R0 | = | Rendering flags:
| ||||||||||||||||||||||||||||||||||||||||||||
R1 | = | Filetype | ||||||||||||||||||||||||||||||||||||||||||||
R2 | = | Pointer to data to render | ||||||||||||||||||||||||||||||||||||||||||||
R3 | = | Length of data | ||||||||||||||||||||||||||||||||||||||||||||
R4 | = | Pointer to extension data, or 0 if none | ||||||||||||||||||||||||||||||||||||||||||||
R5 | = | Image sequence number, or 0 for default image | ||||||||||||||||||||||||||||||||||||||||||||
R6 | = | X coord for origin | ||||||||||||||||||||||||||||||||||||||||||||
R7 | = | Y coord for origin | ||||||||||||||||||||||||||||||||||||||||||||
R8 | = | Transformation data:
| ||||||||||||||||||||||||||||||||||||||||||||
R9 | = | Pointer to colour map descriptor |
This SWI is used to render an image file.
R0 | = | Rendering flags:
| ||||||||||||||||||||||||||||
R1 | = | Filetype | ||||||||||||||||||||||||||||
R2 | = | Pointer to data to render | ||||||||||||||||||||||||||||
R3 | = | Length of data | ||||||||||||||||||||||||||||
R4 | = | Pointer to extension, or 0 if none | ||||||||||||||||||||||||||||
R5 | = | Image sequence number, or 0 for default image | ||||||||||||||||||||||||||||
R6 | = | Pointer to transformation data (see above) | ||||||||||||||||||||||||||||
R7 | = | Pointer to bounding box to fill in |
This SWI is used to calculate the bounding box for a transformation operation.
R0 | = | Rendering flags:
| |||||||||||||||||||||||||
R1 | = | Filetype | |||||||||||||||||||||||||
R2 | = | Pointer to data to render | |||||||||||||||||||||||||
R3 | = | Length of data | |||||||||||||||||||||||||
R4 | = | Pointer to extension, or 0 if none | |||||||||||||||||||||||||
R5 | = | Image sequence number | |||||||||||||||||||||||||
R6 | = | Pointer to transformation data | |||||||||||||||||||||||||
R7 | = | Pointer to output transformation block to fill in |
This SWI is used to calculate the transformation matrix that would be used for an operation without performing that operation. Where clients wish to combine a transform matrix with the operation applied by the scaling specified, this call can obtain the transformation matrix which ImageFileRender will use.
R0 | = | Flags (reserved, must be 0) |
R1 | = | Filetype |
R2 | = | Pointer to data to render |
R3 | = | Length of data |
R4 | = | Pointer to extension data, or 0 if none |
R5 | = | Image sequence number |
R6 | = | Flags to pass to PDriver_DeclareFont |
R0 - R6 | preserved |
This SWI should be used when printing images using the ImageFileRender module before any printing operations begin. Refer to the section 'Declare the fonts your document uses' in the chapter on Printing for more details.
R0 | = | Flags (reserved, must be 0) | ||||||||||
R1 | = | Filetype | ||||||||||
R2 | = | Pointer to data to render | ||||||||||
R3 | = | Length of data | ||||||||||
R4 | = | Pointer to extension data, or 0 if none | ||||||||||
R5 | = | Image sequence number | ||||||||||
R6 | = | Query type:
| ||||||||||
R7 | = | Pointer to query block | ||||||||||
R8 | = | Length of query block |
R8 | = |
If successful, R8 returns the length of block used. If the block was too small, R8 returns a negative value showing how much space was required. If another error occurs, R8 will be positive. |
This SWI should be used to find out information which is not provided by the generic APIs. It may be used (for example) to read the time between frames for a custom renderer, or to read additional information about the image which would otherwise not be available.
The base details query returns the following:
Offset | Contents | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Sequence number | ||||||||||||||||||||
4 | X DPI | ||||||||||||||||||||
8 | Y DPI | ||||||||||||||||||||
12 | Colour type:
| ||||||||||||||||||||
16 | Image flags:
|
The base query is used to get generic information on an image in the file which was not necessary for the rendering of the file. This call is most commonly used to find the sequence number of the default and last logical image within a file. The sequence number may be set to &FFFFFFFF to indicate that the sequence number is not known. This might be the case if the format has no indication of the number of images present.
The image flags provide additional information about the image which might be useful to renderers. The only defined flag at present is that indicating if the image is 'solid' or not. This can be used by clients to decide whether drawing a background behind the image is neccessary or not.
R0 | = | Flags (must be 0) |
R1 | = | Filetype |
R2 | = | Magic identifier |
R0 | = | Pointer to renderer definition block (read only) |
R1 | = | Pointer to renderer name |
This SWI is used to return information about a renderer.
R0 | = | Flags (reserved, must be 0) | ||||||||||||||||||||||||||
R1 | = | Pointer to definition (all will be copied):
Or use 0 to get the current API version |
R1 | = | API version (even if an error occurred) |
This SWI is used to register a new renderer.
R0 | = | Flags (reserved, must be 0) |
R1 | = | Filetype |
R2 | = | Pointer to name used on registration |
R3 | = | Magic value to match (must be the same as when registered |
R0 - R3 | preserved |
This SWI is used to deregister a renderer.
R0 | = | Flags (reserved, must be 0) |
R1 | = | Last filetype, or -1 for first call |
R2 | = | Magic value, or 0 for first call |
R0 | = | Pointer to renderer definition block (read only) |
R1 | = | Filetype of this renderer, or -1 if there are no more |
R2 | = | Magic value of this renderer |
This SWI is used to enumerate the renderers which have been registered with the ImageFileRender module.
Error Messages
This error is returned when the transformation type specified is invalid.
This error is returned when a SWI has been called with flags set which have been defined as reserved. Where possible, this will be returned to allow clients to use new features when they are available, and to fall back to older methods where the features requested are not avialable.
This error is returned during renderer registration when the flags specified in the renderer definition has flags set which have defined as reserved.
This error is returned when there is not enough memory for the rendering (or other) operation.
This error is returned when the renderer being deregistered is not known to the ImageFileRender module.
This error is returned when an operation is attempted on a filetype for which no renderer has been registered.
This error is returned when an operation is attempted for which the renderer API is not understood by the renderer. This will most likely not be seen by external clients. Clients who proxy their rendering through another renderer may see this if the APIs provided do not match between the proxy and the client.
This error is returned when the rendering operation cannot be performed because the renderer does not support the transformation requested by the client. The most likely cause for this error is attempted to skew or rotate a filetype which cannot be skewed or rotated (for example JPEGs).
This error is returned when a rendering operation cannot be performed because the renderer does not support colourmapping and colourmapping has been requested by the client.
This error is returned when the ImageFileRender_Info query type has not been recognised by the renderer.
This error is returned when the ImageFileRender_Info query type has been recognised by the renderer, but the length supplied was not understood.
This error is returned by the sprite renderer when the image being rendered uses a mode which is not understood by the system.
This error is returned by the sprite renderer when the image being rendered is malformed or contains data which is not understood.
This error is returned by the sprite renderer when it cannot locate the sprite named in the extension data.
Entry Points
R0 | = | API version * 100 (102 in this version) | ||||||||||||
R1 | = | Pointer to image descriptor:
| ||||||||||||
R2 | = | 0 | ||||||||||||
R12 | = | Workspace value on entry to ImageFileRender_Register |
The 'start' routine is called before any operations are applied to an image. This allows clients to cache information relevant to the image such that subsequent calls do not have to re-read the data. If the image data is not recognised, it should be faulted. Errors should be reported by setting V and returning an error block in R0.
Clients may fill in the private word with cached data. Usually this is a pointer to some workspace specific to this image.
R0 | = | API version * 100 (102 in this version) | ||||||||||||
R1 | = | Pointer to image descriptor:
| ||||||||||||
R2 | = | 0 | ||||||||||||
R12 | = | Workspace value on entry to ImageFileRender_Register |
The 'stop' routine is called after all operations are applied to an image. This allows clients to release space allocated for cache information relevant to the image. If there is any internal error, the client should tidy up as best it can and return an error. Errors should be reported by setting V and returning an error block in R0.
R0 | = | API version * 100 (102 in this version) | ||||||||||||||||||||||||||||||||||||||||||||||
R1 | = | Pointer to image descriptor:
| ||||||||||||||||||||||||||||||||||||||||||||||
R2 | = | Pointer to rendering descriptor:
| ||||||||||||||||||||||||||||||||||||||||||||||
R12 | = | Workspace value on entry to ImageFileRender_Register |
The rendering routine is called to render an image using a given transformation. If the image data is not recognised, it should be faulted. Errors should be reported by setting V and returning an error block in R0.
The clipping rectangle passed represents the graphics rectangle as external coorinates (OS units) which is currently in use. It is provided for information such that rendering can take advantage of fast rejection of regions which do not need to be redrawn.
R0 | = | API version * 100 (102 in this version) | ||||||||||||||
R1 | = | Pointer to image descriptor:
| ||||||||||||||
R2 | = | Pointer to bounding box descriptor:
|
The bounding box routine is called to calculate the bounding box for a given transformation. If the image data is not recognised, it should be faulted. Errors should be reported by setting V and returning an error block in R0. The bounding box should be returned in draw coordinates for the images extent. That is, OS units * 256. Resolution values should be provided for information. If no DPI information is available, 180 (the screen resolution) should be returned.
If bit 3 of the renderer flags was clear on registration, the transformation matrix will be an identity matrix and can effectively be ignored. The scaling to the clients required size will be performed by ImageFileRender module based on the bounding box returned.
R0 | = | API version * 100 (102 in this version) | ||||||||||||
R1 | = | Pointer to image descriptor:
| ||||||||||||
R2 | = | Pointer to declare fonts descriptor:
|
The font declaration routine need only be provided by renderers which use fonts. The renderer should call SWI PDriver_DeclareFont with the names of all fonts and the flags passed in R4. If the image data is not recognised, it should be faulted. Errors should be reported by setting V and returning an error block in R0.
R0 | = | API version * 100 (102 in this version) | ||||||||||||
R1 | = | Pointer to image descriptor:
| ||||||||||||
R2 | = | Pointer to information descriptor:
|
R0 | = | If V flag set, a pointer to an error block, or a special error code :
|
The information routine should be provided by renderers to query information about the images. The routine should fault invalid queries and invalid query lengths.
*Commands
*ImageFileRenderers is used to list the renderers known to the ImageFileRender module. This can be used to check which file formats are available for use with ImageFileRender from the command line.
&69c 00000000 ConvertBMP 0.05 RISCOS Ltd (via IFC)
&69e 00000000 ConvertPNM 0.02 RISCOS Ltd (via IFC)
&aff 00000000 ImageFileRender 0.25 RISCOS Ltd
&b60 00000000 ConvertPNG 0.09 RISCOS Ltd (via IFC)
&b61 00000000 ConvertXBM 0.06 RISCOS Ltd (via IFC)
&c85 00000000 ImageFileRender 0.25 RISCOS Ltd
&d94 00000000 IFR Artworks 0.08 RISCOS Ltd
&fc9 00000000 ConvertSun 0.05 RISCOS Ltd (via IFC)
&ff9 66990101 ImageFileRender 0.25 RISCOS Ltd
*ImageFileViewer is used to register a command which can be used to view files known to ImageFileRender. The Alias$@RunType_XXX variables will be set for filetypes known to ImageFileRender which have not already been set. If no parameter is passed to the command, the default viewer wil be cleared and all the variables will be unset.
The effect of issuing this command is that any files know to ImageFileRender which are not recognised by running applications when double-clicked in Filer (or run explicitly) will cause the command specified to be run, passing the filename of the file run as the first parameter.