I am getting a parameter is not valid exception..While saving the image
Here is my code to save the image
if (!File.Exists(pictureBox1.Tag.ToString()))
{
Image image = pictureBox1.Image;
image.Save(pictureBox1.Tag.ToString(), ImageFormat.Jpeg);
}
else
{
string delStr = pictureBox1.Tag.ToString();
pictureBox1.Image.Dispose();
File.Delete(delStr);
Image image = pictureBox1.Image;
image.Save(delStr, ImageFormat.Jpeg);
pictureBox1.Image = Image.FromFile(delStr);
}
In your else branch, you start by calling Dispose() on your Image, then you try to save it. That can't possibly work, because:
The Dispose method leaves the Image in
an unusable state.
Maybe you wanted to do:
string delStr = pictureBox1.Tag.ToString();
File.Delete(delStr);
Image image = pictureBox1.Image;
image.Save(delStr, ImageFormat.Jpeg);
image.Dispose();
pictureBox1.Image = Image.FromFile(delStr);
But that's still reloading the Image from the very file it has just been saved to, so it's not very useful. You might want to try something like:
string filename = pictureBox1.Tag.ToString();
if (File.Exists(filename) {
File.Delete(filename);
}
pictureBox1.Image.Save(filename, ImageFormat.Jpeg);
But then again, Image.Save() will overwrite the file anyway... So you only need to do:
pictureBox1.Image.Save(pictureBox1.Tag.ToString(), ImageFormat.Jpeg);
Am I seeing correctly? Are you disposing the image before saving it? If so here is your problem:
pictureBox1.Image.Dispose(); // THIS !!!!!! Just remove this line or move it to after save
Image image = pictureBox1.Image;
image.Save(delStr, ImageFormat.Jpeg);
Related
I've made a ListBox with items that have an image bound to them (Binding BitmapSource, UpdateSourceTrigger=PropertyChanged). They updated at runtime and all was fine but their background was black and not Transparent as i wished for.
Now i want to have the same functionality with PNG.
So now I did bind to the URI of the PNG and tried to change the image and notify afterwards, but i get an error (probably because i want to save an image while its already open?)
I'll try my best to show all the relevant code:
XAML:
<Image Source="{Binding Path=OutfitImageString, UpdateSourceTrigger=PropertyChanged}"/>
C# URI string, I wanted to use this to tell when the PNG was changed:
private string _OutfitImageString;
public string OutfitImageString
{
get { return _OutfitImageString; }
set
{
_OutfitImageString = value;
NotifyPropertyChanged("OutfitImageString");
}
}
And every time I change the Bitmap picture (its bound to an instance of a class) I run this method:
public void UpdateImage()
{
// new bitmap (transparent background by default)
Bitmap nb = new Bitmap(100, 110, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// [ ... ] Create the Bitmap
// save to PNG to get a transparent background, every Person has a unique name
string saveAt = Directory.GetCurrentDirectory() + Name + "_outfit.png";
nb.Save(saveAt, System.Drawing.Imaging.ImageFormat.Png);
// notify that we changed the image (even tho the URI string is the same)
OutfitImageString = saveAt;
}
This line creates an Error, as soon as it is run for a 2. time:
nb.Save(saveAt, System.Drawing.Imaging.ImageFormat.Png);
Exception type -2147467259 Allgemeiner Fehler in GDI+. overflow excpetion: System.Runtime.InteropServices.ExternalException (0x80004005): Allgemeiner Fehler in GDI+. bei System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) bei System.Drawing.Image.Save(String filename, ImageFormat format)
I stored the BitmapSource of the Bitmap before and Bound to that aswell, this used to work perfectly (just the background was not transparent).
Also since these images are kind of temporary, I don't like saving them all the time :/
Thanks for the help, I am sorry the description is kinda messy... Just write if you need further details!
It is not at all necessary to save a bitmap file.
Change the type of your property from string to ImageSource
private ImageSource _OutfitImage;
public ImageSource OutfitImage
{
get { return _OutfitImage; }
set
{
_OutfitImage = value;
NotifyPropertyChanged(nameof(OutfitImage));
}
}
and bind to it like shown below (where setting UpdateSourceTrigger=PropertyChange is pointless).
<Image Source="{Binding Path=OutfitImage}"/>
Then assign a value like this:
OutfitImage = BitmapToBitmapSource(nb);
...
public static BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)
{
var bitmapImage = new BitmapImage();
using (var stream = new MemoryStream())
{
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Position = 0;
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
}
return bitmapImage;
}
I'm having a hard time trying to figure out how to prevent memory leak when repainting PictureBox
That's how my drawing method looks like:
Bitmap image;
image = new Bitmap((Bitmap)baseImage.Clone());
Graphics g = Graphics.FromImage(image);
//here I'm drawing using created "g"
//reason why am doing it on new bitmap, not on paintBox.Image is that..
//..I don't want this drawings to be permanently added to my base image
g.Dispose();
paintBox.Image = image;
Then I'm using method which is changing baseImage and refreshing paintBox many times (hundreds).
Calling this method gives me 'System.OutOfMemoryException' in System.Drawing.dll
This method is recursive, however I'm pretty sure it's not causing this exception, because when I'm changing this method to only modify base image without refreshing paint box it works fine (however I would like to see changes it's making up to date).
So, what's the best method to prevent memory leak in this case?
I was trying something like this:
paintBoxx.Image.Dispose();
paintBox.Image = image;
but it is giving me 'System.NullReferenceException' (because I'm trying to use disposed image).
Any advice would be appreciated.
Change your code to this:
Bitmap image;
image = new Bitmap((Bitmap)baseImage.Clone());
using (Graphics g = Graphics.FromImage(image) )
{
// I am drawing on the bitmap so I don't permanently change my base image
// do your draw stuff here..
g.FillEllipse(Brushes.Yellow, 3, 3, 9, 9);
// ..
}
// don't leak the image and..
// ..don't Dispose without checking for null
if (paintBox.Image != null) paintBox.Image.Dispose();
paintBox.Image = image;
Note the using clause, which will dispose of the Graphics object, even if the drawing runs into problems.
Have you tried using MemoryStream?
Take a look at my example code:
image = new Bitmap((Bitmap)baseImage.Clone());
using (MemoryStream imageStream = new MemoryStream())
{
// put iimagem in memory stream
image.Save(imageStream, System.Drawing.Imaging.ImageFormat.Gif);
// create an array of bytes with image length
byte[] imageContent = new Byte[imageStream.Length];
// reset memory stream
imageStream.Position = 0;
// load array of bytes with the imagem
imageStream.Read(imageContent, 0, (int)imageStream.Length);
// change header page "content-type" to "image/jpeg" and print the image.
Response.ContentType = "image/gif";
Response.BinaryWrite(imageContent);
}
i am using the below code to load a .png file to bitmap
Bitmap original;
if (tbp.LanguageTypingdir =="LTR")
{
original = new Bitmap(#"Images\CC_Logo.png");
}
else
{
original = new Bitmap(#"Images\CC_Logo_ar.png");
}
i get error Additional information: Parameter is not valid.
I don't know about yours, but I know the following syntax works for loading a bitmap image:
Image img = Bitmap.FromFile("C:/Users/xxx/Pictures/1.jpg");
If you need to work on the Bitmap class, just cast the Image object.
Bitmap myBitmap = img as Bitmap;
I am using this code to get images from my webcam, I guess its Metricam library
Anyone knows how to get images without using picturebox?
WebCam camera = new WebCam();
camera.Connect();
pictureBox1.Image = camera.GetBitmap();
pictureBox1.Image.Save(#"c:\image1 " + ".Jpeg", ImageFormat.Jpeg);
pictureBox1.Image is Image type. It can handle saving on its own. It does handle saving when used from PictureBox too, notice how you call Save() method on Image property and not on pictureBox instance.
WebCam camera = new WebCam();
camera.Connect();
Image image = camera.GetBitmap();
image.Save(#"c:\image1 " + ".Jpeg", ImageFormat.Jpeg);
I have this code to rotate an image in an if loop in C# Windows Form application, but the Form does not show anything in the form output.
Can anyone help?
this.splitContainer1.Panel2.Controls.Add(PictureBox1);
PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
PictureBox1.Image = bitmap; //Image.FromFile(#"C:\image.jpg");
PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
PictureBox1.Image = (Image)(RotateImg(bitmap, 30.0f, Color.Transparent));
if you need to rotate an image on common angles you can use RotateFlip method with ease.
Please see my sample code:
string fileName = "somefile.png";
System.Drawing.Imaging.ImageFormat imageFormat = System.Drawing.Imaging.ImageFormat.Png;
Bitmap bitmap =(Bitmap)Bitmap.FromFile(fileName );
//this will rotate image to the left...
bitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
//lets save result back to file...
bitmap.Save(fileName, imageFormat);
bitmap.Dispose();
That's all, hope it helps.
Try this:
PictureBox1.Images.RotateFlip(RotateFlipType.Rotate180FlipX);
PictureBox1.Refresh();