0

I'm facing an issue (ghost border) when an image is resized on the live server, but not on localhost. This is really weird. I did some research on web and found similar solutions:

  1. https://mariusschulz.com/blog/preventing-ghost-borders-when-resizing-images-with-system-drawing
  2. https://www.codeproject.com/Articles/11143/Image-Resizing-outperform-GDI
  3. Ghost-borders ('ringing') when resizing in GDI+

Below is the code that I'm using, inside I have commented old code and new code.

protected byte[] ApplyResize(byte[] byteArray, int targetSize, Size originalSize = default(Size))
{
    using (MemoryStream ms = new MemoryStream(byteArray))
    {
        if (targetSize <= 0)
        {
            targetSize = 800;
        }

        var image = Image.FromStream(ms);
        var size = default(Size);
        if (originalSize != default(Size))
        {
            size = CalculateDimensions(originalSize, targetSize);
        }
        else
        {
            size = new Size(targetSize, targetSize);
        }

        var resized = new Bitmap(size.Width, size.Height);
        using (var graphics = Graphics.FromImage(resized))
        {
            //old code
            //graphics.CompositingQuality = CompositingQuality.HighSpeed;
            //graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            //graphics.CompositingMode = CompositingMode.SourceCopy;
            //graphics.DrawImage(image, 0, 0, size.Width, size.Height);

            //new code
            graphics.CompositingQuality = CompositingQuality.HighSpeed;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.CompositingMode = CompositingMode.SourceCopy;
            var attributes = new ImageAttributes();
            attributes.SetWrapMode(WrapMode.TileFlipXY);
            var destination = new Rectangle(0, 0, size.Width, size.Height);
            graphics.DrawImage(image, destination, 0, 0, size.Width, size.Height, GraphicsUnit.Pixel, attributes);
        }
        using (var ms2 = new MemoryStream())
        {
            resized.Save(ms2, image.RawFormat);
            return ms2.ToArray();
        }
    }
}

I tested on the live server, yes, the ghost border is gone, but the image has gotten a wrong position.

This image is the expected result after resize, all clear, no problem

This is what happens on localhost and live server, when using the new code, image gets cut with weird position

Palle Due
  • 5,929
  • 4
  • 17
  • 32
FeelRightz
  • 2,777
  • 2
  • 38
  • 73
  • [Image is not drawn at the correct spot](https://stackoverflow.com/a/51456467/7444103) – Jimi Dec 11 '19 at 14:13
  • @Jimi the below answer is similar as you link, but i tried, still the same, i suspect it is the DrawImage destination issue, because the old code DrawImage without destination are the clear result, but i not familiar with the Rectangle or DrawImage – FeelRightz Dec 11 '19 at 14:25
  • That is one possible issue. One you absolutely need to take care of. I preferred to leave to the answer you already have the solution, but, since you're asking: your `graphics.DrawImage()` method is completely wrong. You only consider the newly calculated Size (procedure that, here, produces unknown results), the original size is dismissed. See the Docs about the `DrawImage` overload you're using. – Jimi Dec 11 '19 at 14:35
  • Side note: `var image = Image.FromStream(ms)` should also be in a `using` block. Same for the `resized` bitmap later in the code. – Nyerguds Dec 17 '19 at 12:58

2 Answers2

0

To me it looks like the DPI (resolution) of the resized image is different than the real image. This would make sense, as the resolution of the new bitmap is dependent of the resolution of the display. And your server might not really have a display...

To make sure you get the expected results you should call setResolution on it with the resolution of the original image, right after creating the new image and before drawing to it, like this:

var resized = new Bitmap(size.Width, size.Height);
resized.SetResolution(image.HorizontalResolution, image.VerticalResolution);

This should be a good fix in general, as you might also get issues when running locally with image with have a different DPI than the one you are testing with.

On top of that, as was mentioned above, you should change the call to DrawImage to the following, as you forgot to specify the source rectangle:

graphics.DrawImage(image, destination, 0, 0, originalSize.Width, originalSize.Height, GraphicsUnit.Pixel, attributes);

Additionally you might need to explain what CalculateDimensions does, as this might produce something which is wrong and as is not visible here we can only guess.

Robin Krom
  • 180
  • 8
  • This may sound dumb, but, What if you do the reverse? Set the resolution of `image` to that if the newly created `resized` bitmap? – Nyerguds Dec 17 '19 at 12:57
0

I solve my issue by using using (ImageAttributes wrapMode = new ImageAttributes()) inside and upload image size must more than 415x415 , not sure why, but upload lower than 415x415 border will still appear and draw in correct position

protected byte[] ApplyResize(byte[] byteArray, int targetSize, Size originalSize = default(Size))
{
    using (MemoryStream ms = new MemoryStream(byteArray))
    {
        if (targetSize <= 0)
        {
            targetSize = 800;
        }

        var image = Image.FromStream(ms);
        var size = default(Size);
        if (originalSize != default(Size))
        {
            size = CalculateDimensions(originalSize, targetSize);
        }
        else
        {
            size = new Size(targetSize, targetSize);
        }

        var resized = new Bitmap(size.Width, size.Height);
        using (var graphics = Graphics.FromImage(resized))
        {
                graphics.CompositingQuality = CompositingQuality.HighSpeed;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.CompositingMode = CompositingMode.SourceCopy;
                var destination = new Rectangle(0, 0, size.Width, size.Height);
                using (ImageAttributes wrapMode = new ImageAttributes())
                {
                    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
                    graphics.DrawImage(image, destination, 0, 0, originalSize.Width, originalSize.Height, GraphicsUnit.Pixel, wrapMode);
                }
        }
        using (var ms2 = new MemoryStream())
        {
            resized.Save(ms2, image.RawFormat);
            return ms2.ToArray();
        }
    }
}
FeelRightz
  • 2,777
  • 2
  • 38
  • 73
  • I don't really understand if you now solved your issue or not. But please do not forget to dispose your images (var image = Image.FromStream & var resized = new Bitmap) with a using. – Robin Krom Jan 16 '20 at 07:19