how to clear memory of WritableBitmap - c#

I am picking image from gallery using PhotoChooserTask, here is my setup
private void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
PhotoChooserTask photo = new PhotoChooserTask();
photo.Completed += photo_Completed;
photo.Show();
}
void photo_Completed(object sender, PhotoResult e)
{
if (e.ChosenPhoto != null)
{
WriteableBitmap wbmp1 = PictureDecoder.DecodeJpeg(e.ChoosenPhoto, (int)scrnWidth, (int)scrnHeight);
ImageBrush iBru = new ImageBrush();
iBru.ImageSource = wbmp1;
iBru.Stretch = Stretch.Fill;
ContentPanel.Background = iBru;
}
}
Problem: with this way is it works only with .JPEG images
to make it work with other image formats, I tried this:
void photo_Completed(object sender, PhotoResult e)
{
if (e.ChosenPhoto != null)
{
WriteableBitmap wBmp = new WriteableBitmap(0, 0);//6930432
wBmp.SetSource(e.ChosenPhoto);//23105536
MemoryStream tmpStream = new MemoryStream();//23105536
wBmp.SaveJpeg(tmpStream, (int)scrnWidth, (int)scrnHeight, 0, 100);//22831104
tmpStream.Seek(0, SeekOrigin.Begin);//22831104
WriteableBitmap wbmp1 = PictureDecoder.DecodeJpeg(tmpStream, (int)scrnWidth, (int)scrnHeight);//24449024
ImageBrush iBru = new ImageBrush();//24449024
iBru.ImageSource = wbmp1;//24449024
iBru.Stretch = Stretch.Fill;
ContentPanel.Background = iBru;
}
}
this way works with different image formats, but it is not memory efficient.
I have mentioned number of bytes used after each line for better understanding.
Question: In latter code snippet, I do not need wbmp anymore, How can I clear memory used by wbmp object?

As #Soonts suggested I used BitmapImage and it solves my purpose,
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = (int)scrnWidth;
bmp.DecodePixelHeight = (int)scrnHeight;
bmp.SetSource(e.ChosenPhoto);
It consumes less memory and we can scale down image

Get rid of the WriteableBitmap, instead do something like this:
var bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.SetSource( e.ChosenPhoto );
var ib = new ImageBrush() { ImageSource = bmp, Stretch = Stretch.Fill };
ContentPanel.Background = ib;

Related

Image.Source = new BitmapImage(); doesn't work in UWP

I have a problem while reading a file in C#. Here's the code:
protected override void OnNavigatedTo(NavigationEventArgs EvArgs)
{
base.OnNavigatedTo(EvArgs);
var Args = EvArgs.Parameter as Windows.ApplicationModel.Activation.IActivatedEventArgs;
var FArgs = Args as Windows.ApplicationModel.Activation.FileActivatedEventArgs;
if (Args != null)
{
if (Args.Kind == Windows.ApplicationModel.Activation.ActivationKind.File)
{
var IMG = new Image();
IMG.Loaded += IMG_Loaded;
string FP = FArgs.Files[0].Path;
Uri = FP;
IMG.Source = new BitmapImage(new Uri(FP, UriKind.RelativeOrAbsolute));
FV.Items.Add(IMG);
PathBlock.Text = FArgs.Files[0].Name + " - Image Viewer";
void IMG_Loaded(object sender, RoutedEventArgs e)
{
IMG.Source = new BitmapImage(new Uri(Uri));
}
}
}
if (Args == null)
{
PathBlock.Text = "Image Viewer";
}
}
The problem is at this part:
IMG.Source = new BitmapImage(new Uri(FP, UriKind.RelativeOrAbsolute));
The image won't load, even after trying a resource that the app CAN access in its own files:
IMG.Source = new BitmapImage(new Uri("ms-appx:///09.png, UriKind.RelativeOrAbsolute));
It still won't work.
This only works with this code:
var FOP = new Windows.Storage.Pickers.FileOpenPicker();
StorageFile F = await FOP.PickSingleFileAsync();
IRandomAccessStream FS = await F.OpenAsync(FileAccessMode.Read);
var BI = new BitmapImage();
var IMG = new Image();
await BI.SetSourceAsync(FS);
IMG.Source = BI;
Sadly, I can't use a file stream OR a file picker in the first code example, so I can't make it work as I did here.
Image.Source = new BitmapImage(); doesn't work in UWP
The problem is file Path property does not use to set image source directly in UWP platform.
Derive from your code, it looks you open the image file with current app, if you can get the IStorageItem from FArgs.Files list, you could also convert it as StorageFile, and then pass the opened file stream to BitmapImage.
For more detail steps please refer to the following code.
protected async override void OnNavigatedTo(NavigationEventArgs EvArgs)
{
base.OnNavigatedTo(EvArgs);
var Args = EvArgs.Parameter as Windows.ApplicationModel.Activation.IActivatedEventArgs;
var FArgs = Args as Windows.ApplicationModel.Activation.FileActivatedEventArgs;
if (Args != null)
{
if (Args.Kind == Windows.ApplicationModel.Activation.ActivationKind.File)
{
var IMG = new Image();
string FP = FArgs.Files[0].Path;
var Uri = FP;
StorageFile imageFile = FArgs.Files[0] as StorageFile;
using (var stream = await imageFile.OpenReadAsync())
{
var bitmp = new BitmapImage();
bitmp.SetSource(stream);
IMG.Loaded += (s, e) => { IMG.Source = bitmp; };
}
RootLayout.Children.Add(IMG);
}
}
if (Args == null)
{
}
}

unable to display captured image in windows phone listview

I am trying to display the captured image in windows phone listview in order to upload using background agent. But when the cameracapturedtask is completing, the app is deactivating in app.xaml.cs. This same functionality is working fine when I upload image from Gallery. I have included my code below. Please help if there is any solution.
private void Camera_Click(object sender, RoutedEventArgs e)
{
cmb.Dismiss();
CameraCaptureTask cameraCapture = new CameraCaptureTask();
cameraCapture.Completed += new EventHandler<PhotoResult>(cameraCaptureTask_Completed);
cameraCapture.Show();
}
private void cameraCaptureTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
string filename = e.OriginalFileName;
var listSplit = filename.Split('\\');
int i = listSplit.Length;
string name = listSplit[i - 1];
PhotoResult photoResult = e;
j = 1;
//sendImgRequest(name, e);
BitmapImage bmp = new BitmapImage();
bmp.SetSource(e.ChosenPhoto);
arrfilename.Add(filename);
//arrimg.Add(bmp);
arrstream.Add(e.ChosenPhoto);
arrtext.Add("Photo");
using (var isostore = IsolatedStorageFile.GetUserStoreForApplication())
{
var wb = new WriteableBitmap(bmp);
using (var isoFileStream = isostore.CreateFile(name))
wb.SaveJpeg(isoFileStream, wb.PixelWidth, wb.PixelHeight, 0, 100);
}
newimgdata.Add(new imgdata { image = bmp, text = "Photo", filename = name });
lstbox.ItemsSource = newimgdata;
}
}

display an image from file in wpf isn't working?

I have a button b3 and an image named pictureBox1 . Im using WPF, however I'm using the winforms openFileDialog instead of the one that comes with WPF :
below is the code that I put inside the click event of my button :
private void b3_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.OpenFileDialog openDialogIcon = new System.Windows.Forms.OpenFileDialog();
if (openDialogIcon.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
Image i = new Image();
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(openDialogIcon.FileName, UriKind.Absolute);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
i.Source = src;
i.Stretch = Stretch.Uniform;
//int q = src.PixelHeight; // Image loads here
}
}
When I click the button and select an icon. The icon doesn't appear in the pictureBox1.
Can someone please explain why the code above doesn't show the icon inside the pictureBox?
You need to assign your image to the pictureBox, else you wont see it on your screen and you only made the image object in memory.
private void b3_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.OpenFileDialog openDialogIcon = new System.Windows.Forms.OpenFileDialog();
if (openDialogIcon.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(openDialogIcon.FileName, UriKind.Absolute);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
pictureBox1.Source = src;
}
}
Try to drag and drop a Image control in your window
...
//imageStretch <- the name of Image control
i.Stretch = Stretch.Uniform;
//int q = src.PixelHeight; // Image loads here
imageStretch.Source = src;
...

C# save bitmap output

I'm creating a C# program that's capturing the screen with bitmap.
And than I want to save it to an .Avi/ .mpeg file.
But I don't know how to save it to a video.
Here is the code I already have.
public Form1()
{
InitializeComponent();
}
static Bitmap bm;
private void btnFolder_Click(object sender, EventArgs e)
{
FolderBrowserDialog folderDlg = new FolderBrowserDialog();
folderDlg.ShowNewFolderButton = true;
DialogResult result = folderDlg.ShowDialog();
if (result == DialogResult.OK)
{
textBox1.Text = folderDlg.SelectedPath;
Environment.SpecialFolder root = folderDlg.RootFolder;
}
}
private void btnStart_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void btnStop_Click(object sender, EventArgs e)
{
timer1.Stop();
SaveCapture(textBox1.Text);
}
private void SaveCapture(string path)
{
// Here should be the code to save it to mpeg/avi
}
private void timer1_Tick(object sender, EventArgs e)
{
// Take screenshot
bm = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics graphics = Graphics.FromImage(bm as Image);
graphics.CopyFromScreen(0, 0, 0, 0, bm.Size);
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
// Show it in picturebox
pictureBox1.Image = bm;
}
Thank you very much!
Create a Video Stream (AVI) from a Series of Images
I think this might be your best solution. Store all the .jpg's and create an avi from the command line at intervals. I don't see how creating video on the fly would produce a "lightweight" solution.
Hello click this to download the aviwrapper liblary. And the code that you should write is this:
var pngFileList = Directory.EnumerateFiles(folderImages, "*.png");
//load the first image
Bitmap bitmap = (Bitmap)Image.FromFile(pngFileList.First());
//create a new AVI file
AviManager aviManager = new AviManager(fileName, false); // location and the name of video file
//add a new video stream and one frame to the new file
//set IsCompressed = false
VideoStream aviStream = aviManager.AddVideoStream(false, 3, bitmap);
pngFileList.Skip(1).ToList().ForEach(file =>
{
bitmap = (Bitmap)Bitmap.FromFile(file);
aviStream.AddFrame(bitmap);
bitmap.Dispose();
});
aviManager.Close();

How do I get an image to save after rotation at runtime?

I am working with WPF and I have an application that the user loads an image file into a RichTextBox and they can rotate the image and print it. I am not sure as to why the image after it has been rotated will not print as it is displayed on the screen. Instead it prints the original. I am new to this so any help would be greatly appreciated!
The following is the code for my application. Code when the retrieve file Button is clicked:
private void retrieve_button_Click(object sender, RoutedEventArgs e)
{
//Retrieve the file or image you are looking for
OpenFileDialog of = new OpenFileDialog();
of.Filter = "Formats|*.jpg;*.png;*.bmp;*.gif;*.ico;*.txt|JPG Image|*.jpg|BMP image|*.bmp|PNG image|*.png|GIF Image|*.gif|Icon|*.ico|Text File|*.txt";
var dialogResult = of.ShowDialog();
if (dialogResult == System.Windows.Forms.DialogResult.OK)
{
try
{
System.Windows.Controls.RichTextBox myRTB = new System.Windows.Controls.RichTextBox();
{
Run myRun = new Run();
System.Windows.Controls.Image MyImage = new System.Windows.Controls.Image();
MyImage.Source = new BitmapImage(new Uri(of.FileName, UriKind.RelativeOrAbsolute));
InlineUIContainer MyUI = new InlineUIContainer();
MyUI.Child = MyImage;
rotateright_button.IsEnabled = true;
print_button.IsEnabled = true;
Paragraph paragraph = new Paragraph();
paragraph.Inlines.Add(myRun);
paragraph.Inlines.Add(MyUI);
FlowDocument document = new FlowDocument(paragraph);
richTextBox.Document = document;
}
}
catch (ArgumentException)
{
System.Windows.Forms.MessageBox.Show("Invalid File");
}
}
}
When the rotate right button is clicked the following code is executed:
RotateTransform cwRotateTransform;
private void rotateright_button_Click(object sender, RoutedEventArgs e)
{
richTextBox.LayoutTransform = cwRotateTransform;
if (cwRotateTransform == null)
{
cwRotateTransform = new RotateTransform();
}
if (cwRotateTransform.Angle == 360)
{
cwRotateTransform.Angle = 0;
}
else
{
cwRotateTransform.Angle += 90;
}
}
After the Image has been loaded and rotated the user can use the following code to print:
private void InvokePrint(object sender, RoutedEventArgs e)
{
System.Windows.Controls.PrintDialog printDialog = new System.Windows.Controls.PrintDialog();
if ((bool)printDialog.ShowDialog().GetValueOrDefault())
{
FlowDocument flowDocument = new FlowDocument();
flowDocument = richTextBox.Document;
flowDocument.ColumnWidth = printDialog.PrintableAreaWidth;
flowDocument.PagePadding = new Thickness(65);
IDocumentPaginatorSource iDocPag = flowDocument;
printDialog.PrintDocument(iDocPag.DocumentPaginator, "Print Document");
}
}
Try this (substitute yourImageControl in the first line, specify which RotateFlipType you want and be sure to reference the System.Drawing dll):
System.Drawing.Bitmap bitmap = BitmapSourceToBitmap((BitmapSource)YourImageControl.Source);
bitmap.RotateFlip(System.Drawing.RotateFlipType.Rotate90FlipNone);
public static System.Drawing.Bitmap BitmapSourceToBitmap(BitmapSource bitmapsource)
{
System.Drawing.Bitmap bitmap;
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new System.Drawing.Bitmap(outStream);
}
return bitmap;
}
Another option for conversion...
P.S. You would get a better answer in less time if you posted some code and told us more about what you have tried.

Categories