Раньше, когда я использовал win32, я использовал FreeImage для загрузки и сохранения растровых изображений с глубиной бит более 8 бит, С каждым изображением, с которым я работаю, поскольку я занимаюсь медицинской визуализацией, и прежде чем кто-нибудь что-нибудь скажет, да, я и мои клиенты потратили много денег на высокояркие высококонтрастные мониторы с 11 или 12 битами динамического диапазона, На самом деле, если вам интересно, требования ACR для запуска маммографии включают монитор с не менее чем 10 битами динамического диапазона.
Я только что перешел на x64 для накладных расходов на память и получил всю свою разработку на одной платформе и в режиме компиляции. Я бы предпочел не возвращаться к win32, и мои клиенты там со мной (и действительно вынуждают изменения). FreeImage не компилируется на 64-битных окнах; он имеет директиву _asm в коде, который компилятор просто не может обработать.
Я думал, что попробую собственную поддержку .NET в классах Microsoft. Короче говоря: они не работают и терпят неудачу с очень ограниченными сообщениями об ошибках. Я подозреваю, что Microsoft по-прежнему не поддерживает класс Format16bppGrayScale.
Может быть, проблема в моем коде. Здесь мой код для написания:
Bitmap theBitmap = new Bitmap(inImage.XSize, inImage.YSize, PixelFormat.Format16bppGrayScale);
//have to go with lockbits
Rectangle rect = new Rectangle(0, 0, theBitmap.Width, theBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData =
theBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
PixelFormat.Format16bppGrayScale);
IntPtr ptr = bmpData.Scan0;
int theByteSize = theBitmap.Width * theBitmap.Height *2;
byte[] theByteBuffer = new byte[theByteSize];
System.Buffer.BlockCopy(inImage.Data, 0, theByteBuffer, 0, theByteSize);
System.Runtime.InteropServices.Marshal.Copy(theByteBuffer, 0, ptr, theByteSize);
theBitmap.UnlockBits(bmpData);
theBitmap.Save(inDirectory + "\\" + inName);
theBitmap.Dispose();
Этот код сбрасывает программу с помощью
An unhandled exception of type
'System.Runtime.InteropServices.ExternalException' occurred in
System.Drawing.dll
Additional information: A generic error occurred in GDI+.
Интересно, тем более, что я никогда не хочу нарисовать это изображение на экране, как это (хотя было бы неплохо!), но просто хочу использовать функции сохранения/загрузки. Изображение записывается на диск (даже при сбое программы), а следующий код чтения также выдает сообщение о сбое программы:
Bitmap theBitmap = new Bitmap(theCompleteName, false);
ushort[] theData = new ushort[theBitmap.Width * theBitmap.Height];
int x, y;
switch (theBitmap.PixelFormat)
{
case PixelFormat.Format16bppGrayScale:
//have to go with lockbits
{
Rectangle rect = new Rectangle(0, 0, theBitmap.Width, theBitmap.Height);
System.Drawing.Imaging.BitmapData bmpData =
theBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
PixelFormat.Format16bppGrayScale);
IntPtr ptr = bmpData.Scan0;//scanline approach left over from FreeImage
for (y = 0; y < theBitmap.Height; ++y){
byte[] scanline = new byte[theBitmap.Width*2];
System.Runtime.InteropServices.Marshal.Copy(ptr, scanline, y * theBitmap.Width * 2, theBitmap.Width * 2);
System.Buffer.BlockCopy(scanline, 0, theData, y * theBitmap.Width * 2, theBitmap.Width * 2);
}
theBitmap.UnlockBits(bmpData);
}
break;
//for colors, just take the red and call it a day
case PixelFormat.Format24bppRgb:
case PixelFormat.Format32bppArgb://really stupid reading code, always works
for (y = 0; y < theBitmap.Height; ++y) {
for (x = 0; x < theBitmap.Width; ++x) {
theData[y * theBitmap.Width + x] = (byte)(theBitmap.GetPixel(x, y).R);
}
}
break;
}
theNewImage = new ImageContainer(theData, theBitmap.Width, theBitmap.Height, inName, inAssessmentID);
theBitmap.Dispose();//not needed, anymore
Этот код приводит к сбою программы с ошибкой:
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Additional information: Parameter is not valid.
Эти результаты говорят мне, что Microsoft все еще не зафиксировала часть Format16bppGrayScale в перечислении PixelFormat. Это позор.
Итак, что я могу использовать для загрузки и сохранения 16-битных изображений в оттенках серого на x64 с .NET?
(EDIT: я должен добавить, что, хотя я могу сэкономить изображения DICOM, мне нужно запустить эксперименты с данными, отличными от пациента, для проверки правильности алгоритмов и т.д. DICOM требует набора UID и других обязательных полей которые являются излишними для того, что мне нужно, мне просто нужны изображения, а не данные пациентов).