Loss of image quality when zooming in Flex Mobile application - apache-flex

i have a mobile application that i am creating in Adobe Flex (Flash Builder 4), and i am trying to create a zoom function. The one i have works, but the point is to be able to more easily read words that are in the image (the images are .jpg files). The images are 2550x3300 originally, but as soon as you zoom, the image quality reduces drastically, and nothing is readable.
My code for the zoom function is included below.
protected function onZoom(e:TransformGestureEvent, img:Image):void
{
img.transformAround(new Vector3D(e.localX, e.localY, 0), new Vector3D(img.scaleX*e.scaleX, img.scaleY*e.scaleY, 0));
}
and this is the code for the image object:
<s:Image id="titlepage" includeIn="title_page" x="0" y="0" width="320" height="415"
gesturePan="onPan(event, titlepage)"
gestureSwipe="onSwipe(event)"
gestureZoom="onZoom(event, titlepage)"
source="#Embed('assets/myImage.jpg')"/>

Image quality would be improved by setting smooth to true for anti-aliasing.
<s:Image smooth="true" />
There are many ways to handle registration issues - you might be interested in Yahoo Astra utils DynamicRegistration class.
Maybe something like this?
<fx:Script>
<![CDATA[
import com.yahoo.astra.utils.DynamicRegistration;
protected function image_gestureZoomHandler(event:TransformGestureEvent):void
{
DynamicRegistration.scale(image,
new Point(event.localX, event.localY),
image.scaleX *= event.scaleX,
image.scaleY *= event.scaleY);
}
]]>
</fx:Script>
<s:Image id="image"
smooth="true"
gestureZoom="image_gestureZoomHandler(event)" />

I'm not positive on this, but I think the 'transform' functions creates a bitmap out of your Image which is why you're losing quality. Try using the 'smoothing' attribute on your image.
From there, it's simply scaling and moving your image incrementally. However, what I'm not sure about is if the localX/Y property is from the original place of touch, or of the new position on the container (ie. if you're pinch/zooming from the middle and it scales, will the point still be on the middle or slightly top left).
I'll try to test this out on my phone and see what I come up with.

Related

Should I use PurePDF or AlivePdf

My company has only two flex pdf libraries available, AlivePDF and PurePDF.
I am having trouble finding very good documentation related to what I need to do so I hope to get some feedback from people who have used these libs.
The primary thing I need to do is paste a group of DisplayObjects into a pdf, with decent quality of the image. I had used org.alivepdf.pdf.PDF.addImage(..) function before but the image quality was very poor and somehow the process cropped off parts of the image, making it unusable.
Here is an example of something that might need to be pasted into a pdf:
<s:HGroup id="imageGroup">
<s:Label text="Chart Title" />
<mx:Legend dataProvider="myChart" />
<mx:LineChart id="myChart">
<!-- do chart stuff here -->
</mx:LineChart>
</s:HGroup>
PDF.addImage() generates low resolution graphics. For higher quality, use this instead:
take a snapshot of the image group using ImageSnapshot.captureImage(), setting the dpi to 300
add the resulting bytearray to the PDF using addImageStream()
I have used AlivePDF for a while. There are a few quirks and the documentation is sparse, but this is workable and the results are great.

mouseOver and mouseOut on changing size canvas

I am building a graphic component in MXML that has different states, each state having its own size.
I have a "normal" state and a "highlighted state", the highlighted one having a higher height.
On this components I implemented a function to be executed on each mouseOver and mouseOut to change from normal state to highlighted state and back.
My problem is, in the highlighted mode, the mouseout event is triggered according to the size of the normal state.
Here is the code:
<mx:Canvas xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:controller="com.*"
mouseOver="mouseOverHandler(event)" mouseOut="mouseOutHandler(event)"
width="230" height.Playing="40" height.Normal="21" height.Highlighted="40">
<mx:states>
<mx:State name="Normal" />
<mx:State name="Playing" />
<mx:State name="Highlighted" />
</mx:states>
<mx:Button includeIn="Highlighted" left="19" bottom="2" width="15" height="15" />
</mx:Canvas>
Is there something wrong in the way I use mouseOuver and mouseOut ?
Thanks,
Alexandre
I am building a graphic component in
MXML that has different states, each
state having its own size.
You have a misunderstanding of how the Flex Component Architecture works. A component never sizes itself. It is always up to the parent to size it's children. You can override the measure method to set measuredWidth and measuredHeight; however these are only suggestions provided to the component's parent. It is up the component to decide whether to accept them or no.
So, in your example, you can change the height/width of the button (a child); but you cannot change the height/width of the canvas (The component you're extending) and expect it to stick.
Without seeing the code that contains this canvas component, it's hard to say for sure what is going on. But, in this case, you should override the measure method to change the measuredWidth / measuredHeight. Something like this:
override protected measure():void{
if(currentState=='Normal'){
measuredWidth = 0;
measuredHeight = 0;
} else {
measuredWidth = button.width;
measuredHeight = button.height;
}
}
When the state changes, be sure to call the invalidateSize() method. You can do this by listening to the currentStateChange event.
In theory, that will cause the component to change the measuredWidth/measuredHeight; which will force the parent to also redraw itself, accommodating for the new measuredWidth/measuredHeight.
MXML masks a lot of these details.

Flex 4 skin shape tween effect

I have two shapes in a skin:
1.Circle
s:Ellipse width="20" height="20" includeIn="collapsed">
s:fill>
s:SolidColor color="#BBBBBB"/>
/s:fill>
/s:Ellipse>
2.Rectangle
s:Rect radiusX="10" radiusY="10" width="80" height="20" includeIn="expanded">
s:stroke>
s:SolidColorStroke color="0" weight="1"/>
/s:stroke>
s:fill>
s:SolidColor color="#00FF00"/>
/s:fill>
/s:Rect>
I want to have a shape tween. This kind of shape tween that is possible in Flash IDE. Circle needs to transform into rectangle smoothly. Is it possible in mxml ?
Only the Flash IDE can do it using the Timeline. You can't create it using code (unless you draw it manually), hence Flex doesn't support this feature.
However, I did find a Tweening library called Tweensy that says can do Vector Shape Tweens. It's in beta right now and I've never tried it, but it's worth a shot.

Flex: rotating buttons and changing focus

I've got a problem with rotated buttons in Flex. They seem to contaminate other components' focus rectangles.
Take the following source code, which couldn't be much simpler:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:VBox width="100%" height="100%">
<mx:Spacer height="100" />
<mx:Button rotation="10" />
<mx:TextArea rotation="0" />
</mx:VBox>
</mx:WindowedApplication>
Now execute it. Click in the text area, the focus rectangle is correct. Press tab twice, the focus rectangle aroung the TextArea is rotated!
Is there a fix for this, or should I avoid rotating buttons altogether?
I'm using Flex SDK 3.5.
Thanks,
Daniel
I as well recently stumbled upon this bug. Here's a link to suggested fix.
However, I was wondering if there's a more general solution rather then extending each and every component and overriding adjustFocusRect.
I came up with extending FocusManger and overriding the getter for focusPane as follows:
override public function get focusPane():Sprite
{
var fp:Sprite = super.focusPane;
if (fp && fp.numChildren != 0)
fp.getChildAt(0).rotation = 0;
return super.focusPane;
}
and set it as application's focus manager:
private function onPreinitialize():void
{
application.focusManager = new FocusManagerEx(this);
}
This seems to work, though would be nice if some expert could tell if there aren't any pitfalls I'm not aware of.
Seems like a bug in Flex SDK. I see next options:
disable focus rectangles with focusSkin="{null}"
implement your own skin and handle rotations correctly
move to Spark, since 3.5 is the (currently)
last SDK of third generation
try to fix it yourself (I feel it will be
tricky...)
Also, you may file a bug in Adobe's tracker, but they're deep into 4-th generation of Flex.
Update: 3.6 nightly build contains this bug, too.

Unable to access embedded images in htmlText

Images can be included in TextArea controls using the htmlText property:
ta.htmlText = '<img src="http://..."/>';
How can I reference embedded images?
An example:
<mx:TextArea xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
[Embed(source='../assets/img.gif')]
public var img:Class;
]]>
</mx:Script>
<mx:htmlText>
<![CDATA[
<img src="???" />
]]>
</mx:htmlText>
</mx:TextArea>
UPD:
<img src='../assets/img.gif />
works on local machine, but in server environment it throws:
Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
How can I fix this?
OK, I've just spent a couple of hours sorting this out, but I've got it working in Flash and Flex.
Displaying images in a TextField
You can load DisplayObjects into TextField <img /> tags including MovieClips, Sprites and embedded images.
In Flash or Flex if you want to display an embedded image then you will have to create a wrapper class that extends a DisplayObject class (e.g. Sprite or MovieClip).
Make sure your text field is large enough to contain the image. During testing I thought things weren't working when I really had the TextField too small to display the whole image.
Flash Example
Simple example, all code is on the main timeline.
Create a dynamic TextField on the stage. Give it a useful name, I'm calling mine txtImageTest.
Resize txtImageTest to a decent size, e.g. 300x150px.
Create a new MovieClip symbol and give it a class name, e.g. imageClip1.
Draw something in your new clip or place an embedded image inside imageClip1.
Go back to the main timeline, deselect all objects and open the Actionscript editor on the first frame.
Turn on multiline and word-wrapping on the text field:
imageClip1.wordWrap = true;
imageClip1.multiline = true;
imageClip1.htmlText = "<p>You can include an image in your HTML text with the <img> tag.</p><p><img id='testImage' src='imageClip1' align='left' width='30' height='30' hspace='10' vspace='10'/>Here is text that follows the image. I'm extending the text by lengthening this sentence until it's long enough to show wrapping around the bottom of the image.</p>"
Save and test your movie.
Flex Example
Since we can't just create a new MovieClip in the library like we did in Flash we need to create a new class that performs the same task (this method also works in Flash if you want want to create a new clip in the library).
Here is my class for a black triangle bullet, called BlackArrow.as:
// Set the correct package for you class here.
package embed
{
import flash.display.Sprite;
import mx.core.BitmapAsset;
public class BlackArrow extends Sprite
{
// Embed the image you want to display here.
[Embed(source='assets/embed/triangleIcon_black.png')]
[Bindable]
private var TriangleImage:Class;
public function BlackArrow()
{
super();
// Instantiate the embedded image and add it to your display list.
var image:BitmapAsset = new TriangleImage();
addChild(image);
}
}
}
NOTE: Do not extend Bitmap (in Flash) or BitmapAsset (in Flex) as they do not scale or position properly in the TextField. Choose Sprite or something similar.
Here is an example of a class that displays this image in the TextField:
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
width="100%" height="100%">
<mx:Script>
<![CDATA[
import embed.BlackArrow;
// You must include a variable declaration of the same type as your
// wrapper class, otherwise the class won't be compiled into
// the SWF and you will get an IOError.
private var img2:BlackArrow;
]]>
</mx:Script>
<mx:Text id="txtResults1" width="100%" height="100%">
<mx:htmlText>
<![CDATA[<p>You can include an image in your HTML text with the <img> tag.</p><p><img id='testImage' src='embed.BlackArrow' align='left' hspace='10' vspace='10'/>Here is text that follows the image. I'm extending the text by lengthening this sentence until it's long enough to show wrapping around the bottom of the image.</p>]]>
</mx:htmlText>
</mx:Text>
</mx:VBox>
Note that I am using the fully-qualified class name in the src attribute of the image tag.
Final Notes
Images are aligned to the left or right of a text field as determined by the align attribute of the image tag. This means that you cannot position an image in the middle of text without accessing the image directly.
A list of the attributes supported by the image tag is here:
http://blog.coursevector.com/notes-htmltext
The TextField LiveDoc page is here:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/text/TextField.html
The getImageReference() function is what you need to get a reference the images in the textfield:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/text/TextField.html#getImageReference%28%29
Make sure you use fully-qualified class names in the src attribute.
Make sure you declare a variable of your wrapper class to ensure it is compiled into the SWF.
You can specify embedded images as the src for HTML img tags in htmlText by referencing them using their fully qualified class name, which you can determine using getFullyQualifiedClassName). Like so:
public class Example
{
[Embed(source="myImage.png")
public static const MyImage:Class;
public function getHTMLImg() : String
{
return "<img src='" + getQualifiedClassName(MyImage) + "' />";
}
}
That's much simpler than creating a wrapper class for every image which might be embedded...
Try:
<mx:htmlText>
<![CDATA[
<p>
<img src='../assets/butterfly.gif'
width='30' height='30'
align='left'
hspace='10' vspace='10'>
</p>
]]>
</mx:htmlText>
See documentation.
I was looking for the same thing. The idea behind using embedded images is to prevent loading of said images from an external URL. So the accepted answer actually isn't solving the problem. I've seen the documentation, and they too use an URL there, and that image will not be compiled into the swf, but will be loaded at runtime from the server. Why they call that embedded image is probably because it's embedded withing the text, but what I'm looking for is to use an image that is embedded in the compiled code.
Why would you want an embedded image show used in a htmlText? Because it's the easiest way to display an image in a tooltip (you just need to override to default tooltip class to set the htmlText instead of text, and set it as the default tooltip class in the TooltipManager). In my search I discovered this: http://groups.google.com/group/flex_india/browse_thread/thread/cf0aa62afaae3fdc/b21f462f8d5da117?pli=1 . Haven't test it yet, and I guess the problem will come in determining that linkage id. I'll come back with more details when I have them.
Sly_cardinal wrote a very helpful answer. Big thanks to him!
I could not solve this problem for half a day. Sly_cardinal noticed that if you do so getQualifiedClassName (embed bitmap) image is inserted in the text is not correctly just to the upper left corner.
Sly_cardinal offered to make a wrapper class.
I want to append an his answer
A new class wrapper
ImageWrapper.as ->
package
{
import flash.display.Bitmap;
import flash.display.Sprite;
public class ImageWrapper extends Sprite{
public static var img:Class;
public function ImageWrapper() {
var bitmap:Bitmap = new img();
addChild(bitmap);
}
}
}
The call in the code:
[Embed(source = "img/MyImg.png")] var _MyImg:Class;
ImageWrapper.img = _MyImg;
tf.htmlText = "My text, and my image <img src='ImageWrapper'>";
That's it.
Thank you!
Try
src='../assets/img.gif'
Taken from: Using the htmlText property
Use src='assets/img.gif' but you will have to create an assets directory in the directory of the server where the application SWF is deployed and place your img.gif file there. When in html, it is looking for the file relative to the SWF file.
This will allow you to use the same file and location in both development and deployed locations.
It works on localhost because you have the image on the machine, so you can load it. If you are embedding it, it is not uploaded on the server in the specified directory, rather it is contained by the .SWF file itself. Upload the image (browse it for upload from you source files folder) in the corresponding place in the production output.
There's no need to bother ourselves any more buddies! from now on importing MovieClips is not such a big deal! by the help of the new class named TextArea (not TextArea the component, it's an OOP class an extenstion to the original TextField class).
We don't need Embedding or library any more, we can use the TextArea every where instead of Textfield and that enable us to import our own SWF files such as a video player, talking avatar or anything else in line of our texts.
It has lots of more features and doesn't specifically limited to this issue.
Check out www.doitflash.com for more information, the site provides the platform and downloading it is also free of charge :)

Resources