Text within an image is jaggy/broken - Adobe Flash - image

this is a post I have made on the adobe forum...
I'm newish to flash and i'm doing a presentation as part of a University assignment.
My problem is basically this. As part of my presentation I have a photo gallery which uses thumbnail images as buttons and then a UI loader to load a pop up version of the larger image from my webserver - as per https://www.youtube.com/watch?v=Peo_nT9HHa0
The image was created on photoshop. It is a .jpg and has text within the image that describes underneath it what the image is all about. The text within photoshop is set to anti-aliasing 'smooth' and when I test the movie within flash, the text underneath the image looks fine - just as it does in photoshop.
However, when I publish and upload the .swf file to my webserver and view the image through a browser, the text looks awful - all jaggy and broken if that makes sense.
Any ideas why?
I was given a reply of...
If you are loading the images dynamically then you will have to set the smoothing property true after the file(s) has been loaded. So if you don't currently have a listener for the images finishing loading, you will need one, and an event handler function to assign the smoothing property to true for each of them.
Can anyone help with creating the actionscript for this listener and event handler function?
I basically have a gallery movie clip with buttons that act as clickable thumbnails. The actionscript for that is...
btnImage1.addEventListener(MouseEvent.CLICK, loadimage1);
function loadimage1 (event:MouseEvent):void{
imagetxt.text = "a";
togglewindow.gotoAndPlay(2)
}
and then a UI loader that displays the larger image when a thumbnail is clicked
if (MovieClip(this.parent).imagetxt.text == "a"){
var imgurl:String ="IMAGE URL";
var myrequest:URLRequest = new URLRequest(imgurl);
myloader.load(myrequest);
}

As indicated, you should always turn smoothing on if the image is going to be scaled at all. It uses a different scaling algorithm that blurs pixels rather than deletes them. Take note that it is substantially slower to smooth, but on modern machines you shouldn't notice the difference unless you are doing it to thousands of images all at once.
After instantiation, add a Event.COMPLETE handler to Loader.contentLoaderInfo.
var myLoader = new Loader();
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);
Then in the handler, you can access the Bitmap and turn smoothing on.
function loaderCompleteHandler(e:Event):void {
var image:Bitmap = myLoader.content as Bitmap; //Loader.content is typed as a DisplayObject, so we need to cast it as a Bitmap
image.smoothing = true;
}
And that should solve the issue. You may need to add the image object to the stage rather than the myLoader object. I don't think you'll have to, but I can't remember.

Just add event an event listener to your loader. Like this:
load.addEventListener(Event.COMPLETE,doneLoad);
then in the doneLoad function get the event.data and cast it to Bitmap and set the bitmap smoothing to true:
var myBitmap:Bitmap= e.target.data as Bitmap;
myBitmap.smoothing=true;
//add bitmap to parent ....

I wrote you universal method for loading images, you should pass 3 arguments to the method: holder for big images, image path, and rectangle to restrict image bounds and resize them. This method should be sufficient for your task.
private function loadImage(holder:DisplayObjectContainer, path:String, bounds:Rectangle):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (e:Event):void {
var bitmap:Bitmap = loader.content as Bitmap;
if (bitmap != null) {
bitmap.smoothing = true;
//Resize bitmap to fit bounds
var availableRatio:Number = bounds.width / bounds.height;
var componentRatio:Number = bitmap.width / bitmap.height;
if (componentRatio > availableRatio) {
bitmap.width = bounds.width;
bitmap.height = bounds.width / componentRatio;
} else {
bitmap.width = bounds.height * componentRatio;
bitmap.height = bounds.height;
}
//Clear previous
var i:uint, len: uint = holder.numChildren, old: Bitmap;
for(i; i < len; ++i){
old = holder.removeChildAt(0) as Bitmap;
old.bitmapData.dispose();
}
//Here you can add some appear animation
bitmap.x = bounds.x + ((bounds.width - bitmap.width) >> 1);
bitmap.y = bounds.y + ((bounds.height - bitmap.height) >> 1);
holder.addChild(bitmap);
}
});
loader.load(new URLRequest(path));
}
Usage:
loadImage(myContainer, "Path-to-Image", new Rectangle(20, 20, 400, 200));

Related

CodeName One - Image gets pixelated when scaling

I am getting an image dynamically from a webservice. Afterwards I am supposed to use it as background for the upper half of the screen. My problem is that I only get one size of the image (which should be approximately right for many smartphones phones) but when I resize it to make it fill half of the screen it gets pixelated.
I have tried putting it as background of a container (adding padding to the expected size) and using BACKGROUND_IMAGE_SCALED_FILL and/or using Image methods scaledHeight/scaledWidth, fill and scaled.
It doesn't matter if I scale it to a bigger or smaller size it still deteriorates noticeably.
Is this to be expected? Is there another way to scale images?
public class CopyOfVistaPantallaPrincipal extends VistaDisparaEventos {
private Container canvasPantallaPrincipal;
public CopyOfVistaPantallaPrincipal() {
canvasPantallaPrincipal = new Container();
canvasPantallaPrincipal.setName("canvasPantallaPrincipal");
super.canvas = this.canvasPantallaPrincipal;
initPantallaPrincipal();
}
private void initPantallaPrincipal() {
canvasPantallaPrincipal.setLayout(new LayeredLayout());
canvasPantallaPrincipal.getUnselectedStyle().setBgTransparency(0);
ModeloNovedades modelo = new ModeloNovedades();
Image imgPrincipal = createImagenPrincipal(modelo);
canvasPantallaPrincipal.setName("canvas pantalla principal");
Container otro = new Container(new BorderLayout());
if (imgPrincipal != null) {
img.getUnselectedStyle().setBorder(null);
img.getUnselectedStyle().setPadding(0, 0, 0, 0);
img.getUnselectedStyle().setMargin(0, 0, 0, 0);
canvasPantallaPrincipal.addComponent(img);
}
canvasPantallaPrincipal.addComponent(otro);
}
private Container createImagenPrincipal(ModeloNovedades modelo) {
return loadTopImage(modelo, modelo.getDestacado());
}
private Container loadTopImage(ModeloNovedades modelo, Hashtable destacado) {
int width = Display.getInstance().getDisplayWidth();
int imgHeight = (int) ((Display.getInstance().getDisplayHeight() / 2) * 0.95) ;
//Default image
Image foregroundImage = FormFactory.loadImage("/imagenPrincipaLogoOld.png");
if (! modelo.getDestacado().isEmpty()){
String destacadaURL = "" + destacado.get("imagen");
if (! destacadaURL.equals("")){
//After updating it loads the downloaded image here
byte[] data = (byte[]) DataCenter.getInstance().get(destacadaURL, false);
foregroundImage = FormFactory.loadImage(data, 100);
}
}
imageContainer.getAllStyles().setPadding(imgHeight/2, imgHeight/2, width/2, width()/2);
imageContainer.getAllStyles().setBgImage(foregroundImage);
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
return imageContainer;
}
}
If I'm not returning the image but a container having it as background I would add it to a Container like this:
imageContainer.getAllStyles().setPadding(imgHeight/2, imgHeight/2, width/2, width/2);
imageContainer.getAllStyles().setBgImage(foregroundImage);
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED); //only if it was scaled
Original image (please ignore the dark bar over it, it was added recently and I didn't save the previous version, as I said it comes dynamically):
http://i68.tinypic.com/16lmeqr.jpg
Scaled:
http://i68.tinypic.com/w7zafm.jpg
Cropped:
http://i65.tinypic.com/2nkp79l.png
Image as of the last update:
http://i68.tinypic.com/2ik7eiq.png
Remove all of your code that manipulates the image, needs scaling, scale etc... That is all redundant. Every pass you do on manipulating an image deteriorates it a little bit...
You need just one line change and you need to do it always so the image will always "fit" without cropping or any other changes:
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALE_TO_FILL);
Notice that you can just use ScaleImageLabel instead of image container which does roughly the same thing.

Error on saving images

I'm trying to save the content of a MovieClip in a JPEG image, but when I save it the image has this problem:
There is a blank space in it (obvious from quote formatting), this appears in all the images that I try to save using filereference with JPGEncoder.
I believe that the problem might be happening because of the JPGEncoder class but I'm not sure about it.
This is the function I'm using to save the image (some of the strings are in portuguese):
private function fl_Salvar(event:MouseEvent)
{
try
{
var src:BitmapData = new BitmapData(imageViewer.width,imageViewer.height);
var mtx:Matrix = DisplayUtils.fitIntoRect(imageViewer.mcImage.getChildAt(0),rect,true,Alignment.MIDDLE,false);
src.draw(imageViewer,mtx,null,null,null,true);
var jpgEncoder:JPGEncoder = new JPGEncoder(85);
var imgStream:ByteArray = null;
imgStream = jpgEncoder.encode(src);
var file:FileReference = new FileReference();
file.addEventListener( IOErrorEvent.IO_ERROR, ioErrorHandler );
file.save( imgStream, "TESTE.jpg");
}
catch (ioe:IllegalOperationError)
{
trace("Operação Ilegal.");
}
catch (ae:ArgumentError)
{
trace("Argumento Inválido.");
}
catch (me:MemoryError)
{
trace("Memória Insuficiente.");
}
catch (error:Error)
{
trace("Erro ao tentar salvar imagem : "
+ " . Erro : " + error);
}
}
private function ioErrorHandler( event:IOErrorEvent ):void
{
trace("Handler de erro I/O: " + event);
}
I would like to know if someone knows what might be causing this.
Thanks in advance.
Edit:
Here is my rect declaration:
rect = new Rectangle(imageViewer.mcImage.x,imageViewer.mcImage.y,imageViewer.mcImage.width,imageViewer.mcImage.height);
It's because of these two lines:
var mtx:Matrix = DisplayUtils.fitIntoRect(imageViewer.mcImage.getChildAt(0),rect,true,Alignment.MIDDLE,false);
src.draw(imageViewer,mtx,null,null,null,true);
What they do is that they fit your image inside some rect. You haven't provided info what's that rect and how it's defined, but I guess it has some dimensions. So you are fitting image in, and it's not stretched, but resized on the longer side.
Encoder works well, you just need to check the rectangle that you want to fit the image in.
Are you sure it is not you picture viewing software that is doing this? The image seems complete (they are written out to a byteArray pixel by pixel from top left to lower right.) if it were the file stream or byte array that were the trouble I would expect to see a distorted picture.
Is there actually a part of the image missing, or is that the full image?

PDFBox image size issues

I'm new to working with PdfBox and I'm having a small issue when displaying images. I'm able to import the image, which is sized at 800*900 pixels, and looks fine when viewed in an existing pdf at 100%. However when the resulting PDF is generated using the below code, the image becomes blurry, and the image extends beyond the boundaries of the A4 page.
Is there a different way of sizing/saving images so that they display correctly in pdfbox?
public class PDFtest {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException, COSVisitorException {
// TODO code application logic here
// Create a document and add a page to it
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDPage.PAGE_SIZE_A4);
document.addPage(page);
// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.HELVETICA_BOLD;
InputStream in = new FileInputStream(new File("img.jpg"));
PDJpeg img = new PDJpeg(document, in);
// Start a new content stream which will "hold" the to be created content
PDPageContentStream contentStream = new PDPageContentStream(document, page);
// Define a text content stream using the selected font, moving the cursor and drawing the text "Hello World"
contentStream.drawImage(img, 10, 700);
contentStream.beginText();
contentStream.setFont(font, 12);
contentStream.moveTextPositionByAmount(10, 650);
contentStream.drawString("Hello World");
contentStream.endText();
// Make sure that the content stream is closed:
contentStream.close();
// Save the results and ensure that the document is properly closed:
document.save("Hello World.pdf");
document.close();
}
I'd like to point out that as of 2.0 the contentStream.drawXObject function call in Victor's answer is deprecated. If you want to specify a width and height you should use contentStream.drawImage(image, x, y, width, height)
I had the same problem asked in this question, but the given answer is not right.
After some research I found a solution.
Instead of using the function drawImage use the function drawXObject
contentStream.drawXObject( img, 10, 700, 100, 100 );
Where the last two numbers specify the size of the image to be drawn.
For similar situation, for me, with PDF 2.0.11 and a tiff file of dimensions - 1600 x 2100 the following code perfectly fit the image in A4 (portrait) size. Not sure if PDFRectangle is okay with you.
I got this example straight from PDFBOX - Example
The only thing I tweaked/introduced is:
PDRectangle.A4.getWidth(), PDRectangle.A4.getHeight()
Here is the full sample:
public static void main(String[] args) throws IOException
{
// if (args.length != 2)
// {
// System.err.println("usage: " + ImageToPDF.class.getName() + " <image> <output-file>");
// System.exit(1);
// }
String imagePath = "C:/FAX/sample.tiff";
String pdfPath = "C:/FAX/sample.pdf";
if (!pdfPath.endsWith(".pdf"))
{
System.err.println("Last argument must be the destination .pdf file");
System.exit(1);
}
try (PDDocument doc = new PDDocument())
{
PDPage page = new PDPage();
doc.addPage(page);
// createFromFile is the easiest way with an image file
// if you already have the image in a BufferedImage,
// call LosslessFactory.createFromImage() instead
PDImageXObject pdImage = PDImageXObject.createFromFile(imagePath, doc);
// draw the image at full size at (x=20, y=20)
try (PDPageContentStream contents = new PDPageContentStream(doc, page))
{
// draw the image at full size at (x=20, y=20)
contents.drawImage(pdImage, 0, 0, PDRectangle.A4.getWidth(), PDRectangle.A4.getHeight());
// to draw the image at half size at (x=20, y=20) use
// contents.drawImage(pdImage, 20, 20, pdImage.getWidth() / 2, pdImage.getHeight() / 2);
}
doc.save(pdfPath);
System.out.println("Tiff converted to PDF succussfully..!");
}
}
Hope it helps.
If your intention is an A4 sized pic on a PDF, then i guess you find the actual size of typical A4 in pixels.
Also you should be aware of the extension of the picture that you want to view like jpg, gif, or bmp ...
from what I saw in your code, the dimensions of the picture are 10 X 700 which I believe is pretty small size.
contentStream.drawImage(img, 10, 700);
And the extension of the picture is : jpg
InputStream in = new FileInputStream(new File("img.jpg"));
check those and return for more info.
that's all.
good luck'''
As per the new API 2.0.x, one can use the PDRectangle to fetch Pdf page width and height. One can use PDPageContentStream to draw the image in accordance with PDF page.
For reference:
try (PDPageContentStream contents = new PDPageContentStream(pdDocument, pdPage)) {
final PDRectangle mediaBox = pdPage.getMediaBox();
final PDImageXObject pdImage = PDImageXObject.createFromFile(image, pdDocument);
contents.drawImage(pdImage, 0, 0, mediaBox.getWidth(), mediaBox.getHeight());
}

ASp.Net Mvc 1.0 Dynamic Images Returned from Controller taking 154 seconds+ to display in IE8, firefox and all other browsers fast and easy

I have a curious problem with IE, IIS 6.0 dynamic PNG files and I am baffled as to how to fix..
Snippet from Helper (this returns the URL to the view for requesting the images from my Controller.
string url = LinkBuilder.BuildUrlFromExpression(helper.ViewContext.RequestContext, helper.RouteCollection, c => c.FixHeight(ir.Filename, ir.AltText, "FFFFFF"));
url = url.Replace("&", "&");
sb.Append(string.Format("<removed id=\"TheImage\" src=\"{0}\" alt=\"\" />", url)+Environment.NewLine);
This produces a piece of html as follows:-
img id="TheImage" src="/ImgText/FixHeight?sFile=Images%2FUser%2FJulianGuppy%2FMediums%2Fconservatory.jpg&backgroundColour=FFFFFF" alt="" /
brackets missing because i cant post an image... even though I dont want to post an image I jsut want to post the markup... sigh
Snippet from Controller ImgTextController
/// <summary>
/// This function fixes the height of the image
/// </summary>
/// <param name="sFile"></param>
/// <param name="alternateText"></param>
/// <param name="backgroundColour"></param>
/// <returns></returns>
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult FixHeight(string sFile, string alternateText, string backgroundColour)
{
#region File
if (string.IsNullOrEmpty(sFile))
{
return new ImgTextResult();
}
// MVC specific change to prepend the new directory
if (sFile.IndexOf("Content") == -1)
{
sFile = "~/Content/" + sFile;
}
// open the file
System.Drawing.Image img;
try
{
img = System.Drawing.Image.FromFile(Server.MapPath(sFile));
}
catch
{
img = null;
}
// did we fail?
if (img == null)
{
return new ImgTextResult();
}
#endregion File
#region Width
// Sort out the width from the image passed to me
Int32 nWidth = img.Width;
#endregion Width
#region Height
Int32 nHeight = img.Height;
#endregion Height
// What is the ideal height given a width of 2100 this should be 1400.
var nIdealHeight = (int)(nWidth / 1.40920096852);
// So is the actual height of the image already greater than the ideal height?
Int32 nSplit;
if (nIdealHeight < nHeight)
{
// Yes, do nothing, well i need to return the iamge...
nSplit = 0;
}
else
{
// rob wants to not show the white at the top or bottom, so if we were to crop the image how would be do it
// 1. Calculate what the width should be If we dont adjust the heigt
var newIdealWidth = (int)(nHeight * 1.40920096852);
// 2. This newIdealWidth should be smaller than the existing width... so work out the split on that
Int32 newSplit = (nWidth - newIdealWidth) / 2;
// 3. Now recrop the image using 0-nHeight as the height (i.e. full height)
// but crop the sides so that its the correct aspect ration
var newRect = new Rectangle(newSplit, 0, newIdealWidth, nHeight);
img = CropImage(img, newRect);
nHeight = img.Height;
nWidth = img.Width;
nSplit = 0;
}
// No, so I want to place this image on a larger canvas and we do this by Creating a new image to be the size that we want
System.Drawing.Image canvas = new Bitmap(nWidth, nIdealHeight, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(canvas);
#region Color
// Whilst we can set the background colour we shall default to white
if (string.IsNullOrEmpty(backgroundColour))
{
backgroundColour = "FFFFFF";
}
Color bc = ColorTranslator.FromHtml("#" + backgroundColour);
#endregion Color
// Filling the background (which gives us our broder)
Brush backgroundBrush = new SolidBrush(bc);
g.FillRectangle(backgroundBrush, -1, -1, nWidth + 1, nIdealHeight + 1);
// draw the image at the position
var rect = new Rectangle(0, nSplit, nWidth, nHeight);
g.DrawImage(img, rect);
return new ImgTextResult { Image = canvas, ImageFormat = ImageFormat.Png };
}
My ImgTextResult is a class that returns an Action result for me but embedding the image from a memory stream into the response.outputstream.
snippet from my ImageResults
/// <summary>
/// Execute the result
/// </summary>
/// <param name="context"></param>
public override void ExecuteResult(ControllerContext context)
{
// output
context.HttpContext.Response.Clear();
context.HttpContext.Response.ContentType = "image/png";
try
{
var memStream = new MemoryStream();
Image.Save(memStream, ImageFormat.Png);
context.HttpContext.Response.BinaryWrite(memStream.ToArray());
context.HttpContext.Response.Flush();
context.HttpContext.Response.Close();
memStream.Dispose();
Image.Dispose();
}
catch (Exception ex)
{
string a = ex.Message;
}
}
Now all of this works locally and lovely, and indeed all of this works on my production server
BUT Only for Firefox, Safari, Chrome (and other browsers) IE has a fit and decides that it either wont display the image or it does display the image after approx 154seconds of waiting.....
I have made sure my HTML is XHTML compliant, I have made sure I am getting no Routing errors or crashes in my event log on the server....
Now obviously I have been a muppet and have done something wrong... but what I cant fathom is why in development all works fine, and in production all non IE browsers also work fine, but IE 8 using IIS 6.0 production server is having some kind of problem in returning this PNG and I dont have an error to trace... so what I am looking for is guidance as to how I can debug this problem.
Looks like it might be time to install Fiddler or HttpWatch and find out what is going on.
Well, what I wanted to do was to convert my images (jpg, bmp, etc... and return them as png) - however. Although all other browsers would accept the encoding and display them fine, IE decided to hide the png image (after partially displaying it) because it thought it wasn't a PNG image. (Even though it was) So I gave up with the conversion methods and just returned the image in its original format. ---
if anybody comes up with a way of reliably converting any image format into png so that I can return it dynamically from a memory stream, then please do let me know....
So I am closing this for now as IE has won this battle -
I wish IE would just sod off and die. I hate IE so much. Seriously it just sucks the sweat of a dead mans balls.
Never call Response.End()
At least, that's what the maintainer for the HttpResponse documentation says.
Response.End() ends the http connection, often orphaning data in the server's buffer or somewhere in the stream. It's better to let IIS end the connection (or reuse it) instead, since many clients don't have a perfect network stack.
IE has a terrible network stack (as anyone who has used IETab for FF can witness, IE is almost fast when placed on top of the FF network pipe). The other browsers handle the quickly closed connection much better, and so probably aren't responding badly to the closed connection.
On a different topic, it looks like you are re-inventing the wheel. It's not an easy wheel to build properly, either.
Based on the code I see, it looks like you are leaking the GDI bitmap 'img', and additional leaks would occur if anything unexpected happened during the request. Note that .NET does not garbage collection GDI handles properly, and it's one of the biggest causes of server crashes - make sure you get that fixed, my friend :)

Resizing image using as3

I am building a portfolio site which dynamically loads large hi-res images when the user clicks on a thumnail. However I'm having problems maintaining the original image's quality when resizing it to fit the current browser.
Currently I'm just adjusting the width & height properties of the image to width to the stage proportionally which is working fine getting it to fit, however I cannot figure out how to maintain image quality? Do I need to load it as a bitmap and redraw/smooth or something similar?
This is the appropriate code that I am currently using:
var req:URLRequest = new URLRequest("images/101.jpg");
var loader:Loader = new Loader();
var widthRatio:Number;
var heightRatio:Number;
function imageLoaded(e:Event):void
{
//add image to stage
addChild(loader);
// resize proportionally
if (loader.width > stage.stageWidth){
widthRatio=loader.width/stage.stageWidth;
trace(widthRatio)
trace(loader.width);
}
if (loader.height > stage.stageHeight){
heightRatio=loader.height/stage.stageHeight;
trace(heightRatio)
trace(loader.height)
}
if (widthRatio > heightRatio){
loader.width = stage.stageWidth;
loader.height = loader.height/widthRatio;
} else {
loader.height = stage.stageHeight;
loader.width = loader.width/heightRatio;
}
//centre on stage
loader.x=stage.stageWidth/2 - loader.width/2;
loader.y=stage.stageHeight/2 - loader.height/2;
}
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
loader.load(req);
Have a look at Bitmap smoothing.
Your Loader will have a content property which will be a Bitmap. Set it's smoothing to true.
function imageLoaded(e:Event):void
{
//add image to stage
addChild(loader);
Bitmap(loader.content).smoothing = true;
// ...
It makes the image a bit blurry but it is a significant improvement in most cases.

Resources