`
y_yqing
  • 浏览: 13857 次
  • 来自: ...
社区版块
存档分类
最新评论

在Flex中处理图像

阅读更多

转自 http://www.insideria.com/2008/03/image-manipulation-in-flex.html

It seems that the number one request I get for development work is creating applications that do image manipulation or vector drawing or a combination of the two. This article is about my experiences in building applications in Flex to manipulate images. It will cover the basics of loading an image, saving a reference to it, adjusting color, applying pixel effects, changing its dimensions and orientation and ultimately saving these changes. The aim of this article is not to provide production ready solutions but instead to provide ideas for implementing image manipulation solutions in Flex.

Loading image data

The first thing you need to know about loading images into the Flash Player is the limits the Player has with respect to the maximum size of display objects and the maximum size of bitmap data. Currently the Flash Player has a hard coded limit as to the size of bitmap data you can create in the Flash Player (Flash Player 9 and earlier. I am hoping these limits are removed in Flash Player 10). If you create a new BitmapData object in ActionScript it cannot exceed a size of 2880 x 2880. These values are hard coded into the Flash Player and will result in an ‘Invalid BitmapData’ exception if they are exceeded.

For display objects there are no hard coded values (that I have been able to determine) but through testing I have discovered that if a display object exceeds 8191 x 8191 it won’t be rendered. This also applies to the dimensions of images being loaded. If the dimensions of the image exceed this size it will load but it will not be rendered on the display list. So theoretically you can load an image that is up to 8191 x 8191 but if you plan on accessing its bitmap data it can’t exceed 2880 x 2880. More on this below. One thing to keep in mind is that these limits (in the case of BitmapData anyways.) are related to memory allocation so the larger the image you load the more memory you will consume. Ultimately you are going to want to either limit the size of the image a user can load or scale the image down in your application so let’s look at this now.

For simple projects you could just load the image into an image tag and manipulate it. For more complex applications that require functionality like zoom, pan, multiple copies of same image ( for example a thumbnail and full size version) or non destructive editing a better strategy is to load the image with a Loader and store the bitmap data of the image in a variable. You can then use this data to create multiple bitmaps and apply different manipulations to each. This will greatly decrease the amount of memory used and create a faster more responsive application.

In the sample code below you will see how to load an image with the Loader class and store the bitmap data in a variable, scaling it down if necessary.

private var original:BitmapData;
private static const MAX_WIDTH:uint = 2880;
private static var MAX_HEIGHT:uint = 2880;


private function loadImage(url:String):void
{
 var request:URLRequest = new URLRequest(url);
 
 	var imageLoader:Loader = new Loader();
 imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, image_completeHandler);
 	// add other listeners here
 	imageLoader.load(request)
}
			
private function image_completeHandler(event:Event):void
{
 	var bmd:BitmapData = Bitmap(event.currentTarget.content).bitmapData;
 				
 	var originalWidth:Number = bmd.width;
 	var originalHeight:Number = bmd.height;
 	var newWidth:Number = originalWidth;
 	var newHeight:Number = originalHeight;
 			
 	var m:Matrix = new Matrix();
 			
 	var scaleX:Number = 1;
 	var scaleY:Number = 1;
 
 	if (originalWidth > MAX_WIDTH || originalHeight > MAX_HEIGHT)
 	{
  		sx =  MAX_WIDTH / originalWidth;
  		sy = MAX_HEIGHT / originalHeight;
  		var scale:Number = Math.min(sx, sy);
  		newWidth = originalWidth * scale;
  		newHeight = originalHeight * scale;	
  	}
 	m.scale(scale, scale);
 	original = new BitmapData( newWidth, , newHeight); 
 				
 	original.draw(bmd, m);
 				
}



Let’s walk through the code.
We first create a variable to store the bitmap data of the image that we are loading. We then create 2 constants for the maximum width and height this bitmap data can be.

In the loadImage method we take the url of the image as a parameter, create a new URLRequest object with it. We then create a new Loader and attach an event listener to its complete event (other listeners can be added but we are only interested in this event right now). We then call the load method of the loader with the URLRequest as its parameter.

In the event handler we need to access the content property of the loader instance that loaded the image. The content in this case is a Bitmap object. Within a Bitmap there is a property called bitmapData which contains an array of pixel data for this Bitmap. This data is an instance of the BitmapData class.

Once we have a reference to the bitmapData we can check its dimensions and if they exceed our maximum size we can draw it to a new bitmapData object at a new size. To accomplish this we get the amount we need to scale and create a new BitmapData object at this new size. We then use the draw method of the BitmapData class to draw the loaded image to the new BitmapData object and use a matrix to provide the new scale. This BitmapData can now be stored in a variable and used to create as many bitmaps you need each with its own transformations. The transformations applied to you bitmaps don’t affect the original BitmapData so you can always use it as a reference. Now that we have a bitmap data instance that we can use let’s do something with it.

Adjusting Color

One of the things that you are probably going to want to do when manipulating an image is adjust its color. Within the Flash Player API’s there are a number of ways to do this but no matter which you choose what you are basically doing is changing the red, green and blue (and possibly alpha) values of the image. The two main ways to change the values is to either use a ColorTransform or a ColorMatrixFilter. Let’s look at each and how they differ and when to use each.

Using ColorTransform

ColorTransform universally adjust the values of the red, green and blue channels of a display object . Depending on whether you are manipulating a bitmap or a display object the color transform is applied differently. For a display object it is a property of the transform object. For bitmaps it is passed as a parameter to the colorTransform method. To adjust the color you either create a new instance of ColorTransform or get a reference to an existing one and change the red, green and blue values and/or offsets.

Adjusting brightness with a ColorTransform:

*to adjust brightness you change the offsets of the red, green, and blue channels equally

var ct:ColorTransform = new  ColorTransform();
ct.redOffset = value;
ct.blueOffset = value;
 ct.greenOffset = value;
image.transform.colorTransform = ct; // apply the transform to a display object




Using ColorMatrixFilter

The ColorMatrix filter uses a 4 x 5 matirx to adjust the values. Unlike the ColorTransform which universally adjusts the red, green and blue channels, the ColorMatrixFilter adjusts each pixel. The speed of the ColorMatrixFilter is proportional to the size of the image (the number of pixels to change).

Adjusting brightness with a ColorMatrixFilter:

var cmf:ColorMatrixFilter = new ColorMatrixFilter( [ red, green, blue,0, 0, red, green, blue, 0, 0, red,green, blue, 0, 0, 0, 0, 0, 1, 0 ]);

var filtersArray:Array = new Array();
filtersArray.push(cmf);

image.filters = filtersArray;or 
var matrix:Array = new Array();
matrix = matrix.concat([1, 0, 0, 0, value]); // red
matrix = matrix.concat([0, 1, 0, 0, value]); // green
matrix = matrix.concat([0, 0, 1, 0, value]); // blue
matrix = matrix.concat([0, 0, 0, 1, 0]); 	// alpha
var cmf:ColorMatrixFilter = new ColorMatrixFilter(matrix); 

var filtersArray:Array = new Array();
filtersArray.push(cmf);

image.filters = filtersArray;



No matter which you choose you have to remember that each pixel is broken down into its red, green, blue and alpha channels and the range for each channel is 0 to 255. Any values less than 0 will be set to 0 (0x00) and any values greater than 255 will be set to 255 (0xFF). With each of them you can apply multiple effects simultaneously but it is difficult to undo incremental changes made by concatenating multiple ColorTransform objects together. If you use the filter approach undoing one of your effects is as easy as removing it from the filters array and reapplying the array to the display object. With the filter approach you can also apply multiple filters by pushing each of them into the filters array and turning them off by removing them but the filter approach is slower if you have a larger image. More information on the differences can be found in the Flex documentation.

More examples of adjusting color
*Note - there are different formulas that can be used to calculate the values and offsets for these. The ones used here were taken from the Actionscript 3 Cookbook by Joey Lott, Darron Schall and Keith Peters.

Contrast
You adjust brightness by either scaling or offsetting the color values. You change contrast by changing both with all the values being equal and all of the offsets being equal. *value is a number between 0 and 1

var a:Number = value * 11; 
var b:Number = 63.5 - (value * 698.5); 
redValue = greenValue = blueValue = a; 
redOffset = greenOffset = blueOffset = b; 
var cmf:ColorMatrixFilter = new ColorMatrixFilter(a, 0, 0, 0, b, 0, a, 0, 0, b, 0, 0, a, 0, b, 0, 0, 0, 1, 0); 

 

Saturation


These are the constants for the luminance contrasts for the red, green and blue channels

var red:Number = 0.3086; // luminance contrast value for red 
var green:Number = 0.694; // luminance contrast value for green 
var blue:Number = 0.0820; // luminance contrast value for blue 
var a:Number = (1-value) * red + value; 
var b:Number = (1-value) * green; 
var c:Number = (1-value) * blue; 
var d:Number = (1-value) * red; 
var e:Number = (1-value) * green + value; 
var f:Number = (1-value) * blue; 
var g:Number = (1-value) * red ; 
var h:Number = (1-value) * green; 
var i:Number = (1-value) * blue + value; 
var cmf:ColorMatrixFilter = new ColorMatrixFilter(a, b, c, 0, 0, d, e, f, 0, 0, g, h, i, 0 ,0, 0, 0, 0, 1, 0); 


Grey Scale
Apply a grey scale effect by red, green and blue values to their luminance contrast values.

var red:Number = 0.3086; // luminance contrast value for red 
var green:Number = 0.694; // luminance contrast value for green 
var blue:Number = 0.0820; // luminance contrast value for blue 
var cmf:ColorMatrixFilter = new ColorMatrixFilter(red, green, blue, 0, 0, red, green, blue, 0, 0, red, green, blue, 0, 0, 0, 0, 0, 1, 0); 
Negative 


Apply a negative effect by reversing the values of the matrix

var cmf:ColorMatrixFilter = new ColorMatrixFilter(-1, 0, 0, 0, 255, 0, -1, 0, 0, 255, 0, 0, -1, 0, 255, 0, 0, 0, 1, 0); 



Applying Effects

Unlike other aspects of image manipulation there is really only one way to apply effects to your images, a ConvolutionFilter. Like the ColorMatrixFilter, the ConvolutionFilter also uses a matrix to change the image but in this case the matrix can be any size. There are a number of factors that affect performance and they are outlined in the Flex documentation. The most common matrix you will use is a 3x3 matrix. Applying effects is basically the same as applying color effects - you create a filter and add it to the filters array of the display object. Here are some common filters (the first two parameters are the dimensions of the matrix and the third is the matrix).
*the values I am using here are also taken from the Actionscript 3 cookbook

Embossing
Use a negative value in the center and opposite values on each side.

var emboss:ConvolutionFilter = new ConvolutionFilter(3, 3, [-2, -1, 0, -1, 1, 1, 0, 1, 2]) 

 
Edge Detection
Use a negative value in the center with symmetrical surrounding values

var edge:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, 1, 0, 1, -3, 1, ,0, 1, 0])

 

You can change the center value (-3) to apply more or less of an effect. The smaller the number the more of an effect is applied.

Sharpening
This is the opposite of the Edge Detection matrix - a positive value in the center with symmetrical negative values

var sharpen:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, -1, 0, -1, 5, -1, 0, -1, 0]); 

 The larger the center value the less drastic the effect.
There are other parameters and properties of the ConvolutionFilter that can give some very interesting effects so I encourage you to experiment with them.

Rotating and Flipping

Like color adjustments there are different ways to rotate and/ or flip (mirror) an image in the Flash Player. The first way would be to simply change the rotation, scaleX, and scaleY properties of the display object. This may be fine for simple applications but for more complex applications you will want to use a matrix to manipulate these properties. As noted in the in the Adjusting Color section, each display object has a property called ‘transform’ which contains all of the transformations applied to the display object. The ‘matrix’ property is used to move, rotate, scale and skew the display object. As an example let’s scale the image to twice its original size.
To use the matrix to make changes you get a reference to the matrix (you can’t change the matrix directly)

var m:Matrix = image.transform.matrix; 

//make your changes (scale it in the x and y direction by a factor of 2) 

m.scale(2, 2); 

//and reapply the matrix to the display object 

image.transform.matrix = m; 

 


One thing of note - If you get a reference to the matrix and then make changes all of your changes will be applied onto any changes that have already been applied. In other words they are applied incrementally. As an example if the matrix for the display object already has a rotation of 30 and you apply a rotation of 10 the result will be a rotation of 40.If this is not your desired effect you can simply create a new Matrix and apply it instead of referencing the matrix that already exists.
The other reason a matrix is the better choice is that you can pass it as a parameter in bitmapData.draw. This allows you to make multiple changes and then using you original bitmap data you can draw a new image with all of these transformations.
If you look at the example under ‘Loading image data’ you will see we used a matrix to scale the image down after it was loaded.

Rotating
To use a matrix to rotate an image you either create a new Matrix with appropriate parameters

var q:Number  = 30 * Math.PI / 180 // 30 degrees in radians 

var m:Matrix = new Matrix(Math.cos(q), Math.sin(q), -1 * Math.sin(q), Math.cos(q)); 

//or as a shortcut use the rotate method 

var m:Matrix = new Matrix(); 

m.rotate(q) ; 

 

When you rotate something in the Flash Player it will rotate around its registration point. This by default is the top left corner. If you want to rotate it around a different point you will need to offset it in the negative direction, do the rotation and then put it back where it was.

var m:Matrix = new Matrix(); 

// rotate around the center of the image 

var centerX:Number = image.width / 2; 

var centerY:Number = image.height /2; 

m.translate(-1 * centerX, -1 * centerY); 

m.rotate(q); 

m.translate(centerX, centrerY); 

 

 

Flipping
To flip and image is a 2 step process. The first step is to multiply the current scaleX and/or scaleY by -1 and the second is to adjust the x and y position. When you flip and image the registration point does not change and its drawn in the opposite direction. To compensate you will need to change the x position by its width and its y position by its height.

var m:Matrix = new Matrix(); 

m.scale(-1, 0); // flip horizontal assuming that scaleX is currently 1 

m.translate(image.width, 0); // move its x position by its width to put it in the upper left corner again 

 

 

Cropping, Panning and Zooming

Like everything else we have looked at, there are different ways to change the area of an image that you see. You could change the x, y, width and height properties on the display object or a Rectangle to mark out the pixels you want to see.

There are a few reasons that changing the size of the display object is not the best solution. If the user zooms in enough to make the display object larger than 8191 x 8191 it simply will no longer be rendered. Also if you are applying filters with a matrix the new value of each pixel needs to be calculated which can have dire consequences on performance. You only want to apply you filters to the pixels that the user actually sees. The better approach is to redraw the area of the image that the user wants to see using bitmapData.draw and a matrix.

Since you are storing a reference to the original bitmap data of the image you can use a Rectangle to draw any area of that data onto a new bitmap and then use a matrix to scale it to fit the area of the screen it is displayed in.

When you first load the image you set the rectangle to the dimensions of the original bitmap data and store it in an instance variable

var zoomArea:Rectangle 

zoomArea = original.rect // rect is a property of bitmapData containing the rectangle of the data 

 

 

The properties of zoomArea can be updating if you want to zoom in or out or pan the image around. The rectangle can then be used to draw an area of the original bitmapData onto a new bitmap.
To pan the image around you can adjust the left and top position of the rectangle through its offset property.

zoomArea.offset(panX, panY); 
To zoom in or out you adjust the size of the rectangle 

zoomArea.inflate(newWidth, newHeight); 

 

Once you have made the adjustments you can then draw a new bitmapData with the dimensions of zoomArea using the copyPixels method of the bitmapData class. The copyPixels method takes a rectangle as the second parameter.

var newBitmapData:BitmapData = new BitmapData(zoomArea.width, zoomArea.height) 

newBitmapData.copyPixels(original, zoomArea, new Point(0, 0)); 

 The copyPixles method is a fast way to copy bitmap data but it will reset any transformations you have made so these all need to be replied. You could also use the rectangle as the clipRect parameter of the bitmapData.draw method.

Printing and Encoding

Once your user has made all of these changes they are probably going to want to print or save them. The Flex 3 SDK now contains a great way to capture these changes. In the mx.graphics package there is a class called ImageSnapshot and this can be used to capture the bitmapData of you image to print or create a jpeg or png to save. You can event use it to encode a byte stream to send to the server. I am not going to go too deeply into this but will mention that if you used a matrix to draw your bitmap then the resolution will now be at screen resolution regardless of what the dpi was before it was loaded. If you simply send the display object to the printer from the stage it will probably appear pixelatted. You will want to capture the display object with the ImageSnapshot.captureImage and scale it up to about 300 dpi to get a crisper image.

Where to go from here

Image manipulation is a broad subject and there are a lot of different approaches you can take. It really comes down to the project requirements. I hope this article gave you some insight into the different approaches you can take. For maximum speed and performance in your application you should familiarize yourself with the Flash Player APIs mentioned in this article. They include Loader, Bitmap, BitmapData, Matrix, Rectangle, Math, ImageSnapshot, JPEGEncoder, PNGEncoder, PrintJob, FlexPrintJob and all of the bitmap filters.

 

分享到:
评论

相关推荐

    flex 图片操作

    在本话题中,我们将探讨“flex图片操作”,这涉及到如何使用Flex来处理和展示图片,包括调整角度和应用滤镜等视觉效果。 一、Flex中的图片显示 在Flex中,我们可以使用`mx.controls.Image`组件来显示图片。这个...

    flex 两个图片播放小程序

    在图片浏览功能上,Flex可以利用BitmapData类来处理图像。BitmapData允许开发者直接操作像素,进行缩放、旋转、裁剪等各种图像操作。在图片加载完成后,可以创建一个BitmapData对象,然后通过这个对象实现图片的动态...

    图片压缩flex demo

    它涵盖了文件I/O、图片加载、图像处理和压缩算法等多个知识点,对于理解如何在Flex环境中处理图片资源非常有帮助。通过这个示例,开发者可以学习如何优化图片质量和大小,提高应用程序的性能和用户体验。

    Flex 修改图片主色调

    在Flex中处理图像是一项常见的任务,而“Flex 修改图片主色调”涉及到的是图像处理和色彩理论的知识点。以下是对这个主题的详细阐述: 1. **Flex中的图像处理**: 在Flex中,我们可以使用`flash.display.Bitmap`类...

    Flex 图片压缩、上传

    Flex作为一个开源的、基于ActionScript的富互联网应用程序(RIA)框架,提供了丰富的组件和API来处理图像处理任务。这篇博文“Flex 图片压缩、上传”可能探讨了如何在Flex环境中实现图片的压缩和上传功能。 首先,...

    Flex 上传图片 预览 加载图片到内存

    在Flex中处理图片上传并实现预览功能,是一项常见的需求。本篇文章将详细讲解如何在Flex中实现实时图片预览和加载图片到内存的技术。 首先,我们要明白Flex中的图片处理主要是通过`mx.controls.Image`组件来完成的...

    Flex 自定义组件ImageViewer

    Flex是Adobe开发的一种开源框架,主要用于构建富互联网应用程序(RIA)。在Flex中,自定义组件是开发者根据...通过深入研究ImageViewer组件的实现,我们可以掌握如何在Flex中处理图像展示、交互和性能优化等相关技术。

    在flex的dataGrid控件中显示图片的实践

    本文将深入探讨如何在DataGrid中显示图片,特别是在与Spring、Hibernate和Struts等框架集成的背景下,如何处理二进制数据并将其在Flex前端呈现。 首先,让我们了解Flex的基本概念。Flex是一个基于ActionScript和...

    FLex 左右滑动图片墙

    在本文中,我们将深入探讨如何使用Adobe Flex技术创建一个具有左右滑动功能的图片墙。Flex是一种基于ActionScript 3(AS3)的开源框架,主要用于构建富互联网应用程序(RIA)。通过利用Flex,开发者可以轻松地创建...

    flex图片上传带预览功能

    在Flex中,`BitmapData`类可以用于处理图像数据,`load()`方法可以加载文件数据,然后可以创建一个`Bitmap`对象显示预览。 3. **上传处理**:上传图片通常涉及与服务器的交互。在`UploadFile.aspx`和`UploadFile....

    Flex4.6+java+servlet上传图片例子+图片上传预览

    在IT行业中,构建一个能够处理图像上传和预览功能的Web应用是一项常见的需求。这个"Flex4.6+java+servlet上传图片例子+图片上传预览"的项目,结合了前端的Flex技术和后端的Java Servlet,为我们提供了一个完整的解决...

    flex图表导出图片

    本篇文章将深入探讨如何在Flex中实现图表的图片导出功能。 首先,让我们了解Flex中的图表组件。Flex提供了一系列强大的图表组件,如BarChart、LineChart、PieChart等,这些组件基于Adobe Flex SDK,可以方便地创建...

    dtt.rar_flex_flex 图片

    关于Flex中的图片处理,Flex框架提供了一系列API,使得开发者可以方便地处理图像。例如,BitmapData类是Flex中处理像素数据的核心类,它允许读取、修改和绘制位图数据。Camera类则支持访问用户的计算机摄像头,捕捉...

    flex鱼眼显示图片的例子

    3. **图片显示**: 在Flex中,可以使用`mx.controls.Image`组件来显示图片。在这个例子中,可能有一个自定义的组件或者类,扩展了`Image`组件,增加了鱼眼效果的功能。 4. **例子**: 这个Flex项目提供了一个实际操作...

    Flex 图像裁剪、剪切

    标题中的“Flex 图像裁剪、剪切”指的是在Adobe Flex这一开源框架中进行图像处理的技术,特别是关于图像裁剪和剪切的操作。Flex是一种基于ActionScript 3.0的开发框架,常用于构建富互联网应用程序(RIA)。图像裁剪...

    FLEX图片处理的特效

    在Flex开发中,图片处理和特效的实现是一个重要的部分,可以极大地提升用户界面的美观度和交互体验。这里提到的“FLEX图片处理的特效”主要涉及到Flex框架中的一些组件和效果,包括数据绑定、自定义数据效果、滤镜...

    Flex图片上传实例

    此实例不仅提供了一个实际的上传图片的应用场景,而且还包含了一些实用的代码片段,这对于想要了解如何在Flex中实现图片上传功能的开发者来说非常有价值。 #### 标题解析:“Flex图片上传实例” 该标题简洁明了地...

    flex+spring图片上传及预览

    在IT行业中,构建一个完善的图片上传和预览系统是常见的需求,特别是在Web应用中。本教程将关注如何结合Adobe Flex前端框架与Spring后端框架来实现这一功能,同时处理bmp图像格式的转换。Flex提供了丰富的用户界面...

    photo-browser.rar_flex

    对于初学者来说,通过研究这个项目的源代码,可以了解如何在Flex中处理图像、实现图片滑动、缩放、旋转等功能,以及如何创建用户友好的界面。 Flex的核心组件包括MXML和ActionScript。MXML是一种声明式语言,用于...

    flex图片查看器源码

    在图片查看器中,ActionScript可能用于处理图片加载、缩放、保存等操作。 4. **图片缩放**: 源码包含了图片缩放功能,这通常通过调整图片的宽度和高度实现。可能使用了矩阵变换(Matrix class)来实现平滑的缩放...

Global site tag (gtag.js) - Google Analytics