In my project, I need to retrieve a custom image file (from disk). If the image file does not exist at the path provided, then the app will use a default image (embedded resource). Once I have the image, I need to resize it for use futher on in my application.
If I attempt to access only the embedded resource (Code Section 1), everything works as expected. If attempt to place a condition on the image (Code Section 2), the object comes back with all kinds of exceptions on the object, most notably for my purposes:
((System.Drawing.Image)(ReportLogoToUse)).Height' threw an exception of type 'System.ArgumentException' int {System.ArgumentException}
((System.Drawing.Image)(ReportLogoToUse)).Width' threw an exception of type 'System.ArgumentException' int {System.ArgumentException}
Here is my code
// Code Section 1
using (var myImage = Resources.sie_logo_petrol_rgb){
// resize the image to max allowed dimensions (64 x 233)
var resizedImage = Helpers.ResizeImage(myImage, (int)maxWidth, (int)maxHeight); // this code executes with no errors
pictureBox1.Image = resizedImage;
}
// Code Section 2
using (var ReportLogoToUse = Helpers.ReportLogo(filePath)){
// resize the image to max allowed dimensions (64 x 233)
var resizedImage = Helpers.ResizeImage(ReportLogoToUse, (int)maxWidth, (int)maxHeight); // Invalid Parameter error
pictureBox2.Image = resizedImage;
}
public static Bitmap ReportLogo(string filePath){
try{
var myImage = Image.FromFile(filePath, true);
return (Bitmap)myImage;
}
catch (Exception ex){
// use the embedded logo
using (var myResourceImage = Resources.sie_logo_petrol_rgb){
var myImage = myResourceImage;
return (Bitmap)myImage;
}
}
}
What is the difference between the objects in Code Section 1 and Code Section 2? Aren't they returning the same kind of object?
By removing the using... block in the catch... section, and just returning the file itself, it appears to be functioning now.
public static Bitmap ReportLogo(string filePath){
try{
return (Bitmap)Image.FromFile(filePath, true);
}
catch (Exception ex){
// use the embedded logo
return Resources.sie_logo_petrol_rgb;
}
}
Any insight as to why it works now would be greatly appreciated (because I am completely baffled).
Related
I am getting "Value cannot be null.\r\nParameter name: encoder" error while saving a Bitmap image using RawFormat.
Sample code:
class Program
{
static void Main(string[] args)
{
try
{
var image = new System.Drawing.Bitmap(500, 400);
var stream = new MemoryStream();
image.Save(stream, image.RawFormat);
}
catch (Exception exp)
{
Console.WriteLine(exp.ToString());
}
}
}
The RawFormat doesn't exist in the existing list of ImageEncoders as below code returns null.
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == image.RawFormat.Guid);
Note: The image could be any type(JPEG, BMP, PNG) etc. Image.Save() should work on image.RawFormat.
RawFormat is not Bitmap type. If I Change image.RawFormat to ImageFormat.Bmp, the save operation succeeds.
Referred below links but found nothing for making it independent of image type.
Image.Save crashing: {"Value cannot be null.\r\nParameter name: encoder"}
Why is Image.Save(Stream, ImageFormat) throwing an exception?
Any suggestions are welcome.
If you load an image from disk, you can use image.RawFormat to save that image using its original format. However there is no encoder associated with an in-memory bitmap (which is what you are creating in this sample application), so you'll have to specify an image format yourself (ie. ImageFormat.Bmp).
You can use this and it will be fixed:
image.Save(stream,ImageFormat.Jpeg);
Hi All you clever guys,
Im faceing a bit of a challenge here.
Im supposed to create several different PDF's containing multiple (not similar) images.
Unfortunately some of the images are corrupt/defect. This causes the creation of the partikular PDF to fail/dump.
Is there a way I can test the image prior to creation of the PDF?
Please be gentle with me. Im not an expert.
I found out that System.Drawings.Image can test some formats. Better than nothing I guess (it will reduce the subset significantly).
But when using iTextSharp.text.Image for the creation of the PDF's. Then I dont know how to use the System.Drawings.Image because when I try Image newImage = Image.FromFile("SampImag.jpg"); then it (Image) refers to the iTextSharp.text.Image class.
System.Drawings.Image is abstract, so I've tried to create a subclass.
public class ImageTest : System.Drawing.Image
{
}
Now I get the error message:"Error 1 The type 'System.Drawing.Image' has no constructors defined"
Trying to investigate which constructors I can use gives me this attempt.
public class ImageTest : System.Drawing.Image
{
ImageTest(string filename);
{
}
}
But this doesn't work.
Please inform me if there is information you need which is relevant to you for investigating this matter.
Thanks in advance.
You should just be able to use
public bool IsValidImageFile (string imageFile)
{
try
{
// the using is important to avoid stressing the garbage collector
using (var test = System.Drawing.Image.FromFile(imageFile))
{
// image has loaded and so is fine
return true;
}
}
catch
{
// technically some exceptions may not indicate a corrupt image, but this is unlikely to be an issue
return false;
}
}
Catch OutOfMemoryException works:
try
{
// Using System.Drawing.Image
System.Drawing.Image img = (System.Drawing.Bitmap)System.Drawing.Image.FromFile("myimage.png");
}
catch (OutOfMemoryException ex)
{
// Handle the exception...
}
I tested it with this code:
try
{
System.Drawing.Image img = (System.Drawing.Bitmap)System.Drawing.Image.FromFile("myimage.png");
}
catch (OutOfMemoryException ex)
{
Console.WriteLine("Error loading image...");
}
And I deleted a few characters in a .png file, and the console said:
Error loading image...
And to convert it into a iTextSharp.text.Image
I'm doing one application,
i add a picturebox to add image to some products, i have one question, i would like edit the images already added to one product, how can i do that?
This is my actually code.
private void pbImagenEquipo_DoubleClick(object sender, EventArgs e)
{
ofdImagenes.Filter = "Imagenes JPG (*.jpg)|*.jpg; *.jpeg;|Imagenes PNG (*.png)|*.png";
DialogResult resp = ofdImagenes.ShowDialog();
if (resp == DialogResult.OK)
{
Bitmap b = new Bitmap(ofdImagenes.FileName);
string [] archivo = ofdImagenes.FileName.Split('.');
nombre = "Equipo_" + lbID+ "." + archivo[archivo.Length-1];
b.Save(Path.Combine(Application.StartupPath, "Imagenes", nombre));
pbImagenEquipo.Image = b;
}
}
But when i try to replace the image i got this error:
An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll
Additional information: Error generoc in e GDI+.
This is a common issue.
The documentation says:
Saving the image to the same file it was constructed from is not
allowed and throws an exception.
There are two options. One is to delete the file before writing it.
The other is to use a Stream to write it. I prefer the latter..:
string fn = "d:\\xyz.jpg";
// read image file
Image oldImg = Image.FromFile(fn);
// do something (optional ;-)
((Bitmap)oldImg).SetResolution(123, 234);
// save to a memorystream
MemoryStream ms = new MemoryStream();
oldImg.Save(ms, ImageFormat.Jpeg);
// dispose old image
oldImg.Dispose();
// save new image to same filename
Image newImage = Image.FromStream(ms);
newImage.Save(fn);
Note that saving jpeg files often achieves better quality if you take control of encoding options. Use this overload for this..
Also note that since we need to dispose of the image you need to make sure that it is not used anywhere, like in a PictureBox.Image! If it is, set it to null there before disposing : pictureBox1.Image = null; !
For a solution deleting the old file see here
I am running the below code to create a thumbnail when a user sends us an image:
public int AddThumbnail(byte[] originalImage, File parentFile)
{
File tnFile = null;
try
{
System.Drawing.Image image;
using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(originalImage))
{
image = System.Drawing.Image.FromStream(memoryStream);
}
Log.Write("Original image width of [" + image.Width.ToString() + "] and height of [" + image.Height.ToString() + "]");
//dimensions need to be changeable
double factor = (double)m_thumbnailWidth / (double)image.Width;
int thHeight = (int)(image.Height * factor);
byte[] tnData = null;
Log.Write("Thumbnail width of [" + m_thumbnailWidth.ToString() + "] and height of [" + thHeight + "]");
using (System.Drawing.Image thumbnail = image.GetThumbnailImage(m_thumbnailWidth, thHeight, () => false, IntPtr.Zero))
{
using (System.IO.MemoryStream tnStream = new System.IO.MemoryStream())
{
thumbnail.Save(tnStream, System.Drawing.Imaging.ImageFormat.Jpeg);
tnData = new byte[tnStream.Length];
tnStream.Position = 0;
tnStream.Read(tnData, 0, (int)tnStream.Length);
}
}
//there is other code here that is not relevant to the problem
}
catch (Exception ex)
{
Log.Error(ex);
}
return (tnFile == null ? -1 : tnFile.Id);
}
This works fine on my machine, but when I run it on a test server I always get an out of memory exception on the line:
using (System.Drawing.Image thumbnail = image.GetThumbnailImage(m_thumbnailWidth, thHeight, () => false, IntPtr.Zero))
It is not manipulating a large image: it is trying to convert a 480*640 image into a 96*128 thumbnail. I don't know how to investigate / resolve this issue. Has anyone got any suggestions? It always happens, even after I have restarted IIS. I did initially think that the image might be corrupt but the dimensions are correct.
Thanks.
We also had similar problems using GDI+ Operations in our ASP.Net server. Your mention of your code running on a server made me think, that this could be the same problem.
Please be aware, that the usage of classes in the System.Drawing Namespace is not supported on a server. The fatal thing is, that it may work for some time and suddenly (even without code changes) errors occur.
We had to rewrite a significant part of our server code.
See the comment:
Caution note
Classes within the System.Drawing namespace are
not supported for use within a Windows or ASP.NET service. Attempting
to use these classes from within one of these application types may
produce unexpected problems, such as diminished service performance
and run-time exceptions. For a supported alternative, see Windows
Imaging Components.
Source:
http://msdn.microsoft.com/de-de/library/system.drawing(v=vs.110).aspx
Many thanks #vcsjones for pointing me in the right direction. Instead of using image.GetThumbnailImage I call:
public static Image ResizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
The troublesome line of code is now:
using(Image thumbnail = ResizeImage(image, new Size(m_thumbnailWidth, thHeight)))
I got this line from Resize an Image C#
It now works!
I am getting "Value cannot be null.\r\nParameter name: encoder" error while saving a Bitmap image using RawFormat.
Sample code:
class Program
{
static void Main(string[] args)
{
try
{
var image = new System.Drawing.Bitmap(500, 400);
var stream = new MemoryStream();
image.Save(stream, image.RawFormat);
}
catch (Exception exp)
{
Console.WriteLine(exp.ToString());
}
}
}
The RawFormat doesn't exist in the existing list of ImageEncoders as below code returns null.
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(codec => codec.FormatID == image.RawFormat.Guid);
Note: The image could be any type(JPEG, BMP, PNG) etc. Image.Save() should work on image.RawFormat.
RawFormat is not Bitmap type. If I Change image.RawFormat to ImageFormat.Bmp, the save operation succeeds.
Referred below links but found nothing for making it independent of image type.
Image.Save crashing: {"Value cannot be null.\r\nParameter name: encoder"}
Why is Image.Save(Stream, ImageFormat) throwing an exception?
Any suggestions are welcome.
If you load an image from disk, you can use image.RawFormat to save that image using its original format. However there is no encoder associated with an in-memory bitmap (which is what you are creating in this sample application), so you'll have to specify an image format yourself (ie. ImageFormat.Bmp).
You can use this and it will be fixed:
image.Save(stream,ImageFormat.Jpeg);