code

Flex image manipulation

Image file formats are standardized means of organizing and storing images, let’s start to recap the building blocks of them in order to move faster in our flex applications.

Image file size (expressed as the number of bytes) increases with the number of pixels composing an image, and the color depth of the pixels and we use the words color depth or bit depth (usually a computer graphics term) in order to descibe the number of bits used to represent the color of a single pixel in a bitmapped image.

The color depths are summarized as following:

1-bit color (21 = 2 colors) monochrome, often black and white
2-bit color (22 = 4 colors) CGA, gray-scale early
3-bit color (23 = 8 colors) many early home computers with TV displays
4-bit color (24 = 16 colors) as used by EGA and by the least common denominator VGA standard at higher resolution
5-bit color (25 = 32 colors) Original Amiga chipset
6-bit color (26 = 64 colors) Original Amiga chipset
8-bit color (28 = 256 colors) most early color Unix workstations, VGA at low resolution, Super VGA, AGA, color Macintoshes.
12-bit color (212 = 4096 colors) some Silicon Graphics systems, Neo Geo, Color NeXTstation systems, and Amiga systems in HAM mode.
16-bit color (216 = 65536 colors) some color Macintoshes.

You can easily understand by the following images list (tanks to wikipedia) how much the color depth can impact the quality of your images.

There are two types of image file compression algorithms, lossless and lossy.

Lossless compression algorithms reduce file size without losing image quality, though they are not compressed into as small a file as a lossy compression file (when image quality is valued above file size, lossless algorithms are typically chosen).
Lossy compression algorithms take advantage of the inherent limitations of the human eye and discard invisible information, most lossy compression algorithms allow for variable quality levels (compression) and as these levels are increased, file size is reduced.

The most common image formats you can deal with in order to create image manipulation algorithms are: JPEG, TIFF, PNG and GIF.

JPEG (Joint Photographic Experts Group) files are (in most cases) a lossy format, the DOS filename extension is JPG (other operating systems may use JPEG).
Nearly every digital camera can save images in the JPEG format, which supports 8 bits per color (red, green, blue) for a 24-bit total, producing relatively small files so it’s usual that an application acquires images in this format.
JPEG files suffer generational degradation when repeatedly edited and saved are increased, file size is reduced so be careful to save too often the changes you do in your application.
The Exif (Exchangeable image file format) is an algorithm incorporated in the JPEG software used in most cameras, its purpose is to record and to standardize the exchange of data between digital cameras and editing and viewing software.The data is recorded for individual images and includes such things as camera settings, time and date, shutter speed, exposure, image size, compression, name of camera, color information, etc.
When images are viewed or edited by image editing software, all of this image information can be displayed and you can use them to create faster visualization tools.

The TIFF (Tagged Image File Format) is a flexible format that normally saves 8 bits or 16 bits per color (red, green, blue) for 24-bit and 48-bit totals, respectively, using either the TIFF or the TIF file extension. TIFFs compression algorithm are lossy and lossless and some offer relatively good lossless compression for bi-level (black & white) images.
The TIFF can handle device-specific color spaces, such as the CMYK defined by a particular set of printing press inks and for this reason is quite diffused in printing and in the photographer world.

The PNG (Portable Network Graphics) file format was created as the free, open-source successor to the GIF that supports true color (16 million colors) while the GIF supports only 256 colors.
The PNG file excels when the image has large, uniformly colored areas, the lossless PNG format is best suited for editing pictures, and the lossy formats, like JPG, are best for the final distribution of photographic images, because JPG files are smaller than PNG files.

The GIF (Graphics Interchange Format) format is limited to an 8-bit palette, or 256 colors, this makes the GIF format suitable for storing graphics with relatively few colors such as simple diagrams, shapes, logos and cartoon style images.
It uses a lossless compression that is more effective when large areas have a single color, and ineffective for detailed images or dithered images.

Each format has it’s own structure and in order to be able to manipulate images deeply you have to refer to each specific format, here is a list of all the file format specifications http://www.martinreddy.net/gfx/2d-hi.html.

You can consider the image manipulation process divided into two separate steps, the image transformation (rotation, zoom, vertical flip, mirroring, etc.) and the pixel manipulation.
In order to perform transformation the most efficient in Flex and in ActionScript is the affine geometry.

Affine geometry is a form of geometry featuring the unique parallel line property where the notion of angle is undefined and lengths cannot be compared in different directions, it is a generalization of Euclidean geometry characterized by slant and scale distortions.
Affine geometry can be developed in terms of the geometry of vectors, with or without the notion of coordinates, so an affine space is distinguished from a vector space of the same dimension by ‘forgetting’ the origin (sometimes known as free vectors).
Affine geometry can be seen as part of linear algebra, re-open your high school books and take a deep breath!

In linear algebra, linear transformations can be represented by matrices.
Matrices allow arbitrary linear transformations to be represented in a consistent format, suitable for computation (i.e. your transformation data are represented in a way that can be used with any software)…this also allows transformations to be concatenated easily (by multiplying their matrices).

For rotation by an angle θ clockwise about the origin, the functional form is x’ = xcosθ − ysinθ and y’ = xsinθ + ycosθ

Written in matrix form, this becomes

To represent affine transformations with matrices, we must use homogeneous coordinates, this means representing a 2-vector (x, y) as a 3-vector (x, y, 1), and similarly for higher dimensions.
All ordinary linear transformations are included in the set of affine transformations, and can be described as a simplified form of affine transformations hence, any linear transformation can be also represented by a general transformation matrix.

A matrix is a rectangular array (or table) of numbers consisting of any number of rows and columns it consists of m rows and n columns is known as an m x n matrix, this value represents the matrix’s dimensions.
You’ll commonly seen matrices with numbers in rows and columns surrounded by two large bracket symbols

Affine transformations are transformations that preserve collinearity and relative distancing in a transformed coordinate space, this means points on a line will remain in a line after an affine transformation is applied to the coordinate space in which that line exists.
It also means parallel lines remain parallel and that relative spacing or distancing, though it may scale, will always maintain at a consistent ratio.

Flash provides a 3 x 3 matrix in which u,v,w are sort of dummy here though their values remain as 0, 0, 1
You can manipulate the others properties (a,c,c,d,tx and ty) in order to get a transformation, following some examples

  • Translation: tx or ty changes would move either x pixels or y pixels
  • Scale: a or d changes would affect xScale or yScale
  • Skew: b or c changes skew either parallel to the x or y axis
  • Rotation: a,b,c and d changes affect the rotation (for an angle θ  a is cos(θ ), b is sin(θ ), c is -sin(θ ) and d is cos(θ ))

The properties of the Matrix class in ActionScript are basically just a collection of your main a, b, c, d, tx, and ty properties those you need to be concerned about when dealing with transformations, additional methods are also provided to make working with these matrices easier.
Some of the more common methods are:

translate(tx:Number, ty:Number) : voidscale(sx:Number, sy:Number) : void

rotate(angle:Number) : void

identity() : void

Flash Player 10 expands greatly on the drawing API in ActionScript, more so than any other version of the Flash Player since the initial introduction of the drawing API in Flash Player 6
New features include:

  • Use of vectors (typed arrays) for improved throughput and use of memory
  • Support for non-zero winding rules
  • An API for drawing triangles with support for 3D perspective rendering
  • Drawing API data objects

The introduction of vectors help a lot developers to make more efficient and powerful transformations

Vectors are almost exactly like arrays at their core, having pretty much the same API

There are only a few real differences:

  • Elements within a vector all share the same type
  • Vectors have an additional property, fixed, which determines whether or not the length of the vector can change dynamically
  • The vector constructor allows for two optional arguments, length and fixed
  • There is no equivalent to the bracket ([]) array constructor

The Graphics class contains now the drawTriangles method

public function drawTriangles(vertices:Vector.<Number>, indices:Vector.<int>=null, uvtData:Vector.<Number>=null, culling:String="none");

This method uses a Vector.<Number> to specify point locations for a path to be drawn, only with drawTriangles, the commands internally are predefined to use the point locations to draw triangles (Every 3 points, i.e. 6 numbers, represents a triangle path to be drawn)

It seems now that we are starting to talk about 3D because 3D models (in the end) are represented by a collection of triangles in space this is a good starting point for the 3D… Why talking about 3D in Flash if we are dealing with images manipulation?

Trough triangle the transformations are now faster and accurate, affine transformations and the division in triangles of an image help you to get a better image manipulation procedure, see the demo to understand that the drawing mechanism is totally different (no cutting on the sides of the image as if you are working with the classic bitmap transformation.

Let’s start now with some building blocks you need in order to play with pixels and better understand the code that is contained in the luminance, gray scale, tint and red eye correction demos you’ll get at the end of this post.

In order to perform advanced manipulation on an image you need to start to play with the pixels of an image, ActionScript provides a lot of class to help you on this task, the most relevant are

  • Bitmap
  • BitmapData

The Bitmap class represents display objects that represent bitmap images data, These can be images that you load with the flash.display.Loader class, or they can be images that you create with the Bitmap() constructor.

The Bitmap() constructor allows you to create a Bitmap object that contains a reference to a BitmapData object.
After you create a Bitmap object, use the addChild() or addChildAt() method of the parent DisplayObjectContainer instance to place the bitmap on the display list.
I said “image data”, the BitmapData class let you play with this data (i.e. pixels).
You can use the methods of the BitmapData class to create arbitrarily sized transparent or opaque bitmap images and manipulate them in various ways at runtime.
This class lets you separate bitmap rendering operations from the internal display updating routines of Flash Player and moreover by manipulating a BitmapData object directly, you can create complex images without incurring the per-frame overhead of constantly redrawing the content from vector data.
Each 32-bit integer is a combination of four 8-bit channel values (from 0 to 255) that describe the alpha transparency and the red, green, and blue (ARGB) values of the pixel.
There is a complete list of all the method of the class in the ActionScript documemntation, I would like to point your attention on the histogram method added to the player 10 that computes a 256-value binary number histogram of a BitmapData object

histogram(hRect:Rectangle = null):Vector.<Vector.<Number>>

This is one of the key to play with the luminance effect in Flex.
Trough the combination of different pixel manipulation methods you can get complex effects like luminance
Relative luminance follows the photometric definition of luminance, but with the values normalized to 1 or 100 for a reference white.
Like the photometric definition, it is related to the luminous flux density in a particular direction, which is radiant flux density weighted by the luminosity function of the CIE Standard Observer.
For RGB color spaces that use the ITU-R BT.709 primaries relative luminance can be calculated from linear RGB components:

Y = 0.2126 R + 0.7152 G + 0.0722 B

Let see the demos to see a lot of pixel manipulation in place, in order to get the source of the effects you see here please refer to the nabiro images packaging you can get here http://agile.gnstudio.com/nabiro.

Code tuning techniques

Code tuning techniquesCode tuning differs a lot from refactoring because it doesn’t always improve code readability, and changes that you make are not meant to improve the internal structure of a software.
If the changes performed in the code don’t degrade the code’s readability, we believe that you are refactoring rather than fine-tuning.

One of the practices most of the fine tuning papers recommend is to stop testing a condition when an answer is known; this means that it could be better to split a short circuit evaluation into two separate evaluations, but this is not true in the Flash Player, if you make a simple test like this


private function testShortCircuit():void{
var start:int;
start = getTimer();

for(var i:int = 0; i < 100000000; i++){

    if(i > 3000000 && i < 4000000){

        break;

    }

}

trace("Short circuit", (getTimer() - start))

start = getTimer();

for(var j:int = 0; j < 100000000; j++){

    if(j > 3000000){

        if(j < 4000000){

            break;

        }

    }

}

trace("Not short circuit", (getTimer() - start));

you’ll get a result that clearly shows that short circuit in the Flash Player is faster

Short circuit 307
Not short circuit 331

Arrange tests in the conditional statements by frequency, putting the most common case as the first condition to evaluate is a good strategy for increasing performance.

We strongly recommend grouping together loops that operate on the same set of elements, so that you can remove a loop and acquire a lot of speed processing.

When dealing with nested loops we recommend always putting the busiest loop in the inside and moving the one with fewest iterations to the outside.

There are many common mathematical operations that can be done faster than usual

Operation                  Faster solution

Math.floor(1.5);         int(1.5);
Math.ceil(1.5);          int(1.5) + 1;
Math.abs(value);         var test:Number = value < 0 ? value * -1 : value;
value / 2;               value >> 1
value * 2;               value << 1

If you need some values multiple times in a component / class and these values need to be calculated we suggest that you calculate them only once and put the in constants for faster access

private const SOME_VALUE:Number = Math.sqrt(Math.pow(Math.PI, 10));

If the calculation varies during the execution of the class we suggest putting it in a method and avoiding having multiple pieces of code for the same calculation duplicated in the code.

Other resources

http://www.adobe.com/devnet/flex/articles/client_perf.html

Flex item renderers, an expandable list with transitions

I think that each flex developer at a certain point have had the necessity to work with custom item renderers in order to display data in a fancy way.
There is a lot of knowledge around the web regarding this topic but I want to show the process that has driven me to a list that contains custom item renderers with different states and with transitions between each state.
In order to perform this task I’ll show to you how you can create a simple item render, an item renderer with two different states, an item render with some transitions with a visual bug (it’s the default rendering of the list) and one without any bug.
I know that an expandable list can be done also with a VBox and Repeater and that it perform nicely but the list has a caching procedure of the item renderers that is very useful when you have to render on the screen a great number of complex renderers.

A simple item render
Imagine the simple scenario in which your layout require something more than a label in a list and you need to add for instance a “buy now” button, you can create an MXML component

<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
verticalScrollPolicy="off" horizontalScrollPolicy="off"
paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5">
<mx:Button label=" Buy now " enabled="false"/>
<mx:Label text="{data.name}"/>
</mx:HBox>
and set it as the item renderer in the List control
<mx:List id="list" height="300" dataProvider="{listData}" itemRenderer="SimpleRenderer" />

The dataprovider is an ArrayCollection that contain several Article value objects, the class that define an article can be summarized with the following UML diagram

A multi state item render
Imagine now the scenario in which an item renderer needs to show some data and expand itself in order to display on the screen more information about this item, first of all create an MXML component that extends the VBox and that contain three different states, in the first one the component have to show the article name and a button to expand the content

in the second state the component needs to render the price of the article, a “buy now” button and a control in order to expand the third state

In the third state the component has to render the details of the article

In order to complete this task you can define the UI of the component with the following MXML using the <mx:states> tag to define states, label and event handler

<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:HBox>
<mx:Button label="Expand" id="_expand" click="currentState='opened'"/>
<mx:Label text="{this.name}"/>
</mx:HBox>
<mx:states>
<mx:State name="opened" >
<mx:SetProperty target="{_expand}" name="label" value="Collapse"/>
<mx:AddChild position="lastChild">
<mx:HBox id="_dataRender"  width="100%" verticalAlign="middle" >
<mx:Label id="_article"  text="Article" width="80"/>
<mx:Label id="_price" text="Price" width="80"/>
<mx:Button label="Order"/>
<mx:Spacer width="100%"/>
<mx:Button label="Show Details" id="_details" click="currentState='details'"/>
</mx:HBox>
</mx:AddChild>
<mx:SetEventHandler target="{_expand}" name="click" handler="currentState=''"/>
</mx:State>
<mx:State name="details" basedOn="opened">
<mx:AddChild position="lastChild">
<mx:Text id="_detailsData" text="Description" width="100%" height="60" />
</mx:AddChild>
<mx:SetProperty target="{_details}" name="label" value="Hide Details"/>
<mx:SetEventHandler target="{_details}" name="click" handler="currentState='opened'"/>
</mx:State>
</mx:states>
</mx:VBox>

If you come back to the list and set this component as an item renderer you will see that the nested states are not rendered, you have to define the List as a variable row list

<mx:List id="list" height="300" dataProvider="{listData}" itemRenderer="SimpleRendererStates"  variableRowHeight = "true" />

Now the list is able to render the nested states but if you scroll up and down the list you will see that the states and the data of each item renderer are not consistent with your model, this is due to the List behavior that recycle components in order to render data, when items scroll out of view, its itemRenderer will be moved to the bottom of the list.
In order to keep state and data consistent you have to perform some changes in your code, first of all my suggestion is to create a class that can hold state information and data of each item (in this way also if you work with remote value object you don’t need to make any change on the server side), the class can be summarized with the following UML diagram

the state property contains a string that represent the currentState of the component, the renderData property represents the data you need to display in the components.
Inside your component override the public data method in order to be sure that each time the data changes (each time the list is scrolled) the UI elements are updated

override public function set data(value:Object):void{
super.data = value;
if(!data)return
var dt:Article = data.renderData;
if(_article)_article.text = dt.name;
if(_price)_price.text = String(dt.price);
if(_detailsData)_detailsData.text = dt.description;
invalidateProperties();
dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}

Please not that in the method the article value object has been extracted from the object used to define the data of each item.
In order to keep track of the state of each item render override the currentState method and store the value of the new state in the model

override public function set currentState(value:String):void{
super.currentState = value;
if(data)data.state = value;
}

Now is the time to handle the state value in the commitProperties protected method

override protected function commitProperties():void{
super.commitProperties();
if(!data)return;
currentState = data.state;
}

The List component needs to know the dimension of the item render in order to gracefully adapt each item to its state, this is the reason why in the measure() method you have to explicitly set the values of the properties measuredHeight and measuredMinHeight for each state

override protected function measure():void{
super.measure();
if(!data)return;
switch(true){
case currentState == "":
measuredHeight = 30;
measuredMinHeight = 30;
break;
case currentState == "opened":
measuredHeight = 70;
measuredMinHeight = 70;
break;
case currentState == "details":
measuredHeight = 110;
measuredMinHeight = 110;
break;
}
}

If you compile your application now the item renders display the data and the states in a consistent way.

A multi state item render with transitions
In order to add a transition between each state of the your item renderer add the following MXML tags to the previous component and save it with a different name

<mx:transitions>
<mx:Transition fromState="*" toState="*">
<mx:Resize target="{this}" />
</mx:Transition>
</mx:transitions>

If you try now the list with this item renderer you’ll be surprised, the transitions don’t perform very well because the item renderer doesn’t know anything about the state in the data method so use an event handler for the StateChangeEvent.CURRENT_STATE_CHANGE event

protected function onStateChange(e:StateChangeEvent):void{
if(!data)return
var dt:Article = data.renderData;
if(e.newState == ""){
dt.opened = 0;
}
if(e.newState == "opened"){
dt.opened = 1;
}
if(e.newState == "details"){
dt.opened = 2;
}
}

and store a specific int value in the opened property of each value object.
In the overridden data method add a switch case to handle this value

switch(true){
case dt.opened == 0:
currentState = "";
break;
case dt.opened == 1:
currentState = "opened";
break;
case dt.opened == 2:
currentState = "details";
break;
}

Now your item renderer is able to handle state and transitions but you’ll see that scrolling the List when it has to render again an item each transition is rendered with a delay, this is due to the live cycle of the List that calls a last udpateDisplayList after a while, in order to solve this stuff you have to put your hands inside the List source code and create an easy reusable class for the item render.

A smart multi state item render with transitions
Surfing the web I found a nice article on item renderers but when I read this sentence “I think a resizing itemRenderer is too complex and not really worth the effort. I believe there is a better way to do this using VBox and Repeater. However, the catch with Repeater is that every child will be created. If you have 1000 records and use a Repeater, you will get 1000 instances of your itemRenderer.” my mind started to think to a solution because with a great number of instances of a complex item renderer the performance of each Flex application can be seriously impacted.
I started to read the source code of the List and I found the two methods that recycle or create the item renderers in the list

getReservedOrFreeItemRenderer(data:Object):IListItemRenderer
createItemRenderer(data:Object):IListItemRenderer

In order to avoid the delay I need to change the state of each item renderer in these two methods, the first issues I found are that the transitions defined in the item renderer stop to work and that the height is not rendered.
The other issue I found is that without a base class each time I would like to use smart item renderers in my List I have to start over.
The solution I found is create a VariableRowList  class that extends the List, define a base class for item renderers (I started with a class for VBox based item renderers), define an interface that define a method to use in order to update the state and the height and define the effects I need outside the <mx:tranisitions> tag.
The VariableRowList  class makes an override of the methods used in order to create and recycle the item renderers and attempt to call the method defined in the interface ISmartRenderer the renderer needs in order to handle its state and its height at the end of each method

try{
ISmartRenderer(item).updateState(dt.state);
}catch(e:Error){
trace("It's not an ISmartRenderer implementors")
}

The ExpandableVBoxRenderer class first of all implements two interfaces, IDropInListItemRenderer and ISmartRenderer, and define a constant that hold an array of objects used to define the heights for each state

protected const STATES_HEIGHT:Array = [{state: "", height: 30}, {state: "opened", height: 60}, {state: "details", height: 110}];

In the constructor of this class you find the definition of a listener for the StateChangeEvent.CURRENT_STATE_CHANGE  and for the FlexEvent.CREATION_COMPLETE events and the policy for the scroll bars

this.addEventListener(StateChangeEvent.CURRENT_STATE_CHANGE, onStateChange);
this.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
this.verticalScrollPolicy = ScrollPolicy.OFF;
this.horizontalScrollPolicy = ScrollPolicy.OFF;

The override of the data method use a protected method populateControl() that use the data stored in the  renderData property of the SmartRenderData class in order to populate the UI elements (this method is empty and need to be overridden from the classes that extend the ExpandableVBoxRenderer)

override public function set data(value:Object):void{
super.data = value;
if(!data)return;
data.state = currentState;
populateControl(data.renderData);
invalidateProperties();
dispatchEvent(new FlexEvent(FlexEvent.DATA_CHANGE));
}

In the override of the measure method the class calculates the needed height trough a private method that get the data from the STATES_HEIGHT constant

override protected function measure():void{
super.measure();
if(!data)return;
var currentHeight:Number = recoverHeight(currentState || "");
measuredHeight = currentHeight;
measuredMinHeight = currentHeight;
}

The updateState method defined in the ISmartRenderer interface update the state and the height of the component and call the measure method

public function updateState(state:String):void{
currentState = state;
height = recoverHeight(state);
measure();
}

If you want now start to use this stuffs define the namespace you need to use the VariableRowList   class in your application and place these tags in place of the List you have used before

<gn:VariableRowList dataProvider="{listData}" itemRenderer="it.mxml.expandableList.view.ExtendedRenderer" />

Define now a new class that extends the ExpandableVBoxRenderer and use it as the base class for a new MXML component that will have the same tags of the one you defined in order to handle the transitions except for the transitions that will be removed and that will be substituted from the following effects

<mx:Resize id="openInfo" duration="205" heightFrom="30" heightTo="60" target="{this}" />
<mx:Resize id="openDetails" duration="205" heightFrom="60" heightTo="110" target="{this}" />

Came back in the class and define the public members that point to the controls defined via MXML

[Bindable]public var _article:Label;
[Bindable]public var _price:Label;
[Bindable]public var _detailsData:Text;
[Bindable]public var _details:Button;
[Bindable]public var _expand:Button;

Override the populateControls() method in order to render the data inside the item renderer

override protected function populateControl(data:Object):void{
if(_article)_article.text = data.name;
if(_price)_price.text = data.price;
if(_detailsData)_detailsData.text = data.description;
}

and define the handlers for the click event on the buttons in order to play the effect defined trough MXML (see in the source of the sample application to check the other handlers)

private function onDetails(e:MouseEvent):void{
if(e.target.label == "Show Details"){
currentState = "details";
this["openDetails"].play()
}else{
currentState = "opened";
this["openDetails"].play(null, true)
}
}

In this way your List will be able to render the data and the transition like a charm, check the sample application and the source code (right click, view source) in order to read the complete implementation.

Resources
http://www.returnundefined.com/2006/10/item-renderers-in-datagrids-a-primer-for-predictable-behavior

http://blogs.adobe.com/aharui/item_renderers/

http://flexdiary.blogspot.com/2007/11/order-of-events-for-itemrenderers.html

http://www.adobe.com/devnet/flex/articles/itemrenderers_pt4_print.html