Transforms may be used to manipulate images in a number of ways. The transforms discussed below, for use with FlashPix files, may be used to manipulate spatial orientation, color and tone, contrast, and filtering. In some cases, such as contrast manipulation or filtering, a single value may be needed, whereas, with spatial orientation and color and tone manipulation, a matrix of values is required to accomplish the transformation.
The values used to accomplish this are stored in the FILETRANSFORMS structure listed below. It is this structure that is written to the file for storage with the image using the L_WriteFileTransforms. The next time the image is loaded, you may examine the transforms stored with the image using the L_ReadFileTransforms function and decide whether to load the image in its original state, or in any of three transformed states. If you elect to load the image unchanged, you must make sure both the ELO_IGNOREVIEWTRANSFORMS and the ELO_IGNORECOLORTRANSFORMS flags have been set in the Flags data member of LOADFILEOPTION structure before loading the file.
Note: By setting these flags you are telling the system to ignore the transforms.
To load the image with only the effects of the color transforms incorporated, you must set the ELO_IGNOREVIEWTRANSFORMS flag, and clear the ELO_IGNORECOLORTRANSFORMS flag.
To load the image with only the effects of the viewing transforms incorporated, you must set the ELO_IGNORECOLORTRANSFORMS flag and clear the ELO_IGNOREVIEWTRANSFORMS flag.
Finally, to load the image with both the color transforms and the view transforms incorporated, clear both the ELO_IGNOREVIEWTRANSFORMS and the ELO_IGNORECOLORTRANSFORMS flags. Examples of all four loading options may be seen in"Example" under L_LoadFile.
Further explanation of spatial orientation, color and tone manipulation, contrast manipulation and filtering is provided below.
typedef struct _FILETRANSFORMS
{
// AffineMatrix translation, rotation, shear, skew, scale ...
L_FLOAT a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44;
/* matrix values */
// ColorTwistMatrix
L_FLOAT byy, byc1, byc2, bc1y, bc1c1, bc1c2, bc2y, bc2c1, bc2c2; /* matrix values */
// Contrast Adjustment
L_FLOAT fContrastAdjustment; /* adjustment factor */
L_FLOAT fFilteringValue; /* Sharpness adjustment */
} FILETRANSFORMS, * pFILETRANSFORMS;
The FILETRANSFORM structure is used by L_ReadFileTransforms and L_WriteFileTransforms to read or write FlashPix transforms.
Spatial Orientation - Affine matrices
FlashPix supports a number of methods for transforming the spatial orientation of an image. These include shearing, translation, rotation, and scaling and are described using a 4x4 matrix. Image points from the displayed image are mapped to the original image. A generic 4x4 matrix may be seen below:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ a11 a12 a13 a14 │ │ x │
│ y' │ = │ a21 a22 a23 a24 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
where x' and y' are the new, transformed coordinates and x and y are the old coordinates. The values placed in variables a11 through a24 determine what transformation you are performing and the degree of change. The new values are obtained as follows:
x' = a11 * x + a12 * y + a13 * 1 + a14 * 1
y' = a21 * x + a2 2* y + a23 * 1 + a24 * 1
First, is the identity matrix, given below. This performs no manipulation of the image data, so the image itself results.
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1 0 0 0 │ │ x │
│ y' │ = │ 0 1 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To translate a point use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1 0 0 ±X0 │ │ x │
│ y' │ = │ 0 1 0 ±Y0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
where X0
and Y0
indicate the change in X and the change in Y for each point.
To rotate a point about the origin counterclockwise, by the angle ßr
, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ cos(ßr) -sin(ßr) 0 0 │ │ x │
│ y' │ = │ sin(ßr) cos(ßr) 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To shear an image horizontally, by an angle of ßhh
counterclockwise about the origin, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1 -tan(ßhh) 0 0 │ │ x │
│ y' │ = │ 0 1 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To shear an image vertically, by an angle of ßhv
counterclockwise about the origin, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1 0 0 0 │ │ x │
│ y' │ = │ tan(ßhv) 1 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To skew(or flip) an image horizontally, by an angle of ßsh
counterclockwise about the origin, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1 -tan(ßsh) 0 0 │ │ x │
│ y' │ = │ 0 1/cos(ßsh) 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To skew(or flip) an image vertically, by an angle of ßsh
counterclockwise about the origin, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1/cos(ßsv) 0 0 0 │ │ x │
│ y' │ = │ tan(ßsv) 1 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To scale an image about the origin by sx horizontally and sy vertically, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ x' │ │ 1/sx 0 0 0 │ │ x │
│ y' │ = │ 0 1/sy 0 0 │ X │ y │
│ 1 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
For uniform scaling in both directions, sx = sy.
Multiple transformations may be combined into a single affine transformation. This is not usually commutative; the order of application is important. The example below shows the process of multiplying a linear translation matrix, a rotation matrix, and another linear translation matrix. Basically, the image is translated from its original center point to the origin (0, 0) at the upper left, rotated about the origin and then translated back to the original center. For the purpose of the example, the following are true:
C = the cosine of the angle.
S = the sine of the angle.
X^ = image width / 2. The image width may be obtained using L_FileInfo (see "Example").
Y^ = image height / 2. The image height may be obtained using L_FileInfo (see "Example").
X = the x coordinate of the point being manipulated.
Y = the y coordinate of the point being manipulated.
X' = the new x coordinate.
Y' = the new y coordinate.
The negative symbol before X^ and Y^ in the rightmost 4x4 matrix indicates the translation to the origin. Since this is the first step in the process, this matrix is closest to the 4x1 matrix representing the point being manipulated. Conversely, the translation back to the original center is performed last, by the leftmost 4x4 matrix, and the X^ and Y^ are positive.
Once the order of the three transformation matrices is established, the multiplication of these three matrices is commutative. Here the multiplication will be done left to right, multiplying the leftmost and middle matrices first.
┌─ ─┐ ┌─ ─┐ ┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ X' │ │ 1 0 0 X^ │ │ C -S 0 0 │ │ 1 0 0 -X^ │ │ X │
│ Y' │ = │ 0 1 0 Y^ │ X │ S C 0 0 │ X │ 0 1 0 -Y^ │ = │ Y │
│ 1 │ │ 0 0 1 0 │ │ 0 0 1 0 │ │ 0 0 1 0 │ │ 1 │
│ 1 │ │ 0 0 0 1 │ │ 0 0 0 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘ └─ ─┘ └─ ─┘
Multiplying the first row of the leftmost 4x4 matrix above by the first column of the middle matrix above provides the top left entry in the left matrix given below. Multiplying the first row of the leftmost matrix above by the second column of the middle matrix above provides the second entry in the top row of the left matrix below. This continues throughout the entire matrix. The result is the left matrix below, which will then be multiplied by the right matrix to obtain the final 4x4 matrix.
┌─ ─┐ ┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ C -S 0 X^ │ │ 1 0 0 -X^ │ │ 1 0 0 0 │ │ X │
│ S C 0 Y^ │ X │ 0 1 0 -Y^ │ X │ 0 1 0 0 │ = │ Y │
│ 0 0 1 0 │ │ 0 0 1 0 │ │ 0 0 1 0 │ │ 1 │
│ 0 0 0 1 │ │ 0 0 0 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘ └─ ─┘
The multiplication process is carried out as before, multiplying the row of the left matrix by the column of the right matrix. Once this is completed, the 4x4 matrix shown below results. This one matrix will translate, rotate and translate the original image.
┌─ ─┐ ┌─ ─┐
│ C -S 0 (C*(-X^)) + (S*Y^) + X^ │ │ X │
│ S C 0 -(S*X^) - (C*Y^) + Y^ │ X │ Y │
│ 0 0 0 0 │ │ 1 │
│ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘
The new coordinates are determined as follows:
X' = (C\*X) - (S\*Y) + (C\*(-X^)) + (S\*Y^) + X^
Y' = (S\*X) + (C\*Y) - (S\*X^) - (C\*Y\*) + Y^
Color and Tone Manipulation - Color Twist matrices
The FlashPix format uses a Color Twist matrix to allow the user to modify the tone and/or color of an image. This is also accomplished through the use of a matrix. The general form of the matrix is given below:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ byy byc1 byc2 0 │ │ L │
│ C1' │ = │ bc1y bc1c1 bc1c2 0 │ X │ C1 │
│ C2' │ │ bc2y bc2c1 bc2c2 0 │ │ C2 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
where <L, C1, C2, 1> is a vector of normalized YCC values which is used to modify lightness, saturation, and color. The three left-most entries of the bottom row must remain 0. All conversion to the proper colorspace is handled internally.
First, is the identity matrix, given below. This performs no manipulation of the image data, so the image itself results.
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ 1 0 0 0 │ │ L │
│ C1' │ = │ 0 1 0 0 │ X │ C1 │
│ C2' │ │ 0 0 1 0 │ │ C2 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To lighten an image by a factor of L1'
, set L1
equal to the sqrt of L1'
and use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ L1 0 0 0 │ │ L │
│ C1' │ = │ 0 L1 0 0 │ X │ C1 │
│ C2' │ │ 0 0 L1 0 │ │ C2 │
│ 1 │ │ 0 0 0 L1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
Values of L1'
between 0 and 1 darken the image, while values > 1 lighten the image. Therefore, if you wish to lighten the image by 10%, set L1' = 1.1
.
To alter the saturation of an image, use the following matrix:
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ 1 0 0 0 │ │ L │
│ C1' │ = │ 0 Sa 0 0 │ X │ C1 │
│ C2' │ │ 0 0 Sa 0 │ │ C2 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
where Sa
is the saturation factor. Saturation factors between 0 and 1 decrease saturation, which creates a more gray scale image, while values greater than 1 increase saturation. Therefore, if you wish to increase the saturation by 10%, set Sa = 1.1
.
To modify the color balance in red, green, or blue:
C = sqrt(C') - 1
where C'
is the desired factor of the exposure level. To increase a color by 20%, set C' = 1.2
.
To modify the red color balance of an image,
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ 1 0 0.299*C 0 │ │ L │
│ C1' │ = │ -0.299*C 1-0.299*C 0.299*C 0 │ X │ C1 │
│ C2' │ │ 0.701*C 0 1+0.402*C 0 │ │ C2 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To modify the green color balance of an image,
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ 1 -0.114*C -0.299*C 0 │ │ L │
│ C1' │ = │ -0.587*C 1-0.473*C 0.299*C 0 │ X │ C1 │
│ C2' │ │ -0.587*C 0.114*C 1-0.288*C 0 │ │ C2 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
To modify the blue color balance of an image,
┌─ ─┐ ┌─ ─┐ ┌─ ─┐
│ L' │ │ 1 -0.114*C 0 0 │ │ L │
│ C1' │ = │ 0.866*C 1+0.772*C 0.299*C 0 │ X │ C1 │
│ C2' │ │ -0.114*C -0.114*C 1-0.114*C 0 │ │ C2 │
│ 1 │ │ 0 0 0 1 │ │ 1 │
└─ ─┘ └─ ─┘ └─ ─┘
Contrast modification
The contrast in an image may be modified using a contrast factor(fContrastAdjustment in the structure). A factor less than one will decrease the contrast, darkening the image, while a factor greater than 1.0 increases the contrast, lightening the image. To increase the contrast by 20%, set fContrastAdjustment = 1.2.
Sharpness modification
The sharpness factor(fFilteringValue) sharpens or softens an image. A positive value results in image sharpening, while a negative value results in softening or blurring of the image.