I'm trying to build an image viewer for 16-bit PNG images with WPF. My idea was to load the images with PngBitmapDecoder
, then put them into an Image
control, and control the brightness/contrast with a pixel shader.
However, I noticed that the input to the pixel shader seems to be converted to 8 bit already. Is that a known limitation of WPF or did I make a mistake somewhere? (I checked that with a black/white gradient image that I created in Photoshop and which is verified as 16-bit image)
Here's the code to load the image (to make sure that I load with the full 16-bit range, just writing Source="test.png" in the Image control loads it as 8-bit)
BitmapSource bitmap;
using (Stream s = File.OpenRead("test.png"))
{
PngBitmapDecoder decoder = new PngBitmapDecoder(s,BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
bitmap = decoder.Frames[0];
}
if (bitmap.Format != PixelFormats.Rgba64)
MessageBox.Show("Pixel format " + bitmap.Format + " is not supported. ");
bitmap.Freeze();
image.Source = bitmap;
I created the pixel shader with the great Shazzam shader effect tool.
sampler2D implicitInput : register(s0);
float MinValue : register(c0);
float MaxValue : register(c1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(implicitInput, uv);
float t = 1.0f / (MaxValue-MinValue);
float4 result;
result.r = (color.r - MinValue) * t;
result.g = (color.g - MinValue) * t;
result.b = (color.b - MinValue) * t;
result.a = color.a;
return result;
}
And integrated the shader into XAML like this:
<Image Name="image" Stretch="Uniform">
<Image.Effect>
<shaders:AutoGenShaderEffect x:Name="MinMaxShader" Minvalue="0.0" Maxvalue="1.0>
</shaders:AutoGenShaderEffect>
</Image.Effect>
</Image>
I just got a response from Microsoft. It's really a limitation in the WPF rendering system. I'll try D3DImage
as a workaround.