I need the ability to be able to create an image of size 400x400 on the fly in a Windows Phone app, which will have a color of ARGB values that a user selects from a color picker. For instance, the user will click on a HyperlinkButton to take them to a ColorPickerPage and then will select a color, and I will retrieve that value and create the image from it, and display this image back on the MainPage. How might something like this be accomplished one I have retrieved the ARGB value from the user? I have not had luck finding any resources on this particular issue.
EDIT**
I came across http://www.geekchamp.com/forums/windows-phone-development/how-to-correctly-save-uicontrol-with-opacity-to-writeablebitmap which creates a rectangle on the screen and then saves to WriteableBitmap, but how might I skip that step and just save the Rectangle to WriteableBitmap? Note, I only have a single rectangle that I Fill with a custom Color.
You can save any UI element as an image using the code below. Here rect is the name of the rectangle in your XAML. If the rectangle isn't present in the UI then simply create one using C#. I have added the code to create a rectangle using C# and commented it.
public void saveimage(int height, int width, String filename)
{
//Rectangle rect = new Rectangle();
//rect.Height = 40;
//rect.Width = 40;
//rect.Fill = new SolidColorBrush(System.Windows.Media.Colors.Cyan);
var bmp = new WriteableBitmap(width, height);
bmp.Render(rect, null);
bmp.Invalidate();
var isf = IsolatedStorageFile.GetUserStoreForApplication();
if (!isf.FileExists(filename))
{
using (var stream = isf.OpenFile(filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
bmp.SaveJpeg(stream, width, height, 0, 100);
stream.Close();
}
}
}
Did you try using the Drawing Class.
here's the reference from msdn.
These are some samples: System.Drawing and System.Drawing.Imaging alternatives for Windows Phone
http://code.msdn.microsoft.com/windowsapps/Multi-Touch-Drawing-744a0b48
Hope it helps!
Related
To make my question clearer , I created a simple test class as below.
`public void create () {
stage = new Stage();
// GP
Texture texture1 = new Texture(Gdx.files.internal("data/badlogic.jpg"));
TextureRegion tr = new TextureRegion(texture1);
Image image = new Image(tr);
Group gp = new Group();
ImageButton ib = new ImageButton(new Image(tr).getDrawable());
ib.setSize(90, 256);
gp.addActor(ib);
gp.setPosition(0, 0);
stage.addActor(gp);
gp.debugAll();
}`
The size of badlogic logo is 256*256. I set it to 90*256 in the test.But the outcome looks like this http://imgsrc.baidu.com/forum/w%3D580/sign=fb0e4402d21373f0f53f6f97940e4b8b/0958c32397dda1448779b0cbb1b7d0a20df486e2.jpg
If i set the image size before sending it to imagebutton, then it will rendered as 256*256 ,the full original size. This function is so simple. I can not figure out where is going wrong.
First of all, last update of Libgdx project is 1.4.1: http://libgdx.badlogicgames.com/download.html
The problem is the Drawable object that you are sending to the ImageButton, if you want to change the size of the Image or Texture before adding it to the ImageButton (so you will solve the problem asked), you will just need to use the .setBounds() method
I write down a little example:
1. Initialize Image object with your image file:
`Image image = new Image( new Texture ( Gdx.Files.internal("yourPathFile.png") ) );`
2. .setBounds() javadoc: (x coordinate, y coordinate, width of the image, height of the image)
image.setBounds(0f, 0f, 50f, 60f)
then you can send the image to the ImageButton object as Drawable.
`ImageButton myButton = new ImageButton(image.getDrawable());'
That's all.
Here you have some constructors of ImageButton object from the Libgdx official javadoc.
See also:
Release versions: http://libgdx.badlogicgames.com/releases/
ImageButton javadoc: http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/ui/ImageButton.html
I've got a big issue and it's almost a week trying to make it work so any help I would really appreciate - I am trying to create a simple image editor in html5, so I upload an image, load it into canvas and then paint on it -
I also want to be able to zoom in and zoom out- just that I can't figure out how should I save the canvas state - for the paint mouseevents I am using an array which saves canvas.toDataUrl, but this one will save only what it is visible in canvas, only a part of the scaled image, and not the entire one -
if anyone knows how can I un-scale the canvas together with the painting over it and save it in the stack from where I can retrieve it for other painting events, I'll appreciate a lot! Thanks
Saving state
The canvas' save() and restore() is not related to the pixels in the canvas at all. Save() only saves current pen color, fill color, transform, scale, rotation and so forth - parameter values only, not actual pixel data.
And so, the restore() will only restore these parameter values to the previous ones.
The canvas element is passive, meaning it only holds the pixels that you see on the screen. It does not keep a backup of anything so if you change its size, re-size browser window or open dialogs in the browser causing it to clear, you will need to update the canvas yourself.
This also applies when you change a parameter value such as scale. Nothing on the canvas will change setting a new value. The only thing that happens is that your next draw of what-ever will use these parameter values for the drawing (in other words: if you apply rotation nothing rotates, but the next thing you draw will be rotated).
Drawing on existing image
As you need to maintain the content it also means you need to store the image you draw on as well as what you draw.
When you draw for example lines you need to record every stroke to arrays. When the canvas needs an update (ie. zoom) you redraw the original image first at the new scale, then iterate through the arrays with lines and re-render them too.
Same for points, rectangles, circles and what have you..
Think of canvas as just a snapshot of what you have stored elsewhere (image object, arrays, objects) . Canvas is just a view-port for that data.
I would recommend to store as this:
var backgroundImage; //reference to your uploaded image
var renderStack = []; //stores all drawing objects (see below)
//example generic object to hold strokes, shapes etc.
function renderObject() {
this.type = 'stroke'; //or rectangle, or circle, or dot, ...
this.x1;
this.y1;
this.x2;
this.y2;
this.radius;
this.penWidth;
this.penColor;
this.fillColor;
this.points = [];
//... extend as you need or use separate object for each type
}
When you then draw a stroke (pseudo):
var currentRenderObject;
function mouseDown(e) {
//get a new render object for new shape/line etc.
currentRenderObject = new renderObject();
//get type from your selected tool
currentRenderObject.type = 'stroke'; //for example
//do the normal draw operations, mouse position etc.
x =..., y = ...
}
function mouseMove(e) {
//get mouse positions, draw as normal
x = ..., y = ...
//store the points to the array, here:
//we have a line or stroke, so we push the
//values to ourpoint-array in the renderObject
currentRenderObject.points.push(x);
currentRenderObject.points.push(y);
}
function mouseUp(e) {
//when paint is done, push the current renderObject
//to our render stack
renderStack.push(currentRenderObject);
}
Now you can make a redraw function:
function redraw() {
clearCanvas();
drawBackgroundImage();
for(var i = 0, ro; ro = renderStack[i]; i++) {
switch(ro.type) {
case 'stroke':
//... parse through point list
break;
case 'rectangle':
//... draw rectangle
break;
...
}
}
}
function zoom(factor) {
//set new zoom, position (scale/translate if you don't
//want to do it manually). Remember that mouse coords need
//to be recalculated as well to match the zoom factor.
redraw();
}
//when canvas is scaled for some reason, or the window
canvas.onresize = windows.onresize = redraw;
A bonus doing this here is you can use your render stack as a undo/redo stack as well...
Hope this helped to better understand how canvas works.
I have a problem and I have potential solution. But I wanted to confirm if there is an easy and simple way to solve my problem.
App type:
Isometric Game
Problem statement:
I am loading images in my flash app and have mouse events attached to them.
The images I load are prop images like vehicles, trees, buildings etc., and all of them are transparent.
Example: Red ball asset (please ignore the yellow background which I applied to describe the problem)
If I click on the actual image area (colored in red), then every thing works perfect
I don't want to trigger mouseevent when I click on empty image part (or transparent area, which I have shown in yellow color)
There is one way I know by creating masks in flash. I don't want to do it unless that is the final option left because I load image assets instead of flash assets and I don't want to create a new mask asset for all the assets
There is another method I was going to adopt by using getPixel method of Bitmap. Which is discussed here.
But there is another problem with this method.
I might be able to ignore the click event when I click on the empty part of the asset but if there is some other asset is behind the image in the same location, then I need to process the click event for the occluded image.
Well, thinking of solution to this problem takes me to the getObjectsUnderPoint where I can scan the occluded assets
Well, what you proposed as a solution is 100% valid. Just move the logic of determining what game object is clicked outside of that object.
Listen for MOUSE_DOWN/MOUSE_UP events at container which contains your game objects.
Catch an event
Check if the game object which is the target of this event is transparent at this point using BitmapData.getPixel32
If it is use getObjectsUnderPoint to find out all other game objects at this point
Find in a loop the first object which is not transparent at this point
Now you got the actual object which is hit.
One interesting solution is to use Sprite objects with the individual non-transparent pixels burnt onto them.
Suppose this is your Loader "complete" handler:
private function loaderCompleteHandler(event:Event):void
{
// Loader is not our child, we use a Sprite instead (below).
var loader:Loader = Loader(event.target);
var sprite:Sprite = new Sprite();
addChild(sprite);
var w:Number = loader.content.width;
var h:Number = loader.content.height;
// Use transparent bitmap.
var bitmapData:BitmapData = new BitmapData(w, h, true, 0);
bitmapData.draw(loader.content);
// Now burn the image onto the Sprite object, ignoring
// the transparent pixels.
for (var xPos:int = 0; xPos < w; xPos++) {
for (var yPos:int = 0; yPos < h; yPos++) {
var pixel32:uint = bitmapData.getPixel32(xPos, yPos);
var alpha:int = pixel32 >>> 24;
if (alpha != 0) {
sprite.graphics.beginFill(pixel32 & 0xFFFFFF, alpha / 0xFF);
sprite.graphics.drawRect(xPos, yPos, 1, 1);
sprite.graphics.endFill();
}
}
}
}
Essentially you want "empty" pixels that aren't clickable, and fully transparent pixels aren't quite the same thing. With this solution you get empty pixels.
Only problem is that this might be slow. Give it a shot.
In AIR/AS3 Flex Mobile for Android project.
How can I capture an "image" of whats visible on the view
then just save that image as anything like jpg/pdf to the SD card?
Basically a screenshot on Android using AS3.
private function getBitmapData( target:DisplayObject ) : BitmapData
{
//target.width and target.height can also be replaced with a fixed number.
var bd : BitmapData = new BitmapData( target.width, target.height );
bd.draw( target );
return bd;
}
Create the byte array using JPEGEncoder and save this to Your sd card. In some case if the width and height of the target is not working, You can use the getbounds method to get the bounds of the object and from the bounds take the width and height.
How to assign bytearray value to panel background image. If anybody have idea or experiance plz help me to overcome the problem. BRIEF EXP:
I have panel control and want to load image getting from webservice as a backgroundimage. So i used setstyle() but its not accepting that image. so how to add that image into my panel background image.Plz tel me your ideas here.
In Flex 3 or higher, you just need to do:
yourImage.source = yourByteArray;
regards!
uhm, well i presume, since it is an image, you have it in a BitmapData, let's say "myBmp" ...
then use the following to extract all the data from BitmapData:
var bytes:ByteArray = myBmp.getPixels(myBmp.rect);
and the following to write:
myBmp.setPixels(myBmp.rect, bytes);
note that only the raw 32 bit pixel data is stored in the ByteArray, without compression, nor the dimensions of the original image.
for compression, you should refer to the corelib, as ozke said ...
For AS3 you can use adobe corelib. Check this tutorial...
http://ntt.cc/2009/01/09/as3corelib-tutorialhow-to-use-jpegencoder-and-pngencoder-class-in-flex.html
I used a flash.display.Loader() to load an image in an array. It has a Complete event that is fired after the image has been loaded. I then draw the image on to a Bitmap which I set to the data of a Image that could be placed in a panel. Hope you can make since of this good luck.
public static function updateImage(img:Image, matrix:Matrix,
pageDTO:PageDTO, bitmapData:BitmapData):void {
var loader:flash.display.Loader = new flash.display.Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (e:Event) : void {
bitmapData.draw(loader.content, matrix);
pageViewer.data = new Bitmap(bitmapData);
});
loader.loadBytes(pageDTO.thumbnail);
}
<mx:Panel>
<mx:Image id="pageViewer"/>
</mx:Panel>
Using adobe's JPGEncoder (com.adobe.images.JPGEncoder) class and ByteArray is pretty much all you need. Converting image to byte array (assuming CAPS are variables you'd need to fill in):
// -- first draw (copy) the image's bitmap data
var image:DisplayObject = YOUR_IMAGE;
var src:BitmapData = new BitmapData(image.width, image.height);
src.draw(image);
// -- encode the jpg
var quality:int = 75;
var jpg:JPGEncoder = new JPGEncoder(quality);
var byteArray:ByteArray = jpg.encode(src);
I had the same problem. As a workaround I created sub Canvas nested inside a main Canvas and added an Image to the main Canvas behind the sub Canvas. Anything drawn on the sub Canvas will appear on top of the Image.
Just load it into a Loader instance using the loadBytes function.
var ldr:Loader = new Loader();
ldr.loadBytes(myByteArray);
addChild(ldr);