كيف يمكنني حفظ/تحميل صورة 16 بت في .NET X64؟
-
21-09-2019 - |
سؤال
من قبل ، عندما كنت أستخدم Win32 ، استخدمت الحرية من أجل تحميل وحفظ نقطات بعمق بت أكبر من 8 بت. هذه هي كل صورة أعمل معها ، لأنني أقوم بالتصوير الطبي ، وقبل أن يقول أي شخص أي شيء ، نعم ، لقد أنفقت أنا وعملائي الكثير من المال على شاشات عالية التباين مع 11 أو 12 بتات ديناميكية . في الواقع ، إذا كنت فضوليًا ، متطلبات ACR لتشغيل التصوير الشعاعي للثدي incldue شاشة مع ما لا يقل عن 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؟
(تحرير: يجب أن أضيف أنه بينما يمكنني حفظ صور DICOM ، أحتاج إلى إجراء تجارب على البيانات غير المفيدة للتحقق من أن الخوارزميات سليمة ، وهكذا دواليك. يتطلب DICOM مجموعة من UIDs وغيرها من الحقول المطلوبة التي تكون مبالغة لما أحتاجه ؛ أنا فقط بحاجة إلى صور ، وليس بيانات المريض ، في الوقت الحالي).
المحلول
الحرية تستطيع يتم تجميعها إلى X64. بعد التعليمات هنا يمكنك الالتفاف حول _asm
التوجيه. يوجد أيضًا DLL 64 بت في أسفل الصفحة.
أحدث إصدار (3.15.1) يحتوي بالفعل على هذا الإصلاح. لقد التقطت توزيع المصدر لمحاولة (أشعر بالفضول لاستخدام FreeImage في مشروعي الخاص) وتجمع منصة X64 بشكل جيد على الفور.
نصائح أخرى
أنا لا أجيب حقًا على سؤالك ولكن سبق أن استخدمت مكون Imagedraw الذي تم بيعه بواسطة neodnyamic وبالتأكيد أوصي (والاستخدام) مرة أخرى. إنه ليس مجانيًا ولكنه يستحق استثمارًا صغيرًا.