New API for control of text labels in DicomObjects V8 onwards
Since labels on images were introduced in the very early days of DicomObjects, the facilities and flexibility for their display have been extended considerably, both for “specific”
display and also to ensure full support for DICOM presentation states, as well as providing some rather specific requirements at some users' requests. The complexity is now rather excessive, and this has been compounded in V8 by the addition of the ability to rotate images by angles other than multiples of 90° leading to some anomalous effects when the image is rotated but the text is not.
We have therefore stepped right back and considered what is needed, bearing in mind the possible angular rotation, but always subject to the requirements for legibility. These requirements mean that text annotations cannot simply be treated the same as other graphics - to take an extreme example, flipping an image horizontally with a fully “image tied” label should fully flip an arrow etc., but clearly “mirror-image” text would be useless and possibly dangerous. Therefore the following options are planned for the new versions (.NET & COM). Whilst the primary design was based on text labels only, some users have expressed a wish to allow the same behaviour for non-text labels such as rectangles or ellipses and this has been incorporated, but the defaultfor the 2 classes is different, being non-rotation for image tied text labels, but image tied rotation for non-text labels.
General
- Text may be rotated and resized, but never mirrored
- There is a (controllable) minimum font size
- The specified size of the label will be used for wrapping and alignment, but will NOT cause text to be “clipped” - it will extend “downwards” (relative to its rendering angle) to ensure that whole string is rendered (but this might not all still be visible if obscured by other labels, images, or by the edge of the image area)
Auto-Sizing and Alignment
Auto-sizing is most useful when combined with showing a box around the text, or adding a line from the text to an “anchor point”, as well as when adding “child labels” to the corners (.NET only). Previous versions have supported autosize as a simple Boolean, but with an obscure (user requested) means to specify that only the height should be shrunk, with the width remaining unchanged. These are being combined, with the addition (for consistency if nothing else) of a new option to preserve height but not width. As in all cases below, the dotted line indicates the defined “Area” of the label, and red indicates what is actually displayed:
This behaviour is controlled by a new AutoSizeMode property, which replaces the previous AutoSize (Boolean) property – the possibilities are:
- NoAutoSize
- AutoSizeWidth
- AutoSizeHeight
- Auto
This behaviour is of course modified by the chosen alignment, so for instance if the text is right & bottom aligned, then the appearance would be:
Similarly, if rotated, then the height/width remain relative to the rotated image’s “text” frame of reference, giving for a 90° rotation (see below for when this would occur) this would be:
Explicit Rotation
This type of rotation is controlled by the Angle property of the label, and can be used on images of all scale modes (see following section for interaction with image pixel scale mode and rotated images). Whilst the DicomObjects API allows any degree of rotation, it should be noted that the DICOM Presentation State specification only allows exact multiples of 90° (via designation of one of the 4 corners as being “top left”). Whilst the angle is easy to specify as a single floating point value, there is an additional level of complexity due to the need to define the “centre of rotation”, as not all users would necessarily wish this to be the centre of the label (especially if the area is defined as having a very large/unlimited right margin to avoid wrapping, as is often the case). Furthermore, if the centre were used by default, would that be the centre of the “whole” Area, or the centre of the reduced effective area actually occupied by the text (as used in AutoSized labels). A new enumeration and property have therefore been defined to control this behaviour:
RotationCentre:
- RotateAtLabelCentre - default - centre of whole Area
- RotateAtTextCentre - centre of actual text area (whether or not AutoSize is actually used)
- RotateAtAutoSizeCentre - centre of whatever AutoSize is chosen
- RotateAtPoint - defined by RotationPoint(.NET) or RotationPointX/Y (COM)
Transformation with the image
a) Rotation and Flipping
This is where the major complications arise, compounded by the different wishes of different developers. Before looking at the new model, I review the issues with the existing one. In the existing model, all works well if the text is allowed to rotate with the image (RotateTextWithImage = true), as all aspects of the label rotate in unison - e.g.
In the above scenarios, there is no need for any other adjustments to the text position, alignment nor angulation, and indeed it is important to prevent such accidental changes which were possible in the previous API - hence the decision as detailed below to move the top level control to a single enumeration, of which “RotationMode.WithImage” is a complete definition. The only situation in which the overall effect is not the same as a simple transformation of the combined image & label is when the image is “flipped”, either horizontally or vertically. In this case, the text is not mirrored, and the top left of the above set when flipped vertically would look like this:
With RotateAtLabelCentre
or
With RotateAtLabelCentre
However, if the rectangle defining the area is allowed to rotate without rotation of the text, then the text and its container are mis-matched shapes, and some ambiguity arises. In these images, the green rectangle is the largest “straight” rectangle fitting within the rotated rectangle:
The above is the default behaviour of versions until now, inherited from V6, and whilst it makes some sense for the multiples of 90°, it makes no sense for other angles, and will therefore be dropped from now on. In its place will be a new “NoRotation” mode, which acts in an analogous but reversed manner to the simple rotation of an image without being image tied - i.e. the text will retain the same size and shape as if the image were NOT rotated. Like the simple rotation, this requires definition and use of a “rotation point”, and the same RotationPoint and RotationCentre(X/Y) properties but in this case the definition will be in image pixel coordinates.
Equivalents to the above (moved slightly to separate centres of image and label) with NoRotate mode would now be:
With RotateAtLabelCentre: |
---|
With RotateAtTextCentre |
---|
Similarly, the rotation point (the dot in the above) could be positioned elsewhere for RotateAtPoint mode.
2) Alignment
Previous versions have included a Boolean to specify whether the “Alignment” of a non-rotated text label within its overall Area should or should not be modified to match the rotation and flipping of the underlying image. This allowed text to stay at the “same corner” of the box as the box rotated
e.g.
Non-rotated |
RotateAlignment = false |
RotateAlignment = true |
This however is not well defined when the angle can be a non multiple of 90°, and is superfluous when there is instead the ability to define the “rotation point” as being the centre of the actual text, thereby maintaining the equivalent effect of keeping the text in approximately the same place, irrespective of the “far” edges of the Area. This property is therefore being removed.
Combination of Image and Explicit Text Rotation angles
There can be independent angles for the image and the label. Logically, the point of rotation is selected, and an angle is calculated as the sum of the image rotation (if RotateWithImage mode, else 0) and the explicit rotation of the label itself. The text is then rotated about that combined angle.
Summary
The new API uses 4 properties (+1 in COM) to define the positioning and angle of the image relative to its Area and the image.
The following are new properties:
- AutoSizeMode: enum
- AutoSize
- AutoSizeHeight
- AutoSizeWidth
- NoAutoSize
- RotationMode: enum
- RotateWithImage
- NoRotate
- Default (RotateWithImage for non-text and NoRotate for text labels)
- RotationCentre: enum
- RotateAtLabelCentre
- RotateAtTextCentre
- RotateAtAutoSizeCentre
- RotateAtPoint
- RotationPoint (PointF in .NET - X&Y floats in COM)
These completely replace the following properties and registry values:
- RotateTextWithImage : bool
- RotateAlignmentWithImage: bool
- AutoSize: bool
- RegistryWord “FixedAutoWidth”