Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Rotate and scale bitmaps

by Retired on ‎04-28-2010 10:26 AM - edited on ‎11-17-2010 12:29 PM by Retired (19,199 Views)

Summary

 

This article applies to the following:

 

  • BlackBerry® Device Software 4.2 and later
  • BlackBerry smartphones

 

Details

 

Introduction

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.

 

Two-dimensional transformations

 

The fundamental two-dimensional transformations are scale, rotate, mirror, and translate.

These transformations are illustrated in the following diagram:

 

1818iF9A31E7A81210E8B

 

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

 

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

 

Procedure:

  1. Determine the path of the original bitmap.
  2. Determine the path of the transformed bitmap and its bounding box.
  3. Create the transformed bitmap.
  4. Create a scaled bitmap from the original bitmap that matches the size of the transformed bitmap path.
  5. Fill the transformed bitmap path with the scaled bitmap.
  6. Return the 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:

 

1819iDDBB410C3162FA61

 

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:

 

1820i9772FD1759F59656

 

Because matrix multiplication is not commutative, that is,

 

1821i5EEBCA44385EF317

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.
1822iB0415103467D522F

 

The transformation equation for the Scale x Rotate x Mirror + Translate ordering is

 

1823i3648B3749A8246C2

 

which can be simplified to

 

1824i00F46A9BC474BD17

 

You can use these equations to perform steps 2 and 3 of the bitmap operations.

 

Bitmap Scaling

 

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 scaleInto of the Bitmap class. There are three variants of scaleIntoand the one best suited to the algorithm is:

 

 

public void scaleInto(
Bitmap result,
int filterType,
int iAspectRatioOption );

 

 

 

where:

 

  • result is the transformed Bitmap.
  • filterType specifies the type of filter algorithm to use. The following three filtering algorithms are available: Bitmap.FILTER_BILINEAR, Bitmap.FILTER_BOX and Bitmap.FILTER_LANCZOS.
  • iAspectRatioOption specifies how the aspect ratio is maintained. Bitmap.SCALE_STRETCH does not maintain the aspect ratio, Bitmap.SCALE_FIT scales to match the smallest destination dimension, and Bitmap.SCALE_FILL scales to match the largest destination dimension. Note that when you use the Bitmap.SCALE_FIT algorithm, the resulting bitmap might have horizontal or vertical bands if the aspect ratios of the original and transformed bitmaps are not the same.

In the case of a non-1:1 mapping in BlackBerry Device Software 5.0 you can use scaleInto to create a bitmap that is of better quality (compared with a 1:n mathematical mapping) and of the exact size needed to fill the transformed bitmap. In versions of BlackBerry OS prior to 5.0 where scaleInto is not available, you must use another scale operation.

 

Drawing the transformed bitmap

 

Step 5 of the algorithm involves filling the transformed bitmap path. You can use drawTexturedPath of the Graphics class in the BlackBerry API to tile a bitmap into an arbitrary path. You can use this method to fill a transformed Bitmap path with either a pre-scaled Bitmap (in BlackBerry Device Software 5.0 or later) or to perform the scaling itself (on pre-BlackBerry Device Software 5.0). The method signature is as follows:

 

 

public void drawTexturedPath(
int[] xPts,
int[] yPts,
byte[] pointTypes,
int[] offsets,
int xOrigin,
int yOrigin,
int dux,
int dvx,
int duy,
int dvy,
Bitmap textureData );

 


 

where:

 

  • xPts, yPts are the vertex co-ordinates of the transformed bitmap.
  • pointTypes is not used and null is passed.
  • offsets is not used and null is passed.
  • xOrigin, yOrigin are the translation [ tx ty ].
  • dux, dvx is a walk vector in Fixed32 format to map from texture co-ordinate space (u,v) to transformed bitmap co-ordinate space (x).
  • duy, dvy is a walk vector in Fixed32 format to map from texture co-ordinate space (u,v) to transformed bitmap co-ordinate space (y).
  • textureData is a Bitmap. Of note is that the bitmap is tiled into the defined path.

The parameters, dux, dvx, duy, dvy are referred to in the documentation as walk vectors in that they define how to walk through, or index, the textureData bitmap to fill the transformed bitmap path. The walk vectors can be computed using

1825iD589EFEB6323F5C9

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 scaleInto. In this case, scaling the walk vectors is not required and the above transformation matrix is used with sx = sy = 1.

 

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).

 

The net.rim.device.api.math.Fixed32 class provides methods for conversions between integers and the Fixed32 format, along with operations on Fixed32 objects. In addition, the class net.rim.device.api.math.VecMath performs vector and matrix operations on Fixed32 format numbers.

 

One Last Thing

 

Since drawtexturedPath tiles the bitmap into the transformed path, the bitmap can easily be reflected by indexing u or v, or both u and v in a negative direction.

 

1826iDC07EA535BC62534

 

The result is a bitmap that is reflected internally, which yields:

 

1827i8D4705CBC0A7F553

 

This transformation is independent of the two-dimensional transformations.

 

The ImageManipulator class

 

The ImageManipulator class performs transformations on a bitmap. There are getter and setter methods for the bitmap and the transformation parameters. The following methods also apply the transformations to a bitmap.

 

 

public static Bitmap scale( Bitmap bitmap, int scale );

 

 

  • A scaled bitmap is returned. The scale value is specified in Fixed32 format.

 

public static Bitmap rotate( Bitmap bitmap, int angle );

 

 

  • A bitmap that is rotated by angle degrees (a positive angle rotates the bitmap counter-clockwise) is returned.

 

 

public void resetTransform();

 


 

  • Reset the transformations to the identity transformations, that is no scaling, no rotating, and no mirroring.

 

 

public void transformByAngle( int angle, boolean mirrorX, boolean mirrorY );

 


 

  • Set the angle and mirror (X and Y axis) of the transformation.

 

 

public void transformbyMatrix( int ux, int uy, int vx, int vy );

 


 

  • Set the transformation matrix directly. (Note that the parameters are in Fixed32 format.)

 

 

public void applyTransformation();

 


 

  • Apply the current transformations to the bitmap.

 

 

public void transformAndPaintBitmap( Graphics g );

 


 

  • Apply the current transformations to the bitmap and paint the bitmap onto the Graphics context g.

 

 

public Bitmap transformAndPaintBitmap();

 


 

  • Apply the current transformations to the bitmap and return the transformed Bitmap.

 

 

public void scaleInto( Bitmap dst, int filterType );

 


  • Scale the bitmap into the dst bitmap using the filterType.

 

 

public void scaleInto( Bitmap dst, int filterType,int iAspectRatio );

 


  • Scale the bitmap into the dst bitmap using the filterType and iAspectRatio.

 

 

public void scaleInto( int srcLfet, int srcTop, int srcWidth, int srcHeight, Bitmap dst, int dstLeft, int dstTop, int dstWidth, int dstHeight );

 


  • Scale the given region from the bitmap into the specified region in the transformed bitmap.

Additional Information

 

ImageManipulator provides operations on bitmaps that were previously only available on two-dimensional geometric shapes. You can use this class to manipulate any bitmap, including photographic images, and provides zoom, rotate, and reflect operations. In addition, the class can be used in conjunction with time-based algorithms to create two-dimensional animations. In such cases, ImageManipulator can generate individual frames (or parts of frames), while the time-based algorithms manage the rate of change of the transformation.

 

Users Online
Currently online: 39 members 807 guests
Please welcome our newest community members: