.NET - граница вокруг измененного размера изображения

Я пытаюсь изменить размер изображения в .NET, но получаю бледную черную рамку вокруг измененного изображения. Я нашел сообщение - http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/cf765094-c8c1-4991-a1f3-cecdbd07ee15/, который от кого-то, кто сказал, что прямоугольник назначения больше, чем холст, работал, но у меня это не работает. Он избавляется от верхней и левой границ, но правая и нижняя границы остаются на месте и представляют собой полный черный цвет толщиной 1 пиксель.

Я что-то упускаю? Мой код ниже.

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

person Echilon    schedule 27.03.2011    source источник


Ответы (3)


Попробуйте вот так, думаю, у меня никогда не было черной рамки ...

Если вы хотите использовать библиотеки System.Drawing:

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

или вы можете сделать то же самое с wpf, например:

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

Я рекомендую способ WPF. Сжатие и качество кажутся лучше ...

person CaptainPlanet    schedule 28.03.2011
comment
Я прочитал код, и первая версия идентична той, что у меня сейчас (не работает). Однако второй метод работает. Кажется немного грязным добавлять ссылки на PresentationCore и System.Xaml в проект ASP.NET, но это работает, так почему бы и нет ... - person Echilon; 28.03.2011

Просто предоставьте методу DrawImage экземпляр ImageAttributes, для которого для параметра WrapMode установлено значение TileFlipXY. Это предотвратит смешивание края с цветом фона.

Для примера кода, который не пропускает память, как другие ответы здесь, см. Эту суть

person Lilith River    schedule 07.08.2012
comment
Ура! Мне нужно было взять всего одну строчку из вашего кода, и я решил свою уродливую проблему с границами, спасибо! g.PixelOffsetMode = PixelOffsetMode.HighQuality; - person Magnus Smith; 29.05.2013
comment
TileFlipXY - это то, что на самом деле полностью решает, есть две возможные причины проблемы. Вы пробовали изменить размер серого изображения и поместить его на тот же цветовой фон? - person Lilith River; 29.05.2013

Для меня это был плохой параметр Bitmap. Вместо этого:

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

Просто удалите PixelFormat для этого:

new Bitmap(width, height);

И тогда все было нормально.

С PixelFormat у меня была черная рамка сверху и слева. Затем я попробовал g.PixelOffsetMode = PixelOffsetMode.HighQuality; что сначала казалось прекрасным. Но потом я заметил светло-серые границы вокруг всего изображения.

person Jan Matousek    schedule 13.02.2017
comment
это отлично работает для меня, очень простой способ удалить только этот PixelFormat.Format32bppPArgb - person LittleDragon; 28.09.2017