I'm looking for a way to resize images without saving them on the server. The ways that i have found includes a controller file and such.
Is there a way to get the image from the stream, resize it and add it to the response?
Check out ImageResizer - it's a suite of NuGet packages designed for this exact purpose.
It runs eBay in Denmark, MSN Olympics, and a few other big sites.
Dynamic image processing can be done safely and efficiently, but not in a sane amount of code. It's trickier than it appears.
I wouldn't recommend this but you can do next thing:
using (Image img = Image.FromStream(originalImage))
{
using (Bitmap bitmap = new Bitmap(img, width, height))
{
bitmap.Save(outputStream, ImageFormat.Jpeg);
}
}
Be aware that this could cause OutOfMemoryException.
Related
Im creating software for a Symbol MC75A using c# .net CF 2.0. We scan a barcode and it returns stock information but i am trying to add a feature that gets an image from a url. Each scan refreshes the screen with new data from database and also gets the image from the new url. It scans a few barcodes and returns maybe 4/5 images without issue then all of a sudden a OutOfMemoryException occurs. The code im using to Get Image is:
public Bitmap GetImage(string URL)
{
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(URL);
myRequest.Method = "GET";
myRequest.AllowWriteStreamBuffering = false;
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(myResponse.GetResponseStream());
myResponse.Close();
return bmp;
}
Called by:
pbImage.Image = GetImage(ProductImage);
pbImage.SizeMode = PictureBoxSizeMode.StretchImage;
I have tried to dispose of image before each new GET with pbImage.Image.Dispose() but still getting the same exception. The image sizes are between 100KB and 550KB. Whether it makes a difference the images sizes are always over 1000px each side.
Am i missing the correct way of disposing before re-getting or is it somehow caching all these images which then creates an outofMemory exception?
I have found my solution herer:
OutOfMemoryException loading big image to Bitmap object with the Compact Framework
It seems it is the system.drawing when decompressing the 2000px image it is creating an uncompressed image giving a larger size on the memory hense the exception. The solution shows a way to obtain a thumbnail of the image rather than the whole image.
Thanks for your help again.
Just incase someone has access to the image location. A better work around for me was to creat a webpage named resize.aspx and have the picture box populate from the page with the image filename as a parameter. Now that page (being on the server in the same location as the images) was able to resize the image and return a small 300x300px image. Seemed to be the best solution i could think of. This can also work for images at any url if you pass the full url of the image into another page and that page returns the required thumbnail.
I'm trying to use this class but I'm getting a Generic error occured in GDI+ in Image.Save() method. From what I read it's some stream I need to close but I don't know which one.
I'm calling using this:
Image image = Image.FromFile(#"C:\a.jpg");
using (var resized = ImageUtilities.ResizeImage(image, 50, 100))
{
//save the resized image as a jpeg with a quality of 90
ImageUtilities.SaveJpeg(#"C:\myimage.jpeg", resized, 90);
}
Why is that error and how do I solve this?
Unless your program is running as administrator you can not save directly to the root of C: make a folder and save it inside there instead.
Have you tested saving the images in different locations?
If it is still failing then without knowing exactly what is going on in your code I would hazard a guess to say that the original image is getting disposed somewhere before it should be. That's usually the most common cause of the error.
I've written a library that handles many different imaging operations whilst ensuring that memory is correctly handled. It's well tested and very simple to use.
You can get it here. http://imageprocessor.org/
Example code using the library:
using (ImageFactory imageFactory = new ImageFactory())
{
// Load, resize, set the quality and save an image.
imageFactory.Load(#"C:\a.jpg")
.Resize(new Size(50, 100))
.Quality(90)
.Save(#"C:\myimage.jpeg);
}
After spending 2 days to realize that the C# Bitmap.Save method was bugged (for JPEG/grayscale/8bbp), I tried FreeImage to see if I could save it correctly, and at first glance it seemed so, but after closer inspection it seems it doesn't work either.
Here are my tests:
If I do
FreeImage.SaveBitmap(aImage, aSavePath, FREE_IMAGE_FORMAT.FIF_JPEG, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
the image DPI's aren't saved correctly and if I convert the Bitmap into a FIBITMAP (so that I can specify the DPI's
MemoryStream imageStream = new MemoryStream();
aImage.Save(imageStream, aImageFormat);
FIBITMAP dib = FreeImage.LoadFromStream(imageStream, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE, freeImageFormat);
FreeImage.SetResolutionX(dib, (uint)aImage.HorizontalResolution);
FreeImage.SetResolutionY(dib, (uint)aImage.VerticalResolution);
FreeImage.Save(FREE_IMAGE_FORMAT.FIF_JPEG, dib, aSavePath, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
Any ideas on how I can save a Bitmap using FreeImage and preserve the DPI's and bpp's? Or is the FreeImage.Save method also bugged?
Some software relies on metadata while getting resolution, so you can try to add EXIF with DPI fields to jpeg created with FreeImage.
P.S. Your task seems to be pretty easy, I’m sure you can find a few more SDKs for that.
I gave up on this 2 options (FreeImage and Magick.NET) and went with GraphicsMagick.NET.
I've got an webapplication where users can upload images. The current problem i'm running into is that the images being uploaded are being saved to the database in the original format. This causes a lot of performance issues when the images are used on a webpage. I used dotTrace to profile the application and I see significant problems when images are processed from the database.
The idea I have is to resize the image when it's uploaded to the server. Take the following example which I want the application to do when the user uploads a new image;
User uploads an image
The image is being resized to an size of 7.500 x 7.500 in pixels in 72 dpi
The image is being saved into the database
Original file gets disposed
The only stored image is the one mentioned above and the webapplication contains technology to resize this on the fly.
I've already read several topics here on SO. And most of them point me into the direction of ImageMagick. This tool is already familiar at my company, and being used in PHP projects. But are there any good and stable released C# wrappers for this tool? I already found the tools below but they're either in Béta release, Alpha Release or currently not updated.
ImageMagick.NET
ImageMagick APP
I also found this topic on SO. In this topic the following code example is supplied;
private static Image CreateReducedImage(Image imgOrig, Size newSize)
{
var newBm = new Bitmap(newSize.Width, newSize.Height);
using (var newGrapics = Graphics.FromImage(newBm))
{
newGrapics.CompositingQuality = CompositingQuality.HighSpeed;
newGrapics.SmoothingMode = SmoothingMode.HighSpeed;
newGrapics.InterpolationMode = InterpolationMode.HighQualityBicubic;
newGrapics.DrawImage(imgOrig, new Rectangle(0, 0, newSize.Width, newSize.Height));
}
return newBm;
}
In short the questions i have;
Are there any advantages in relation to performance using the example above?
Is there a good and reliable C# wrapper for ImageMagick i can use to do this?
Any other good tips relating to the performance are welcome!
We use the latter approach - I can't comment on performance but it certainly makes handling dependencies simpler.
However, one thing to note is that the above code is probably too simple if your users are able to upload images in all sorts of formats. The underlying library (GDI+) has issues with a lot of color formats, but it also is dependent on the OS version. Here's the core of the code we use:
// GDI+ has problems with lots of image formats, and it also chokes on unknown ones (like CMYK).
// Therefore, we're going to take a whitelist approach.
// see http://bmpinroad.blogspot.com/2006/04/file-formats-pixel-formats.html
// also see http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/c626a478-e5ef-4a5e-9a73-599b3b7a6ecc
PixelFormat format = originalImage.PixelFormat;
if (format == PixelFormat.Format16bppArgb1555 ||
format == PixelFormat.Format64bppArgb)
{
// try to preserve transparency
format = PixelFormat.Format32bppArgb;
}
else if (format == PixelFormat.Format64bppPArgb)
{
// try to preserve pre-multiplied transparency
format = PixelFormat.Format32bppPArgb;
}
else if (format != PixelFormat.Format24bppRgb && format != PixelFormat.Format32bppRgb)
{
format = PixelFormat.Format24bppRgb;
}
// GIF saving is probably still an issue. If we ever need to tackle it, see the following:
// http://support.microsoft.com/kb/319061
// http://www.bobpowell.net/giftransparency.htm
// http://support.microsoft.com/kb/318343
using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, format))
{
using (Graphics Canvas = Graphics.FromImage(newImage))
{
using (ImageAttributes attr = new ImageAttributes())
{
attr.SetWrapMode(WrapMode.TileFlipXY);
Canvas.SmoothingMode = SmoothingMode.AntiAlias;
Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
Canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
Canvas.DrawImage(originalImage, new Rectangle(new Point(0, 0), newSize), srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, attr);
newImage.Save(outputImageStream, originalImage.RawFormat);
}
}
}
I've never used ImageMagic, but I have used the GDI+ image resize functions, including on a site that generates and resizes 100,000+ images a day without performance issues.
I would say using the GDI+ methods are just fine. Don't worry about wrapping an external tool or framework.
I've used ImageGen in Umbraco sites. (It's certainly not tied to Umbraco, it's good for any ASP.NET app, it just so happened that some of the Umbraco packages I was using required it.) It's simple to use, and you might be able to get away with the free version...
Is it possible to use the FromStream method of System.Drawing.Image without having to keep the stream open for the lifetime of the image?
I have an application which loads a bunch of toolbar graphics from resource files, using a combination of Image.FromStream and Assembly.GetManifestResourceStream.
The problem I'm having is while this works fine on Windows 7, on Windows XP the application crashes if a user interface element linked to one of these images is disabled. On Windows 7, the image is rendered in grayscale. On XP, it crashes with an out of memory exception.
After a load of hairpulling I have finally traced it to the initial loading of the image. As a matter of course, if I create any object implementing IDisposable that is also destroyed in the same method, I wrap it in a using statement, for example
using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
{
image = Image.FromStream(resourceStream);
}
If I remove the using statement so that the stream isn't disposed, then the application no longer crashes on XP. But I now have a bunch of "orphan" streams hanging about - the images are stored in command classes and these correctly dispose of the images when they themselves are disposed, but the original stream isn't.
I checked the documentation for FromStream and it confirms the stream needs to remain open. Why this hasn't crashed and burned on the Windows 7 development system is a mystery however!
I really don't want this stream hanging around, and I certainly don't want to have to store a reference to this stream as well as the image so I can dispose of it later. I only have need of that stream once so I want to get rid of it :)
Is it possible to create the image and then kill of the stream there and then?
The reason the stream needs to be open is the following:
GDI+, and therefore the System.Drawing namespace, may defer the decoding of raw image bits until the bits are required by the image. Additionally, even after the image has been decoded, GDI+ may determine that it is more efficient to discard the memory for a large Bitmap and to re-decode later. Therefore, GDI+ must have access to the source bits for the image for the life of the Bitmap or the Image object.
The documented workaround is to create either a non-indexed image using Graphics.DrawImage or to create an indexed Bitmap from the original image as described here:
Bitmap and Image constructor dependencies
According to the documentation of Image.FromStream, the stream must be kept open while the image is in use. Therefore, even if closing worked (and there's nothing to say you can't close a stream before it's disposed, as far as the stream object itself goes) it may not be a very reliable approach.
You could copy the image to another image object, and use that. However, this is likely to be more memory intensive than just keeping the stream open.
You could save the stream to a temporary file and use the Image.FromFile method. Or simply don't embed the image, keep it as a file and load it from this file at runtime.
I'am sure this will help someone :)
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;
}