2009-12-11 1 views
18

Что происходит (только заметное на определенных изображениях), я увижу белую рамку с 1 пикселем, которая будет вставлена ​​на один пиксель. Это происходит в областях, которые светлые, но не белые (например, небо). Это похоже на то, что что-то перечеркнуто, а призрачная граница видна рядом с высококонтрастными краями.Призрачные границы («звонок») при изменении размера в GDI +

Вот и воспроизводимый код, который воспроизводит его отлично. Я использую все настройки самого высокого качества для масштабирования.

ImageCodecInfo encoder = null; 
EncoderParameters encoderParams = null; 

foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders()) 
{ 
    if (codec.MimeType == "image/jpeg") 
    { 
     encoder = codec; 

     // use highest quality compression settings 
     encoderParams = new EncoderParameters(1); 
     encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 
     break; 
    } 
} 

using (Bitmap input = (Bitmap)Bitmap.FromFile(inputPath, true)) 
{ 
    // shrink by multiple of 2 
    Rectangle rect = new Rectangle(0, 0, input.Width/32, input.Height/32); 

    using (Bitmap output = new Bitmap(rect.Width, rect.Height)) 
    { 
     using (Graphics g = Graphics.FromImage(output)) 
     { 
      // use highest quality settings (updated per Mark Ransom's answer) 
      g.CompositingMode = CompositingMode.SourceCopy; 
      g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      g.PixelOffsetMode = PixelOffsetMode.HighQuality; 
      g.SmoothingMode = SmoothingMode.HighQuality; 

      g.DrawImage(input, rect); 
     } 

     output.Save(outputPath, encoder, encoderParams); 
    } 
} 

Любые идеи? Я полностью сбит с толку. Я прочитал тонну вопросов/ответов, и ни один из них, похоже, не повлиял на мою ситуацию.


Edit:

Это пример перед тем изображение: http://img14.imageshack.us/img14/4174/mg1647.jpg

Это пример после изображения: http://img64.imageshack.us/img64/3156/afterringing.jpg

Это более выражено с оригиналом файлов (до того, как служба хостинга «оптимизирует» их), но вы можете видеть в e небо более светлая полоса на один пиксель на меньшем изображении.

+0

Я читал ваше описание немного более тщательно, и то, что вы описываете, называется «звон». Он может появляться прямо на краю или на очень коротком расстоянии от него. Однако я не вижу ничего очевидного в вашем коде, которое могло бы вызвать его. Образцы изображений до/после могут помочь. –

+0

Да, это похоже на то, что он выполняет алгоритм заточки, который пытается посмотреть на значения пикселей за пределами края изображения.Я пытаюсь найти хорошее место для публикации изображений до/после. – mckamey

+0

Этот образец * после * изображения не показывает его так ярко, как я вижу его в своем приложении, но вы все еще можете сказать, что это неправильно. – mckamey

ответ

38

Наконец-то я нашел статью, в которой говорится об этом.

Libor Tinka случайно упоминает об этом, прежде чем переходить, чтобы показать свой обширный набор фильтров, способ опережать GDI + Масштабирование:

Из его советов, это звучит, как он делает именно то, что мы подозревали: он вытягивает усреднение деталей из окружающих пикселей за пределы изображения. Это кажется недостатком в алгоритме для меня, но это открыто для обсуждения. Чтобы решить эту проблему, существует класс ImageAttributes, в котором вы можете указать, что пиксели за пределами являются просто зеркальными изображениями пикселей внутри. Установка этого, кажется, полностью удалить звона:

using (ImageAttributes wrapMode = new ImageAttributes()) 
{ 
    wrapMode.SetWrapMode(WrapMode.TileFlipXY); 
    g.DrawImage(input, rect, 0, 0, input.Width, input.Height, GraphicsUnit.Pixel, wrapMode); 
} 

Огромное спасибо как Libor Tinka для решения, и Марк Рэнсом за помощь мне кажется, через это и дает мне термин «звона», который был, что сделал Libor Решение Tinka даже появляется в моих поисках.

+0

. Корневая причина представляется чрезмерно агрессивным фильтром при изменении размера в сочетании с неправильным маскированием пикселей по краям. Пиксели с края изображения не должны вносить свой вклад в результат, но, очевидно, это происходит, так как обертывание исправляет его. Вы все еще можете видеть звонки в темных/легких переходах, таких как линия крыши в вашем примере. –

+0

Что действительно интересно, так это то, что звон вдоль линии крыши теперь также фиксируется. Это может быть побочным эффектом добавления во все другие настройки «HighQuality», такие как «CompositingMode» и «PixelOffsetMode». Текущее состояние измененных изображений значительно улучшено. – mckamey

+0

Это сработало для меня тоже - спасибо – Graeme

3

Try:

g.CompositingMode = CompositingMode.SourceCopy; 

Из моего ответа here, скорректированной синтаксиса.

Изменение размера создает частичную прозрачность вокруг границы. Установка SourceCopy сообщает, что заменить этот частично прозрачный пиксель полностью непрозрачным.

+0

+1 Я согласен с Марком, он на самом деле избил меня. –

+2

Я думаю, вы правы в том, что воспринимаете его как частично прозрачный. Если я добавлю 'g.Clear (Color.Black);' перед тем, как я его нарисую, тогда белый будет по-прежнему, но теперь крайний пиксель потемнеет. К сожалению, установка 'g.CompositingMode = CompositingMode.SourceCopy;' избавляется от любого кровотока сзади (например, темная рамка), но у него все еще есть белая рамка с 1 пикселем. – mckamey

+0

Я не вижу места, где вы определяете «качество», вы уверены, что используете сжатие JPEG высокого качества? –

 Смежные вопросы

  • Нет связанных вопросов^_^