My utility is supposed to resize either .jpg or .png files.
It seems to work fine in one location (at work, where I don't have IrfanView installed). But at home, when I open a *.jpg and then save it (resized), I see:
However, the image still displays fine in either case (whether I select "Yes" or "No" in the dialog.
IOW, I'm able to load and save both jpgs and pngs, and they save as such, and display fine. But IrfanView claims they are messed up.
Actually, I'm not sure how the image is saved; I was assuming it just saved it in the proper format "behind the scenes" based on the extension. Anyway, as this is a rather simple utility, I will just show all the code:
using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace FileResizingUtil
{
public partial class FormFileResizer : Form
{
private Image _imgToResize;
String _originalFilename = String.Empty;
public FormFileResizer()
{
InitializeComponent();
}
private void buttonChooseImage_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog
{
InitialDirectory = "c:\\",
Filter = "JPG files (*.jpg)|*.jpg| PNG files (*.png)|*.png", FilterIndex = 2, RestoreDirectory = true
};
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
_originalFilename = ofd.FileName;
_imgToResize = Image.FromFile(_originalFilename);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
// If made it to here, it must be good
String preamble = labelImgSelected.Text;
labelImgSelected.Text = String.Format("{0}{1}", preamble, _originalFilename);
textBoxOrigHeight.Text = _imgToResize.Height.ToString();
textBoxOrigWidth.Text = _imgToResize.Width.ToString();
buttonApplyPercentageChange.Enabled = true;
//buttonResizeImage.Enabled = true;
}
private void buttonResizeImage_Click(object sender, EventArgs e)
{
// Really large images take awhile, so show an hourglass
Cursor.Current = Cursors.WaitCursor;
try
{
var size = new Size { Height = Convert.ToInt32(textBoxNewHeight.Text), Width = int.Parse(textBoxNewWidth.Text) };
// Two different ways of getting the int val
Image resizedImg = FileResizeUtils.GetResizedImage(_imgToResize, size);
String fileNameSansExtension = Path.GetFileNameWithoutExtension(_originalFilename);
String fileNameExtension = Path.GetExtension(_originalFilename);
String newFilename = String.Format("{0}{1}_{2}{3}", fileNameSansExtension, size.Height, size.Width, fileNameExtension);
// If used a different extension (jpg where the original was png, or vice versa) would the Save be intelligent enough to actually save in the other format?
resizedImg.Save(newFilename);
MessageBox.Show(String.Format("Done! File saved as {0}", newFilename));
Recycle();
}
finally
{
Cursor.Current = Cursors.Default;
}
}
private void Recycle()
{
buttonResizeImage.Enabled = false;
buttonApplyPercentageChange.Enabled = false;
labelImgSelected.Text = "Image selected: ";
textBoxOrigHeight.Text = String.Empty;
textBoxOrigWidth.Text = String.Empty;
// Retain the percentage vals, as it may be that all in a batch need to be the same pair of vals
}
private void buttonApplyPercentageChange_Click(object sender, EventArgs e)
{
int origHeight = _imgToResize.Height;
int origWidth = _imgToResize.Width;
// Two ways to convert the val
double heightFactor = (double)numericUpDownHeight.Value / 100.0;
double widthFactor = Convert.ToDouble(numericUpDownWidth.Value) / 100.0;
if (heightFactor < 0 || widthFactor < 0)
{
// show an error - no negative values allowed- using updown, so that should not be possible
}
var newHeight = Convert.ToInt32(origHeight * heightFactor);
var newWidth = Convert.ToInt32(origWidth * widthFactor);
textBoxNewHeight.Text = newHeight.ToString();
textBoxNewWidth.Text = newWidth.ToString();
buttonResizeImage.Enabled = true;
}
private void textBoxNewHeight_TextChanged(object sender, EventArgs e)
{
EnableResizeButtonIfValidDimensionsEntered();
}
private void EnableResizeButtonIfValidDimensionsEntered()
{
if (String.IsNullOrWhiteSpace(textBoxOrigHeight.Text)) return;
String candidateHeight = textBoxNewHeight.Text;
String candidateWidth = textBoxNewWidth.Text;
int validHeight;
int validWidth;
buttonResizeImage.Enabled = (int.TryParse(candidateHeight, out validHeight)) &&
(int.TryParse(candidateWidth, out validWidth));
}
private void numericUpDownHeight_ValueChanged(object sender, EventArgs e)
{
if (checkBoxRetainRatio.Checked)
{
numericUpDownWidth.Value = numericUpDownHeight.Value;
}
}
private void numericUpDownWidth_ValueChanged(object sender, EventArgs e)
{
if (checkBoxRetainRatio.Checked)
{
numericUpDownHeight.Value = numericUpDownWidth.Value;
}
}
}
}
..and the GUI (just prior to hitting the "Resize Image" button:
UPDATE
Based on Eugene Sh.'ls comment, I changed my Save method to the following block:
bool success = true;
. . .
if (fileNameExtension != null && fileNameExtension.ToLower().Contains("jpg"))
{
resizedImg.Save(newFilename, ImageFormat.Jpeg);
}
else if (fileNameExtension != null &&
fileNameExtension.ToLower().Contains("png"))
{
resizedImg.Save(newFilename, ImageFormat.Png);
}
else
{
success = false;
}
if (success)
{
MessageBox.Show(String.Format("Done! File saved as {0}", newFilename));
}
else
{
MessageBox.Show("Something went awry. The file was not saved");
}
UPDATE 2
So here is my new code, implementing the suggestion, and supporting several new file types:
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;
namespace FileResizingUtil
{
public partial class FormFileResizer : Form
{
private Image _imgToResize;
String _originalFilename = String.Empty;
public FormFileResizer()
{
InitializeComponent();
}
private void buttonChooseImage_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog
{
InitialDirectory = "c:\\",
Filter = "JPG files (*.jpg)|*.jpg| PNG files (*.png)|*.png| BMP files (*.bmp)|*.bmp| TIFF files (*.tiff)|*.png| ICO files (*.ico)|*.ico| EMF files (*.emf)|*.emf| WMF files (*.wmf)|*.wmf",
FilterIndex = 1, RestoreDirectory = true
};
if (ofd.ShowDialog() == DialogResult.OK)
{
try
{
_originalFilename = ofd.FileName;
_imgToResize = Image.FromFile(_originalFilename);
}
catch (Exception ex)
{
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
}
}
if (String.IsNullOrWhiteSpace(_originalFilename)) return;
// If made it to here, it must be good
String preamble = labelImgSelected.Text;
labelImgSelected.Text = String.Format("{0}{1}", preamble, _originalFilename);
textBoxOrigHeight.Text = _imgToResize.Height.ToString();
textBoxOrigWidth.Text = _imgToResize.Width.ToString();
buttonApplyPercentageChange.Enabled = true;
}
private void buttonResizeImage_Click(object sender, EventArgs e)
{
bool success = true;
// Really large images take awhile, so show an hourglass
Cursor.Current = Cursors.WaitCursor;
try
{
// Two different ways of getting the int val
var size = new Size { Height = Convert.ToInt32(textBoxNewHeight.Text), Width = int.Parse(textBoxNewWidth.Text) };
Image resizedImg = FileResizeUtils.GetResizedImage(_imgToResize, size);
String fileNameSansExtension = Path.GetFileNameWithoutExtension(_originalFilename);
String fileNameExtension = Path.GetExtension(_originalFilename);
String newFilename = String.Format("{0}{1}_{2}{3}", fileNameSansExtension, size.Height, size.Width, fileNameExtension);
if (fileNameExtension != null && fileNameExtension.ToLower().Contains("jpg"))
{
resizedImg.Save(newFilename, ImageFormat.Jpeg);
}
else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("png"))
{
resizedImg.Save(newFilename, ImageFormat.Png);
}
else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("bmp"))
{
resizedImg.Save(newFilename, ImageFormat.Bmp);
}
else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("ico"))
{
resizedImg.Save(newFilename, ImageFormat.Icon);
}
else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("tiff"))
{
resizedImg.Save(newFilename, ImageFormat.Tiff);
}
else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("emf"))
{
resizedImg.Save(newFilename, ImageFormat.Emf);
}
else if (fileNameExtension != null && fileNameExtension.ToLower().Contains("wmf"))
{
resizedImg.Save(newFilename, ImageFormat.Wmf);
}
else
{
success = false;
}
MessageBox.Show(success
? String.Format("Done! File saved as {0}", newFilename)
: "Something went awry. The file was not saved");
Recycle();
}
finally
{
Cursor.Current = Cursors.Default;
}
}
private void Recycle()
{
buttonResizeImage.Enabled = false;
buttonApplyPercentageChange.Enabled = false;
labelImgSelected.Text = "Image selected: ";
textBoxOrigHeight.Text = String.Empty;
textBoxOrigWidth.Text = String.Empty;
// Retain the percentage vals, as it may be that all in a batch need to be the same pair of vals
}
private void buttonApplyPercentageChange_Click(object sender, EventArgs e)
{
int origHeight = _imgToResize.Height;
int origWidth = _imgToResize.Width;
// Two ways to convert the val
double heightFactor = (double)numericUpDownHeight.Value / 100.0;
double widthFactor = Convert.ToDouble(numericUpDownWidth.Value) / 100.0;
if (heightFactor < 0 || widthFactor < 0)
{
// show an error - no negative values allowed- using updown, so that should not be possible
}
var newHeight = Convert.ToInt32(origHeight * heightFactor);
var newWidth = Convert.ToInt32(origWidth * widthFactor);
textBoxNewHeight.Text = newHeight.ToString();
textBoxNewWidth.Text = newWidth.ToString();
buttonResizeImage.Enabled = true;
}
private void textBoxNewHeight_TextChanged(object sender, EventArgs e)
{
EnableResizeButtonIfValidDimensionsEntered();
}
private void EnableResizeButtonIfValidDimensionsEntered()
{
if (String.IsNullOrWhiteSpace(textBoxOrigHeight.Text)) return;
String candidateHeight = textBoxNewHeight.Text;
String candidateWidth = textBoxNewWidth.Text;
int validHeight;
int validWidth;
buttonResizeImage.Enabled = (int.TryParse(candidateHeight, out validHeight)) &&
(int.TryParse(candidateWidth, out validWidth));
}
private void numericUpDownHeight_ValueChanged(object sender, EventArgs e)
{
if (checkBoxRetainRatio.Checked)
{
numericUpDownWidth.Value = numericUpDownHeight.Value;
}
}
private void numericUpDownWidth_ValueChanged(object sender, EventArgs e)
{
if (checkBoxRetainRatio.Checked)
{
numericUpDownHeight.Value = numericUpDownWidth.Value;
}
}
}
}
From the Image.Save documentation:
If no encoder exists for the file format of the image, the Portable
Network Graphics (PNG) encoder is used. When you use the Save method
to save a graphic image as a Windows Metafile Format (WMF) or Enhanced
Metafile Format (EMF) file, the resulting file is saved as a Portable
Network Graphics (PNG) file. This behavior occurs because the GDI+
component of the .NET Framework does not have an encoder that you can
use to save files as .wmf or .emf files.
If you want to save in a different format, use the overloaded Save method, taking format as a second parameter:
Save(String, ImageFormat)
Most image viewers don't use the extension of the file to determine the type of the file, but use so called "magic numbers" (http://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files). They basically check the first X bytes of the file wich is often unique to a specific image format.
My guess is, that the library you're using saves the file as PNG as default (edit: see Eugenes answer), not considering what extension you put there. IrfanView notices, that the magic number and the extension don't match but still shows the image by defaulting to the magic number.
Go to a console and print out the file. If it is a PNG file, you will see PNG displayed and it stops.
If is is JPEG, you will get a lot of garbage but should see EXIF or JFIF at the top. The very start is FF D8
Because the JPEG and PNG have different signatures, the application can tell them apart from their contents and invite the appropriate decoder.
Image applications normally identify the type of image from the contents of the stream, not the extension.
Related
There are 55 images in the folder, none of them are bigger than 80kb, the biggest is 78kb, while most of the others are between 30-50kb
I have this block of code that makes a picturebox for each picture found in a folder then it adds them all to a flowlayoutpanel
It shows an Out of Memory exception at PictureBox picture = new()
I have tried changing the platform target to x64 in the build options, adding an App.config and adding this to it <gcallowverylargeobjects enabled="true"></gcallowverylargeobjects> and finally I added a GC.Collect() but none of these helped. It still throws the exception
If I move the pictures out of the folder, then slowly add them instead of adding them to the folder all at once, it works and the error doesn't appear. All my images are PNG.
Also I think it's worth noting that it doesn't appear at all if there only 4 images, once I start adding more the error occurs more often
My code:
for (int pictureCreator = 0; pictureCreator < files.Length; pictureCreator++)
{
FileInfo file = files[pictureCreator];
if (file.FullName.EndsWith(FileFormats[3]))
{
string url = File.ReadAllText(file.FullName);
if (url != null)
{
try
{
GC.Collect();
Image gif = Image.FromStream(await httpClient.GetStreamAsync(url));
PictureBox picture = new()
{
Name = url,
Size = new(45, 45),
Image = gif,
SizeMode = PictureBoxSizeMode.Zoom
};
picture.Click += Gif_Click;
flowLayoutPanelGif.Controls.Add(picture);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
The block of code where the issue is caused:
if (file.FullName.EndsWith(FileFormats[0]))
{
PictureBox picture = new()
{
Name = "picture",
Size = new(45, 45),
Image = Image.FromFile(file.FullName),
SizeMode = PictureBoxSizeMode.Zoom
};
picture.Click += Pic_Click;
flowLayoutPanel1.Controls.Add(picture);
GC.Collect();
PictureBox picture = new() is throwing the exception.
readonly HttpClient httpClient = new();
public static readonly string FolderPath = #".\Storage";
public void Detailed_View_Load_1(object sender, EventArgs e)
{
RefreshData();
}
private void Pic_Click(object? sender, EventArgs e)
{
if (sender is PictureBox pictureBox)
{
PicGen _ = new(pictureBox);
}
}
private void Gif_Click(object? sender, EventArgs e)
{
if (sender is PictureBox pictureBox)
{
string url = pictureBox.Name;
GifGen _ = new(url);
}
}
private async void RefreshData()
{
DirectoryInfo directory = new(FolderPath);
FileInfo[] files = directory.GetFiles();
string[] FileFormats = { ".png", ".jpg", ".jpeg", ".txt" };
for (int pictureCreator = 0; pictureCreator < files.Length; pictureCreator++)
{
FileInfo file = files[pictureCreator];
if (file.FullName.EndsWith(FileFormats[3]))
{
string url = File.ReadAllText(file.FullName);
if (url != null)
{
try
{
Image gif = Image.FromStream(await httpClient.GetStreamAsync(url));
PictureBox picture = new()
{
Name = url,
Size = new(45, 45),
Image = gif,
SizeMode = PictureBoxSizeMode.Zoom
};
picture.Click += Gif_Click;
flowLayoutPanelGif.Controls.Add(picture);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
if (file.FullName.EndsWith(FileFormats[0]))
{
PictureBox picture = new()
{
Name = "picture",
Size = new(45, 45),
Image = Image.FromFile(file.FullName),
SizeMode = PictureBoxSizeMode.Zoom
};
picture.Click += Pic_Click;
flowLayoutPanel1.Controls.Add(picture);
}
}
}
private void BTN_AddGif_Click(object sender, EventArgs e)
{
try
{
string picID = new String(TXT_Add.Text.Where(char.IsDigit).ToArray());
string picURL = TXT_Add.Text;
string picLocation = FolderPath + "\\" + picID + ".txt";
File.WriteAllText(picLocation, picURL);
flowLayoutPanel1.Controls.Clear();
flowLayoutPanelGif.Controls.Clear();
RefreshData();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
Context: When the form loads, I want to display every image and in their own flowlayoutpanels. However, when the user enters a url of a gif in the textbox, I clear each flaylayoutpanel to avoid duplicating each image and gif and instead include the new one among the already loaded images and gifs.
However, when the number of images exceed four, there's a big chance that the line PictureBox picture = new() throw's an out of memory exception. I have not had this exception appear when the number of images was just four.
The biggest image size is 78kb, but as pointed out by the comments, I multiplied the height, width and bit depth (Bit Depth = 32 * Width = 293 * Height = 254) and the result is 2381504 however I'm not sure what unit that's in.
I've created an image uploader for users to upload/crop their profile pics. When a user uploads a file, it gets saved to a file that gets accessed immediately after for them to crop it.
I've tried using Path.GetTempPath() as well as Path.GetTempFileName(), but my cropper was unable to locate the file locations for some reason.
Any suggestions are greatly appreciated.
UPDATE: So I added File.Delete(filePath) to the end of btnCropClick, but I get an error saying The process cannot access the file because it is being used by another process. How can I "release" that file to be deleted instantly ?
Below is the code for where a user uploads their orignal image of choice
protected void btnUploadClick(object sender, EventArgs e)
{
//Upload Original Image Here
String UploadFileName = "";
String UploadFilePath = "";
if (fileUploader.HasFile)
{
String ext = Path.GetExtension(fileUploader.FileName).ToLower();
if (ext == ".jpg" || ext == ".jpeg" || ext == ".png")
{
UploadFileName = "orig_" + Guid.NewGuid().ToString() + ext;
UploadFilePath = Path.Combine(Server.MapPath("images/OriginalImages"), UploadFileName);
try
{
fileUploader.SaveAs(UploadFilePath); //TODO: Need to make this a temp file that gets "destroyed" later
imgUpload.ImageUrl = "images/OriginalImages/" + UploadFileName;
panCrop.Visible = true;
}
catch (Exception ex)
{
lblMsg.Text = "Error! Please Try Again. ";
}
}
else
{
lblMsg.Text = "Invalid File Type Selected. | Please Choose .jpg, .jpeg, or .png file only.";
}
}
else
{
lblMsg.Text = "Please Click 'Choose File' & Select An Image To Upload";
}
}
And here is the code for the cropper (Not sure anything in here needs to be changed, but I'll include it anyway for context & relevancy
protected void btnCropClick(object sender, EventArgs e)
{
//Crop Image Here & Save
String fileName = Path.GetFileName(imgUpload.ImageUrl);
String filePath = Path.Combine(Server.MapPath("images/OriginalImages"), fileName);
String cropFileName = "";
String cropFilePath = "";
if (File.Exists(filePath))
{
System.Drawing.Image orgImg = System.Drawing.Image.FromFile(filePath);
Rectangle CropArea = new Rectangle(
Convert.ToInt32(X.Value),
Convert.ToInt32(Y.Value),
Convert.ToInt32(W.Value),
Convert.ToInt32(H.Value)
);
try
{
Bitmap bitMap = new Bitmap(CropArea.Width, CropArea.Height);
using (Graphics g = Graphics.FromImage(bitMap))
{
g.DrawImage(orgImg, new Rectangle(0, 0, bitMap.Width, bitMap.Height), CropArea, GraphicsUnit.Pixel);
Bitmap resized = new Bitmap(bitMap, new Size(200, 200)); //Resize image to save as 200x200
cropFileName = "crop_" + fileName; //+UserID so each fileName is unique
cropFilePath = Path.Combine(Server.MapPath("images/CroppedImages"), cropFileName);
resized.Save(cropFilePath); //Where final, cropped image is saved
imgHeadshot.ImageUrl = "images/CroppedImages/" + cropFileName;
}
}
catch (Exception ex)
{
throw;
}
panCrop.Visible = false;
}
}
Was able to dispose of the original file by adding:
orgImg.Dispose();
bitMap.Dispose();
File.Delete(filePath);
to the end of btnCropClick method.
I am writing a winform application in C# to open an image and overlay another image on top of it.
The bottom image is a .jpg and the top one is a .bmp converted from .svg. The .jpg and the .svg are the only ones I want to keep in the folder. The .bmp works as a temp.
I was using the following code to overlay the images. But I am having trouble to delete the temp .bmp as it is used by another process. I think it is this combine code still have access to the last .bmp file.
Could anyone help me on this? Thanks.
private void buttonSearch_Click(object sender, EventArgs e)
{
FailInfo.Text = "";
deletebmp(strFolderPath);
...
// Check if the specified front image exists. Yes, show the file name and convert SVG to BMP. No, show the error msg.
if (File.Exists(strFilePathF))
{
labelFront.Text = strFileNameF;
var svgConvert = SvgDocument.Open(svgFilePathF);
svgConvert.Draw().Save(bmpFilePathF);
pictureBoxFront.Image = Image.FromFile(strFilePathF);
}
else
{
labelFront.Text = "Couldn't find the file!";
pictureBoxFront.Image = null;
}
// Check if the specified back image exists. Yes, show the file name and convert SVG to BMP. No, show the error msg.
if (File.Exists(strFilePathBF))
{
labelBack.Text = strFileNameBF;
strFilePathB = strFilePathBF;
pictureBoxBack.Image = Image.FromFile(strFilePathB);
labelResult.Text = "FAIL";
labelResult.BackColor = Color.FromArgb(255, 0, 0);
var svgConvert = SvgDocument.Open(svgFilePathBF);
bmpFilePathB = strFolderPath + strFileNameBF + ".bmp";
svgConvert.Draw().Save(bmpFilePathB);
svgFilePathB = svgFilePathBF;
inspectionres(svgFilePathB);
labelreason.Visible = true;
}
else if (File.Exists(strFilePathBP))
{
labelBack.Text = strFileNameBP;
strFilePathB = strFilePathBP;
pictureBoxBack.Image = Image.FromFile(strFilePathB);
labelResult.Text = "PASS";
labelResult.BackColor = Color.FromArgb(0, 255, 0);
var svgConvert = SvgDocument.Open(svgFilePathBP);
bmpFilePathB = strFolderPath + strFileNameBP + ".bmp";
svgConvert.Draw().Save(bmpFilePathB);
svgFilePathB = svgFilePathBP;
inspectionres(svgFilePathB);
labelreason.Visible = false;
}
else
{
labelBack.Text = "Couldn't find the file!";
pictureBoxBack.Image = null;
labelResult.Text = "ERROR";
labelResult.BackColor = Color.FromArgb(0, 255, 255);
labelreason.Visible = false;
}
}
//
// Overlay the SVG file on top of the JPEG file
//
private Bitmap Combine(string jpegFile, string bmpFile)
{
Image image1 = Image.FromFile(jpegFile);
Image image2 = Image.FromFile(bmpFile);
Bitmap temp = new Bitmap(image1.Width, image1.Height);
using (Graphics g = Graphics.FromImage(temp))
{
g.DrawImageUnscaled(image1, 0, 0);
g.DrawImageUnscaled(image2, 0, 0);
}
return temp;
}
//
// Show the overlaid graphic in the picturebox
//
private void checkBoxOverlay_CheckedChanged(object sender, EventArgs e)
{
try
{
if (FindFront)
if (checkBoxOverlay.Checked)
pictureBoxFront.Image = Combine(strFilePathF, bmpFilePathF);
else
pictureBoxFront.Image = Image.FromFile(strFilePathF);
else
pictureBoxFront.Image = null;
if (FindBack)
if (checkBoxOverlay.Checked)
pictureBoxBack.Image = Combine(strFilePathB, bmpFilePathB);
else
pictureBoxBack.Image = Image.FromFile(strFilePathB);
else
pictureBoxBack.Image = null;
}
catch (Exception ex)
{
MessageBox.Show("Error loading image" + ex.Message);
}
}
//
// Option of changing the image folder
//
private void buttonPath_Click(object sender, EventArgs e)
{
FolderBrowserDialog FolderBrowserDialog1 = new FolderBrowserDialog();
if (FolderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
strFolderPath = FolderBrowserDialog1.SelectedPath + "\\";
}
}
//
// Pull the inspection result info from the SVG file
//
private void inspectionres(string filename)
{
XDocument document = XDocument.Load(filename);
XElement svg_Element = document.Root;
string sb = null;
var faillist = (from svg_path in svg_Element.Descendants("{http://www.w3.org/2000/svg}text") select svg_path).ToList();
foreach (var item in faillist)
{
sb += item.ToString();
}
}
//
// Delete all the .bmp files generated from .svg files
//
private void deletebmp(string path)
{
// Unload the images from the picturebox if applicable
pictureBoxFront.Image = null;
pictureBoxBack.Image = null;
string[] files = Directory.GetFiles(path, "*.bmp");
for (int i = 0; i < files.Length; i ++ )
File.Delete(files[i]);
}
}
Image implements IDisposable, so simply setting the pictureBox.Image property to null will not release resources (in your case, the file). Your Combine method also leaves the images open. You have to call Dispose before attempting to delete the file:
Image image1 = Image.FromFile(path1);
File.Delete(path1); // error - file is locked
Image image2 = Image.FromFile(path2);
image2.Dispose();
File.Delete(path2); // works
An alternative approach (and I assume you're using WinForms here, in WPF it's a little different) would be to load the bitmap from the file manually (using FromStream). Then, you can close the stream immediately and delete the file:
Image image;
using (Stream stream = File.OpenRead(path))
{
image = System.Drawing.Image.FromStream(stream);
}
pictureBox.Image = image;
File.Delete("e:\\temp\\copy1.png"); //works
Vesan's answer didn't helped me so I found an different solution.
So I can safe/open an image and if I want instantly delete the image.
i used it for my dataGridView_SelectionChanged:
private void dataGridViewAnzeige_SelectionChanged(object sender, EventArgs e)
{
var imageAsByteArray = File.ReadAllBytes(path);
pictureBox1.Image = byteArrayToImage(imageAsByteArray);
}
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
All above answers are perfectly fine, but I've got a different approach.
Using Image abstract class, you will not get quite a lot of options for manipulating and resizing image.
Rather you do as follows:-
Bitmap img = new Bitmap(item);
img.SetResolution(100, 100);
Image imgNew = Image.FromHbitmap(img.GetHbitmap());
pictureBox1.Image = imgNew;
img.Dispose();
I have an OpenFileDialog in my WinForm and I want when to select an image to limit the image's size in 100 Ko and the Dimensions in 350x350.
How can I do that ??
private bool ValidFile(string filename, long limitInBytes, int limitWidth, int limitHeight)
{
var fileSizeInBytes = new FileInfo(filename).Length;
if(fileSizeInBytes > limitInBytes) return false;
using(var img = new Bitmap(filename))
{
if(img.Width > limitWidth || img.Height > limitHeight) return false;
}
return true;
}
private void selectImgButton_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if(ValidFile(openFileDialog1.FileName, 102400, 350, 350))
{
// Image is valid and U can
// Do something with image
// For example set it to a picture box
pictureBox1.Image = new Bitmap(openFileDialog1.FileName);
}
else
{
MessageBox.Show("Image is invalid");
}
}
}
It depends on what types of images you need to support. For most common types (bmp, jpg, png), you can easily retrieve image info:
string filename = // get it from OpenFileDialog
if (new FileInfo(filename).Length > SOME_LIMIT)
{
MessageBox.Show("!!!");
}
else
{
Image img = Image.FromFile(filename);
MessageBox.Show(string.Format("{0} x {1}", img.Width, img.Height));
}
If you need more extensive support for many image formats, then I suggest using a library like ImageMagick.NET
put this as global variable
int imgSize = 0
private void button1_Click(object sender, EventArgs e)
{
Image imageFile;
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Open Image";
dlg.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*";
if (dlg.ShowDialog() == DialogResult.OK)
{
imageFile = Image.FromFile(dlg.FileName);
imgHeight = imageFile.Height;
if (imgHeight > 350)
{
MessageBox.Show("Not 350x350 Image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
imgPhoto.Image = null;
}
else
{
PictureBox1.Image = new Bitmap(dlg.OpenFile());
}
}
dlg.Dispose();
}
Hope this will help.
Try this :
OpenFileDialog fileDialog = new OpenFileDialog
{
// managed GDI+ supports bmp, jpeg, gif, png and tiff.
Filter =
"Image files (*.bmp;*.jpg;*.gif;*.png;*.tiff)|*.bmp;*.jpg;*.gif;*.png;*.tiff|All files (*.*)|*.*",
};
if (fileDialog.ShowDialog() == DialogResult.OK)
{
// Many exceptions could be raised in the following code
try
{
var fileSize = new FileInfo(fileDialog.FileName);
var validFilesize = fileSize.Length <= 1024 * 100; // 100 kilo bytes
var validDimensions = false;
// free the file once we get the dimensions
using (Image image = Image.FromFile(fileDialog.FileName))
{
validDimensions = (image.Width <= 350) && (image.Height <= 350);
}
if (!validDimensions || !validFilesize)
{
MessageBox.Show("Error ! Choose another image");
}
else
{
// do something with the file here
}
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
}
The error is on the line:
for (int x = 0; x < myList.Count(); x++)
The x++is painted with green.
Im using backgroundoworker and I used this code same code in another form before without a backgroundworker and it worked good. Now in the other form im using a click button event to show() this form and I want to use a progressBar1 to show the progress of the backgroundowrker work.
I used now try and catch inside this for loop and it went to the catch point and showed me the error. The full exception message is:
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at mws.Animation_Radar_Preview.backGroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in D:\C-Sharp\Download File\Downloading-File-Project-Version-012\Downloading File\Animation_Radar_Preview.cs:line 163
gifImages isnt null.
This is the full code of this form:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using DannyGeneral;
using unfreez_wrapper;
namespace mws
{
public partial class Animation_Radar_Preview : Form
{
int mtpStart;
int mtpEnd;
Picturebox1_Fullscreen pb1;
string radar_images_download_directory;
string tempRadarPngToGifDirectory;
int numberOfFiles;
UnFreezWrapper unfreez;
string path_exe;
List<string> myList;
string previewDirectory;
int animatedGifSpeed;
bool loop;
string nameOfStartFile;
string nameOfEndFile;
string previewFileName;
BackgroundWorker backGroundWorker1;
Image img;
private MemoryStream _memSt = null;
public Animation_Radar_Preview()
{
InitializeComponent();
mtpStart = Picturebox1_Fullscreen.mtp1Start;
mtpEnd = Picturebox1_Fullscreen.mtp1End;
animatedGifSpeed = Picturebox1_Fullscreen.animatedSpeed;
loop = Picturebox1_Fullscreen.looping;
pb1 = new Picturebox1_Fullscreen();
radar_images_download_directory = Options_DB.Get_Radar_Images_Download_Directory();
path_exe = Path.GetDirectoryName(Application.LocalUserAppDataPath);
tempRadarPngToGifDirectory = path_exe + "\\" + "tempRadarPngToGifDirectory";
if (Directory.Exists(tempRadarPngToGifDirectory))
{
}
else
{
Directory.CreateDirectory(tempRadarPngToGifDirectory);
}
previewDirectory = path_exe + "\\" + "previewDirectory";
if (Directory.Exists(previewDirectory))
{
}
else
{
Directory.CreateDirectory(previewDirectory);
}
previewFileName = previewDirectory + "\\" + "preview.gif";
loop = false;
animatedGifSpeed = 0;
unfreez = new UnFreezWrapper();
backGroundWorker1 = new BackgroundWorker();
backGroundWorker1.WorkerSupportsCancellation = true;
this.backGroundWorker1.WorkerReportsProgress = true;
backGroundWorker1.ProgressChanged += new ProgressChangedEventHandler(backGroundWorker1_ProgressChanged);
backGroundWorker1.DoWork += new DoWorkEventHandler(backGroundWorker1_DoWork);
backGroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backGroundWorker1_RunWorkerCompleted);
backGroundWorker1.RunWorkerAsync();
progressBar1.Value = 0;
}
private void button2_Click(object sender, EventArgs e)
{
DialogResult result1;
result1 = new DialogResult();
SaveFileDialog sd = new SaveFileDialog();
sd.Title = "Select a folder to save the animated gif to";
sd.InitialDirectory = "c:\\";
sd.FileName = null;
sd.Filter = "Gif File|*.gif;*.jpg|Gif|*.gif";
sd.FilterIndex = 1;
sd.RestoreDirectory = true;
result1 = sd.ShowDialog();
string file1 = sd.FileName;
if (result1 == DialogResult.OK)
{
File.Move(previewFileName, file1);
}
}
public void pictureBoxImage(string pbImage)
{
Image img2 = null;
try
{
using (img = Image.FromFile(pbImage))
{
//get the old image thats loaded from the _memSt memorystream
//and dispose it
Image i = this.pictureBox1.Image;
this.pictureBox1.Image = null;
if (i != null)
i.Dispose();
//grab the old stream
MemoryStream m = _memSt;
//save the new image to this stream
_memSt = new MemoryStream();
img.Save(_memSt, System.Drawing.Imaging.ImageFormat.Gif);
if (m != null)
m.Dispose();
//create our image to display
img2 = Image.FromStream(_memSt);
}
if (img2 != null)
pictureBox1.Image = img2;
label2.Text = numberOfFiles.ToString();
label6.Text = nameOfStartFile.ToString();
label4.Text = nameOfEndFile.ToString();
//File.Delete(pbImage);
}
catch(Exception err)
{
Logger.Write("Animation Error >>> " + err);
}
}
private void backGroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backGroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
List<string> myGifList;
Image gifImages = null;
//button1.Enabled = false;
Animation_Radar_Preview ap = new Animation_Radar_Preview();
//ap.FormClosing += new FormClosingEventHandler(ap_FormClosing);
FileInfo[] fi;
DirectoryInfo dir1 = new DirectoryInfo(radar_images_download_directory);
fi = dir1.GetFiles("*.png");
myList = new List<string>();
myGifList = new List<string>();
for (int i = mtpStart; i < mtpEnd; i++)
{
myList.Add(fi[i].FullName);
}
for (int x = 0; x < myList.Count(); x++)
{
try
{
gifImages = Image.FromFile(myList[x]);
gifImages.Save(tempRadarPngToGifDirectory + "\\" + x.ToString("D6") + ".Gif", System.Drawing.Imaging.ImageFormat.Gif);
}
catch (Exception ex)
{
MessageBox.Show(x.ToString() + "\r\n" + (gifImages == null).ToString() + "\r\n" + ex.Message);
}
}
myGifList = new List<string>();
dir1 = new DirectoryInfo(tempRadarPngToGifDirectory);
fi = dir1.GetFiles("*.gif");
nameOfStartFile = fi[0].Name;
for (int i = 0; i < fi.Length; i++)
{
myGifList.Add(fi[i].FullName);
//backGroundWorker1.ReportProgress(i);
nameOfEndFile = fi[i].Name.Length.ToString();
}
numberOfFiles = myGifList.Count();
unfreez.MakeGIF(myGifList, previewFileName, animatedGifSpeed, loop);
/*this.Invoke((MethodInvoker)delegate
{
pictureBoxImage(previewFileName);
});*/
}
private void backGroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pictureBoxImage(previewFileName);
}
}
}
I'm not entirely sure what is going wrong, especially as you say this same code worked previously — but it is not clear whether it worked with the same set of images.
Anyhow, the documentation for the Save method says that an ExternalException will be thrown in one of two situations:
Image was saved with the wrong format.
Image is saved to the file it was created from.
It cannot be that you are saving over the file because you are changing its extension, so it must be the wrong format. What this actually means is not clear. Perhaps one of the source images is using capabilities of the PNG format that cannot be converted to GIF, e.g. alpha channel transparency.
If I may take a moment to make some other suggestions too:
if (Directory.Exists(tempRadarPngToGifDirectory))
{
}
else
{
Directory.CreateDirectory(tempRadarPngToGifDirectory);
}
The empty 'success' case is not required if you invert the logic:
if (!Directory.Exists(tempRadarPngToGifDirectory)
{
Directory.CreateDirectory(tempRadarPngToGifDirectory);
}
Code that manipulates file paths such as the following:
tempRadarPngToGifDirectory = path_exe + "\\" + "tempRadarPngToGifDirectory";
You should consider using the Path class as this will handle the edge cases better and make more portable code:
tempRadarPngToGifDirectory = Path.Combine(path_exe, "tempRadarPngToGifDirectory");