Я хочу создать 16-битное изображение в градациях серого из значений данных в моей программе WPF. В настоящее время я смотрю на использование WriteableBitmap с набором PixelFormats.Gray16.
Однако я не могу заставить это работать, и страница 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
).
Кто-нибудь знает, как создать 16-битное изображение на пиксель или выше в градациях серого с использованием WPF? В конечном итоге это изображение также необходимо сохранить.
Любой совет очень ценится.
EDIT
В дополнение к этому я провел некоторое редактирование и теперь получаю разумное изображение, используя PixelFormat Gray16. Мне очень сложно определить, действительно ли он 16-битный, поскольку подсчет цветов программой изображения дает 256, и я не уверен, что это потому, что изображение ограничено WPF, или, возможно, программа изображения делает это. не поддерживают его, так как, очевидно, многие графические программы игнорируют младшие 8 бит. А пока я буду придерживаться того, что у меня есть.
Для информации код выглядит так:
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);
В этом примере startLine и shiftFactor уже установлены и зависят от того, с какой точки в файле данных просматривает пользователь, с shiftFactor только ненулевым в случае файла данных меньше, чем экран, и в этом случае я центрирую изображение по вертикали, используя это значение.