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
Related
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).
I've set up a thumbnail provider for a file type.
The project is made with
C#
.NET 4.5
And I am running Windows x64
My provider successfully generates the thumbnail as expected and I can move, delete, copy, ect, the file. The issue of the locking seems to be caused by the file being placed in a folder. At that point, moving, deleting, ect, the folder all show the error, "File In Use".
I have confirmed Explore locking the file using Sysinternal's Process Explorer, if you are familiar with it.
I've tried 2 approaches to try to resolve this...
implemented IThumbnailProvider and IInitializeWithStream myself.
used 3rd party Sharpshell
Both suffer from this same issue, the file not being released.
On Sharpshell's github, an issue has been started specifying this too.
https://github.com/dwmkerr/sharpshell/issues/78
I associate the file type in the registry like so
HKEY_CLASSES_ROOT
---- .qb
----shellex
----{e357fccd-a995-4576-b01f-234630154e96} : my CLSID...
I have also tried instead...
HKEY_CLASSES_ROOT
---- .qb
-----PersistentHandler : my CLSID...
Both result in this issue being created.
If I was to implement IExtractImage instead... will I see the same issue?
I know C# isn't "officially" supported to do this, is that where my issue lies? If I was to implement this in C++ would I wind up with the same issue?
EDIT:
I'd like to mention the file after around 1 minute seems to get freed, and things go back to normal.
Thumbnail Creation
Some bytes are read into a buffer... then then image is generated from that.
public void GetThumbnail(int cx, out IntPtr hBitmap, out WTS_ALPHATYPE bitmapType)
{
... bunch of other code
using (MemoryStream steam = new MemoryStream(buffer))
using (var image = new Bitmap(steam))
using (var scaled = new Bitmap(image, cx, cx))
{
hBitmap = scaled.GetHbitmap();
hBitmap = (IntPtr)(hBitmap.ToInt64());
}
}
EDIT 2:
Doing some more testing, I called DeleteObject(hBitmap), (even though this destroys the thumbnail), and the file is still locked. I even removed all the code from GetThumbnail... just gives the same result, file locked. There has to be something more going on?
Turns out you need to release the COM IStream object that you get from IInitializeWithStream.
I came to this conclusion by reading more about disposing COM objects.
Proper way of releasing COM objects?
I followed MS's example on how to wrap IStream
https://msdn.microsoft.com/en-us/library/jj200585%28v=vs.85%29.aspx
public class StreamWrapper : Stream
{
private IStream m_stream;
// initialize the wrapper with the COM IStream
public StreamWrapper(IStream stream)
{
if (stream == null)
{
throw new ArgumentNullException();
}
m_stream = stream;
}
// .... bunch of other code
protected override void Dispose(bool disposing)
{
if (m_stream != null)
{
Marshal.ReleaseComObject(m_stream); // releases the file
m_stream = null;
}
}
}
Here's a sample.
Follow the link above to see StreamWrapper's implementation...
[ComVisible(true), ClassInterface(ClassInterfaceType.None)]
[ProgId("mythumbnailer.provider"), Guid("insert-your-guid-here")]
public class QBThumbnailProvider : IThumbnailProvider, IInitializeWithStream
{
#region IInitializeWithStream
private StreamWrapper stream{ get; set; }
public void Initialize(IStream stream, int grfMode)
{
// IStream passed to our wrapper which handles our clean up
this.stream = new StreamWrapper(stream);
}
#endregion
#region IThumbnailProvider
public void GetThumbnail(int cx, out IntPtr hBitmap, out WTS_ALPHATYPE bitmapType)
{
hBitmap = IntPtr.Zero;
bitmapType = WTS_ALPHATYPE.WTSAT_ARGB;
try
{
//... bunch of other code
// set the hBitmap somehow
using (MemoryStream stream = new MemoryStream(buffer))
using (var image = new Bitmap(stream))
using (var scaled = new Bitmap(image, cx, cx))
{
hBitmap = scaled.GetHbitmap();
}
}
catch (Exception ex)
{
}
// release the IStream COM object
stream.Dispose();
}
#endregion
}
Basically it comes down to two lines of code
Marshal.ReleaseComObject(your_istream); // releases the file
your_istream = null;
Side Note
The GDI Bitmap created with scaled.GetHbitmap(); probably needs to disposed of, but I can't find a way to do it without loosing the created thumbnail.
I have no idea how to read an image in as a binary image. I have being using the following lines however it keeps reading in null.
FileStream inf = new FileStream(name.ToString(), FileMode.OpenOrCreate, FileAccess.ReadWrite);
BinaryReader data = new BinaryReader(inf);
Can anyone help?
It really depends on what you want to do. For example, if you want to read in a .bmp file and display it in a PictureBox, you can do something like the following:
(assumes there's a PictureBox named pictureBox1)
Stream bmpStream = null;
var ofd1 = new OpenFileDialog();
if(ofd1.ShowDialog()==DialogResult.OK)
{
try
{
bmpStream = ofd1.OpenFile();
if(bmpStream != null)
{
using (bmpStream)
{
pictureBox1.Image = new Bitmap(bmpStream);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: could not read file. " + ex.Message);
}
}
why don't you take a look on this topic How to open image in C# and convert to binary,it seems to be like what you're asking for, but for image in black and white, however there are some methods that can help you. I hope you find this helpful or at least that lead you in the right direction.
Regards
I have a potentially easy question. I have an image stored in a database, I then used a C# method in my application that gets that image and stores it in a custom class that looks like this:
public class MyImage
{
public System.Drawing.Image myImageFromDB;
public string imageName;
public int imageNumberInCollection;
}
My question is this: Can I/How can I use the image from this class in an HTML image tag? I have attempted the following but it just returns a box with a red X in it:
//myImageFromDBCollection is a list of MyImage objects
foreach(var ind in myImagesFromDBCollection)
{
table += String.Format("<image src={0} />", ind.myImageFromDB);
}
Any ideas on what I am doing wrong?
I ended up going with Brads Method of solving this (See the comment under the question) I ended up creating a method that takes in a System.Drawing.Image and converts it to a byte array then encode that byte array to get the image. The code looks like the following:
byte[] imgBytes = turnImageToByteArray(ind.ind.myImageFromDB);
string imgString = Convert.ToBase64String(imgBytes);
table += String.Format("img src=\"data:image/Bmp;base64,{0}\">", imgString);
private byte[] turnImageToByteArray(System.Drawing.Image img)
{
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
return ms.ToArray();
}
Currently this works for my purposes so thank you to everyone and their suggestions, as always everyone comes though and helps :-)
Images can be served using generic handlers (ashx files):
public class StickerHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/png";
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.BufferOutput = false;
//TODO: link your MyImage to iSource using imageId query parameter...
Image iSource = null;
MemoryStream ms = new MemoryStream();
iSource.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] data = ms.ToArray();
ms.Dispose();
g.Flush();
g.Dispose();
iSource.Dispose();
context.Response.BinaryWrite(data);
}
public bool IsReusable
{
get
{
return true;
}
}
}
More about generic handlers can be found here:
http://msdn.microsoft.com/en-us/library/bb398986(v=vs.100).aspx
Inside your image:
<img src='StickerHandler.ashx?img=imageId' />
Happy coding!
If I were you, I'd keep image files on disk, and just have the image filenames in your db.
If you're having a problem with your image formatting, than just look at your source and make sure it's correct.
If you have to store your images in the database, a simple way to view them would be to use an image handler.
Basically, you can create an ASHX handler which accepts a query string that is the Image ID in the database and returns the image content along with the correct mime type. This is quite simple to do in C#.
You can then point the <img /> tag to the handler with the specified ID. Something like
table += String.Format("<image src='/ViewImage.ashx?id={0}' />", ind.myImageId);
Here is a basic tutorial to get you started.
A common performance improvement would be to cache the images on disk within the handler.
I'm using a custom ashx HttpHandler to retrieve gif images from a database and show it on a website - when the image exists, it works great.
However, there are cases when the image will not exist, and I'd like to have the html table holding the image to become invisible so the "image not found" icon is not shown.
But since the HttpHandler is not synchronous, all my attempts checking for image size at Page_Load were frustrated. Any ideas on how this can be accomplished?
EDIT::
Here's how it's happening so far:
This is my handler:
public void ProcessRequest(HttpContext context)
{
using (Image image = GetImage(context.Request.QueryString["id"]))
{
context.Response.ContentType = "image/gif";
image.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);
}
}
private Image GetImage(string id)
{
try
{
System.IO.MemoryStream ms;
byte[] rawImage;
Image finalImage;
// Database specific code!
rawImage = getImageFromDataBase(id);
ms = new System.IO.MemoryStream(rawImage, 0, rawImage.Length);
ms.Write(rawImage, 0, rawImage.Length);
finalImage = System.Drawing.Image.FromStream(ms, true);
return finalImage;
}
catch (Exception ex)
{
System.Console.WriteLine("ERROR:::: " + ex.Message);
return null;
}
}
And I use it like this:
myImage.ImageUrl = "Image.ashx?id=" + properId;
However, there are cases when the
image will not exist, and I'd like to
have the html table holding the image
to become invisible so the "image not
found" icon is not shown.
The easiest way to fix this is to check to see if the image exists in the Http-handler (in the image.ashx file.) before returning.
if(image == null) {image = new blankImage();}
If it's not there, substitute it with a blank image. That way this is no image not found icon. If you really want it to disappear and not hold the image size, just make the blank image a 1x1 square.
Can you not just use a NullReferenceException, or am I misunderstanding the question?
try
{
//try to get the photo
}
catch (NullReferenceException)
{
//handle the error
}
You could also check if image == null I suppose, that may make more sense in your situation.
since the ashx gets executed after page_load, you can make it return a 1x1 square, however if you want to entirely hide the column, you are going to have some issues because of the lifecycle.
you could create a placeholder on your page, and build your table dynamically. If you can avoid using an ashx, and instead do the image retrieval and rendering in your code-behind, you will be able to know when to hide the column or not
Even though this makes the page fetch the image twice, I'm using small images and on very few pages, so I think it is worth the cost.
This is the code I added to the page:
public static bool CheckImageExistance(string url)
{
try
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "HEAD";
request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
response.Close();
return (response.StatusCode == HttpStatusCode.OK);
}
catch (Exception ex)
{
return false;
}
And it works as expected. Thanks for all the input.