Flex mobile resized image layout - image

I'm trying to display a resized image in a flex mobile application and I couldn't get it displayed correctly.
When set to width="100%" it looks OK. (Image 1)
When I scale it down to let's say 30% by Flex (scaleMode="letterbox"), it is scaled down, but the components above and below the image still keep the distance from the Image control as it were 100% height. (Image 2)
I tried dozens of layout tricks from autolayout=true to dynamically scaled elements, but couldn't find a solution. What am I doing wrong?
(I use Flash Builder 4.7, Flex 4.6 and Air SDK 13.0 on a 64-bit Win 7 Machine.)

Thank you for your answer, really appreciate it! However, this is unfortunately not a solution as it just sets the height the same as width. In this case, the two labels gets closer to the image, but not in the place where they supposed to go.
Meanwhile I could find a way to correctly resize the image along with its bounding box.
The main idea is to put the image in a container, and adjust the image size according to the ratio of the container size divided by the original image size.
Then the image will fully fill the container, and I can then set the desired scaling ratio by adjusting the container's width.
Here is my code that works perfectly, and I really hope that it will help someone else in the future:
<?xml version="1.0" encoding="utf-8"?>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.components.Image;
private var img:Image = new Image();
private function init():void {
drawImg("assets/image.png");
}
private function drawImg(src:String):void {
img.source = src;
img.scaleMode = "letterbox";
img.smooth = true;
imgHolder.addElement(img);
img.addEventListener(FlexEvent.READY, imgStatus);
}
private function imgStatus(e:FlexEvent):void {
var imgw:Number = e.currentTarget.bitmapData.width;
var imgh:Number = e.currentTarget.bitmapData.height;
var ratio:Number = Number(imgHolder.width/imgw);
img.width = imgw*ratio
img.height = imgh*ratio
}
]]>
</fx:Script>
<s:VGroup width="100%" horizontalAlign="center">
<s:Label text="Foo" />
<s:HGroup id="imgHolder" width="30%" />
<s:Label text="Bar" />
</s:VGroup>
First I always got a null object, so I found that I need to listen for the image to be fully loaded, and now it works perfectly.
Again, the desired width property can be set on the container and not the image.
Here's a screenshot with the results.

The height of the image indeed remains untouched by only setting the image width.
If you draw a rectangle around the image you will see the bounding box with the same size all the time.
You can modify your code like the following to have a dynamic height and have the labels positioned as you wish:
<s:VGroup width="100%"
horizontalAlign="center">
<s:Label verticalAlign="bottom"
text="Foo" />
<s:Image id="img"
source="test.gif"
width="30%"
height="{img.width}"
scaleMode="letterbox" />
<s:Label verticalAlign="top"
text="Bar" />
</s:VGroup>

Related

In Storybook theming for brandImage how to change logo height or width?

Within Storybook's manager.js when changing the theme I've found the documentation where you can add a custom logo with:
import { create } from '#storybook/theming'
import logo from '../src/images/logo.png'
export default create({
brandImage: logo,
})
However I've been unable to find a way to adjust the logo size of a PNG. From my research it seems the only way to adjust the size is to implement a width or height in the SVG:
logo.svg:
<svg width="100" height="40" viewBox="0 0 290.72 112.41" [...]
maanger.js:
import { create } from "#storybook/theming"
import logo from "../src/logo.svg"
export default create({
brandImage: logo,
})
I'm unable to find a way in the docs (params or themeing) if there is a way to set the width or height of a PNG.
Research
Storybook change logo
Link to brandImage not working
Custom theme brand image not being displayed in the Sidebar
Storybook's styling overrides all
In Storybook is there a way when using a PNG for brandImage I can adjust the width or height without having to implement it as a SVG?

How to embed SVG graphics properly in JSF application using OmniFaces

This is a follow-up to How can I embed an SVG image using JSF/OmniFaces/PrimeFaces?
In that question, I learned that the OmniFaces-2.1 snapshot supports utilizing InputStream/byte[] through it's o:graphicImage tag.
In Getting started with SVG graphics objects in JSF 2.0 pages I learned that the standard graphicImage tags simply renders an img tag and SVG's should be rendered as and object tag like this: <object type="image/svg+xml" data="#{bean.svgUrl}">.
My question is really directed directly at BalusC from the OmniFaces project:
Should not o:graphicImage render SVG's in this manner? All I'm getting is img-tags and they don't work in IE10+.
Update #2: It's a scaling problem! I set the height to 125 and started seeing the edge my graphic.
UPDATE #1: Example rendered img tags:
This one is just based on a static SVG file: <img height="25" alt="" src="/javax.faces.resource/images/Logo.svg.xhtml;jsessionid=cc0acf6def65ac5c127d09384977?ln=default">
This is based on a byte array:
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iMzE5LjEzNzUxIgogICBoZWlnaHQ9IjI3OS40NjI0OSIKICAgaWQ9InN2ZzIiCiAgIHhtbDpzcGFjZT0icHJlc2VydmUiPjxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTgiPjxyZGY6UkRGPjxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj48ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD48ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+PC9jYzpXb3JrPjwvcmRmOlJERj48L21ldGFkYXRhPjxkZWZzCiAgICAgaWQ9ImRlZnM2IiAvPjxnCiAgICAgdHJhbnNmb3JtPSJtYXRyaXgoMS4yNSwwLDAsLTEuMjUsMCwyNzkuNDYyNSkiCiAgICAgaWQ9ImcxMCI+PGcKICAgICAgIHRyYW5zZm9ybT0ic2NhbGUoMC4xLDAuMSkiCiAgICAgICBpZD0iZzEyIj48cGF0aAogICAgICAgICBkPSJNIDEzNTMuOTYsMjE4OS44OCAyNTM5Ljc5LDEzNSBjIDguNjUsLTEzLjY5MSAxMi4yNCwtMjguODAxIDEyLjI0LC00NC42NDA2IDAsLTQ4Ljk2MSAtMzkuNiwtODkuMjgxMjcgLTg5LjI4LC04OS4yODEyNyBsIC0yMzcyLjM5ODQsMCBjIC00OC45NjEsMCAtODkuMjc3MzgsNDAuMzIwMjcgLTg5LjI3NzM4LDg5LjI4MTI3IDAsMTUuODM5NiA0LjMyMDMxLDMxLjY3OTYgMTIuMjQyMTgsNDUuMzUxNiBMIDExOTkuMTYsMjE4OS44OCBjIDM0LjU2LDU5Ljc2IDEyMC4yMyw1OS43NiAxNTUuNTEsLTAuNzIgbCAtMC43MSwwLjcyIgogICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICBpZD0icGF0aDE0IgogICAgICAgICBzdHlsZT0iZmlsbDojZjE0ODI0O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgIGQ9Ik0gMTM1My45NiwyMTg5Ljg4IDI1MzkuNzksMTM1IGMgOC42NSwtMTMuNjkxIDEyLjI0LC0yOC44MDEgMTIuMjQsLTQ0LjY0MDYgMCwtNDguOTYxIC0zOS42LC04OS4yODEyNyAtODkuMjgsLTg5LjI4MTI3IGwgLTIzNzIuMzk4NCwwIGMgLTQ4Ljk2MSwwIC04OS4yNzczOCw0MC4zMjAyNyAtODkuMjc3MzgsODkuMjgxMjcgMCwxNS44Mzk2IDQuMzIwMzEsMzEuNjc5NiAxMi4yNDIxOCw0NS4zNTE2IEwgMTE5OS4xNiwyMTg5Ljg4IGMgMzQuNTYsNTkuNzYgMTIwLjIzLDU5Ljc2IDE1NS41MSwtMC43MiBsIC0wLjcxLDAuNzIgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgxNiIKICAgICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6I2YxNDgyNDtzdHJva2Utd2lkdGg6Mi4xNTAwMDAxO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjQ7c3Ryb2tlLW9wYWNpdHk6MTtzdHJva2UtZGFzaGFycmF5Om5vbmUiIC8+PHBhdGgKICAgICAgICAgZD0ibSAxMjc2LjkxLDE3ODcuNCA4NzYuMjQsLTE1MTcuNzU5IC0xNzUzLjE4NSwwIDg3Ni45NDUsMTUxNy43NTkiCiAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgIGlkPSJwYXRoMTgiCiAgICAgICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgZD0ibSAxMjc2LjkxLDE3ODcuNCA4NzYuMjQsLTE1MTcuNzU5IC0xNzUzLjE4NSwwIDg3Ni45NDUsMTUxNy43NTkgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIKICAgICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6I2ZmZmZmZjtzdHJva2Utd2lkdGg6Mi4xNTAwMDAxO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjQ7c3Ryb2tlLW9wYWNpdHk6MTtzdHJva2UtZGFzaGFycmF5Om5vbmUiIC8+PHBhdGgKICAgICAgICAgZD0ibSAxNTQyLjU5LDEyMDcuNzkgLTI1NC44OCw2OS4xMiBjIC0wLjcyLDAgLTAuNzIsMCAtMS40NCwwIC0zLjU5LDAgLTYuNDgsLTIuODcgLTYuNDgsLTYuNDcgMCwtMS40NCAwLC0yLjE2IDAuNzIsLTIuODkgbCAzNy40NCwtNjQuMDYgLTE5MS41MSwtNzAuNTcgQyA5ODAuMjczLDEwNzkuNjQgODgzLjA3NCw5MzkuOTYxIDg4My4wNzQsNzg0LjQ0MSBsIDAsLTQzNC44ODIgMTYwLjU1NiwwIDAsNDM1LjYxMyBjIDAsODcuMTA5IDU0LjcyLDE2NS41OSAxMzYuOCwxOTUuODI4IGwgMTkyLjk2LDcxLjI4IDEyLjk2LC03Mi43MjEgYyAwLjczLC0yLjg3OSAzLjYxLC01LjAzOSA2LjQ4LC01LjAzOSAyLjE3LDAgMy42MSwwLjcxOCA1LjA1LDIuODcxIGwgMTQ5Ljc1LDIxNi43MjkgYyAwLjcyLDEuNDQgMS40NCwzLjYgMS40NCw1LjA0IDAsNC4zMyAtMi44OCw3LjkyIC02LjQ4LDguNjMiCiAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMyMzFmMjA7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgZD0ibSAxNTQyLjU5LDEyMDcuNzkgLTI1NC44OCw2OS4xMiBjIC0wLjcyLDAgLTAuNzIsMCAtMS40NCwwIC0zLjU5LDAgLTYuNDgsLTIuODcgLTYuNDgsLTYuNDcgMCwtMS40NCAwLC0yLjE2IDAuNzIsLTIuODkgbCAzNy40NCwtNjQuMDYgLTE5MS41MSwtNzAuNTcgQyA5ODAuMjczLDEwNzkuNjQgODgzLjA3NCw5MzkuOTYxIDg4My4wNzQsNzg0LjQ0MSBsIDAsLTQzNC44ODIgMTYwLjU1NiwwIDAsNDM1LjYxMyBjIDAsODcuMTA5IDU0LjcyLDE2NS41OSAxMzYuOCwxOTUuODI4IGwgMTkyLjk2LDcxLjI4IDEyLjk2LC03Mi43MjEgYyAwLjczLC0yLjg3OSAzLjYxLC01LjAzOSA2LjQ4LC01LjAzOSAyLjE3LDAgMy42MSwwLjcxOCA1LjA1LDIuODcxIGwgMTQ5Ljc1LDIxNi43MjkgYyAwLjcyLDEuNDQgMS40NCwzLjYgMS40NCw1LjA0IDAsNC4zMyAtMi44OCw3LjkyIC02LjQ4LDguNjMgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyNCIKICAgICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzIzMWYyMDtzdHJva2Utd2lkdGg6Mi4xNTAwMDAxO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1taXRlcmxpbWl0OjQ7c3Ryb2tlLW9wYWNpdHk6MTtzdHJva2UtZGFzaGFycmF5Om5vbmUiIC8+PC9nPjwvZz48L3N2Zz4=" alt="100.1 - Farlig sving" title="100.1 - Farlig sving" width="40" style="margin-left: 3px; pointer-events: none;" height="40">
Since I discovered this to be a SVG scaling problem and I seem not to be the only one who has encountered this I'll post my solution here.
In short, I
Retrieve the SVG.
Parse it using JDOM.
Inject a view box if it is missing based on the specified size
Here's the Java code without error handling:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = execute(builder.buildGet(), InputStream.class);
Document doc = new SAXBuilder().build(is);
Element root = doc.getRootElement();
if (root.getAttribute("viewBox") == null)
{
String width = root.getAttributeValue("width"), height = root.getAttributeValue("height");
root.setAttribute("viewBox", String.format("0 0 %s %s", width, height));
}
new XMLOutputter().output(doc, baos);
return baos.toByteArray();

how to use html content inside a canvas element

Can any one tell me how to place my html content on a canvas.And if we can do that, will the properties and events of those elements works or not, and also I have animations drawn on that canvas.
From this article on MDN:
You can't just draw HTML into a canvas. Instead, you need to use an
SVG image containing the content you want to render. To draw HTML
content, you'd use a element containing the HTML, then
draw that SVG image into your canvas.
It than suggest you follow these steps:
The only really tricky thing here—and that's probably an
overstatement—is creating the SVG for your image. All you need to do
is create a string containing the XML for the SVG and construct a Blob
with the following parts.
The MIME media type of the blob should be "image/svg+xml".
The element.
Inside that, the element.
The (well-formed) HTML itself, nested inside the .
By using a object URL as described above, we can inline our HTML
instead of having to load it from an external source. You can, of
course, use an external source if you prefer, as long as the origin is
the same as the originating document.
The following example is provided (you can see more information about this in this blog by Robert O'Callahan):
DEMO
const ctx = document.getElementById("canvas").getContext("2d");
const data = `
<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'>
<foreignObject width='100%' height='100%'>
<div xmlns='http://www.w3.org/1999/xhtml' style='font-size:40px'>
<em>I</em> like <span style='color:white; text-shadow:0 0 2px blue;'>CANVAS</span>
</div>
</foreignObject>
</svg>
`;
const img = new Image();
const svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
const url = URL.createObjectURL(svg);
img.onload = function() {
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(url);
};
img.src = url;
<canvas id="canvas" style="border:2px solid black;" width="200" height="200"></canvas>
This example results in this HTML being rendered to canvas as this:
Will the properties and events of those elements works or not ?
No, everything drawn to a canvas is forgotten as passive pixels - they becomes simply an image.
You will need to provide custom logic that you provide yourselves in order to to handle any such things as clicks, objects, events etc. The logic need to define the areas, objects and anything else.

How to draw only the visible pixels which are >0% alpha with a custom color in canvas?

I would like to make a good performance hit test for png images and other shapes. I don't really care what shapes they are because with this technique there is no performance issues at checking (not setup).
I intent to collect all the images on the screen in a secondary canvas just for hit test. For each image drawn I will create a new color which is attached to that particular image. Then I draw all of them in the canvas, each image will have a different fill color.
When I click on a pixel (x, y) it will get the color (r, g, b). Every color is mapped to a image, so I get the image clicked with no error (I don't waste with finding what was hit with that click).
I know it will be limited to 256*256*256=16 777 216 items because those are all the colors but I don't think it will be a problem for now...
So what I really need is to know how to put those fill colors on the secondary canvas which is based only on the visible pixels for each image.
UPDATE
As you can see to the right it's the hit test map. So if I click on the black shade (c) I instantly know I've clicked on the blue box without any other calculation.
One improvement it would be to cache the alpha data. Also reuse the same alpha data for each image instance (we must take care about scaling and rotation...).
thanks
Here’s how you would color-mask the non-transparent pixels of a canvas image.
Be sure you replace "PutYourImageHere.png" with your own image url.
<!doctype html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid blue;}
</style>
<script>
$(function(){
var img=new Image();
img.onload=function(){
var red=255;
var blue=0;
var green=0;
var canvasCopy=document.getElementById("canvasCopy");
var ctxCopy=canvasCopy.getContext("2d");
var c=document.getElementById("canvas");
var ctx=c.getContext("2d");
ctx.drawImage(this,0,0);
var imgData=ctx.getImageData(0,0,c.width,c.height);
for (var i=0;i<imgData.data.length;i+=4)
{
if(imgData.data[i+3]>0){
imgData.data[i]=red;
imgData.data[i+1]=green;
imgData.data[i+2]=blue;
imgData.data[i+3]=255;
}
}
ctxCopy.putImageData(imgData,0,0);
}
img.src = "PutYourImageHere.png";
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width="300" height="300"></canvas>
<canvas id="canvasCopy" width="300" height="300"></canvas>
</body>
</html>

Working with images when uploading in Adobe Flex

I'm beginner with Flex and I already have a hard task to develop, so I could use some help! :)
What I have to do is upload some images to a server, which is OK, but before uploading I must downsize this images by reducing their quality and width/height. I've found many information about the class JPGEncoder, but I couldn't make it work.
Could anyone help me with that?
Thanks!
Rafael.
you can use encodeByteArray() method of JPEGEncoder. link
some good article for image uploading to server is available at
1. insideRIA
2. http://henryjones.us/articles/using-the-as3-jpeg-encoder
3. http://blog.pigdev.com/?p=137
Here is a little sample:
farg. this code editor leaves a little to be desired...
import mx.graphics.codec.JPEGEncoder;
private function btnClick(e:Event):void
{
var encoder:JPEGEncoder = new JPEGEncoder(0); // Terrible quality
picNew.source = encoder.encode( Bitmap(picOrig.content).bitmapData );
}
<mx:Image id="picOrig" x="10" y="10" source="image1.png"/>
<mx:Image id="picNew" x="200" y="10" />
<mx:Button x="100" y="300" label="Button" click="btnClick(event);"/>

Resources