I would like to resize a picture to a specific file size. For example, no more than 200KB.
What is the best approach to achieve this with C# .NET ?
Thanks !
If you think about it, you aren't going to know the filesize of the image until after it's resized. So you've either got to perform a successive iteration of attempts and compare the file sizes afterwards or you could change your constraints to restrict images to a particular set of height and width dimensions.
See How to resize an image in C# to a certain hard disk size
If this is not a very important function, trial and error works well enough. Just assume that if you need to shrink the input to N * 100%, you do so by scaling both dimensions by sqrt(N) * 100%.
If it is important, you need to understand image compression technologies better. I'll assume JPG. It's an image format that achievs lossy compression by breaking the image down into 8x8 pixel blocks, DFT transforming them, throwing away small coefficients, and then compressing the resulting bitstream.
Now it follows that you can fiddle quite a bit with the quality level, how many of the small coefficients you throw away. You don't need to redo the (expensive) DFT for this. So if the file ends just slightly too large, you can throw away a few more coefficients and recompress. And if you were slightly to aggressive, then put back a few coeffecients and compress again. This is all fairly fast.
You can do quite alot with the Drawing.Image class in order to resize an image.
There are many questions on how to do that. Here is one.
In terms of the size - you will not know what the size is untill after the resize operation. The only way to be certain is to resize, check the result and if it is too large try resizing with lower quality. Repeat until done.
You can approximate the size if you know the dimensions and color depth, as described in the answers to this (identical?) question.
A rough estimate is as follows:
size(KB) = (width * height * bitdepth) / (8 * 1024)
The file size is inflated a bit more due to file information (compression info, etc).
Related
If there is a JPEG image with dimensions 800x600 and I want to reduce its file size by reducing its dimensions to, say, 768x576, how would I go about it?
Using the GDI+ library in .NET, I would have thought that by just opening the image, copying it to another with the desired dimensions and a quality setting of 100, the resulting image would have the same quality and would be automatically smaller (in bytes), because its dimensions are smaller than the original, but in my tests this doesn't seem to be the case. In fact, the size of the resulting image is larger than the original: from ~70K to ~280K.
So, is there any way this can be done? The final goal is to reduce the image size. I have also tried to save the image with the same dimensions and a quality setting of 70 or even 50, but I don't want to do that because it's impossible to determine if the original image has already been compressed to a point where saving it with such low settings will produce too much quality loss.
You shoudn't save the file with a quality setting of 100. What you are doing is like taking a 128 kbps mp3 file and saving it at 192 kbps. You get a larger file with the same information in it, and you are probably losing some data just by decoding and encoding again.
I would start by keeping the image size and finding the quality at which you get the same file size. After that you can play around with the size and quality until you get your desired file size.
I am working on images in current application and facing lot of issues like resize image , image quality etc.
I have seen lot of website uploading image with good quality and minimum size length. One thing that i noticed image quality does not loose when increase or decrease the dimensions.
So my question is What will be efficient techniques to handle following issues
Reduce image size length
Resize image dimensions
For example if i want minimum image dimensions should be (width = 800 * height=600) so how can i increase dimensions without respect to image quality and how decrease image dimensions according to ratio.
I am working on asp.net MVC3 C# but your suggestion in any language will be helpful for me.
One thing that i noticed image quality does not loose when increase or decrease the dimensions.
If this is the case, then the image is a vector format, such as SVG - PNG and JPEG images will always lose their quality when you increase the size, since the pixels will be stretched. There's ways you can mitigate that, but no way to circumvent it completely.
If you want to scale an image in Java however with as good a quality as you can reasonably get:
BufferedImage scaled = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(2.0, 2.0);
AffineTransformOp scaleOp = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC);
BufferedImage scaledImage = scaleOp.filter(img, scaled);
The key part that determines how the image is scaled is AffineTransformOp.TYPE_BICUBIC, which generally gives the best results (as far as it can, anyway.) C# will no doubt have a similar switch that can be set. The scale factor is given by at.scale(2.0, 2.0);, which will increase length and height by two - if you want to, say, reduce the dimensions by half, use at.scale(0.5, 0.5).
I need to generate some large graphs whose width and height can go up to millions of pixels in size. Please note that I do NOT want to scale down the image. Each point must represent one pixel.
Now using the Bitmap and Graphics objects, this is very much possible if I split the image into smaller squares but it is painfully slow.
I already calculate the pixel RGB values so was wondering if there is a way to create a byte array with these values and manually save them as an uncompressed BMP format file instead of dealing with the Bitmap class and the drawing functions of the Graphics class.
I am comfortable with unsafe code if that helps to speed up the process.
If you're displaying graphs, why don't you use a technology like SVG that can be rendered on the fly with very little processing power, yet can scale to near-infinite sizes thanks to vector expansion?
(While there is good question if anything will be able to read such files...)
BMP format is very simple - you can write it directly to disk (I'd recommend avoiding building huge file in memory unless you have other reasons to do so). There is a fixed-size header and then (for 24bpp) sequences of colors aligned on some width. Assuming you can pick width you will not even need to add any padding - just rows of colors for each pixel.
I have a treeview that contains icons. The icons are ugly. and by ugly i mean low quality. and by low quality i mean something i would expect to see from a dos program
i would hope there would be a way to improve the image quality of the icons, but after looking around on microsoft's development site, I have yet to find a solution.
to be honest, at this point i don't even know what to look for. 'image quality' is very too broad of a phrase to search for (i've gotten very random results from google searches).
i am using an ImageList to store these icons in the TreeView. there really isnt much code to show that would be of use here - at least i dont think so.
sorry for the boring question.
Is this what you're looking for?
http://msdn.microsoft.com/en-us/library/system.windows.forms.imagelist.colordepth.aspx
The default value is set to 8-bit, so changing this property of your list will probably help. Essentially, just add the following line to your code:
imagelist.ColorDepth = ColorDepth.Depth32Bit;
It can be improved. What you need to do is to open it in photoshop or gimp and resample it at 3 times it size. Then resample it at 600 dpi and resize it down to 8 x 10.
Notice, that I specified to resize and not down size. You click on the pic and the corners have a handle for you to click on and size it down to the appropraite size. This way, the pixels are closer together.
Then, you use a very soft blur, I mean really soft. The secret is when it is printed. We print at 600 to 1200 dpi which is what will enhance the picture and that is what a printer has to keep in mind. When you print on glossy paper at 600 dpi, the pic comes out really nice and sharp.
My application is used to design airports for a flight simulator. Users can add one or more images as background. The image(s) can be sized accurately and then used as a template to lay down features such as runways, aprons and so on.
I use a third party graphics library (Piccolo) which has an image class (as far as I can see it is a simple wrapper for System.Drawing.Image).
So far I have done little except allow the user to add an image, size it and so on. It will be no surprise that users sometimes complain of poor performance. We tell them not to load large images (up to 100k seem OK) but don't stop them and 100Mb bitmaps have been used with horrible results.
I need to fix this in a couple of ways. First by converting any image they use to an efficient format (size vs definition) and second by ensuring that the loaded image is suitably sized for the dimensions - at the moment I don't do anything specific to deal with the resizing of say a 2000 x 2000 image to fit a 500 x 500 area of the display.
The default 1:1 display of the application represents 1m per pixel. Once the user has resized the image to fit accurately would I be right in thinking that the best resoultion for the image would be to resample it to that size? I am aware that if the user zooms in way past 1:1 which they will probably do then the clarity of the image will fall.
My ignorance of handling images is complete. I have looked at some image manipulation libraries (ImageMagick and the free version of dotIamge) first for converting the input image to a standard one and second for resizing -resampling. The truth is that they do far more than I need.
Any pointer much appreciated.
Yes, resampling so that the bitmap doesn't constantly have to be rescaled for every paint should make a big difference. The default Graphics.InterpolationMode makes pretty images but is not cheap.
Another biggie is the pixel format of the bitmap. Format32bppPArgb is 10 times faster than any of the others on most video adapters.
private static Bitmap Resample(Image img, Size size) {
var bmp = new Bitmap(size.Width, size.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
using (var gr = Graphics.FromImage(bmp)) {
gr.DrawImage(img, new Rectangle(Point.Empty, size));
}
return bmp;
}