I'm resizing jpeg 1200x900 ,556kb by method:
public static Image ResizeImage(Image imgToResize, int height) //height=400
{
int destWidth;
int destHeight;
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentH = 0;
nPercentH = ((float)height / (float)sourceHeight);
nPercent = nPercentH;
destWidth = (int)(sourceWidth * nPercent);
destHeight = height;
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return b;
}
SavingÅ
Image image = Image.FromStream(new FileStream(path, FileMode.Open));
Image imageAfterResizing =ResizeImage(image,400);
imageAfterResizing.Save(#"c:\myPhoto.jpg");
gives me 555kb 533x400 jpeg.
Why this photo is so heavy.
For photo jpeg 2111kb 2156x1571
I get 556kb 533x400 jpeg
Why in first case is so terrible !
http://img6.imageshack.us/img6/1127/photo1nz.jpg
http://img248.imageshack.us/img248/8063/photo2y.jpg
Looks like you aren't specifying the save format, it's likely coming out the other end as a bitmap.
Specify the format during the save: img.Save("C:\\foo.jpg", ImageFormat.Jpeg);
The compression of the JPEG image is decided when you save it, which is not included in the code that you show.
The default level of compression is pretty low, so you can set it to compress the image a bit more when you save it.
I think you'll find that in both cases you've converted larger jpegs into bitmap images.
Both bitmaps are 533x400 pixels and both have roughly the same file size 556kb.
If you want to resize the file size, you'll need to use a different format than a bitmap image.
Are you sure it is an JPEG, not some other file format with a JPEG file extension?
Set the JPEG quality lower.
Related
I am Resizing a Image and add watermark to image. And Return the image. Here is my code.
Image resizedImage = ResizeImage(original6, new Size(500, 375));
Re size function:
public static System.Drawing.Image ResizeImage(System.Drawing.Image image, Size size)
{
int newWidth;
int newHeight;
if (true)
{
int originalWidth = image.Width;
int originalHeight = image.Height;
float percentWidth = (float)size.Width / (float)originalWidth;
float percentHeight = (float)size.Height / (float)originalHeight;
float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
newWidth = (int)(originalWidth * percent);
newHeight = (int)(originalHeight * percent);
}
else
{
newWidth = size.Width;
newHeight = size.Height;
}
System.Drawing.Image newImage = new Bitmap(newWidth, newHeight);
using (Graphics graphicsHandle = Graphics.FromImage(newImage))
{
graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
}
System.Drawing.Bitmap bitmapimage = new System.Drawing.Bitmap(newImage, size.Width, size.Height);// create bitmap with same size of Actual image
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmapimage);
SolidBrush brush = new SolidBrush(Color.FromArgb(113, 255, 255, 255));
//Adding watermark text on image
g.DrawString("My watermark", new Font("Arial", 16, FontStyle.Bold), brush, 5, 100);
return bitmapimage;
}
I am retrieve the new re sized image with watermark and going to save as new image file.
resized6.Save(Server.MapPath(sSavePath + ownerRef + "Pic6v2" + ".jpg"));
This is working fine. However I can't control the file size.
When my original JPG is only 45kb but when my new re-sized image is 500kb. How can I reduce the file size.?
info: original resolution (400x300 px) and new image (500x375px)
I don't remember this off the top of my head, but file size generally has to do with JPEG quality settings. You also need to make sure it's saved as an actual jpg, not a bitmap, which I don't see that you're doing..
See also: C# Simple Image Resize : File Size Not Shrinking
JPEG Quality settings:
http://msdn.microsoft.com/en-us/library/bb882583.aspx
You may be able to change the quality of the JPEG to get a smaller file size. See
http://msdn.microsoft.com/en-us/library/bb882583.aspx
also
Quality of a saved JPG in C#
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I get better results when shrinking an image
I am trying to generate a thumbnail of size 200 x 200px using the code below. It works fine for certain images but does not for others. When it does not work, the thumbnail is generated with that size but only partial image is seen and the other part is gray (like you have used a gray brush and smeared on top of the thumbnail). I haven't been able to see a trend when it fails. For example, it fails for a JPEG image with 400px x 400px size. If I try to generate the thumbnail with size 150px x 150px, there is no image loss.
If this helps here is one image that causes problems - http://s11.postimage.org/sse5zhpqr/Drawing_8.jpg
Appreciate your time.
public Bitmap GenerateThumbnail(Bitmap sourceBitmap, int thumbnailWidth, int thumbnailHeight)
{
Bitmap thumbnailBitmap = null;
decimal ratio;
int newWidth = 0;
int newHeight = 0;
// If the image is smaller than the requested thumbnail size just return it
if (sourceBitmap.Width < thumbnailWidth &&
sourceBitmap.Height < thumbnailHeight)
{
newWidth = sourceBitmap.Width;
newHeight = sourceBitmap.Height;
}
else if (sourceBitmap.Width > sourceBitmap.Height)
{
ratio = (decimal)thumbnailWidth / sourceBitmap.Width;
newWidth = thumbnailWidth;
decimal tempDecimalHeight = sourceBitmap.Height * ratio;
newHeight = (int)tempDecimalHeight;
}
else
{
ratio = (decimal)thumbnailHeight / sourceBitmap.Height;
newHeight = thumbnailHeight;
decimal tempDecimalHeight = sourceBitmap.Width * ratio;
newWidth = (int)tempDecimalHeight;
}
thumbnailBitmap = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage(thumbnailBitmap);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
g.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
g.DrawImage(sourceBitmap, 0, 0, newWidth, newHeight);
g.Dispose();
return thumbnailBitmap;
}
Update:
I did some more analysis and it seems that the issue is while saving the thumbnail to the SQL Server database in a varbinary column. I am using a MemoryStream to do that as below. If I save it to the disk it appears just fine. Here is my thumbnail from the database - http://s12.postimage.org/a7j50vr8d/Generated_Thumbnail.jpg
using (MemoryStream thumbnailStream = new MemoryStream())
{
thumbnailBitmap.Save(thumbnailStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return thumbnailStream.ToArray();
}
Update - This problem is resolved. The issue was NHibernate mapping that I was using for the varbinary column. I had to specify the type as "BinaryBlob" to make sure there is no silent truncation of data > 8KB.
I appreciate, this should probably be a comment and not an answer, but for the extra formatting I'm posting as an answer.
Here's the code I've used to shrink an image and I've never had this issue:
private byte[] ResizeImage(System.Drawing.Image image, double scaleFactor)
{
//a holder for the result
int newWidth = (int)(image.Width * scaleFactor);
int newHeight = (int)(image.Height * scaleFactor);
Bitmap result = new Bitmap(newWidth, newHeight);
//use a graphics object to draw the resized image into the bitmap
using (Graphics graphics = Graphics.FromImage(result))
{
//set the resize quality modes to high quality
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//draw the image into the target bitmap
graphics.DrawImage(image, 0, 0, result.Width, result.Height);
}
//return the resulting bitmap
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(result, typeof(byte[]));
}
Granted, I return a byte[] and not a Bitmap, as I then save it to a database.
The only differences I can really see is that instantiate my result Bitmap with a height and width, I have no call to the FillRectangle method, and I do not set the PixelOffsetMode. I also start off with an Image instead of a Bitmap
Hope this helps you somehow though.
I using simple re-size method to change my bitmap to new size.
The original bitmap size is 320x240 and i change the size two times
To 250x160
Doing some process on the bitmap
Change it back to 320x240
I found out that after i change it back to 320x240 i see that the bitmap is little smooth and not as i excepted.
How can i avoid this smooth to appear ?
The Resize method:
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
The sad thing is you cannot.
When you resize your bitmap to a smaller size, information is lost. And information is interpolated from the small image (with less information) to create the new redimensionned image with the original size. It's this interpolation that gives the resulting image its smooth aspect.
To avoid this, the only thing you can do is finding a way to do the processing you have to without resizing down your image as part of your process.
Since you're using the HighQualityBicubic interpolation mode, the image will be prefiltered and resized using the highest possible quality, resulting in the "smoothing effect".
You can try setting the InterpolationMode property to NearestNeighbor to obtain a "rougher" result:
Bitmap b = new Bitmap(destWidth, destHeight);
using (Graphics g = Graphics.FromImage((Image) b)) {
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
}
I'am using this code to resize image. But result is not fine, I want to best quality. I know its low quality because I also resize same image with photoshop and result is different so better. How do I fix it?
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
This is the routine I use. Perhaps you'll find it useful. It is an extension method, to boot. The only difference is that I omit the code to preserve the aspect ratio, which you could just as easily plug in.
public static Image GetImageHiQualityResized(this Image image, int width, int height)
{
var thumb = new Bitmap(width, height);
using (var g = Graphics.FromImage(thumb))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(image, new Rectangle(0, 0, thumb.Width, thumb.Height));
return thumb;
}
}
Example usage of this extension method could include:
// Load the original image
using(var original = Image.FromFile(#"C:\myimage.jpg"))
using(var thumb = image.GetImageHiQualityResized(120, 80))
{
thumb.Save(#"C:\mythumb.png", ImageFormat.Png);
}
Notes
See http://msdn.microsoft.com/en-us/library/84767bxk.aspx for additional methods of saving and loading images.
The difference between the default JPG encoding and the default PNG encoding is, indeed, very different. Below are two thumbs using your example, one saved with ImageFormat.Png and one with ImageFormat.Jpeg.
PNG Image
JPEG Image
You may find the work done by the original poster in this question to be helpful if you determine that you absolutely must use JPEG. It involves configuring the image codec and encoding parameters to high-quality settings. .NET Saving jpeg with the same quality as it was loaded
Were it me, I'd just as soon use the PNG format, as it is lossless.
i have an image file which is of (600* 800 size) or any size . now i need to convert them into an thubnail image size which is of size ****(110*110)****
but if i reduce the size of an image i should not change the Quality of image. as once we reduce an image size the the Quality of the image is gone
is there any way without affecting the Quality of the image we can convert them into an thumbnail image[ is there any built in class for that in .net)
any help would be great
Well, about how to do it, there's a interesting material here the may help you.
About losing quality, if you mean resolution, there's no way as long as you are downsizing an image, you are throwing away spacial information that no longer can be rebuilt. Of course if you use some sort of interpolation, but it will never be the same as your original picture.
What you can do is store one version of each.
Here's the code got from the link and honestly, I think that the last 5 lines of code starting at Bitmap b = new Bitmap(destWidth, destHeight); is enough to solve your problem.
private static Image resizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercent = 0;
float nPercentW = 0;
float nPercentH = 0;
nPercentW = ((float)size.Width / (float)sourceWidth);
nPercentH = ((float)size.Height / (float)sourceHeight);
if (nPercentH < nPercentW)
nPercent = nPercentH;
else
nPercent = nPercentW;
int destWidth = (int)(sourceWidth * nPercent);
int destHeight = (int)(sourceHeight * nPercent);
Bitmap b = new Bitmap(destWidth, destHeight);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(imgToResize, 0, 0, destWidth, destHeight);
g.Dispose();
return (Image)b;
}
when you downsize an image you do not reduce it's quality, only when you try to bring it back to it's original size from the downsized version the quality will be affected.