在WPF中创建16位+灰度图像

时间:2012-03-06 17:04:02

标签: c# wpf .net-4.0

我想从我的WPF程序中的数据值创建一个16位灰度图像。目前我一直在寻找使用带有PixelFormats.Gray16 set的WriteableBitmap。

但是我不能让它工作,并且Microsoft页面(http://msdn.microsoft.com/en-us/magazine/cc534995.aspx)将Gray16格式列为不能通过WriteableBitmap写入,但是不建议以这种方式制作一个人。

目前我的代码在循环中运行,其中i代表图像高度,j代表宽度,看起来像这样:

short dataValue = GetDataSamplePixelValue(myDataValue);

//the pixel to fill with this data value:
int pixelOffset = ((i * imageWidth) + j) * bytesPerPixel;

//set the pixel colour values:
pixels[pixelOffset] = dataValue;

我确实得到了这个图像,但它只是一堆垂直的黑白线条。如果仅使用8位灰度数据(在上例中short中的byte更改为myBitmap = new WriteableBitmap((int)visualRect.Width, (int)visualRect.Height, 96, 96, PixelFormats.Gray16, null); int bytesPerPixel = myBitmap.Format.BitsPerPixel / 8; ushort[] pixels = new ushort[(int)myBitmap.PixelWidth * (int)myBitmap.PixelHeight]; //if there is a shift factor, set the background colour to white: if (shiftFactor > 0) { for (int i = 0; i < pixels.Length; i++) { pixels[i] = 255; } } //the area to be drawn to: Int32Rect drawRegionRect = new Int32Rect(0, 0, (int)myBitmap.PixelWidth, (int)myBitmap.PixelHeight); //the number of samples available at this line (reduced by one so that the picked sample can't lie beyond the array): double availableSamples = myDataFile.DataSamples.Length - 1; for (int i = 0; i < numDataLinesOnDisplay; i++) { //the current line to use: int currentLine = ((numDataLinesOnDisplay - 1) - i) + startLine < 0 ? 0 : ((numDataLinesOnDisplay- 1) - i) + startLine; for (int j = 0; j < myBitmap.PixelWidth; j++) { //data sample to use: int sampleToUse = (int)(Math.Floor((availableSamples / myBitmap.PixelWidth) * j)); //get the data value: ushort dataValue = GetDataSamplePixelValue(sampleToUse); //the pixel to fill with this data value: int pixelOffset = (((i + shiftFactor) * (int)myBitmap.PixelWidth) + j); //set the pixel colour values: pixels[pixelOffset] = dataValue; } } //copy the byte array into the image: int stride = myBitmap.PixelWidth * bytesPerPixel; myBitmap.WritePixels(drawRegionRect, pixels, stride, 0); ),则没有问题。

有谁知道如何使用WPF创建每像素16位或更高的灰度图像?最终也需要保存此图像。

非常感谢任何建议。

修改

除此之外,我还做了一些编辑,现在使用Gray16 PixelFormat获得合理的图像。我很难判断它是否实际上是16位,因为图像程序的颜色计数为256,我不确定这是因为图像受到WPF的约束,或者图像程序可能不支持它,因为显然许多图像程序忽略较低的8位。现在我会坚持我所拥有的。

有关信息,代码如下:

{{1}}

在此示例中,startLine和shiftFactor已经设置,并且取决于用户正在查看的数据文件中的哪个点,在数据文件小于屏幕的情况下,shiftFactor仅为非零,在这种情况下,我使用此值垂直居中图像。

2 个答案:

答案 0 :(得分:2)

在代码中查找错误或显示完整代码

下一个示例,其中gray16图像正常工作

  var width = 300;
  var height = 300;

  var bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Gray16, null);
  var pixels = new ushort[width * height];
  for (var y = 0; y < height; ++y)
    for (var x = 0; x < width; ++x)
    {
      var v = (0x10000*2 * x/width + 0x10000 * 3 * y / height);
      var isMirror = (v / 0x10000) % 2 == 1;
      v = v % 0xFFFF;
      if (isMirror)
        v = 0xFFFF - v;

      pixels[y * width + x] = (ushort)v;
    }

  bitmap.WritePixels(new Int32Rect(0, 0, width, height), pixels, width *2, 0);

  var encoder = new PngBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bitmap));
  using (var stream = System.IO.File.Create("gray16.png"))
    encoder.Save(stream);

答案 1 :(得分:0)

作为参考,屏幕不太可能显示16位灰度图像,而且Windows不能很好地支持这种格式。例如,Windows XP甚至无法在Photo Viewer中显示16位灰度图像,虽然Windows 7+可以(我不确定Vista,我没有它)。

最重要的是,.NET open TIF方法不会加载16位灰度图像。

加载和保存16位灰度图像的解决方案,我建议TIF一般为LibTIFF。然后,您可以选择加载整个TIF,或逐行加载,以及其他方法。我建议逐行加载,因为你可以只保留屏幕上可见的数据,因为现在有些TIF变得非常大,并且不能由单个数组保存。

所以最终,不要担心在屏幕上显示16位灰度,它可能会受到系统/监视器功能的限制,而人眼无论如何都无法区分这个和8位。但是,如果需要加载或保存16位,请使用LibTIFF。