.NET - Border around resized imaged
Asked Answered
H

3

5

I'm trying to resize an image in .NET, but get a faint black border around the resized image. I found a post - http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/cf765094-c8c1-4991-a1f3-cecdbd07ee15/ which from someone who said making the destination rectangle larger than the canvas worked, but this doesn't work for me. It gets riid of the top and left borders, but the right and bottom are still there, and are a full 1px thick black.

Am I missing something? My code is below.

Image image = ... // this is a valid image loaded from the source
Rectangle srcRectangle = new Rectangle(0,0,width, height);
        Size croppedFullSize = new Size(width+3,height+3);
        Rectangle destRect = new Rectangle(new Point(-1,-1), croppedFullSize);
        using(Bitmap newImage = new Bitmap(croppedFullSize.Width, croppedFullSize.Height, format))
        using(Graphics Canvas = Graphics.FromImage(newImage)) {
            Canvas.SmoothingMode = SmoothingMode.AntiAlias;
            Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
            Canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
            Canvas.FillRectangle(Brushes.Transparent, destRect);
            Canvas.DrawImage(image, destRect, srcRectangle, GraphicsUnit.Pixel);


            newImage.Save(filename, image.RawFormat);
        }
Haematosis answered 27/3, 2011 at 21:3 Comment(0)
D
3

Try it like this, i think i've never got a black border...

If you want to use System.Drawing libraries:

using (var sourceBmp = new Bitmap(sourcePath))
{
  decimal aspect = (decimal)sourceBmp.Width / (decimal)sourceBmp.Height;
  int newHeight = (int)(newWidth / aspect);

   using (var destinationBmp = new Bitmap(newWidth, newHeight))
   {
     using (var destinationGfx = Graphics.FromImage(destinationBmp))
     {
       destinationGfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
       destinationGfx.DrawImage(sourceBmp, new Rectangle(0, 0, destinationBmp.Width, destinationBmp.Height));
       destinationBmp.Save(destinationPath, ImageFormat.Jpeg);
      }
    }
}

or you can do the same with wpf, like this:

using (var output = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
{
   var imageDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
   var imageFrame = imageDecoder.Frames[0];

   decimal aspect = (decimal)imageFrame.Width / (decimal)imageFrame.Height;
   var height = (int)(newWidth / aspect);

   var imageResized = new TransformedBitmap(imageFrame,new ScaleTransform(
                                                                 newWidth / imageFrame.Width * Dpi / imageFrame.DpiX,
                                                                 height / imageFrame.Height * Dpi / imageFrame.DpiY, 0, 0));

   var targetFrame = BitmapFrame.Create(imageResized);

   var targetEncoder = new JpegBitmapEncoder();
   targetEncoder.Frames.Add(targetFrame);
   targetEncoder.QualityLevel = 80;
   targetEncoder.Save(output);
}

I recommend the WPF way. The compression & quality seems better...

Doc answered 28/3, 2011 at 0:29 Comment(1)
I read through the code, and the first version is identical to what I have now (doesn't work). The second method, however, does work. It feels a bit dirty adding references to PresentationCore and System.Xaml to an ASP.NET project, but it works so why not...Haematosis
P
13

Simply provide the DrawImage method with an ImageAttributes instance which has WrapMode set to TileFlipXY. This will prevent the edge from blending against the background color.

For sample code that doesn't leak memory like the other answers here, see this gist

Premiere answered 7/8, 2012 at 17:20 Comment(2)
Hurrah! I only had to take one line from your code, and I've solved my ugly border issue, thanks! g.PixelOffsetMode = PixelOffsetMode.HighQuality;Shaffer
TileFlipXY is actually what solves it completely, there are 2 potential causes for the issue. Have you tried resizing a gray image and putting it against the same color background?Premiere
D
3

Try it like this, i think i've never got a black border...

If you want to use System.Drawing libraries:

using (var sourceBmp = new Bitmap(sourcePath))
{
  decimal aspect = (decimal)sourceBmp.Width / (decimal)sourceBmp.Height;
  int newHeight = (int)(newWidth / aspect);

   using (var destinationBmp = new Bitmap(newWidth, newHeight))
   {
     using (var destinationGfx = Graphics.FromImage(destinationBmp))
     {
       destinationGfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
       destinationGfx.DrawImage(sourceBmp, new Rectangle(0, 0, destinationBmp.Width, destinationBmp.Height));
       destinationBmp.Save(destinationPath, ImageFormat.Jpeg);
      }
    }
}

or you can do the same with wpf, like this:

using (var output = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
{
   var imageDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
   var imageFrame = imageDecoder.Frames[0];

   decimal aspect = (decimal)imageFrame.Width / (decimal)imageFrame.Height;
   var height = (int)(newWidth / aspect);

   var imageResized = new TransformedBitmap(imageFrame,new ScaleTransform(
                                                                 newWidth / imageFrame.Width * Dpi / imageFrame.DpiX,
                                                                 height / imageFrame.Height * Dpi / imageFrame.DpiY, 0, 0));

   var targetFrame = BitmapFrame.Create(imageResized);

   var targetEncoder = new JpegBitmapEncoder();
   targetEncoder.Frames.Add(targetFrame);
   targetEncoder.QualityLevel = 80;
   targetEncoder.Save(output);
}

I recommend the WPF way. The compression & quality seems better...

Doc answered 28/3, 2011 at 0:29 Comment(1)
I read through the code, and the first version is identical to what I have now (doesn't work). The second method, however, does work. It feels a bit dirty adding references to PresentationCore and System.Xaml to an ASP.NET project, but it works so why not...Haematosis
B
3

For me it was a bad Bitmap parameter. Instead of this:

new Bitmap(width, height, PixelFormat.Format32bppPArgb);

Just remove the PixelFormat to this:

new Bitmap(width, height);

And everything was ok then.

With the PixelFormat I had black border on the top and left border. Then I tried g.PixelOffsetMode = PixelOffsetMode.HighQuality; which seemed fine at first. But then I noticed light gray borders around the whole image.

Biped answered 13/2, 2017 at 20:36 Comment(1)
this is working fine for me , very easy method only remove this PixelFormat.Format32bppPArgbTwoway

© 2022 - 2024 — McMap. All rights reserved.