This article applies to the following:
- BlackBerry® Device Software 4.2 and later
- BlackBerry smartphones
Today’s UIs are more graphically rich with animated controls and media management. The BlackBerry platform supports a large variety of two-dimensional shapes. It also supports a number of attributes for each shape, such as rotation, scaling, and color fill. However, one feature that is not available is the ability to perform the same types of operations on bitmaps. This article summarizes the two-dimensional graphic operations you can perform on bitmaps and presents a Java® class for performing these transformations.
The fundamental two-dimensional transformations are scale, rotate, mirror, and translate.
These transformations are illustrated in the following diagram:
Each transformation can be expressed as a matrix operation that is applied to each vertex of a bitmap. Transformations can be combined to produce composite changes in the bitmap, for example a rotation followed by a translation. The resulting set of vertices define the path of the transformed bitmap. The vertex located at[ 0 0 ] is defined as the reference vertex. All transformations are relative to it.
The algorithm for transforming a Bitmap is as follows:
Inputs: a bitmap and a set of transformations (scale, rotate, mirror, translate)
Output: a transformed bitmap
If no scaling is required, you can omit step 4 and use the given bitmap in step 5.
Mathematics of two-dimensional transformations
The composite transformation for each vertex of a bitmap is calculated using the following equation:
where p is a vertex of the original bitmap, p* is the transformed vertex, and Mi is a scale, rotate, or mirror matrix, and T is the translate matrix. The scale, mirror, rotate, and translate matrices appear in the following form:
Because matrix multiplication is not commutative, that is,
the order of the operations is significant. With four matrix operands there are 24 different transformation equations. In this article, the order of operations used is scale, rotate, mirror, translate. This order results in a bitmap that is always rectangular. This is known as a conformal mapping and is illustrated below.
The transformation equation for the Scale x Rotate x Mirror + Translate ordering is
which can be simplified to
You can use these equations to perform steps 2 and 3 of the bitmap operations.
Step 4 of the algorithm involves scaling the transformed bitmap using the original bitmap. If image scaling is not required, that is, sx = sy = 1, the bitmap fill operation is a 1:1 mapping of pixels between the two bitmaps. The interesting case is when scaling is not a 1:1 pixel mapping. It is relatively easy to calculate a pixel mapping using a simple 1:n mathematical algorithm. However, the resulting images tend to be of poor quality. In particular diagonal edges appear jagged or saw-toothed.
Better scaling algorithms have been developed to preserve image quality: bilinear interpolation, bicubic interpolation and Lanczos resampling are three such algorithms. These algorithms consider the values of adjacent pixels when they calculate the value of the current pixel.
BlackBerry Device Software 5.0 introduces the ability to scale images using
public void scaleInto(
In the case of a non-1:1 mapping in BlackBerry Device Software 5.0 you can use
Drawing the transformed bitmap
Step 5 of the algorithm involves filling the transformed bitmap path. You can use
public void drawTexturedPath(
which is recognized as a variation of the transformation matrix for a bitmap path. In BlackBerry Device Software 5.0, a scaled bitmap can be created using
About the Fixed32 format
The Fixed32 format is a signed 15.16 floating point format that is stored in a 32-bit integer. The machine epsilon is 1/65536, or approximately 0.00001526, and the range is (‑32,768.0, 32,767.9999).
One Last Thing
The result is a bitmap that is reflected internally, which yields:
This transformation is independent of the two-dimensional transformations.
The ImageManipulator class
public static Bitmap scale( Bitmap bitmap, int scale );
public static Bitmap rotate( Bitmap bitmap, int angle );
public void resetTransform();
public void transformByAngle( int angle, boolean mirrorX, boolean mirrorY );
public void transformbyMatrix( int ux, int uy, int vx, int vy );
public void applyTransformation();
public void transformAndPaintBitmap( Graphics g );
public Bitmap transformAndPaintBitmap();
public void scaleInto( Bitmap dst, int filterType );
public void scaleInto( Bitmap dst, int filterType,int iAspectRatio );
public void scaleInto( int srcLfet, int srcTop, int srcWidth, int srcHeight, Bitmap dst, int dstLeft, int dstTop, int dstWidth, int dstHeight );