BitmapImage Rotation - c#

In my ModelView I have an ObservableCollection of BitmapImages that displays in a listbox on my view. I am trying to rotate the selected image in the ObservableCollection.

Ok, figured it out and you can let me know if something looks stupid
//Create a transform
TransformedBitmap tBmp = new TransformedBitmap();
tBmp.BeginInit();
//Set the source = to the image currently selected
tBmp.Source = _Scans[_selectedImage].MyImage;
RotateTransform rt = new RotateTransform(180);
tBmp.Transform = rt;
tBmp.EndInit();
//Create a new source after the transform
BitmapSource s1 = tBmp;
BitmapImage bi = BitmapSourceToBitmapImage(s1);
//Add create the item and replace the current item in the collection
//edited according to comment
//ScannedImages s = new ScannedImages();
//s.MyImage = bi;
//_Scans[_selectedImage] = s;
Scans[_selectedImage].MyImage = BitmapSourceToBitmapImage(s1);

In your DateTemplate where you define how you would like to display your Image (as ListBox Item), you can use .RenderTransform property to transform/rotate your Control.
Example for Button:
<Button
<Button.RenderTransform>
<RotateTransform CenterX="0" CenterY="0" Angle="45"/>
</Button.RenderTransform>
Test</Button>
Have a read more on How to Rotate an object? MSDN Article

Related

BitmapImage Stretch mode to Image tag in xaml

I am using in xaml with some fix image source, later on I wanted to use local image and wanted to assign to the xaml. But I am not able to use stretch in new image created .
Is there any way to use the stretch in other way ?
My code in xaml :
<Image Source="/Assets/Images/fix.png" Visibility="Visible" x:Name="ContentImage" Stretch="UniformToFill" />
and in C#
if (File.Exists(imagePath))
{
Image newImage = new Image();
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri(imagePath);
logo.EndInit();
newImage.Source = logo;
newImage.Stretch = Stretch.UniformToFill;
ContentImage.Source = newImage.Source;
}
It makes no sense to create another Image element. It is also not necessary to call Begin/EndInit. Use the BitmapImage constructor that takes an Uri argument instead.
This should be sufficient:
if (File.Exists(imagePath))
{
ContentImage.Source = new BitmapImage(new Uri(imagePath));
}

How can I drop a ListViewItem onto a Canvas and render the image, the Item contains?

I have a custom object of type "Module", where I store an Image and a Name. These objects are stored in a ListView, where I drag and drop them onto a Canvas, so I can arrange them (Kind of like a puzzle). First, I just drew the Image:
var module = e.Data.GetData("MyFormat") as Module;
Canvas CanvasView = sender as Canvas;
Image image = new Image();
image.Source = module.ModuleImage;
Point enterPoint = e.GetPosition(this.moduleCanvas);
Point PointToDraw = new Point(0, 0);
PointToDraw.X = enterPoint.X - DropPosition.X;
PointToDraw.Y = enterPoint.Y - DropPosition.Y;
//+35 and +43 so the Module gets dropped in the way you picked it up
image.SetValue(Canvas.LeftProperty, PointToDraw.X + 35);
image.SetValue(Canvas.TopProperty, PointToDraw.Y + 43);
CanvasView.Children.Add(image);
But then I realized, I need an Object on the canvas, not just an image, so I tried this:
ListViewItem lvitem = new ListViewItem();
var module = e.Data.GetData("MyFormat") as Module;
Canvas CanvasView = sender as Canvas;
lvitem.Content = module;
CanvasView.Children.Add(lvitem);
But this won't render the Image on the canvas of course. It just tells me MyNamespace.Module. How can I make the Canvas render the Image of the object, the ListViewItem contains?
If the Image property of your Module class returns an actual Image element, you could set the Content property to this one:
lvitem.Content = module.Image;
If Image returns a path, you could set the Content property to a ContentControl with a ContentTemplate that you may create programmatically using either a FrameworkElementFactory or XamlReader.Parse. In the ContentTemplate, you define the Image element:
ContentControl cc = new ContentControl();
cc.Content = new LongTextConverter();
FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(Image));
frameworkElementFactory.SetBinding(Image.SourceProperty, new Binding("Image"));
cc.ContentTemplate = new DataTemplate() { VisualTree = frameworkElementFactory };
lvitem.Content = cc;
Or use a ListView with a Canvas as the ItemsPanel. See this answer for an example. You could then set the ItemsSource of the ListView to an IEnumerable<Module> and define an ItemTemplate that will be applied to each Module.

Convert the grid background to image through code behind

I want to convert the grid background to image through code behind,how to do this-
I have tried this-
ImageBrush gridBackground = (ImageBrush)(((Grid)sender).Background);
System.Windows.Controls.Image gridBackImage = new System.Windows.Controls.Image();
gridBackImage.Source = gridBackground.ImageSource;
it is giving error-
Unable to cast object of type 'System.Windows.Media.SolidColorBrush' to type 'System.Windows.Media.ImageBrush'.
I feel you need to clarify your requirements more, because what you might be attempting might be a wrong approach. I feel you haven't set any image to the background of the grid but only a color.
So setting background to a color it will return an SolidColorBrush and not an Image, i.e. ImageBrush.
If you have set it to an Image background then your code will work fine. But the question is what is that you are intending to do with gridBackImage? because I feel we are converting it to something which is not necessary. If you say what you intent to do it would be better to solve.
var grid = sender as Grid;
Image gridBackImage =new Image();
gridBackImage.Source = grid.Background.ImageSource;
ImageBrush myBrush = new ImageBrush();
Image image = new Image();
image.Source = new BitmapImage(
new Uri(
"pack://application:,,,/MyClassLibrary;/Images/Image1.jpg"));
myBrush.ImageSource = image.Source;
Grid grid = (Grid)sender;
grid.Background = myBrush;
You can easily be acheived in the xaml by adding the following code in the grid
<Grid>
<Grid.Background>
<ImageBrush ImageSource="/MyProject;component/Images/bg.png"/>
</Grid.Background>
</Grid>
Left for you to do, is adding a folder to the solution called 'Images' and adding an existing file to your new 'Images' folder, in this case called 'bg.png'
You can convert the Backround to ImageBrush instead of Image.
ImageBrush img = (Grid_Image.Background as ImageBrush);
You should be able to reverse Saritha.S.R's answer like:
ImageBrush myBrush = (ImageBrush)(((Grid)sender).Background);
Image image = new Image();
image.Source = myBrush.ImageSource;
Is that what you're after?
Edit:
Your edit:
Unable to cast object of type 'System.Windows.Media.SolidColorBrush' to type System.Windows.Media.ImageBrush'.
Indicates that you don't really have an image set as background. You need something like:
<Grid.Background>
<ImageBrush ImageSource="YourBackgroundImage.jpg"/>
</Grid.Background>
Or in code behind:
ImageBrush myBrush = new ImageBrush();
Image image = new Image();
image.Source = new BitmapImage(
new Uri("pack://application:,,,/YourProject;component/YourBackgroundImage.jpg"));
myBrush.ImageSource = image.Source;
yourGrid.Background = myBrush;
For this to work. You simply can't get an image from a SolidColorBrush
Please check whether the Image Background is set as ImageBrush, like
<Grid Height="300" Width="100" x:Name="Grid_Image">
<Grid.Background>
<ImageBrush ImageSource="ms-appx:///Assets/SmallLogo.scale-100.png"/>
</Grid.Background>
</Grid>
Then you can cast in code behind as mentioned by you.
ImageBrush im = ((ImageBrush)(((Grid)sender).Background);
Image gridBackImage =new Image();
gridBackImage.Source = im.ImageSource;
Solved,My code is-
ImageBrush gridBackground;
if (((Grid)sender).Children.Count > 0)
{
gridBackground = (ImageBrush)(((Grid)sender).Background);
System.Windows.Controls.Image gridBackImage = new System.Windows.Controls.Image();
gridBackImage.Source = gridBackground.ImageSource;
ImageCar.Source = gridBackImage.Source;
}

Rotating an Image in Windows Phone

I display a photo I took on one of my pages.
I capture the photo in Portrait mode and it works ok.
When I show the picture on my next view, it treats the photo like it was taken in Landscape.
So I need to rotate the picture/image by -90 to correct this.
Here is the relevant code of my .XAML:
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanelx" Grid.Row="1" Margin="0,0,0,0">
</Grid>
And here is the methods where I load the photo and put it into the ContentPanel.:
void loadImage()
{
// The image will be read from isolated storage into the following byte array
byte[] data;
// Read the entire image in one go into a byte array
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
// Open the file - error handling omitted for brevity
// Note: If the image does not exist in isolated storage the following exception will be generated:
// System.IO.IsolatedStorage.IsolatedStorageException was unhandled
// Message=Operation not permitted on IsolatedStorageFileStream
using (IsolatedStorageFileStream isfs = isf.OpenFile("0.jpg", FileMode.Open, FileAccess.Read))
{
// Allocate an array large enough for the entire file
data = new byte[isfs.Length];
// Read the entire file and then close it
isfs.Read(data, 0, data.Length);
isfs.Close();
}
}
// Create memory stream and bitmap
MemoryStream ms = new MemoryStream(data);
BitmapImage bi = new BitmapImage();
// Set bitmap source to memory stream
bi.SetSource(ms);
// Create an image UI element – Note: this could be declared in the XAML instead
Image image = new Image();
// Set size of image to bitmap size for this demonstration
image.Height = bi.PixelHeight;
image.Width = bi.PixelWidth;
// Assign the bitmap image to the image’s source
image.Source = bi;
// Add the image to the grid in order to display the bit map
ContentPanelx.Children.Add(image);
}
}
I am thinking on a simple rotate on the image after I've loaded this. I can do this in iOS, but my C# is skills are worse than bad.
Can anybody advise on this?
If the image is declared in xaml you can rotate it like this:
//XAML
<Image.RenderTransform>
<RotateTransform Angle="90" />
</Image.RenderTransform>
Same thing can be done thru c# also. If you always rotate the image , then doint it in xaml is the better optioin
//C#
((RotateTransform)image.RenderTransform).Angle = angle;
Please try this one:
RotateTransform rt = new RotateTransform();
rt.Angle = 90;
image.RenderTransform = rt;
You can create a RotateTransform object to use for the image's RenderTransform property. This will cause WPF to rotate the Image control when rendered.
If you want to rotate the image about it's center you will also need to set the rotation origin, as shown below:
RotateTransform rt = new RotateTransform();
rt.Angle = 90;
image.RenderTransform = rt;
image.RenderTransformOrigin = new Point(0.5, 0.5);

Replace Image with cropped BitmapSource

I have an Image on my wpf control
and I am trying to generate croped part of it - this is ok more or less.
I have used a codeproject solution to generate BitmapSource of croped image (http://www.codeproject.com/KB/WPF/CropAdorner.aspx) but when I am trying to
replace current image with generated BitmapSource like this
imgCurrent.Source = generatedBitmapSource;
I see very strange behaviour ((
I need an advice how to change current Image with new based on BitmapSource.
my XAML(there is nothing extraordinary - and by the right click I am trying to replace currentImage with croped):
<DockPanel Height="395" Width="926">
<!--Went with a DockPanel here so that the image would always be centered in its parent control.-->
<Image x:Name="imgCurrent" VerticalAlignment="Center" HorizontalAlignment="Center" MouseRightButtonDown="imgCurrent_MouseRightButtonDown"/>
</DockPanel>
right click:
private void imgCurrent_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
generatedBitmapSource = _clp.BpsCrop();
//this clears croping adonder
AdornerLayer aly = AdornerLayer.GetAdornerLayer(_felCur);
aly.Remove(_clp);
//
imageCurrent.Source = generatedBitmapSource;
}
croping method (from codeproject):
public BitmapSource BpsCrop()
{
Thickness margin = AdornerMargin();
Rect rcInterior = _prCropMask.RectInterior;
Point pxFromSize = UnitsToPx(rcInterior.Width, rcInterior.Height);
// It appears that CroppedBitmap indexes from the upper left of the margin whereas RenderTargetBitmap renders the
// control exclusive of the margin. Hence our need to take the margins into account here...
Point pxFromPos = UnitsToPx(rcInterior.Left + margin.Left, rcInterior.Top + margin.Top);
Point pxWhole = UnitsToPx(AdornedElement.RenderSize.Width + margin.Left, AdornedElement.RenderSize.Height + margin.Left);
pxFromSize.X = Math.Max(Math.Min(pxWhole.X - pxFromPos.X, pxFromSize.X), 0);
pxFromSize.Y = Math.Max(Math.Min(pxWhole.Y - pxFromPos.Y, pxFromSize.Y), 0);
if (pxFromSize.X == 0 || pxFromSize.Y == 0)
{
return null;
}
System.Windows.Int32Rect rcFrom = new System.Windows.Int32Rect(pxFromPos.X, pxFromPos.Y, pxFromSize.X, pxFromSize.Y);
RenderTargetBitmap rtb = new RenderTargetBitmap(pxWhole.X, pxWhole.Y, s_dpiX, s_dpiY, PixelFormats.Default);
rtb.Render(AdornedElement);
return new CroppedBitmap(rtb, rcFrom);
}
Are you sure you don't have issue with your "BitmapSource of croped image"? Can you for test purpose replace it with another valid Bitmap and try if it works. If it works with another one, but not "BitmapSource of croped image" then maybe you have issue with creating "BitmapSource of croped image".

Categories