2009-12-11 7 views
18

Was passiert (nur auf bestimmten Bildern bemerkbar) ist, ich sehe eine 1 Pixel weiße Grenze, die ein Pixel eingefügt ist. Es scheint in Bereichen zu passieren, die hell sind, aber nicht weiß (z. B. der Himmel). Es ist ähnlich, wenn etwas übermäßig scharf ist und eine Geistergrenze neben kontrastreichen Kanten zu sehen ist.Ghost-Grenzen ('Klingeln') beim Ändern der Größe in GDI +

Hier ist der Reprocode, der es perfekt reproduziert. Ich verwende die höchsten Qualitätseinstellungen für die Skalierung.

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

Irgendwelche Ideen? Ich bin völlig verwirrt. Ich habe eine Menge Fragen/Antworten gelesen und keiner von ihnen scheint meine Situation zu beeinflussen.


bearbeiten:

Dies ist ein Beispiel vor Bild: http://img14.imageshack.us/img14/4174/mg1647.jpg

Dies ist ein Beispiel nach Bild: http://img64.imageshack.us/img64/3156/afterringing.jpg

Es ist ausgeprägter mit dem Original Dateien (bevor der Hosting-Service sie "optimiert"), aber Sie können in th sehen e Himmel ein helleres Band ein Pixel auf dem kleineren Bild.

+0

Ich habe Ihre Beschreibung ein wenig genauer gelesen, und was Sie beschreiben, heißt "Klingeln". Es kann sich direkt am Rand oder in sehr kurzer Entfernung von ihm zeigen. Ich kann jedoch nichts Offensichtliches in deinem Code sehen, das dies verursachen würde. Beispielbilder Vorher/Nachher könnten helfen. –

+0

Ja, es ist so, als würde es einen Schärfungsalgorithmus machen, der versucht, die Werte von Pixeln über den Rand des Bildes hinaus zu betrachten.Ich versuche, einen guten Platz zu finden, um die Vorher-Nachher-Bilder zu posten. – mckamey

+0

Das Beispiel * nach * Bild zeigt es nicht ganz so ausgeprägt, wie ich es in meiner Anwendung sehe, aber Sie können immer noch sagen, dass es nicht richtig ist. – mckamey

Antwort

38

Endlich habe ich einen Artikel gefunden, der darüber spricht.

Libor Tinka erwähnt beiläufig dies, bevor er auf seine umfangreiche Reihe von Filtern zu zeigen, welche Art und Weise outperform GDI + Skalierung:

Von seinem Rat, es klingt wie es genau das tut, was wir haben vermutet: Es zieht Mittelung Detail von umgebenden Pixeln über den Rand des Bildes hinaus. Das scheint mir ein Fehler im Algorithmus zu sein, aber das ist offen für Diskussionen. Um dies zu lösen, gibt es eine ImageAttributes-Klasse, in der Sie angeben können, dass die Pixel dahinter einfach Spiegelbilder der darin enthaltenen Pixel sind. Wenn Sie diese Option scheint das Klingeln vollständig zu entfernen:

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

Vielen Dank an beide Libor Tinka für die Lösung, und Mark Ransom zu helfen, denken Sie mich dies durch und für die mir den Begriff „Klingeln“, das war es, was Libor Tinkas Lösung zeigt sich sogar in meinen Recherchen.

+0

Die Ursache scheint ein zu aggressiver Filter in der Größenanpassung zu sein, gepaart mit unpassender Pixelmaskierung an den Kanten. Pixel am Rand des Bildes sollten nicht zum Ergebnis beitragen, aber offensichtlich sind sie seit dem Einbetten behoben. In dunklen/hellen Übergängen, wie z. B. der Dachlinie in Ihrem Beispiel, können Sie immer noch klingeln. –

+0

Interessant ist, dass das Klingeln entlang der Dachlinie nun ebenfalls behoben zu sein scheint. Es kann ein Nebeneffekt sein, alle anderen 'HighQuality'-Einstellungen wie' CompositingMode' und 'PixelOffsetMode' hinzuzufügen. Der aktuelle Zustand der skalierten Bilder ist stark verbessert. – mckamey

+0

Das funktionierte auch für mich - danke – Graeme

3

Versuchen:

g.CompositingMode = CompositingMode.SourceCopy; 

Aus meiner Antwort here, für Syntax korrigiert.

Die Größenanpassung erzeugt teilweise Transparenz an der Grenze. Die Einstellung SourceCopy weist darauf hin, dass das teilweise transparente Pixel durch ein vollständig undurchsichtiges ersetzt werden soll.

+0

+1 Ich stimme Mark zu, er hat mich tatsächlich geschlagen. –

+2

Ich denke, Sie haben Recht damit, dass es als teilweise transparent behandelt wird. Wenn ich 'g.Clear (Color.Black);' hinzufüge, bevor ich es zeichne, dann ist das Weiß immer noch da, aber jetzt ist das Randpixel dunkel. Leider wird durch das Setzen von 'g.CompositingMode = CompositingMode.SourceCopy;' jegliches Durchlaufen von hinten (z. B. die dunkle Umrandung) beseitigt, aber es hat immer noch den 1 Pixel großen weißen Rand. – mckamey

+0

Ich sehe nirgendwo, wo Sie "Qualität" definieren, sind Sie sicher, dass Sie JPEG-Komprimierung höchster Qualität verwenden? –

Verwandte Themen