I'm currently trying to update a program by having a button (nextImg) that when clicked calls a function that creates two bitmaps, generates a number starting from 0, and increments every time the nextImg button gets clicked. Then the program takes that number(num) and returns a string from a List[num] which has all the Uri sources of my photos. However when I click next image I get a
System.NullReferenceException.
private void Image_Loaded(object sender, RoutedEventArgs e)
{
// Create a new BitmapImage.
BitmapImage b = new BitmapImage();
BitmapImage b1 = new BitmapImage();
Image img = new Image();
string sSrc = numGen();
b.BeginInit();
b.UriSource = new Uri(sSrc);
b.EndInit();
b1.BeginInit();
b1.UriSource = b.UriSource;
b1.EndInit();
img = sender as Image;
img.Source = b; // Error on this line
Canvas1.Height = Picturebox1.Height;
Canvas1.Width = Picturebox1.Width;
Canvas1.Margin = Picturebox1.Margin;
}
Related
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;
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;
...
I have been having quite a problem with this.
Here is my code.
int frame = 0;
//This is a wpf button event
private void up_Click(object sender, RoutedEventArgs e)
{
frame++;
LoadPic();
}
private void LoadPic()
{
string fn = #"C:\Folder\image" + (frame % 2).ToString() + ".png";
Bitmap bmp = new Bitmap(302, 170);
bmp.Save(fn);
bmp.Dispose();
//Picebox is a wpf Image control
Picbox.Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(fn));
}
private void down_Click(object sender, RoutedEventArgs e)
{
frame--;
LoadPic();
}
When I start the program, a wpf window pops open. There are two buttons with the events shown in the code.
When I press the up button twice it works fine. This saves two PNGs to the locations
"C:\Folder\image0.png" and "C:\Folder\image1.png"
The third time I press the button, it should save it to "C:\Folder\image0.png" again.
Instead, it gives the exception 'A generic error occurred in GDI+'.
I have had a similar problem before, and solved it by adding these two lines:
GC.Collect();
GC.WaitForPendingFinalizers();
It didn't work this time.
To avoid the filelock that BitmapImage creates you have to take care of a bit more initialization. According to this question here on SO, it can be done like this (ported to C# from their VB.Net code).
private void LoadPic()
{
string fn = #"C:\Folder\image" + (frame % 2).ToString() + ".png";
Bitmap bmp = new Bitmap(302, 170);
bmp.Save(fn);
bmp.Dispose();
var img = new System.Windows.Media.Imaging.BitmapImage();
img.BeginInit();
img.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
img.UriSource = new Uri(fn);
img.EndInit();
Picbox.Source = img;
}
I have datatable with byte[] column.
On app page I iterate through rows and bind column data to SourceProperty
for (i = 0;..) {
Image img = new Image();
img.Width = 100;
img.Height = 100;
Binding bnd = new Binding("Fields[" + i + "].Blob"); // Blob column
bnd.Converter = new ByteToImageConverter();
img.SetBinding(Image.SourceProperty, bnd);
}
Near every image I have button that calls CameraCaptureTask camTask.
Before camtask.Show() I assign current Image to global pointer _imgCurrent = img
camtask.Completed += (s, e)
{
if (e.TaskResult != TaskResult.OK) return;
BitmapImage bmp = new BitmapImage();
bmp.SetSource(e.ChosenPhoto);
_imgCurrent.Source = bmp;
_imgCurrent.SetValue(Image.SourceProperty, bmp);
}
But in that case DataContext don't update. I suppose that I need to implement INotifyPropertyChanged? I need to inherit Image from that interface or I can trigger it in time of Source update?
The problem was at Binding creation: I forgot about Mode=TwoWay.
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.