Avant, lorsque j'utilisais win32, j'utilisais FreeImage pour charger et sauvegarder des bitmaps de profondeur supérieure à 8 bits. Toutes les images avec lesquelles je travaille, puisque je fais de l'imagerie médicale, et avant que qui que ce soit, oui, mes clients et moi avons dépensé beaucoup d'argent sur des moniteurs à contraste élevé et à luminosité élevée avec 11 ou 12 bits de dynamique . En fait, si vous êtes curieux, requirements by the ACR for running mammography incluue un moniteur avec au moins 10 bits de gamme dynamique.Comment puis-je sauvegarder/charger une image 16 bits dans .net x64?
Je viens commuté à x64 pour les frais généraux de mémoire et d'obtenir tout mon développement sur une plate-forme et le mode compilation. Je préfère ne pas revenir à win32, et mes clients sont là avec moi (et vraiment forçant le changement). FreeImage ne compile pas sur les fenêtres de 64 bits; il a une directive _asm dans le code que le compilateur ne peut pas gérer.
Je pensais que je vais essayer le support natif .NET dans les classes Microsoft. Longue histoire courte: Ils ne fonctionnent pas, et échouent avec des messages d'erreur très limités. Je suppose que c'est parce que Microsoft ne supporte toujours pas la classe Format16bppGrayScale.
Peut-être qu'il y a un problème dans mon code. Voici mon code écrit:
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();
Ce code provoque le plantage du programme avec
An unhandled exception of type
'System.Runtime.InteropServices.ExternalException' occurred in
System.Drawing.dll
Additional information: A generic error occurred in GDI+.
Intéressant, surtout que je ne veux plus jamais dessiner cette image à l'écran comme celui-ci (même si ce serait bien!) , mais je veux juste utiliser la fonctionnalité de sauvegarde/chargement. L'image ne s'écrit sur le disque (même si le programme se bloque), et le code de lecture suivante bloque également le programme:
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
Ce code provoque le plantage du programme avec l'erreur:
An unhandled exception of type 'System.ArgumentException' occurred in System.Drawing.dll
Additional information: Parameter is not valid.
Ces résultats dis-moi que Microsoft n'a toujours pas corrigé la partie Format16bppGrayScale de l'énumération PixelFormat. C'est une honte.
Que puis-je utiliser pour charger et enregistrer 16 bits des images en niveaux de gris sur 64 bits avec .NET?
(EDIT: Je dois ajouter que, bien que je puisse sauvegarder des images DICOM, j'ai besoin de faire des expériences sur des données non-patient pour vérifier que les algorithmes sont sains, etc ... DICOM nécessite un ensemble d'UID et autres champs qui sont trop exigeants pour ce dont j'ai besoin, j'ai juste besoin d'images, et pas de données patient, pour le moment).
Vous avez raison-- à partir de maintenant, le projet freeimage compile pour x64. Merci de l'avoir signalé! – mmr