使用 mDCM 从 Dicom 文件中导出 JPG

发布于 2024-08-27 12:11:32 字数 1897 浏览 7 评论 0原文

我使用 mDCM 和 C# 来查看 dicom 标签,但我试图将像素数据转换为位图并最终转换为 JPG 文件。我已阅读 mDCM Google Group 上有关该主题的所有帖子,并且所有代码示例要么不起作用,要么缺少重要的代码行。我正在处理的图像是 16 位单色1(这是提到的格式,但实际上是 16 位灰度)。我尝试过使用 LockBits、SetPixel 和不安全代码将像素数据转换为位图,但所有尝试都失败了。有谁有任何代码可以使这个工作。

这是我使用 SetPixel 的最新尝试:

DcmElement pixelData = this.currentFileFormat.Dataset.GetElement(new DcmTag(DcmConstTags.PixelData));
ushort[] pixels = this.currentPixelData.GetFrameDataU16(0);
this.currentImage = new Bitmap(this.currentPixelData.ImageWidth, this.currentPixelData.ImageHeight, PixelFormat.Format16bppRgb555);
int resample = (int)Math.Pow(2, (this.currentPixelData.BitsStored - 8));

int pxCounter = 0;
int min = ushort.MaxValue;
int max = 0;

for (int c = 0; c < this.currentPixelData.ImageHeight; c++)
{
    for (int r = 0; r < this.currentPixelData.ImageWidth; r++)
    {
        ushort pxColor = pixels[pxCounter];
        int temp = 255 - (pxColor / resample);
        if (temp < min) min = temp;
        if (temp > max) max = temp;
        this.currentImage.SetPixel(r, c, Color.FromArgb(temp, temp, temp));
        pxCounter++;
    }
}

更新: 通过使用 LockBits 和 Marshal.Copy,我已经接近了,但图像以彩虹色而不是灰度显示。所以我猜我需要一种将灰度数据转换为 RBG 格式的方法:

byte[] pixels = this.currentPixelData.GetFrameDataU8(frameIndex);
this.currentImage = new Bitmap(this.currentPixelData.ImageWidth, this.currentPixelData.ImageHeight, PixelFormat.Format16bppRgb555);
BitmapData bitmapData = this.currentImage.LockBits(new Rectangle(0, 0, this.currentImage.Width, this.currentImage.Height), ImageLockMode.ReadWrite, this.currentImage.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bitmapData.Scan0, this.currentImage.Width * this.currentImage.Height * 2);
this.currentImage.UnlockBits(bitmapData);

提前

致谢在有人建议尝试像 ClearCanvas 这样的其他东西之前,请知道 mDCM 是唯一适合我的需求的库,而 ClearCanvas 对于我需要做的事情来说太臃肿了。

I'm using mDCM with C# to view dicom tags, but I'm trying to convert the pixel data to a Bitmap and eventually out to a JPG file. I have read all of the posts on the mDCM Google Group on the subject and all of the code examples either don't work or are missing important lines of code. The image I am working with is a 16 bit monochrome1 (that's the format mentioned, but it's actually 16 bit grayscale). I have tried using LockBits, SetPixel, and unsafe code in order to convert the pixel data to a Bitmap but all attempts fail. Does anyone have any code that could make this work.

Here is my latest attempt using SetPixel:

DcmElement pixelData = this.currentFileFormat.Dataset.GetElement(new DcmTag(DcmConstTags.PixelData));
ushort[] pixels = this.currentPixelData.GetFrameDataU16(0);
this.currentImage = new Bitmap(this.currentPixelData.ImageWidth, this.currentPixelData.ImageHeight, PixelFormat.Format16bppRgb555);
int resample = (int)Math.Pow(2, (this.currentPixelData.BitsStored - 8));

int pxCounter = 0;
int min = ushort.MaxValue;
int max = 0;

for (int c = 0; c < this.currentPixelData.ImageHeight; c++)
{
    for (int r = 0; r < this.currentPixelData.ImageWidth; r++)
    {
        ushort pxColor = pixels[pxCounter];
        int temp = 255 - (pxColor / resample);
        if (temp < min) min = temp;
        if (temp > max) max = temp;
        this.currentImage.SetPixel(r, c, Color.FromArgb(temp, temp, temp));
        pxCounter++;
    }
}

UPDATE:
I have gotten closer by using LockBits and Marshal.Copy, but the image comes out in a rainbow of colors instead of grayscale. So I'm guessing I need a way to convert the grayscale data to RBG format:

byte[] pixels = this.currentPixelData.GetFrameDataU8(frameIndex);
this.currentImage = new Bitmap(this.currentPixelData.ImageWidth, this.currentPixelData.ImageHeight, PixelFormat.Format16bppRgb555);
BitmapData bitmapData = this.currentImage.LockBits(new Rectangle(0, 0, this.currentImage.Width, this.currentImage.Height), ImageLockMode.ReadWrite, this.currentImage.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, bitmapData.Scan0, this.currentImage.Width * this.currentImage.Height * 2);
this.currentImage.UnlockBits(bitmapData);

Thanks in advance

P.S. Before anyone suggests trying something else like ClearCanvas, know that mDCM is the only library that suits my needs and ClearCanvas is WAY too bloated for what I need to do.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

脱离于你 2024-09-03 12:11:32

我最终想通了,所以如果其他人偶然发现这个问题,我可以使用 CodeProject 文章中的代码显示并保存 16 位灰度图像。这是该文章的链接:

http://www.codeproject.com /KB/graphics/Image16bit.aspx?msg=3210733

I eventually figured it out, so if anyone else stumbles onto this problem, I was able to display and save the 16-bit grayscale images using code from a CodeProject article. Here's a link to that article:

http://www.codeproject.com/KB/graphics/Image16bit.aspx?msg=3210733

绾颜 2024-09-03 12:11:32

太糟糕了,您没有将 GDCM 与 C# 一起使用。这将是一段 5 行代码:

http://gdcm.sourceforge .net/html/ExtractEncapsulatedFile.cs-example.html

Too bad you are not using GDCM with C#. This would be a 5-lines piece of code:

http://gdcm.sourceforge.net/html/ExtractEncapsulatedFile.cs-example.html

花辞树 2024-09-03 12:11:32

我在 Atalasoft 工作,我们有一个成像组件可以为您完成此操作:

DicomDecoder decoder = new DicomDecoder();
using (AtalaImage image = decoder.Read(stream, frameIndex, null)) {
    AtalaImage imageToSave = null;
    if (image.PixelFormat == PixelFormat.Pixel16bppGrayscale) {
        imageToSave = image.GetChangedPixelFormat(PixelFormat.Pixel8bppGrayscale);
    }
    else if (image.PixelFormat == PixelFormat.Pixel48bppBgr) {
        imageToSave = image.GetChangedPixelFormat(PixelFormat.Pixel24bppBgr);
    }
    else {
        imageToSave = image;
    }
    imageToSave.Save(outputStream, new JpegEncoder(), null);
    if (imageToSave != image)
        imageToSave.Dispose();
}

这比它更冗长一些严格需要 - 我会制定一个例程,以适合您要使用的编码器的格式返回图像。一般来说,Jpeg 是它可以处理的相当有限的像素格式,而 dicom 可以封装一些相当宽的格式。 TIFF 可能是输出文件格式的更好选择。

我提出这一点是因为 DicomDecoder 对象自动处理 dicom 更深奥的像素格式,允许您在图像的原始空间中进行窗口和调平(又名亮度和对比度),以及获取标签,我们给您胜利/用于显示 AtalaImages 的 Web 表单控件,这可能会大大减小您的应用程序大小。

当然,有一系列合理的原因导致您可能被迫使用 mDCM,但我认为这可能会帮助您(或其他人)看到另一种选择。

I work for Atalasoft and we have an imaging component that will do this for you:

DicomDecoder decoder = new DicomDecoder();
using (AtalaImage image = decoder.Read(stream, frameIndex, null)) {
    AtalaImage imageToSave = null;
    if (image.PixelFormat == PixelFormat.Pixel16bppGrayscale) {
        imageToSave = image.GetChangedPixelFormat(PixelFormat.Pixel8bppGrayscale);
    }
    else if (image.PixelFormat == PixelFormat.Pixel48bppBgr) {
        imageToSave = image.GetChangedPixelFormat(PixelFormat.Pixel24bppBgr);
    }
    else {
        imageToSave = image;
    }
    imageToSave.Save(outputStream, new JpegEncoder(), null);
    if (imageToSave != image)
        imageToSave.Dispose();
}

This is a little wordier than it strictly needs to be - I would factor out a routine to return an image in a format suitable for the encoder you want to use. Jpeg, in general, is a fairly limited pixel formats it can handle, whereas dicom can encapsulate some fairly wide formats. TIFF would probably be a better choice for an output file format.

I bring this up because the DicomDecoder object automatically handles dicom's more esoteric pixel formats, allows you to do window and leveling (aka, brightness and contrast) in the image's raw space, as well as get at the tags, and we give you win/web form controls for displaying AtalaImages, which would probably cut your app size way down.

There are, of course, a set of reasonable reasons why you might be constrained to use mDCM, but I thought it might help you (or others) to see another option.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文