BMP转DICOM

前言:

转载请附上连接,本帖原创请勿照抄。

使用DCMTK库实现BMP转DCM的互相转换以及JPEG转DCM。使用DCMTK库其中在编译的时候错了好几次,在这有编译好的库给大家分享在此附上连接只需要1积分(https://download.csdn.net/download/qq_37529913/10793075)。直接使用DCMTK库实现的功能,期间本人也下载了好多但是大部分都没用复制粘贴出来的水贴有点多。其中借鉴了zssure大神的两篇文章(JPEGhttps://blog.csdn.net/zssureqh/article/details/42200303/)(BMPhttps://blog.csdn.net/zssureqh/article/details/42119303)zussre大神在贴中介绍了包括BMP、JPG结构和需要引入的一些文件,我在这再给大家介绍一些Dcm常用的Tag属性值(https://blog.csdn.net/wenzhi20102321/article/details/75127362)很感谢峥嵘life大佬,这里再给大家附上一个全的dcm的Tag(https://sno.phy.queensu.ca/~phil/exiftool/TagNames/DICOM.html)属于DICOM官方给出的标签很实用虽然没有详解。

使用VC++,MFC实现了Bmp和JPG的相互转换,JPEG转DCM图。包括dcm图Tag值的讲解以及实现。

代码实例:

DCMTK库的使用(使用VS大部分版本属性设置都是一样的)

VS2017项目->属性->

VC++目录->

包含目录填DCMTK库的include目录(X:\dcmtk库\include\)

库目录填DCMTK库的LIB目录(X:\dcmtk库\lib\)

C++常规->附加包含目录(X:\dcmtk库\include\)

预处理器添加(_CRT_SECURE_NO_WARNINGS)

链接器->输入->附加依赖项->

WS2_32.lib;NetAPI32.lib;WSock32.lib;charls.lib;dcmdata.lib;dcmdsig.lib;dcmimage.lib;dcmimgle.lib;dcmjpeg.lib;dcmjpls.lib;dcmnet.lib;dcmpstat.lib;dcmqrdb.lib;dcmsr.lib;dcmtls.lib;dcmwlm.lib;i2d.lib;ijg8.lib;ijg12.lib;ijg16.lib;oflog.lib;ofstd.lib;

引入头文件

    #include "stdafx.h"
    #include <stdio.h>
    #include "afxdialogex.h"
    #include "dcmtk/dcmimgle/dcmimage.h"
    #include "dcmtk/dcmdata/dcistrmf.h"
    #include "dcmtk/dcmdata/dctk.h"
    #include "dcmtk/config/osconfig.h"
    #include "dcmtk/dcmdata/libi2d/i2dbmps.h"
     
    #include "dcmtk/dcmdata/dcpixel.h"
    #include "dcmtk/dcmdata/dcpixseq.h"
    #include "dcmtk/dcmdata/dcpxitem.h"
     
    #include <direct.h>
    /*----BMP图像解析----*/
    #include "dcmtk/dcmdata/libi2d/i2dbmps.h"
    /*----JPEG图像解析----*/
    #include "dcmtk/dcmdata/libi2d/i2djpgs.h"
    #include "dcmtk/dcmdata/libi2d/i2doutpl.h"
    #include "dcmtk/dcmdata/dcerror.h"

BMP转DCM:

    //CString BatchConversionFile bmp图片路径
    OFCondition status;
            DcmFileFormat fileformat;
            DcmDataset* mydatasete = fileformat.getDataset();
            AddDicomElements((DcmDataset*&)mydatasete);
            Uint16 rows, cols, samplePerPixel, bitsAlloc, bitsStored, highBit, pixelRpr, planConf, pixAspectH, pixAspectV;
            OFString photoMetrInt;
            Uint32 length;
     
            E_TransferSyntax ts;
            //10
            char* mydata = new char[1024 * 1024 * 110];
     
            memset(mydata, 0, sizeof(char) * 1024 * 1024 * 110);
     
            char* tmpData = mydata;
     
            char curDir[100];
     
            getcwd(curDir, 100);
     
            //循环添加4张图片
     
            for (int i = 0; i < 1; ++i)
            {
                OFString num;
                char numtmp[100];
                memset(numtmp, 0, sizeof(char) * 100);
                sprintf(numtmp, "1.bmp", curDir, i + 1);
                OFString filename = OFString(numtmp);
                I2DBmpSource* bmpSource = new I2DBmpSource();
                bmpSource->setImageFile(filename);
                char* pixData = NULL;
                bmpSource->readPixelData(rows, cols, samplePerPixel, photoMetrInt, bitsAlloc, bitsStored, highBit, pixelRpr, planConf, pixAspectH, pixAspectV, pixData, length, ts);
                memcpy(tmpData, pixData, length);
                tmpData += length;
                delete bmpSource;
     
            };
     
            mydatasete->putAndInsertUint16(DCM_SamplesPerPixel, samplePerPixel);
     
            mydatasete->putAndInsertString(DCM_NumberOfFrames, "1");
     
            mydatasete->putAndInsertUint16(DCM_Rows, rows);
     
            mydatasete->putAndInsertUint16(DCM_Columns, cols);
     
            mydatasete->putAndInsertUint16(DCM_BitsAllocated, bitsAlloc);
     
            mydatasete->putAndInsertUint16(DCM_BitsStored, bitsStored);
     
            mydatasete->putAndInsertUint16(DCM_HighBit, highBit);
     
            mydatasete->putAndInsertUint8Array(DCM_PixelData, (Uint8*)mydata, 1 * length);
     
            mydatasete->putAndInsertOFStringArray(DCM_PhotometricInterpretation, photoMetrInt);
     
            status = fileformat.saveFile("Multibmp2dcmtest.dcm", ts);
     
            if (status.bad())
     
            {
                AfxMessageBox("BMP TO DCM Conversion Error");
            }
     
            return ;

Dcm转Bmp

    //CString DcmFileTo图片的路径
    // CString TheFileName输出的文件名
    if (DcmFileTo.IsEmpty())
        {
            AfxMessageBox("DcmConversion_File NULL");
            return;
        }
        if (TheFileName.IsEmpty())
        {
            AfxMessageBox("DcmConversion_Place NULL");
            return;
        }
        DcmFileFormat *pDcmFile = new DcmFileFormat();
        OFFilename filePath = DcmFileTo;
        OFCondition pCondition = pDcmFile->loadFile(filePath);//filePath为DCM文件路径
        if (pCondition.good())
        {
            E_TransferSyntax xfer = pDcmFile->getDataset()->getOriginalXfer();
            DicomImage *pDicomImage = new DicomImage(pDcmFile, xfer);
            pDicomImage->setWindow(100, 400);//调窗这里值设置不同出来的效果就会大不相同
            char bmpto_file[100];
            strncpy(bmpto_file, (LPCTSTR)TheFileName, sizeof(bmpto_file));
            if (pDicomImage->writeBMP(bmpto_file)) {
            }
            else {
                AfxMessageBox("非标准Dcm格式文件转换失败");
                return;
            }
        }

JPEG转DCM:

    /*CString TheJPGFile图片路径
    */
    if (TheJPGFile.IsEmpty())
        {
            AfxMessageBox(" JPG File Error");
            return;
        }
        //TheName 输出的后缀   TheFile 获取到的第一张BMP图的文件名  TheFileName 输出的文件名
        CString TheName = ".dcm", TheFileName, The_Name = "_T.dcm", The_FileName;
        //删除路径多余符号
        int nPos = TheJPGFile.Find('\\');
        CString sSubStr = TheJPGFile;
        while (nPos)
        {
            sSubStr = sSubStr.Mid(nPos + 1, sSubStr.GetLength() - nPos);  //取'\'右边字符串
            nPos = sSubStr.Find('\\');   //不包含'\',函数值返回-1
            if (nPos == -1)
            {
                nPos = 0;
            }
        }
        //删除后缀
        int pos = sSubStr.ReverseFind('.');
        if (pos > 0) {}
        CString strRet = sSubStr.Left(pos);
        //输出的文件名
        TheFileName = strRet + TheName;
        The_FileName = strRet + The_Name;
     
        OFCondition status;
        DcmPixelSequence *seq = new DcmPixelSequence(DcmTag(DCM_PixelData, EVR_OB));
        DcmFileFormat fileformat;
        DcmDataset* mydatasete = fileformat.getDataset();
        AddDicomElements((DcmDataset*&)mydatasete);
        Uint16 rows, cols, samplePerPixel, bitsAlloc, bitsStored, highBit, pixelRpr, planConf, pixAspectH, pixAspectV;
        OFString photoMetrInt;
        Uint32 length;
        E_TransferSyntax ts;
        char curDir[255];
        getcwd(curDir, 255);
        seq->insert(new DcmPixelItem(DcmTag(DCM_Item, EVR_OB)));
        for (int i = 0; i < 1; ++i)
        {
            OFString num;
            char numtmp[255];
            memset(numtmp, 0, sizeof(char) * 255);
            sprintf(numtmp, TheJPGFile, curDir, i + 1);
            OFString filename = OFString(numtmp);
            I2DJpegSource* bmpSource = new I2DJpegSource();
            bmpSource->setImageFile(filename);
     
            char* pixData = NULL;                            //photoMetrInt
            bmpSource->readPixelData(rows, cols, samplePerPixel, photoMetrInt, bitsAlloc, bitsStored, highBit, pixelRpr, planConf, pixAspectH, pixAspectV, pixData, length, ts);
            DicomImage *pDicomImage = new DicomImage(TheJPGFile);
            pDicomImage->setWindow(3570, 5020);//调窗这里值设置不同出来的效果就会大不相同
            DcmPixelItem *newItem = new DcmPixelItem(DcmTag(DCM_Item, EVR_OB));
            if (newItem != NULL)
            {
                seq->insert(newItem);
                OFCondition result = newItem->putUint8Array((Uint8*)pixData, length);
                //OFCondition result = newItem->putUint16Array((Uint16*)pixData, length);
            }
            delete bmpSource;
        };
        OFFilename str_FileName = TheFileName;
        //pDicomImage->setWindow(100, 400);
        mydatasete->putAndInsertUint16(DCM_SamplesPerPixel, samplePerPixel);
        mydatasete->putAndInsertString(DCM_NumberOfFrames, "1");
        mydatasete->putAndInsertUint16(DCM_Rows, rows);
        mydatasete->putAndInsertUint16(DCM_Columns, cols);
        mydatasete->putAndInsertUint16(DCM_BitsAllocated, bitsAlloc);
        mydatasete->putAndInsertUint16(DCM_BitsStored, bitsStored);
        mydatasete->putAndInsertUint16(DCM_HighBit, highBit);
        mydatasete->putAndInsertOFStringArray(DCM_PhotometricInterpretation, photoMetrInt);//"MONOCHROME2"
        mydatasete->putAndInsertString(DCM_UltrasoundColorDataPresent, "0");
        mydatasete->putAndInsertUint16(DCM_SamplesPerPixel, 1);
        mydatasete->insert(seq, OFFalse, OFFalse);
        //????
     
        mydatasete->putAndInsertString(DCM_SourceApplicationEntityTitle, "Holter");
        mydatasete->putAndInsertString(DCM_SOPClassUID, "1.2.840.10008.5.1.4.1.17");
        mydatasete->putAndInsertString(DCM_SOPInstanceUID, "1.2.7.3.8.2019.02.08.00.16.28.1.1");
        status = fileformat.saveFile(str_FileName, ts);
        if (status.bad())
        {
            AfxMessageBox("Error");
        }
        return;

 PS:以上是三种转换方式楼主亲测,虽然补了很多漏洞,毕竟努力了好久了完整版的就不发出来了,把大概的实现发出来了。AddDicomElements((DcmDataset*&)mydatasete);这个删掉就好缺什么字段在后面使用mydatasete->这个添加就好,有三四处内存泄漏需要各位小伙伴自己找一下,dcmtk的标准还有一些字段的意思还得大家自己去研究,按照这个改一改完整版的完全可以做出来,有什么问题可以留言,看到会及时回复的。

附加的完整Lib包下载链接(https://download.csdn.net/download/qq_37529913/11013779);

 
---------------------
作者:Dream.2017@qq.com
来源:CSDN
原文:https://blog.csdn.net/qq_37529913/article/details/88416516
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值