Image loss when compressing certain images using Graphics.DrawImage ()

Possible duplicate:
How can I get the best image compression results?

I am trying to create a 200 x 200px thumbnail using the following code. It works great for certain images, but not for others. When this does not work, a thumbnail is created with this size, but only a partial image is visible, and the other part is gray (for example, you used a gray brush and smeared it on top of the thumbnail). I could not see the trend when it fails. For example, it is not suitable for JPEG images with a size of 400px x 400px. If I try to create a sketch with a size of 150px x 150px, there is no image loss. If this helps here - this is one image that causes problems - http://s11.postimage.org/sse5zhpqr/Drawing_8.jpg

Rate 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 another analysis, and it seems that the problem is saving the thumbnail in the SQL Server database in the varbinary column. I am using a MemoryStream for this as shown below. If I save it to disk, it looks 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 has been resolved. The problem was the NHibernate mapping that I used for the varbinary column. I had to specify the type as "BinaryBlob" to make sure that there is no silent data truncation> 8KB.

+4
source share
1 answer

I appreciate it should be a comment, not an answer, but for additional formatting I am sending as an answer.

Here is the code I used to compress the image and I never had this problem:

 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[])); } 

Of course, I return byte[] , not a Bitmap , as I then store it in the database.

The only differences that I really see is to create an instance of my Bitmap result with height and width, I don't have a FillRectangle method FillRectangle , and I don't set PixelOffsetMode . I also start with Image instead of Bitmap

Hope this helps you.

+2
source

Source: https://habr.com/ru/post/1442109/


All Articles