Cropping specific part of the image - windows-phone-8

I am building a windows phone 8 camera app. After a photograph has been taken i want to give the user the option of cropping specific part of the image. Like if there are some specific objects in the image, when crop option is selected, it should highlight or outline that specific part of the image, and it should be able to crop it, rather than manually cropping it.
Any specific ways to do it?.
Thanks In advance.

One way would be to create a WriteableBitmap and do a TranslateTransform of the original image into the WritableBitmap. Something like::
Image workImage = new Image { Source = originalImage, Width = originalWidth, Height = originalHeight };
WriteableBitmap writeableBitmap = new WriteableBitmap(newWidth, newHeight);
writeableBitmap.Render(temporaryImage, new TranslateTransform { X = (originalWidth – newWidth) / -2, Y = (originalHeight – newHEight) / -2 });
writeableBitmap.Invalidate();
//... or some other stream
Stream newImageStream = new MemoryStream();
//set whatever quality settings you like if 75 is no good
writeableBitmap.SaveJpeg(newImageStream, newWidth, newHeight, 0, 75);
// TODO: do something with newImageStream

Related

Merge two images and retain its transparency

It was a while since I programmed AS3. Now I have a problem where I need to merge the two images where the upper image is a png that must retain its transparency. The upper image is an area that must pass through the lower image. A bit like a masked layer.
The result of this merge should result in a a display object. This object will later be sent to a method with the following signature:
public function addImage (
display_object:DisplayObject,
x:Number = 0,
y:Number = 0,
width:Number = 0,
height:Number = 0,
image_format:String = "PNG",
quality:Number = 100,
alpha:Number = 1,
resizeMode:String = "None",
blendMode:String = "Normal",
keep_transformation:Boolean = true,
link:String = ''
):void
Any advice is of the utmost interest. Thanks!
UPDATE;
After some struggling I've come up with this:
var bitmapDataBuffer:BitmapData = new BitmapData ( front.loader.width, front.loader.height, true );
bitmapDataBuffer.draw ( front.loader );
var bitmapOverlay:BitmapData = new BitmapData ( front.loader.width, front.loader.height, true );
bitmapOverlay.draw ( frontBanner.loader );
var rect:Rectangle = new Rectangle(0, 0, front.loader.width, front.loader.height);
var pt:Point = new Point(0, 0);
var mult:uint = 0x00;
bitmapOverlay.merge(bitmapDataBuffer, rect, pt, mult, mult, mult, mult);
var bmp:Bitmap = new Bitmap(bitmapOverlay);
pdf.addImage(bmp,0,0,0,0,ImageFormat.PNG,100,1,ResizeMode.FIT_TO_PAGE);
The problem is that my background image (represented by bitmapDataBuffer) will be totally overwritten by my upper image (the one I call overlay).
The overlay image is a png image. This image has a part of it that is transparent. Through this transparency I want to see my background image.
Any more suggestions?
You should be more specific about what kind of merge you want. You have a few options:
BitmapData.copyPixels - Provides a fast routine to perform pixel manipulation between images with no stretching, rotation, or color effects. This method copies a rectangular area of a source image to a rectangular area of the same size at the destination point of the destination BitmapData object.
BitmapData.merge - Performs per-channel blending from a source image to a destination image. For each channel and each pixel, a new value is computed based on the channel values of the source and destination pixels.
BitmapData.draw - Draws the source display object onto the bitmap image, using the Flash runtime vector renderer. You can specify matrix, colorTransform, blendMode, and a destination clipRect parameter to control how the rendering performs.
Each will work out for a different thing - the first will just copy some image over another (can keep/merge alphas). The second will merge channels data and modify them. The third one is the easiest and can draw one bitmap over another, as well as use blend modes.
Just chose one! :)
In order to make overlay image over the buffer image in your case, you are to use copyPixels() with mergeAlpha set to true.
bitmapDataBuffer.copyPixels(bitmapOverlay, rect, new Point(), null, null, true);
This will place data from bitmapOverlay to those parts of bitmapDataBuffer where overlay's alpha is above 0, blending semitransparent regions with the background.

Change Bitmap to different shapes in Windows Phone app

I've been looking for the solution for some time and haven't yet found it. One of the functions of my app is to load an image and then to change its shape - e.g. I load a normal rectangular image, and then there are 2-3 buttons - change the image to a circle, triangular or some other shape. Is sth like that even possible with Bitmaps? I found a lot of interesting things about Nokia imaging SDK, but all the shape stuff i found was LensBlurEffect, which isn't exactly what i need.
If someone could point me in the right direction, I would be really grateful!
Thank You in advance for help!
Best regards,
Roman
I'm working on filters that draws shapes using Nokia Imaging SDK. To solve your problem, I created sample project that uses Nokia Imaging SDK's blend filter and my custom shape filters.
Actually you can do the same thing with shape image as David refers (background is black, foreground white) instead of using my custom filters (EllipseShapeFilter above example code).
Here is sample code;
var ellipseImage = new WriteableBitmap(1024, 768);
Rect origin = new Rect(new Point(512, 384), new Size(512, 384));
uint white = 0xff000000 | (255 << 16) | (255 << 8) | 255;
var image = LoadFromResources(new Uri(#"/BlendImageSample;component/Assets/Sample.jpg", UriKind.Relative));
using (var ellipseSource = new BitmapImageSource(ellipseImage.AsBitmap()))
using (var ellipse = new EllipseShapeFilter(ellipseSource, white, origin))
{
ellipseImage = await new WriteableBitmapRenderer(ellipse, ellipseImage).RenderAsync();
}
ImageViewer.Source = ellipseImage;
using (var backgroundSource = new BitmapImageSource(ellipseImage.AsBitmap()))
using (var foregroundSource = new BitmapImageSource(image.AsBitmap()))
using (var filterEffect = new FilterEffect(backgroundSource))
{
using (BlendFilter blendFilter = new BlendFilter())
{
blendFilter.ForegroundSource = foregroundSource;
blendFilter.BlendFunction = BlendFunction.Darken;
filterEffect.Filters = new[] { blendFilter };
var OutputBitmap = new WriteableBitmap(image.PixelWidth, image.PixelHeight);
var result = await new WriteableBitmapRenderer(filterEffect, OutputBitmap).RenderAsync();
ImageViewer.Source = result;
}
}
Github - BlendImageSample
Well the bitmap is always going to be rectangular, there is nothing you can do about that.
What you can do is make some pixels transparent, thus making the bitmap appear of a different shape.
One way to do this using the Nokia Imaging SDK is to use the BlendFilter to blend a transparent image (I suggest just a ColorImageSource) over the original image. You can provide different masks to create different "shapes."

What is the proper way to add MANY images to WP8 map?

In building a program that displays a map, I have two sliders:
that changes the map's pitch
that rotates the map's heading
And, two Buttons that change the Zoom_Level of the map
I have close to 200 images that need to be displayed on the map at any given time based on the zoom level. (each one is click-able)
With so many Images, I'm getting an:
"A first chance exception of type 'System.OutOfMemoryException' occurred in System.Windows.ni.dll"
thrown.
Many of these Images are the same - just displayed in different places. I find it very inefficient that I need to initialize each different Image separately and place it inside it's own MapOverlay instead of referencing a globally constructed Image and referencing it when I need it. (there is also a problem with Clearing the Map.Layers when the Images are defined globally).
Is there a better way to add many Images to a map?
After I hit about 50 Images I get the OutOfMemoryException (the Images need to be defined separately so that they are square in dimension for the rotating to work properly).
Does it matter how the Images are added to the Project/App ("Build Action" or the "Copy to Output Directory")? Would it be better to have them in Isolated Storage? Would this make a difference?
Here is the code I'm currently using to add Images:
MapLayer pinLayerZoom12 = new MapLayer();
MapOverlay pinOverlay = new MapOverlay();
// Add the location of the Pushpin using latitude and longitude.
pinOverlay.GeoCoordinate = new GeoCoordinate(49.33783000, -0.45215600);
Image pinOverlayImage = new Image();
pinOverlayImage.Source = new BitmapImage(new Uri("images/Hedgehog.png", UriKind.Relative));
pinOverlay.Content = pinOverlayImage;
pinOverlay.PositionOrigin = new Point(0.0, 0.0);
pinOverlayImage.Opacity = 0.8;
pinOverlayImage.Height = 10;
pinOverlayImage.Width = 10;
pinOverlayImage.Tap += pinOverlayImage_Tap;
pinLayerZoom12.Add(pinOverlay);
MapOverlay pinOverlay2 = new MapOverlay();
// Add the location of the Pushpin using latitude and longitude.,
pinOverlay2.GeoCoordinate = new GeoCoordinate(49.33783000, -0.44547083);
Image pinOverlay2Image = new Image();
pinOverlay2Image.Source = new BitmapImage(new Uri("images/Hedgehog.png", UriKind.Relative));
pinOverlay2.Content = pinOverlay2Image;
pinOverlay2.PositionOrigin = new Point(0.0, 0.0);
pinOverlay2Image.Opacity = 0.8;
pinOverlay2Image.Height = 10;
pinOverlay2Image.Width = 10;
pinOverlayImage.Tap += pinOverlayImage2_Tap;
pinLayerZoom12.Add(pinOverlay2);
// Add the layer to the map
map1.Layers.Add(pinLayerZoom12);
Thank you for any help you can give me!

How to properly create a Point relative to an Image using FigPanZoom?

I have an Image that's 5000 pixels by 5000 pixels. It's scaled up and down regularly to fit different parts of the image into the window.
I'm making a function that focuses in on different places on the image (like a map) and then zooms into a certain scale that I specify.
I pass my point into this function (new Point(2000,2500) for example)) however this always breaks because it's not relative to the image specifically.
How do I make the Point relative to the image at the image's given scale at any given time?
Additional Info: I'm using the guide here http://www.adobe.com/devnet/flex/samples/fig_panzoom.html for panning and zooming functionality.
Solved:
One of my pitfalls was that I was using a possible bitmapScaleFactor > 1 which would mess up the scaling. This was the final function that worked for my usage.
protected function testFocus(p:Point):void
{
var content:ContentRectangle = boardViewer._contentRectangle;
var panToPoint:PanToPointCommand = new PanToPointCommand(boardViewer, content);
var scale:Number = boardViewer.bitmapScaleFactor;
var location = new Point((p.x*scale)+content.x, (p.y*scale)+content.y);
var center = new Point(boardViewer.width/2, boardViewer.height/2);
//Move the point to the center
panToPoint.fromPoint = location;
panToPoint.toPoint = center;
panToPoint.execute();
}
I've not tested this but how about using the scale factor that is being applied to the image to alter the point coordinates.
e.g.
var scaler:Number = 0.5;
image.scaleX = image.scaleY = scaler;
new Point(2000*scaler,2500*scaler);
Are you looking for DisplayObject.mouseX/mouseY? These do not take any rotation into account, however.
To take rotation into account, you could do something like (untested code):
var mat:Matrix = image.transform.concatenatedMatrix;
mat.invert();
// now use mat to transform point from 'stage space' to 'image space'
var pImage:Point = mat.transform(new Point(stage.mouseX, stage.mouseY));

Reporting services partially colored cell

How can i create partialy colored cell in reporting services table or matrix? For example: I hava value of 45& i want to fill only 45% of cell with red color, and other 55% stay white?
The only way I can see that working is to have a background image that is x% full of red for each percentage band you want to show.
Then you can set an expression to fill the background with the correct image depending on the value of a particular field.
Not quite the greatest solution as you are going to need 20 images just to get 5% bands.
The other option is to write a webservice/asp.net page that will generate an image in the correct proportions based on a querystring. Then you can set the background image to the aspx page.
This article is an example of how to create an image on the fly through asp.net
Tested the following code and it works quite nicely to produce an in cell chart.
protected void Page_Load(object sender, EventArgs e)
{
int percent = 0;
int height = 20;
if (Request.QueryString.AllKeys.Contains("percent"))
{
int.TryParse(Request.QueryString["percent"], out percent);
}
if (Request.QueryString.AllKeys.Contains("height"))
{
int.TryParse(Request.QueryString["height"], out height);
}
Bitmap respBitmap = new Bitmap(100, height, PixelFormat.Format32bppRgb);
Graphics graphics = Graphics.FromImage(respBitmap);
Brush brsh = new SolidBrush(Color.White);
graphics.FillRectangle(brsh, new Rectangle(0, 0, respBitmap.Width, respBitmap.Height));
brsh = new SolidBrush(Color.Red);
graphics.FillRectangle(brsh, new Rectangle(0, 0, respBitmap.Width * percent / 100, respBitmap.Height));
Response.ContentType = "image/jpeg";
Response.Charset = "";
respBitmap.Save(Response.OutputStream, ImageFormat.Jpeg);
}
Go to the text box you want, change the BackGroundImage source to external and the value to an expression.
Use an expression something like
= "http://mysite/chartimage.aspx?percentage=" & Fields!MyField.Value