3

I have a PNG with transparency that loses a lot of quality when I convert it to ImageSource. What I do to convert it is the following:

public static ImageSource ToImageSource()
    {   Bitmap bitmap = Properties.Resources.Image;
        IntPtr hBitmap = bitmap.GetHbitmap();

        ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(
            hBitmap,
            IntPtr.Zero,
            Int32Rect.Empty,
            BitmapSizeOptions.FromEmptyOptions());
        RenderOptions.SetBitmapScalingMode(wpfBitmap, BitmapScalingMode.HighQuality);

        return wpfBitmap;
    }

But the quality is really bad. when I call directly to the file on my computer the quality is correct:

<DataGridTemplateColumn Width="14" IsReadOnly="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="C:\Users\MyUser\Desktop\Image.png" Width="14" Height="14"></Image>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

Is there another way to transform the resource without losing quality and transparency?

Aragorn
  • 39
  • 3
  • 5
    "BitmapScalingMode.LowQuality" This bit wasn't a clue? – Steve Todd Jun 21 '19 at 09:59
  • 1
    @SteveTodd sorry, It was a test to see if something changed. I have already modified the question – Aragorn Jun 21 '19 at 10:10
  • Is ImageSource your fixed output type? or is it flexible? – Gowshik Jun 21 '19 at 10:18
  • @Gowshik I need to show the png in my WPF window (and the image is sent from another project in the solution). If there is another option I do not mind modifying the type. – Aragorn Jun 21 '19 at 10:23
  • Note that WPF's unit system is device independent, with the unit being equivalent to 1/96 inch. Thus, `` will display the image the scaled to a width and height of 14/96 inch (assuming your display device correctly reports its DPI settings). You can disable this scaling behavior by setting the Image control property `Stretch` accordingly. Also note that the Image control might not necessarily align the bitmap pixels with the display pixel grid, possibly causing some blur. (1/2) –  Jun 21 '19 at 10:40
  • (2/2) To enforce pixel-aligned rendering for your bitmap, set the `SnapsToDevicePixels` property of the Image control to `true`. If none of my suggestions here helps, please edit your question and add links to both your original PNG and a (lossless, preferably no JPG) screenshot of how the image is being rendered in your UI. –  Jun 21 '19 at 10:44
  • @elgonzo with `` keeps happening – Aragorn Jun 21 '19 at 11:40
  • Throw away the entire conversion code. Instead, load the image directly from an assembly resource file, as e.g. shown here: https://stackoverflow.com/a/25714375/1136211 or here: https://stackoverflow.com/a/15008178/1136211 – Clemens Jun 21 '19 at 14:32

3 Answers3

0

Sadly i can not test your code but i think you have to set the Mode to NearestNeighbor

Try this

public static ImageSource ToImageSource()
{   
   Bitmap bitmap = Properties.Resources.Image;
   IntPtr hBitmap = bitmap.GetHbitmap();

   ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(
       hBitmap,
       IntPtr.Zero,
       Int32Rect.Empty,
       BitmapSizeOptions.FromEmptyOptions());
   RenderOptions.SetBitmapScalingMode(wpfBitmap, BitmapScalingMode.NearestNeighbor);

   return wpfBitmap;
}

Zer0
  • 1,146
  • 6
  • 15
0

Or... try this :)

public static ImageSource ToImageSource()
{
     Bitmap bitmap = Properties.Resources.Image;
     IntPtr hBitmap = bitmap.GetHbitmap();

     ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(
                        hBitmap,
                        IntPtr.Zero,
                        new Int32Rect(0, 0, bitmap.Width, bitmap.Height),
                        BitmapSizeOptions.FromEmptyOptions());

      DeleteObject(hBitmap);
      return wpfBitmap;
}

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);

Calling DeleteObject will release the GDI handle.

TonyMkenu
  • 7,597
  • 3
  • 27
  • 49
-1

Try This:

BitmapImage image = new BitmapImage(new Uri("your image path here", UriKind.Relative));

Edit: Assuming you have the image path.

Gowshik
  • 320
  • 4
  • 13