Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitmap with Nearest Neighbor Causes Tearing

Tags:

c#

bitmap

wpf

I've created a test application that generates a Code 39 barcode. The problem is that when I display the barcode on screen, it either blurs or gets torn. If I use any BitmapScalingMode other than NearestNeighbor, I get the blurred barcode. When I use NearestNeighbor, I get the diagonal slash as shown below. The diagonal only occurs when I resize the window. (It stays there if I stop in the right spot.) The image itself does not change size, but instead moves across the screen as I resize the window.

I've tried using RenderOptions.EdgeMode="Aliased" as well, but it doesn't seem to have any effect...

Torn / Blurred / Correct

Torn BarcodeBlurred BarcodeCorrect Barcode

WPF Sample Code:

<Border BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,50,0,0">
    <Image x:Name="imgBarcode" Stretch="Fill" RenderOptions.BitmapScalingMode="HighQuality" RenderOptions.EdgeMode="Aliased" />
</Border>

Image generation:

imgBarcode.Source = loadBitmap(c.Generate(barcodeText.Text));
imgBarcode.Width = c.GetWidth();
imgBarcode.Height = c.GetHeight();

Sample generation code:

Bitmap bmp = new Bitmap(width, height);
using (Graphics gfx = Graphics.FromImage(bmp))
using (SolidBrush black = new SolidBrush(Color.Black))
using (SolidBrush white = new SolidBrush(Color.White))
{
    // Start the barcode:
    addBar(gfx, black, white, '*');

    foreach (char c in barcode)
    {
        addCharacter(gfx, black, white, c);
    }

    // End the barcode:
    addBar(gfx, black, white, '*');
}

Sample rectangle addition:

g.FillRectangle(white, left, top, narrow, height);
left += narrow;

Load Bitmap taken from another StackOverflow question:

[DllImport("gdi32")]
static extern int DeleteObject(IntPtr o);

public static BitmapSource loadBitmap(System.Drawing.Bitmap source)
{
    IntPtr ip = source.GetHbitmap();
    BitmapSource bs = null;
    try
    {
        bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip,
           IntPtr.Zero, Int32Rect.Empty,
           System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
    }
    finally
    {
        DeleteObject(ip);
    }

    return bs;
}
like image 906
teynon Avatar asked Jan 31 '14 14:01

teynon


1 Answers

Setting UseLayoutRounding="True" on your main window should solve this issue.

like image 152
Adi Lester Avatar answered Oct 22 '22 05:10

Adi Lester