#include "SDCMImage.h"

// #include "dcmtk/dcmdata/libi2d/i2d.h"
// #include "dcmtk/dcmdata/libi2d/i2dbmps.h"
// #include "dcmtk/dcmdata/libi2d/i2djpgs.h"
// #include "dcmtk/dcmdata/libi2d/i2dplsc.h"
// #include "dcmtk/dcmdata/libi2d/i2dplnsc.h"
// #include "dcmtk/dcmdata/libi2d/i2dplvlp.h"

#include "charconvert.h"

#ifdef UNICODE
#undef UNICODE
#undef _UNICODE
#define UNICODE_DEFINED
#endif

#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dcfilefo.h"
#include "dcmtk/dcmdata/dcdeftag.h"
#include "dcmtk/dcmdata/dcuid.h"
#include "dcmtk/dcmdata/dcmetinf.h"
#include "dcmtk/dcmdata/dcdict.h"
#include "dcmtk/dcmdata/dcdicent.h"

#include "dcmtk/dcmnet/diutil.h"

#include "dcmtk/dcmdata/dcxfer.h"

#include "dcmtk/dcmjpeg/djdecode.h"  /* for JPEG decoders */
#include "dcmtk/dcmjpeg/djencode.h"  /* for JPEG encoders */
#include "dcmtk/dcmjpls/djdecode.h"  /* for JPEG-LS decoders */
#include "dcmtk/dcmjpls/djencode.h"  /* for JPEG-LS encoders */
#include "dcmtk/dcmdata/dcrledrg.h"  /* for RLE decoder */
#include "dcmtk/dcmdata/dcrleerg.h"  /* for RLE encoder */
#include "dcmtk/dcmjpeg/dipijpeg.h"  /* for dcmimage JPEG plugin */
#include "dcmtk/dcmjpeg/djrplol.h"


#include "dcmtk/dcmimage/diregist.h"
#include "dcmtk/dcmdata/dcpixseq.h"
#include "dcmtk/dcmjpeg/djcparam.h"
#include "dcmtk/dcmjpeg/djeijg8.h"
#include "dcmtk/dcmjpeg/djcodece.h"
#include "dcmtk/dcmdata/dcchrstr.h"
#include "dcmtk/ofstd/ofchrenc.h"

#include "dcmtk/dcmdata/dcvrui.h"
#include "dcmtk/dcmdata/dcvrsh.h"

#include "dcmtk/dcmdata/dcostrmf.h"
#include "dcmtk/dcmdata/dcwcache.h"

#include "mainwindow.h"

//#include "SDCMWorklistDlg.h"


/*
#include "dcmtk/dcmimgle/dcmimage.h"


#include "dcmtk/dcmdata/dcpxitem.h"

//#include "dcmtk/dcmjpeg/djencsv1.h"


*/

#ifdef UNICODE_DEFINED
#define UNICODE
#define _UNICODE
#undef UNICODE_DEFINED
#endif



#define PRIVATE_CREATOR_NAME "VideoNetworkFileLink" 

#define PRIVATE_CREATOR_TAG  0x0029, 0x0010
#define PRIVATE_VIDEO_FILE_LINK 0x0029, 0x1000
#define PRIVATE_ELEMENT2_TAG 0x0029, 0x1010
#define PRIVATE_ELEMENT3_TAG 0x0029, 0x1020

#define PRV_PrivateCreator   DcmTag(PRIVATE_CREATOR_TAG)
#define PRV_VIDEO_FILE_LINK  DcmTag(PRIVATE_VIDEO_FILE_LINK, PRIVATE_CREATOR_NAME)
#define PRV_PrivateElement2  DcmTag(PRIVATE_ELEMENT2_TAG, PRIVATE_CREATOR_NAME)
#define PRV_PrivateElement3  DcmTag(PRIVATE_ELEMENT3_TAG, PRIVATE_CREATOR_NAME)



CSDCMImage::CSDCMImage(void)
{	
    //register global JPEG decompression codecs
    DJDecoderRegistration::registerCodecs();

    // register global JPEG compression codecs
    DJEncoderRegistration::registerCodecs();

    // register JPEG-LS decompression codecs
    DJLSDecoderRegistration::registerCodecs();

    // register JPEG-LS compression codecs
    DJLSEncoderRegistration::registerCodecs();

    // register RLE compression codec
    DcmRLEEncoderRegistration::registerCodecs();

    // register RLE decompression codec
    DcmRLEDecoderRegistration::registerCodecs();

	m_nInputFileFormat = 1;
	m_nOutputFileFormat = 1;

	m_pData = NULL;

    //m_TransferSyntaxOutput = EXS_JPEG2000;//EXS_LittleEndianExplicit; // EXS_JPEGProcess14SV1, EXS_JPEG2000
    //m_TransferSyntaxOutput = EXS_JPEGProcess14SV1;//EXS_LittleEndianExplicit; // EXS_JPEGProcess14SV1, EXS_JPEG2000

    m_TransferSyntaxOutput = EXS_LittleEndianExplicit;



	m_strImplementationClassUID = "1.2.3.4.5.6.7.8.9.10";
	m_strImplementationVersionName = "SSD_Gateway_1_0";
}


CSDCMImage::~CSDCMImage(void)
{
	SAFE_ARRAY_DELETE(m_pData);

    //cleanup global JPEG decompression codecs
    DJDecoderRegistration::cleanup();

    // cleanup global JPEG compression codecs
    DJEncoderRegistration::cleanup();

    // cleanup JPEG-LS decompression codecs
    DJLSDecoderRegistration::cleanup();

    // cleanup JPEG-LS compression codecs
    DJLSEncoderRegistration::cleanup();

    // cleanup RLE compression codec
    DcmRLEEncoderRegistration::cleanup();

    // cleanup RLE decompression codec
    DcmRLEDecoderRegistration::cleanup();
}



void CSDCMImage::LoadImage(OFString strFilename, BOOL bGray)
{
    QImage image((QString)strFilename.c_str());
    int nWidth = 0;
    int nHeight = 0;

    image = image.convertToFormat(QImage::Format_RGB888);

    nWidth = image.width();
    nHeight = image.height();

    SAFE_ARRAY_DELETE(m_pData);
    if (bGray == TRUE)
    {
        m_pData = new uint8_t[nWidth*nHeight];
    }
    else
    {
        m_pData = new uint8_t[nWidth*nHeight * 3];
    }

    m_nWidth = nWidth;
    m_nHeight = nHeight;

    uint8_t* pData = (uint8_t*)image.bits();
    memcpy(m_pData, pData, image.byteCount());
}

void CSDCMImage::LoadImage(QString strFilename, BOOL bGray)
{
    QImage image((QString)strFilename);
    int nWidth = 0;
    int nHeight = 0;

    image = image.convertToFormat(QImage::Format_RGB888);

    nWidth = image.width();
    nHeight = image.height();

    SAFE_ARRAY_DELETE(m_pData);
    if (bGray == TRUE)
    {
        m_pData = new uint8_t[nWidth*nHeight];
    }
    else
    {
        m_pData = new uint8_t[nWidth*nHeight * 3];
    }

    m_nWidth = nWidth;
    m_nHeight = nHeight;

    uint8_t* pData = (uint8_t*)image.bits();
    memcpy(m_pData, pData, image.byteCount());
}

int CSDCMImage::WriteDCM(OFString strInputImageFile, OFString strDcmFilename, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, OFString strNewStudyInstanceUID, BOOL bUsePDFCompress)
{
    return WriteDCM(strInputImageFile, strDcmFilename, pWorklistData, nSeriesNumber, nImageNumber, bChangeUID, strNewStudyInstanceUID);
}

int CSDCMImage::WriteDCM(OFString strInputImageFile, OFString strDcmFilename, OFString strContentDate, OFString strContentTime, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, OFString strNewStudyInstanceUID)
{
    int nRet = 0;
    DcmFileFormat cDcmFileFormat;
    E_TransferSyntax opt_ixfer = EXS_Unknown;
    E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit;
    const Uint32 DCM_MaxReadLength = 4096;
    E_FileReadMode opt_readMode = ERM_autoDetect;

    OFString ofFilename;

    DcmStack cDcmStack;
    DcmVR vr;
    OFCondition error;
    DcmDataset* pDcmDataset = NULL;
    DcmElement* pElement = NULL;
    OFString ofData;

    OFString strModality = pWorklistData->m_Series.strModality.toStdString().c_str();

    if(strInputImageFile.length()>0)
    {
        BOOL bGray = FALSE;

        if(strModality=="CR")
        {
            bGray = TRUE;
        }
        bGray = FALSE;
        m_nWidth = 0;
        m_nHeight = 0;
        LoadImage(strInputImageFile, bGray);
        if(m_nWidth==0 || m_nHeight==0)
        {
            //WRITE_FUNCTION_LOG_PARAM("Error Load Image\n");
            return -1;
        }
    }



    //DeleteFile(strDcmFilename);



    ofFilename = (OFString)strDcmFilename;
    error = cDcmFileFormat.loadFile(ofFilename, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);
    pDcmDataset = cDcmFileFormat.getDataset();

    pDcmDataset->loadAllDataIntoMemory();

    cDcmStack.clear();
    pDcmDataset->search(DCM_ImageType, cDcmStack);




    WriteDeviceInfo(pDcmDataset);
    WriteImageType(pDcmDataset, pWorklistData->m_Image.strImageType);
    WriteLaterality(pDcmDataset, pWorklistData->m_Series.strLaterality, pWorklistData->m_Image.strImageLaterality);
    WriteDateTime(pDcmDataset, pWorklistData);

    WritePatientInfo(pDcmDataset, pWorklistData);

    WriteScheduledProcedureStep(pDcmDataset, pWorklistData);


    WriteImageInfo(pDcmDataset, strContentDate, strContentTime, pWorklistData, nImageNumber);


    OFString strPixelSpacing = "0.01296529\\0.02018628";

    //PutAndInsertString(pDcmDataset, DCM_PixelSpacing, strPixelSpacing);//"0.01296529\\0.02018628");


    //PutAndInsertString(pDcmDataset, DCM_PatientOrientation, "L""\0x5f""F");


    if(strModality=="OP")
    {
        DcmItem* pSubItem = NULL;
        if (pDcmDataset->findOrCreateSequenceItem(DCM_AcquisitionDeviceTypeCodeSequence, pSubItem, -2 /*append*/).good() == true)
        {
            pSubItem->putAndInsertString(DCM_CodeValue, "LSO");
            pSubItem->putAndInsertString(DCM_CodingSchemeDesignator, "99CZM_ACQDEVTYPE");
            pSubItem->putAndInsertString(DCM_CodingSchemeVersion, "20120703");
            pSubItem->putAndInsertString(DCM_CodeMeaning, "Line Scanning Ophthalmoscope");
        }

        pSubItem = NULL;
        if (pDcmDataset->findOrCreateSequenceItem(DCM_LensesCodeSequence, pSubItem, -2 /*append*/).good() == true)
        {
            pSubItem->putAndInsertString(DCM_CodeValue, "R-10219");
            pSubItem->putAndInsertString(DCM_CodingSchemeDesignator, "SRT");
            pSubItem->putAndInsertString(DCM_CodeMeaning, "Indirect ophthalmoscopy lens");
        }

        pSubItem = NULL;
        if (pDcmDataset->findOrCreateSequenceItem(DCM_ChannelDescriptionCodeSequence, pSubItem, -2 /*append*/).good() == true)
        {
            pSubItem->putAndInsertString(DCM_CodeValue, "R-102BE");
            pSubItem->putAndInsertString(DCM_CodingSchemeDesignator, "SRT");
            pSubItem->putAndInsertString(DCM_CodeMeaning, "Infrared");
        }

        PutAndInsertString(pDcmDataset, DCM_BurnedInAnnotation, "NO");
    }




    if(strInputImageFile.length()>0)
    {
        DJ_RPLossless params; // codec parameters, we use the defaults
        opt_oxfer = m_TransferSyntaxOutput;
        pDcmDataset->chooseRepresentation(opt_oxfer, &params);


        if (pDcmDataset->canWriteXfer(opt_oxfer) == OFTrue)
        {
            pDcmDataset->findAndGetElement(DCM_MediaStorageSOPClassUID, pElement);

            if (pElement != NULL)
            {
                pElement->getOFStringArray(ofData);
            }


            DcmMetaInfo* pMetaInfo = cDcmFileFormat.getMetaInfo();

            delete pMetaInfo->remove(DCM_MediaStorageSOPClassUID);
            delete pMetaInfo->remove(DCM_MediaStorageSOPInstanceUID);
            //delete pMetaInfo->remove(DCM_ImplementationClassUID);
            //delete pMetaInfo->remove(DCM_ImplementationVersionName);

            /*
            DcmElement *elem=NULL;

            DcmTag implementationClassUID(DCM_ImplementationClassUID);
            DcmTag ImplementationVersionName(DCM_ImplementationVersionName);

            elem = new DcmUniqueIdentifier(implementationClassUID);
            pMetaInfo->insert(elem, OFTrue);
            const char *uid = "1.2.276.0.7230010.3.0.1.1.1";
            ((DcmUniqueIdentifier*)elem)->putString(uid);

            elem = new DcmShortString(ImplementationVersionName);
            pMetaInfo->insert(elem, OFTrue);
            const char *versionName = "test1.2.3.4";
            ((DcmShortString*)elem)->putString(versionName);
            */





            //PutAndInsertString(pDcmDataset, DCM_ImplementationClassUID, "1.2.3.4");
            //PutAndInsertString(pDcmDataset, DCM_ImplementationVersionName, "SDCM1.0");


            if(m_TransferSyntaxOutput==EXS_JPEG2000)
            {
                PutAndInsertString(pDcmDataset, DCM_LossyImageCompressionMethod, "ISO_15444_1");
                PutAndInsertString(pDcmDataset, DCM_PhotometricInterpretation, "RGB");
            }

            pMetaInfo->findAndGetElement(DCM_MediaStorageSOPClassUID, pElement);
            pMetaInfo->findAndDeleteElement(DCM_MediaStorageSOPClassUID);
            pMetaInfo->findAndGetElement(DCM_MediaStorageSOPClassUID, pElement);

            WriteStudyInfo(pDcmDataset, pWorklistData, nSeriesNumber, nImageNumber, bChangeUID, strNewStudyInstanceUID);
            CharacterSetConversion(pDcmDataset);
            //error = cDcmFileFormat.saveFile(ofFilename, opt_oxfer);
            {
                /*
                virtual OFCondition saveFile(const OFFilename &fileName,
                                                 const E_TransferSyntax writeXfer = EXS_Unknown,
                                                 const E_EncodingType encodingType = EET_UndefinedLength,
                                                 const E_GrpLenEncoding groupLength = EGL_recalcGL,
                                                 const E_PaddingEncoding padEncoding = EPD_noChange,
                                                 const Uint32 padLength = 0,
                                                 const Uint32 subPadLength = 0,
                                                 const E_FileWriteMode writeMode = EWM_createNewMeta);
                                                 */

                const E_TransferSyntax writeXfer = opt_oxfer;
                const E_EncodingType encodingType = EET_UndefinedLength;
                {
                    DcmWriteCache wcache;

                    /* open file for output */
                    FILE* pFile = fopen(ofFilename.c_str(), "wb");
                    DcmOutputFileStream* fileStream = new DcmOutputFileStream(pFile);
                    //DcmOutputFileStream fileStream(ofFilename);

                    /* check stream status */
                    error = fileStream->status();
                    if (error.good())
                    {
                        /* write data to file */
                        cDcmFileFormat.transferInit();
                        error = cDcmFileFormat.write(*fileStream, writeXfer, encodingType, &wcache);//, groupLength,
                            //padEncoding, padLength, subPadLength, 0 /*instanceLength*/, writeMode);
                        cDcmFileFormat.transferEnd();

                        fileStream->flush();


                    }

                    //fsync(pFile);
                    fflush(pFile);
                    //fclose(pFile);

                    if(fileStream!=NULL)
                    {
                        delete fileStream;
                        fileStream = NULL;
                    }
                }

            }





        }
    }

    if(error.good()==OFFalse)
    {
        nRet = -1;
    }

    return nRet;
}


int CSDCMImage::WriteDCM(QString strInputImageFile, QString strDcmFilename, QString strContentDate, QString strContentTime, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, QString strNewStudyInstanceUID)
{
    int nRet = 0;
    DcmFileFormat cDcmFileFormat;
    E_TransferSyntax opt_ixfer = EXS_Unknown;
    E_TransferSyntax opt_oxfer = EXS_LittleEndianExplicit;
    const Uint32 DCM_MaxReadLength = 4096;
    E_FileReadMode opt_readMode = ERM_autoDetect;

    OFString ofFilename;
    OFString ofData;

    DcmStack cDcmStack;
    DcmVR vr;
    OFCondition error;
    DcmDataset* pDcmDataset = NULL;
    DcmElement* pElement = NULL;


    QString strModality = pWorklistData->m_Series.strModality;

    if(strInputImageFile.size()>0)
    {
        BOOL bGray = FALSE;

        if(strModality=="CR")
        {
            bGray = TRUE;
        }
        bGray = FALSE;
        m_nWidth = 0;
        m_nHeight = 0;
        LoadImage(strInputImageFile, bGray);
        if(m_nWidth==0 || m_nHeight==0)
        {
            //WRITE_FUNCTION_LOG_PARAM("Error Load Image\n");
            return -1;
        }
    }



    //DeleteFile(strDcmFilename);



    ofFilename = strDcmFilename.toStdString().c_str();
    error = cDcmFileFormat.loadFile(ofFilename, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);
    pDcmDataset = cDcmFileFormat.getDataset();

    pDcmDataset->loadAllDataIntoMemory();

    cDcmStack.clear();
    pDcmDataset->search(DCM_ImageType, cDcmStack);




    WriteDeviceInfo(pDcmDataset);
    WriteImageType(pDcmDataset, pWorklistData->m_Image.strImageType);
    WriteLaterality(pDcmDataset, pWorklistData->m_Series.strLaterality, pWorklistData->m_Image.strImageLaterality);
    WriteDateTime(pDcmDataset, pWorklistData);

    WritePatientInfo(pDcmDataset, pWorklistData);

    WriteScheduledProcedureStep(pDcmDataset, pWorklistData);


    WriteImageInfo(pDcmDataset, strContentDate, strContentTime, pWorklistData, nImageNumber);


    OFString strPixelSpacing = "0.01296529\\0.02018628";

    //PutAndInsertString(pDcmDataset, DCM_PixelSpacing, strPixelSpacing);//"0.01296529\\0.02018628");


    //PutAndInsertString(pDcmDataset, DCM_PatientOrientation, "L""\0x5f""F");


    if(strModality=="OP")
    {
        DcmItem* pSubItem = NULL;
        if (pDcmDataset->findOrCreateSequenceItem(DCM_AcquisitionDeviceTypeCodeSequence, pSubItem, -2 /*append*/).good() == true)
        {
            pSubItem->putAndInsertString(DCM_CodeValue, "LSO");
            pSubItem->putAndInsertString(DCM_CodingSchemeDesignator, "99CZM_ACQDEVTYPE");
            pSubItem->putAndInsertString(DCM_CodingSchemeVersion, "20120703");
            pSubItem->putAndInsertString(DCM_CodeMeaning, "Line Scanning Ophthalmoscope");
        }

        pSubItem = NULL;
        if (pDcmDataset->findOrCreateSequenceItem(DCM_LensesCodeSequence, pSubItem, -2 /*append*/).good() == true)
        {
            pSubItem->putAndInsertString(DCM_CodeValue, "R-10219");
            pSubItem->putAndInsertString(DCM_CodingSchemeDesignator, "SRT");
            pSubItem->putAndInsertString(DCM_CodeMeaning, "Indirect ophthalmoscopy lens");
        }

        pSubItem = NULL;
        if (pDcmDataset->findOrCreateSequenceItem(DCM_ChannelDescriptionCodeSequence, pSubItem, -2 /*append*/).good() == true)
        {
            pSubItem->putAndInsertString(DCM_CodeValue, "R-102BE");
            pSubItem->putAndInsertString(DCM_CodingSchemeDesignator, "SRT");
            pSubItem->putAndInsertString(DCM_CodeMeaning, "Infrared");
        }

        PutAndInsertString(pDcmDataset, DCM_BurnedInAnnotation, "NO");
    }




    if(strInputImageFile.size()>0)
    {
        DJ_RPLossless params; // codec parameters, we use the defaults
        opt_oxfer = m_TransferSyntaxOutput;
        pDcmDataset->chooseRepresentation(opt_oxfer, &params);


        if (pDcmDataset->canWriteXfer(opt_oxfer) == OFTrue)
        {
            pDcmDataset->findAndGetElement(DCM_MediaStorageSOPClassUID, pElement);

            if (pElement != NULL)
            {
                pElement->getOFStringArray(ofData);
            }


            DcmMetaInfo* pMetaInfo = cDcmFileFormat.getMetaInfo();

            delete pMetaInfo->remove(DCM_MediaStorageSOPClassUID);
            delete pMetaInfo->remove(DCM_MediaStorageSOPInstanceUID);
            //delete pMetaInfo->remove(DCM_ImplementationClassUID);
            //delete pMetaInfo->remove(DCM_ImplementationVersionName);

            /*
            DcmElement *elem=NULL;

            DcmTag implementationClassUID(DCM_ImplementationClassUID);
            DcmTag ImplementationVersionName(DCM_ImplementationVersionName);

            elem = new DcmUniqueIdentifier(implementationClassUID);
            pMetaInfo->insert(elem, OFTrue);
            const char *uid = "1.2.276.0.7230010.3.0.1.1.1";
            ((DcmUniqueIdentifier*)elem)->putString(uid);

            elem = new DcmShortString(ImplementationVersionName);
            pMetaInfo->insert(elem, OFTrue);
            const char *versionName = "test1.2.3.4";
            ((DcmShortString*)elem)->putString(versionName);
            */





            //PutAndInsertString(pDcmDataset, DCM_ImplementationClassUID, "1.2.3.4");
            //PutAndInsertString(pDcmDataset, DCM_ImplementationVersionName, "SDCM1.0");


            if(m_TransferSyntaxOutput==EXS_JPEG2000)
            {
                PutAndInsertString(pDcmDataset, DCM_LossyImageCompressionMethod, "ISO_15444_1");
                PutAndInsertString(pDcmDataset, DCM_PhotometricInterpretation, "RGB");
            }

            pMetaInfo->findAndGetElement(DCM_MediaStorageSOPClassUID, pElement);
            pMetaInfo->findAndDeleteElement(DCM_MediaStorageSOPClassUID);
            pMetaInfo->findAndGetElement(DCM_MediaStorageSOPClassUID, pElement);

            WriteStudyInfo(pDcmDataset, pWorklistData, nSeriesNumber, nImageNumber, bChangeUID, strNewStudyInstanceUID);
            CharacterSetConversion(pDcmDataset);
            //error = cDcmFileFormat.saveFile(ofFilename, opt_oxfer);
            {
                /*
                virtual OFCondition saveFile(const OFFilename &fileName,
                                                 const E_TransferSyntax writeXfer = EXS_Unknown,
                                                 const E_EncodingType encodingType = EET_UndefinedLength,
                                                 const E_GrpLenEncoding groupLength = EGL_recalcGL,
                                                 const E_PaddingEncoding padEncoding = EPD_noChange,
                                                 const Uint32 padLength = 0,
                                                 const Uint32 subPadLength = 0,
                                                 const E_FileWriteMode writeMode = EWM_createNewMeta);
                                                 */

                const E_TransferSyntax writeXfer = opt_oxfer;
                const E_EncodingType encodingType = EET_UndefinedLength;
                {
                    DcmWriteCache wcache;

                    /* open file for output */
                    FILE* pFile = fopen(ofFilename.c_str(), "wb");
                    DcmOutputFileStream* fileStream = new DcmOutputFileStream(pFile);
                    //DcmOutputFileStream fileStream(ofFilename);

                    /* check stream status */
                    error = fileStream->status();
                    if (error.good())
                    {
                        /* write data to file */
                        cDcmFileFormat.transferInit();
                        error = cDcmFileFormat.write(*fileStream, writeXfer, encodingType, &wcache);//, groupLength,
                            //padEncoding, padLength, subPadLength, 0 /*instanceLength*/, writeMode);
                        cDcmFileFormat.transferEnd();

                        fileStream->flush();


                    }

                    //fsync(pFile);
                    fflush(pFile);
                    //fclose(pFile);

                    if(fileStream!=NULL)
                    {
                        delete fileStream;
                        fileStream = NULL;
                    }
                }

            }





        }
    }

    if(error.good()==OFFalse)
    {
        nRet = -1;
    }

    return nRet;
}


int CSDCMImage::WriteDCM(OFString strInputImageFile, OFString strDcmFilename, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, OFString strNewStudyInstanceUID)
{
    OFString strCreationDate;
    OFString strCreationTime;

    strCreationDate = pWorklistData->m_Image.strContentDate.toStdString().c_str();
    strCreationTime = pWorklistData->m_Image.strContentTime.toStdString().c_str();

    return WriteDCM(strInputImageFile, strDcmFilename, strCreationDate, strCreationTime, pWorklistData, nSeriesNumber, nImageNumber, bChangeUID, strNewStudyInstanceUID);
}

int CSDCMImage::WriteDCM(QString strInputImageFile, QString strDcmFilename, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, QString strNewStudyInstanceUID)
{
    QString strCreationDate;
    QString strCreationTime;

    strCreationDate = pWorklistData->m_Image.strContentDate;
    strCreationTime = pWorklistData->m_Image.strContentTime;

    return WriteDCM(strInputImageFile, strDcmFilename, strCreationDate, strCreationTime, pWorklistData, nSeriesNumber, nImageNumber, bChangeUID, strNewStudyInstanceUID);
}

void CSDCMImage::RegisterPrivateTags()
{
	DcmDataDictionary &dict = dcmDataDict.wrlock();
	dict.addEntry(new DcmDictEntry(PRIVATE_VIDEO_FILE_LINK, EVR_LO, "PrivateText", 1, 1, "private", OFTrue, PRIVATE_CREATOR_NAME));
	dict.addEntry(new DcmDictEntry(PRIVATE_ELEMENT2_TAG, EVR_US, "PrivateInteger", 1, 1, "private", OFTrue, PRIVATE_CREATOR_NAME));
	dict.addEntry(new DcmDictEntry(PRIVATE_ELEMENT3_TAG, EVR_OB, "PrivateBlob", 1, 1, "private", OFTrue, PRIVATE_CREATOR_NAME));
    //dcmDataDict.unlock();
    dcmDataDict.wrunlock();
}

void CSDCMImage::AddPrivateElements(DcmItem &item, OFString strFileLocation)
{
	RegisterPrivateTags();
	if (!item.tagExists(PRV_PrivateCreator))
	{
		item.putAndInsertString(PRV_PrivateCreator, PRIVATE_CREATOR_NAME);
        item.putAndInsertOFStringArray(PRV_VIDEO_FILE_LINK, strFileLocation);
		//item.putAndInsertUint16(PRV_PrivateElement2, 12345);
		//item.putAndInsertUint8Array(PRV_PrivateElement3, NULL /*data*/, 0 /*length*/);
	}
}

int CSDCMImage::LoadDCMFile(OFString strFilename)
{
    int nRet = 0;
	DcmFileFormat cDcmFileFormat;
	OFCondition error;
    OFString ofFilename = (OFString)strFilename;
	E_TransferSyntax opt_ixfer = EXS_Unknown;
	E_FileReadMode opt_readMode = ERM_autoDetect;
	DcmDataset* pDcmDataset = NULL;
//	DcmElement* pElement = NULL;

	//RegisterPrivateTags();

	error = cDcmFileFormat.loadFile(ofFilename, opt_ixfer, EGL_noChange, DCM_MaxReadLength, opt_readMode);

	pDcmDataset = cDcmFileFormat.getDataset();


	pDcmDataset->loadAllDataIntoMemory();

	OFString strTransferSyntax;
	pDcmDataset->findAndGetOFString(DCM_TransferSyntaxUID, strTransferSyntax);

	OFString val;
//	int nSamplePerPixel = 1;
	pDcmDataset->findAndGetOFString(PRV_PrivateCreator, val);
	pDcmDataset->findAndGetOFString(PRV_VIDEO_FILE_LINK, val);

    Uint16 nRows = 0;
    Uint16 nColumns = 0;
    pDcmDataset->findAndGetUint16(DCM_Rows, nRows);
    pDcmDataset->findAndGetUint16(DCM_Columns, nColumns);

    if(nRows==0 || nColumns==0)
    {
        return -1;
    }

    unsigned long nImagePixelCount = 0;
    //Uint8* pTestPixelData = new Uint8[nRows*nColumns*4];
    const Uint8* pTestPixelData = NULL;

    pDcmDataset->findAndGetUint8Array(DCM_PixelData, pTestPixelData, &nImagePixelCount);
    if(pTestPixelData==NULL)
    {
        return -2;
    }
    if(nImagePixelCount==0)
    {
        return -3;
    }

    return nRet;

}




SDCM_AGE CSDCMImage::ComputeAge(QString strBirthdate)
{
	SDCM_AGE nAge;
	
    if(strBirthdate.length()==0)
	{
		return nAge;
	}

    /*
	int nYears = 0;
	int nMonths = 0;
	int nDays = 0;

	COleDateTime dt = COleDateTime::GetCurrentTime();

	int nBirthYear = atoi(strBirthdate.Mid(0, 4));
	int nBirthMonth = atoi(strBirthdate.Mid(4, 2));
	int nBirthDay = atoi(strBirthdate.Mid(6, 2));

	int nCurrentYear = dt.GetYear();
	int nCurrentMonth = dt.GetMonth();
	int nCurrentDay = dt.GetDay();

	COleDateTime dtBirthDate(nBirthYear, nBirthMonth, nBirthDay, 0, 0, 0);

	COleDateTimeSpan dtSpan = dt - dtBirthDate;
	nDays = dtSpan.GetDays();

	if(nDays<0)
	{
		return nAge;
	}

	nYears = nCurrentYear - nBirthYear;
	nMonths = nCurrentMonth - nBirthMonth;
	
	nMonths = (nYears*12)+nMonths;
	nYears = nMonths%12;

	nAge.m_nYears = nYears;
	nAge.m_nMonths = nMonths;
	nAge.m_nDays = nDays;
    */

	/*
	nYears = nCurrentYear - nBirthYear;
	if(nYears>0)
	{
		BOOL bDecrement = FALSE;
		if(nBirthMonth>nCurrentMonth)
		{	
			bDecrement = TRUE;
		}
		else if(nBirthMonth==nCurrentMonth)
		{
			if(nBirthDay>=nCurrentDay)
			{
				bDecrement = TRUE;
				
			}
		}

		if(bDecrement==TRUE)
		{
			nYears--;
		}

	}

	if(nYears<0)
	{
		nYears = 0;
	}

	nAge.m_nYears = nYears;
	*/

	return nAge;
	
}

OFCondition CSDCMImage::PutAndInsertString(DcmDataset* pDcmDataset, const DcmTag &tag, const char *value)
{
	OFCondition cond;

	if(strlen(value)>0)
	{
		cond = pDcmDataset->putAndInsertString(tag, value);
	}

	return cond;
}

OFCondition CSDCMImage::PutAndInsertString(DcmDataset* pDcmDataset, const DcmTag &tag, QString strValue)
{
    OFCondition cond;

    if(strValue.size()>0)
    {
        cond = pDcmDataset->putAndInsertString(tag, strValue.toStdString().c_str());
    }

    return cond;
}

OFCondition CSDCMImage::PutAndInsertString(DcmDataset* pDcmDataset, const DcmTag &tag, OFString strValue)
{
	OFCondition cond;

	cond = PutAndInsertString(pDcmDataset, tag, strValue.c_str());

	return cond;
}

void CSDCMImage::InsertCreationDate(DcmDataset* pDcmDataset)
{
    QString strDate;
	strDate = GetCurrentDate();

    PutAndInsertString(pDcmDataset, DCM_InstanceCreationDate, strDate);
}

void CSDCMImage::InsertCreationTime(DcmDataset* pDcmDataset)
{
    QString strTime;
	strTime = GetCurrentTime();

    PutAndInsertString(pDcmDataset, DCM_InstanceCreationTime, strTime);
}

QString CSDCMImage::GetCurrentDate()
{
    QDate nDate = QDate::currentDate();
    QString strCreationDateString = QString("%1%2%3").arg(nDate.year(), 4, 10, QChar('0')).arg(nDate.month(), 2, 10, QChar('0')).arg(nDate.day(), 2, 10, QChar('0'));
    return strCreationDateString;
}

QString CSDCMImage::GetCurrentTime()
{
    QTime nTime = QTime::currentTime();
    QString strCreationTimeString = QString("%1%2%3").arg(nTime.hour(), 2, 10, QChar('0')).arg(nTime.minute(), 2, 10, QChar('0')).arg(nTime.second(), 2, 10, QChar('0'));
    return strCreationTimeString;
}

void CSDCMImage::WritePatientInfo(DcmDataset* pDcmDataset, WorklistResponseData* pWorklistData)
{
    QString strPatientName;
    strPatientName = pWorklistData->m_Patient.strPatientName;

	PutAndInsertString(pDcmDataset, DCM_PatientName, strPatientName);

    PutAndInsertString(pDcmDataset, DCM_PatientID, pWorklistData->m_Patient.strPatientID);
    PutAndInsertString(pDcmDataset, DCM_PatientSex, pWorklistData->m_Patient.strPatientSex);

    if(pWorklistData->m_Patient.strPatientBirthDate.isEmpty()==false)
	{
        PutAndInsertString(pDcmDataset, DCM_PatientBirthDate, pWorklistData->m_Patient.strPatientBirthDate);

		
		SDCM_AGE nAge;
        nAge = ComputeAge(pWorklistData->m_Patient.strPatientBirthDate);
		if(nAge.m_nYears>0)
		{
            QString strAge;
            strAge = QString("%1Y").arg(QString::number(nAge.m_nYears));                        
            PutAndInsertString(pDcmDataset, DCM_PatientAge, (OFString)strAge.toStdString().c_str());
		}
    }

    PutAndInsertString(pDcmDataset, DCM_PatientWeight, pWorklistData->m_Patient.strPatientWeight);

    PutAndInsertString(pDcmDataset, DCM_PatientComments, pWorklistData->m_Patient.strPatientComments);


    //BodyPartExamined
    PutAndInsertString(pDcmDataset, DCM_BodyPartExamined, pWorklistData->m_Series.strBodyPartExamined);


    //PatientOrientation
    PutAndInsertString(pDcmDataset, DCM_PatientOrientation, pWorklistData->strPatientOrientation);

    //Patient Location
    PutAndInsertString(pDcmDataset, DCM_CurrentPatientLocation, pWorklistData->m_Patient.strPatientLocation);
}

void CSDCMImage::WriteScheduledProcedureStep(DcmDataset* pDcmDataset, WorklistResponseData* pWorklistData)
{

}

OFString CSDCMImage::CreateStudyInstanceUID()
{
    OFString strStudyInstanceUID;
    OFString strTmp;
	int i=0;

    /*

	COleDateTime dt = COleDateTime::GetCurrentTime();		
	strTmp.Format(".%04d%02d%02d.%02d%02d%02d.", dt.GetYear(), dt.GetMonth(), dt.GetDay(), dt.GetHour(),dt.GetMinute(), dt.GetSecond());

	strStudyInstanceUID = CSDCM::m_strManufacturerUID;
	strStudyInstanceUID += strTmp;

	strTmp = CSDCM::m_strInstitutionName;	
	for(i=0 ; i<CSDCM::m_strStationName.GetLength() ; i++)
	{
		char c = CSDCM::m_strStationName.GetAt(i);
		strTmp.Format("%d", c);
		strStudyInstanceUID += strTmp;
	}
	strTmp += ".";

	strTmp = CSDCM::m_strStationName;
	for(i=0 ; i<CSDCM::m_strStationName.GetLength() ; i++)
	{
		char c = CSDCM::m_strStationName.GetAt(i);
		strTmp.Format("%d", c);
		strStudyInstanceUID += strTmp;
	}
    */

	return strStudyInstanceUID;
}

void CSDCMImage::WriteStudyInfo(DcmDataset* pDcmDataset, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, OFString strNewStudyInstanceUID)
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    OFString strSOPClassUID;
    OFString strMediaStorageSOPClassUID;
    OFString strModality;

    OFString strStudyInstanceUID;
    OFString strSeriesInstanceUID;
    OFString strImageInstanceUID;

	
    OFString strStudyDescription;
    OFString strSeriesDescription;

	
    OFString strAccessionNumber;
    OFString strSeriesNumber;
    OFString strImageNumber;

    OFString strReferringPhysicianName;

    OFString strPerformedProcedureStepStartDate;
    OFString strPerformedProcedureStepStartTime;
    OFString strPerformedProcedureStepDescription;

    OFString strOperatorsName;

    OFString strStudyID;

    strStudyID = pWorklistData->m_ScheduledData.strScheduledCodeValue.toStdString().c_str();


    strPerformedProcedureStepStartDate = pWorklistData->m_ScheduledData.strScheduledProcedureStepStartDate.toStdString().c_str();
    strPerformedProcedureStepStartTime = pWorklistData->m_ScheduledData.strScheduledProcedureStepStartTime.toStdString().c_str();
    strPerformedProcedureStepDescription =  pWorklistData->m_ScheduledData.strScheduledStepDescription.toStdString().c_str();

    strOperatorsName = pWorklistData->m_Series.strOperatorsName.toStdString().c_str();

    strModality = pWorklistData->m_Series.strModality.toStdString().c_str();

    if(strModality.size()==0)
    {
        CommonData* pCommonData = MainWindow::GetCommonData();
        QString strDefualtModality = pCommonData->GetModality();
        strModality = strDefualtModality.toStdString().c_str();
    }
	
    //strSeriesNumber.Format("%d", nSeriesNumber);
    //strImageNumber.Format("%d", nImageNumber);
    strSeriesNumber = QString::number(nSeriesNumber).toStdString().c_str();
    strImageNumber = QString::number(nImageNumber).toStdString().c_str();

    if(nImageNumber==0)
    {

    }

    if(pWorklistData->m_Study.strStudyInstanceUID.size()==0)
    {

    }

    strSeriesInstanceUID = pWorklistData->m_Series.strSeriesInstanceUID.toStdString().c_str();
    strImageInstanceUID = pWorklistData->m_Image.strInstanceUID.toStdString().c_str();

    if(pWorklistData->m_Study.strStudyInstanceUID.size()>0)
    {
        strStudyInstanceUID = pWorklistData->m_Study.strStudyInstanceUID.toStdString().c_str();
    }
    else
    {
        strStudyInstanceUID = "1.2.276.0.75.2.2.42.896740696295.1.2.3";
    }


    //if(strSeriesInstanceUID.length()==0)
    {
        strSeriesInstanceUID = strStudyInstanceUID + "." + strSeriesNumber;
    }

    if(strImageInstanceUID.length()==0)
    {
        strImageInstanceUID = strSeriesInstanceUID + "." + strImageNumber;
    }



	if(bChangeUID==TRUE)
	{
		//strStudyInstanceUID = CreateStudyInstanceUID();
        if(strNewStudyInstanceUID.length()>0)
		{
			strStudyInstanceUID = strNewStudyInstanceUID;
		}
	}

	//strStudyInstanceUID = "1.2.276.0.75.2.5.30.25.20170601.2343000.123.4";

    //strSeriesInstanceUID = strStudyInstanceUID + "." + strSeriesNumber;
    //strImageInstanceUID = strSeriesInstanceUID + "." + strImageNumber;


    strAccessionNumber = pWorklistData->m_Study.strAccessionNumber.toStdString().c_str();
    if (strAccessionNumber.length() == 0)
	{
		strAccessionNumber = "1";
	}

    strReferringPhysicianName = pWorklistData->strReferringPhysicianName.toStdString().c_str();
	
    if (strModality == "SC")
	{
		strSOPClassUID = UID_SecondaryCaptureImageStorage;
		//strMediaStorageSOPClassUID = UID_SecondaryCaptureImageStorage;

        strStudyDescription = "SC Study Description";
        strSeriesDescription = "SC Series Description";
	}
    else if (strModality == "OT")
	{
		strSOPClassUID = UID_SecondaryCaptureImageStorage;
		//strMediaStorageSOPClassUID = UID_SecondaryCaptureImageStorage;

        strStudyDescription = "OT Study Description";
        strSeriesDescription = "OT Series Description";
	}
    else if (strModality == "ES")
	{
		strSOPClassUID = UID_VLEndoscopicImageStorage;
		strMediaStorageSOPClassUID = UID_VLEndoscopicImageStorage;

        strStudyDescription = "ES Study Description";
        strSeriesDescription = "ES Series Description";
	}
    else if (strModality == "CR")
	{
		strSOPClassUID = UID_ComputedRadiographyImageStorage;
		strMediaStorageSOPClassUID = UID_ComputedRadiographyImageStorage;

        strStudyDescription = "CR Study Description";
        strSeriesDescription = "CR Series Description";
	}
    else if (strModality == "DR")
	{
		strSOPClassUID = UID_DigitalXRayImageStorageForPresentation;
		strMediaStorageSOPClassUID = UID_DigitalXRayImageStorageForPresentation;

        strStudyDescription = "DR Study Description";
        strSeriesDescription = "DR Series Description";
	}
    else if (strModality == "BMD")
    {
        strSOPClassUID = UID_DigitalXRayImageStorageForPresentation;
        strMediaStorageSOPClassUID = UID_DigitalXRayImageStorageForPresentation;

        strStudyDescription = "BMD Study Description";
        strSeriesDescription = "BMD Series Description";
    }
    else if (strModality == "OP")
	{
		strSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
		//strMediaStorageSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        strStudyDescription = "OP Study Description";
        strSeriesDescription = "OP Series Description";
	}
    else if (strModality == "OPT")
	{
		strSOPClassUID = UID_OphthalmicTomographyImageStorage;
		//strMediaStorageSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        strStudyDescription = "OPT Study Description";
        strSeriesDescription = "OPT Series Description";
	}
    else if (strModality == "OCT")
	{
		strSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
		//strMediaStorageSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        strStudyDescription = "OCT Study Description";
        strSeriesDescription = "OCT Series Description";
	}

    if (pWorklistData->m_Series.strSeriesDescription.size()>0)
    {
        strSeriesDescription = pWorklistData->m_Series.strSeriesDescription.toStdString().c_str();
    }

    if (pWorklistData->m_Study.strStudyDescription.size()>0)
	{
        strStudyDescription = pWorklistData->m_Study.strStudyDescription.toStdString().c_str();
        strSeriesDescription = pWorklistData->m_Study.strStudyDescription.toStdString().c_str();
	}

	//Media Storage SOP UID
    if (strMediaStorageSOPClassUID.length() > 0)
	{
        //PutAndInsertString(pDcmDataset, DCM_MediaStorageSOPClassUID, (OFString)strMediaStorageSOPClassUID);
	}
	


	//SOP Common Info
	//UTF-8 : ISO_IR 192 
	//Ansi : ISO_IR 100
	//PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO_IR 100"); //(ISO IR 100), (ISO 2022 IR 149)	

	
    //OFString strEncDICOM = CSDCMStringEncoder::GetStringEncDICOM();
    OFString strEncDICOM = "UTF-8";

    strEncDICOM = pCommonData->GetDICOMCharacterSet().toStdString().c_str();

	if (strEncDICOM == "ASCII")
	{
		PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO_IR 100"); //ANSI
	}
	else if (strEncDICOM == "ISO-2022-KR")
	{
		PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO 2022 IR 149"); //KOREAN
	}
	else if (strEncDICOM == "EUC-KR")
	{
		PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO 2022 IR 149"); //KOREAN
	}
	else if (strEncDICOM == "UTF-8")
	{
		PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO_IR 192"); //UTF-8
	}
	
	
	PutAndInsertString(pDcmDataset, DCM_SOPClassUID, strSOPClassUID);	

	//Scheduled Info
	PutAndInsertString(pDcmDataset, DCM_PerformedProcedureStepStartDate, strPerformedProcedureStepStartDate);

    if(strPerformedProcedureStepStartTime.length()>0)
	{
        //if(strPerformedProcedureStepStartTime.Find(".")<0)
        if(strPerformedProcedureStepStartTime.find(".")<=0)
		{
            strPerformedProcedureStepStartTime += "";
		}
		PutAndInsertString(pDcmDataset, DCM_PerformedProcedureStepStartTime, strPerformedProcedureStepStartTime);
	}
	
	PutAndInsertString(pDcmDataset, DCM_PerformedProcedureStepDescription, strPerformedProcedureStepDescription);
	
	//UID Info
	PutAndInsertString(pDcmDataset, DCM_StudyInstanceUID, strStudyInstanceUID);
	PutAndInsertString(pDcmDataset, DCM_SeriesInstanceUID, strSeriesInstanceUID);
	PutAndInsertString(pDcmDataset, DCM_SOPInstanceUID, strImageInstanceUID);

	//General Study	
	PutAndInsertString(pDcmDataset, DCM_ReferringPhysicianName, strReferringPhysicianName);


	PutAndInsertString(pDcmDataset, DCM_AccessionNumber, strAccessionNumber);
	PutAndInsertString(pDcmDataset, DCM_StudyDescription, strStudyDescription);
	
	
	//General Series
	PutAndInsertString(pDcmDataset, DCM_Modality, strModality);
	PutAndInsertString(pDcmDataset, DCM_SeriesDescription, strSeriesDescription);	
	PutAndInsertString(pDcmDataset, DCM_SeriesNumber, strSeriesNumber);


    PutAndInsertString(pDcmDataset, DCM_OperatorsName, strOperatorsName);

    //Study ID
    PutAndInsertString(pDcmDataset, DCM_StudyID, strStudyID);
}


void CSDCMImage::WriteStudyInfo(DcmDataset* pDcmDataset, WorklistResponseData* pWorklistData, int nSeriesNumber, int nImageNumber, BOOL bChangeUID, QString strNewStudyInstanceUID)
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    QString strSOPClassUID;
    QString strMediaStorageSOPClassUID;
    QString strModality;

    QString strStudyInstanceUID;
    QString strSeriesInstanceUID;
    QString strImageInstanceUID;


    QString strStudyDescription;
    QString strSeriesDescription;


    QString strAccessionNumber;
    QString strSeriesNumber;
    QString strImageNumber;

    QString strReferringPhysicianName;

    QString strPerformedProcedureStepStartDate;
    QString strPerformedProcedureStepStartTime;
    QString strPerformedProcedureStepDescription;

    QString strOperatorsName;

    QString strStudyID;

    strStudyID = pWorklistData->m_ScheduledData.strScheduledCodeValue;


    strPerformedProcedureStepStartDate = pWorklistData->m_ScheduledData.strScheduledProcedureStepStartDate;
    strPerformedProcedureStepStartTime = pWorklistData->m_ScheduledData.strScheduledProcedureStepStartTime;
    strPerformedProcedureStepDescription =  pWorklistData->m_ScheduledData.strScheduledStepDescription;

    strOperatorsName = pWorklistData->m_Series.strOperatorsName;

    strModality = pWorklistData->m_Series.strModality;

    if(strModality.size()==0)
    {
        CommonData* pCommonData = MainWindow::GetCommonData();
        QString strDefualtModality = pCommonData->GetModality();
        strModality = strDefualtModality;
    }

    //strSeriesNumber.Format("%d", nSeriesNumber);
    //strImageNumber.Format("%d", nImageNumber);
    strSeriesNumber = QString::number(nSeriesNumber);
    strImageNumber = QString::number(nImageNumber);

    if(nImageNumber==0)
    {

    }

    if(pWorklistData->m_Study.strStudyInstanceUID.size()==0)
    {

    }

    strSeriesInstanceUID = pWorklistData->m_Series.strSeriesInstanceUID;
    strImageInstanceUID = pWorklistData->m_Image.strInstanceUID;

    if(pWorklistData->m_Study.strStudyInstanceUID.size()>0)
    {
        strStudyInstanceUID = pWorklistData->m_Study.strStudyInstanceUID;
    }
    else
    {
        strStudyInstanceUID = "1.2.276.0.75.2.2.42.896740696295.1.2.3";
    }


    //if(strSeriesInstanceUID.length()==0)
    {
        strSeriesInstanceUID = strStudyInstanceUID + "." + strSeriesNumber;
    }

    if(strImageInstanceUID.size()==0)
    {
        strImageInstanceUID = strSeriesInstanceUID + "." + strImageNumber;
    }



    if(bChangeUID==TRUE)
    {
        //strStudyInstanceUID = CreateStudyInstanceUID();
        if(strNewStudyInstanceUID.length()>0)
        {
            strStudyInstanceUID = strNewStudyInstanceUID;
        }
    }

    //strStudyInstanceUID = "1.2.276.0.75.2.5.30.25.20170601.2343000.123.4";

    //strSeriesInstanceUID = strStudyInstanceUID + "." + strSeriesNumber;
    //strImageInstanceUID = strSeriesInstanceUID + "." + strImageNumber;


    strAccessionNumber = pWorklistData->m_Study.strAccessionNumber;
    if (strAccessionNumber.length() == 0)
    {
        strAccessionNumber = "1";
    }

    strReferringPhysicianName = pWorklistData->strReferringPhysicianName;

    if (strModality == "SC")
    {
        strSOPClassUID = UID_SecondaryCaptureImageStorage;
        //strMediaStorageSOPClassUID = UID_SecondaryCaptureImageStorage;

        strStudyDescription = "SC Study Description";
        strSeriesDescription = "SC Series Description";
    }
    else if (strModality == "OT")
    {
        strSOPClassUID = UID_SecondaryCaptureImageStorage;
        //strMediaStorageSOPClassUID = UID_SecondaryCaptureImageStorage;

        strStudyDescription = "OT Study Description";
        strSeriesDescription = "OT Series Description";
    }
    else if (strModality == "ES")
    {
        strSOPClassUID = UID_VLEndoscopicImageStorage;
        strMediaStorageSOPClassUID = UID_VLEndoscopicImageStorage;

        strStudyDescription = "ES Study Description";
        strSeriesDescription = "ES Series Description";
    }
    else if (strModality == "CR")
    {
        strSOPClassUID = UID_ComputedRadiographyImageStorage;
        strMediaStorageSOPClassUID = UID_ComputedRadiographyImageStorage;

        strStudyDescription = "CR Study Description";
        strSeriesDescription = "CR Series Description";
    }
    else if (strModality == "DR")
    {
        strSOPClassUID = UID_DigitalXRayImageStorageForPresentation;
        strMediaStorageSOPClassUID = UID_DigitalXRayImageStorageForPresentation;

        strStudyDescription = "DR Study Description";
        strSeriesDescription = "DR Series Description";
    }
    else if (strModality == "BMD")
    {
        strSOPClassUID = UID_DigitalXRayImageStorageForPresentation;
        strMediaStorageSOPClassUID = UID_DigitalXRayImageStorageForPresentation;

        strStudyDescription = "BMD Study Description";
        strSeriesDescription = "BMD Series Description";
    }
    else if (strModality == "OP")
    {
        strSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        //strMediaStorageSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        strStudyDescription = "OP Study Description";
        strSeriesDescription = "OP Series Description";
    }
    else if (strModality == "OPT")
    {
        strSOPClassUID = UID_OphthalmicTomographyImageStorage;
        //strMediaStorageSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        strStudyDescription = "OPT Study Description";
        strSeriesDescription = "OPT Series Description";
    }
    else if (strModality == "OCT")
    {
        strSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        //strMediaStorageSOPClassUID = UID_OphthalmicPhotography8BitImageStorage;
        strStudyDescription = "OCT Study Description";
        strSeriesDescription = "OCT Series Description";
    }

    if (pWorklistData->m_Series.strSeriesDescription.size()>0)
    {
        strSeriesDescription = pWorklistData->m_Series.strSeriesDescription;
    }

    if (pWorklistData->m_Study.strStudyDescription.size()>0)
    {
        strStudyDescription = pWorklistData->m_Study.strStudyDescription;
        strSeriesDescription = pWorklistData->m_Study.strStudyDescription;
    }

    //Media Storage SOP UID
    if (strMediaStorageSOPClassUID.length() > 0)
    {
        //PutAndInsertString(pDcmDataset, DCM_MediaStorageSOPClassUID, (OFString)strMediaStorageSOPClassUID);
    }



    //SOP Common Info
    //UTF-8 : ISO_IR 192
    //Ansi : ISO_IR 100
    //PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO_IR 100"); //(ISO IR 100), (ISO 2022 IR 149)


    //OFString strEncDICOM = CSDCMStringEncoder::GetStringEncDICOM();
    QString strEncDICOM = "UTF-8";

    strEncDICOM = pCommonData->GetDICOMCharacterSet();

    if (strEncDICOM == "ASCII")
    {
        PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO_IR 100"); //ANSI
    }
    else if (strEncDICOM == "ISO-2022-KR")
    {
        PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO 2022 IR 149"); //KOREAN
    }
    else if (strEncDICOM == "EUC-KR")
    {
        PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO 2022 IR 149"); //KOREAN
    }
    else if (strEncDICOM == "UTF-8")
    {
        PutAndInsertString(pDcmDataset, DCM_SpecificCharacterSet, "ISO_IR 192"); //UTF-8
    }


    PutAndInsertString(pDcmDataset, DCM_SOPClassUID, strSOPClassUID);

    //Scheduled Info
    PutAndInsertString(pDcmDataset, DCM_PerformedProcedureStepStartDate, strPerformedProcedureStepStartDate);

    if(strPerformedProcedureStepStartTime.size()>0)
    {
        /*
        if(strPerformedProcedureStepStartTime.find(".")<=0)
        {
            strPerformedProcedureStepStartTime += "";
        }
        */

        strPerformedProcedureStepStartTime.replace(".", "");
        PutAndInsertString(pDcmDataset, DCM_PerformedProcedureStepStartTime, strPerformedProcedureStepStartTime);
    }

    PutAndInsertString(pDcmDataset, DCM_PerformedProcedureStepDescription, strPerformedProcedureStepDescription);

    //UID Info
    PutAndInsertString(pDcmDataset, DCM_StudyInstanceUID, strStudyInstanceUID);
    PutAndInsertString(pDcmDataset, DCM_SeriesInstanceUID, strSeriesInstanceUID);
    PutAndInsertString(pDcmDataset, DCM_SOPInstanceUID, strImageInstanceUID);

    //General Study
    PutAndInsertString(pDcmDataset, DCM_ReferringPhysicianName, strReferringPhysicianName);


    PutAndInsertString(pDcmDataset, DCM_AccessionNumber, strAccessionNumber);
    PutAndInsertString(pDcmDataset, DCM_StudyDescription, strStudyDescription);


    //General Series
    PutAndInsertString(pDcmDataset, DCM_Modality, strModality);
    PutAndInsertString(pDcmDataset, DCM_SeriesDescription, strSeriesDescription);
    PutAndInsertString(pDcmDataset, DCM_SeriesNumber, strSeriesNumber);


    PutAndInsertString(pDcmDataset, DCM_OperatorsName, strOperatorsName);

    //Study ID
    PutAndInsertString(pDcmDataset, DCM_StudyID, strStudyID);
}

void CSDCMImage::WriteImageInfo(DcmDataset* pDcmDataset, OFString strContentDate, OFString strContentTime, WorklistResponseData* pWorklistData, int nImageNumber)
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    bool bIsUseFixWidthLevel = (bool)pCommonData->GetUseFixWidthLevel();
    OFString strImageNumber;

    OFString strAcquisitionDateTime;


    OFString strModality;



    strAcquisitionDateTime = strContentDate.c_str();
    strAcquisitionDateTime += strContentTime.c_str();

    //strImageNumber.Format("%d", nImageNumber);
    strImageNumber = QString::number(nImageNumber).toStdString().c_str();
    PutAndInsertString(pDcmDataset, DCM_InstanceNumber, strImageNumber);
    //PutAndInsertString(pDcmDataset, DCM_ImageComments, "Comment NULL");

    PutAndInsertString(pDcmDataset, DCM_AcquisitionDateTime, strAcquisitionDateTime);

    if(bIsUseFixWidthLevel==true)
    {
        //PutAndInsertString(pDcmDataset, DCM_WindowCenter, "156.0");
        //PutAndInsertString(pDcmDataset, DCM_WindowWidth, "268.0");

        PutAndInsertString(pDcmDataset, DCM_WindowCenter, "128.0");
        PutAndInsertString(pDcmDataset, DCM_WindowWidth, "185.0");
    }
    else
    {
        PutAndInsertString(pDcmDataset, DCM_WindowCenter, "128.0");
        PutAndInsertString(pDcmDataset, DCM_WindowWidth, "256.0");

    }

    pDcmDataset->putAndInsertUint16(DCM_BitsAllocated, 8);
    pDcmDataset->putAndInsertUint16(DCM_BitsStored, 8);
    pDcmDataset->putAndInsertUint16(DCM_HighBit, 7);
    pDcmDataset->putAndInsertUint16(DCM_PixelRepresentation, 0);


    DcmStack cDcmStack;
    cDcmStack.clear();
    OFCondition error = pDcmDataset->search(DCM_PixelData, cDcmStack);

    strModality = pWorklistData->m_Series.strModality.toStdString().c_str();
    BOOL bGray = FALSE;
    if(strModality == "CR")
    {
        bGray = TRUE;
    }

    bGray = FALSE;

    if (bGray == TRUE)
    {
        pDcmDataset->putAndInsertUint16(DCM_SamplesPerPixel, 1);
        PutAndInsertString(pDcmDataset, DCM_PhotometricInterpretation, "MONOCHROME2");
        pDcmDataset->putAndInsertUint16(DCM_Rows, m_nHeight);
        pDcmDataset->putAndInsertUint16(DCM_Columns, m_nWidth);
        pDcmDataset->putAndInsertUint8Array(DCM_PixelData, (Uint8*)m_pData, m_nWidth*m_nHeight, TRUE);
    }
    else
    {
        pDcmDataset->putAndInsertUint16(DCM_PlanarConfiguration, 0);

        PutAndInsertString(pDcmDataset, DCM_NumberOfFrames, "1");
        pDcmDataset->putAndInsertUint16(DCM_SamplesPerPixel, 3);
        PutAndInsertString(pDcmDataset, DCM_PhotometricInterpretation, "RGB");

        PutAndInsertString(pDcmDataset, DCM_ConversionType, "DV");

        pDcmDataset->putAndInsertUint16(DCM_Rows, m_nHeight);
        pDcmDataset->putAndInsertUint16(DCM_Columns, m_nWidth);
        pDcmDataset->putAndInsertUint8Array(DCM_PixelData, (Uint8*)m_pData, m_nWidth*m_nHeight*3, TRUE);
    }

}

void CSDCMImage::WriteImageInfo(DcmDataset* pDcmDataset, QString strContentDate, QString strContentTime, WorklistResponseData* pWorklistData, int nImageNumber)
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    bool bIsUseFixWidthLevel = (bool)pCommonData->GetUseFixWidthLevel();
    QString strImageNumber;
    QString strAcquisitionDateTime;
    QString strModality;

    strAcquisitionDateTime = strContentDate;
    strAcquisitionDateTime += strContentTime;

    //strImageNumber.Format("%d", nImageNumber);
    strImageNumber = QString::number(nImageNumber);
    PutAndInsertString(pDcmDataset, DCM_InstanceNumber, strImageNumber);
    //PutAndInsertString(pDcmDataset, DCM_ImageComments, "Comment NULL");

    PutAndInsertString(pDcmDataset, DCM_AcquisitionDateTime, strAcquisitionDateTime);

    if(bIsUseFixWidthLevel==true)
    {
        //PutAndInsertString(pDcmDataset, DCM_WindowCenter, "156.0");
        //PutAndInsertString(pDcmDataset, DCM_WindowWidth, "268.0");

        PutAndInsertString(pDcmDataset, DCM_WindowCenter, "128.0");
        PutAndInsertString(pDcmDataset, DCM_WindowWidth, "185.0");
    }
    else
    {
        PutAndInsertString(pDcmDataset, DCM_WindowCenter, "128.0");
        PutAndInsertString(pDcmDataset, DCM_WindowWidth, "256.0");

    }

    pDcmDataset->putAndInsertUint16(DCM_BitsAllocated, 8);
    pDcmDataset->putAndInsertUint16(DCM_BitsStored, 8);
    pDcmDataset->putAndInsertUint16(DCM_HighBit, 7);
    pDcmDataset->putAndInsertUint16(DCM_PixelRepresentation, 0);


    DcmStack cDcmStack;
    cDcmStack.clear();
    OFCondition error = pDcmDataset->search(DCM_PixelData, cDcmStack);

    strModality = pWorklistData->m_Series.strModality;
    BOOL bGray = FALSE;
    if(strModality == "CR")
    {
        bGray = TRUE;
    }

    bGray = FALSE;

    if (bGray == TRUE)
    {
        pDcmDataset->putAndInsertUint16(DCM_SamplesPerPixel, 1);
        PutAndInsertString(pDcmDataset, DCM_PhotometricInterpretation, "MONOCHROME2");
        pDcmDataset->putAndInsertUint16(DCM_Rows, m_nHeight);
        pDcmDataset->putAndInsertUint16(DCM_Columns, m_nWidth);
        pDcmDataset->putAndInsertUint8Array(DCM_PixelData, (Uint8*)m_pData, m_nWidth*m_nHeight, TRUE);
    }
    else
    {
        pDcmDataset->putAndInsertUint16(DCM_PlanarConfiguration, 0);

        PutAndInsertString(pDcmDataset, DCM_NumberOfFrames, "1");
        pDcmDataset->putAndInsertUint16(DCM_SamplesPerPixel, 3);
        PutAndInsertString(pDcmDataset, DCM_PhotometricInterpretation, "RGB");

        PutAndInsertString(pDcmDataset, DCM_ConversionType, "DV");

        pDcmDataset->putAndInsertUint16(DCM_Rows, m_nHeight);
        pDcmDataset->putAndInsertUint16(DCM_Columns, m_nWidth);
        pDcmDataset->putAndInsertUint8Array(DCM_PixelData, (Uint8*)m_pData, m_nWidth*m_nHeight*3, TRUE);
    }

}


void CSDCMImage::WriteImageInfo(DcmDataset* pDcmDataset, WorklistResponseData* pWorklistData, int nImageNumber)
{
    QString strCreationDate;
    QString strCreationTime;

    strCreationDate = GetCurrentDate();
    strCreationTime = GetCurrentTime();

    WriteImageInfo(pDcmDataset, strCreationDate, strCreationTime, pWorklistData, nImageNumber);
	
}

void CSDCMImage::WriteDateTime(DcmDataset* pDcmDataset, WorklistResponseData* pWorklistData)
{
    QString strCreationDate;
    QString strCreationTime;
    QString strStudyDate;
    QString strStudyTime;
    QString strSeriesDate;
    QString strSeriesTime;
	

    if(pWorklistData->m_Image.strAcquisitionDate.length()>0)
    {
        strCreationDate = pWorklistData->m_Image.strAcquisitionDate;
        strCreationTime = pWorklistData->m_Image.strAcquisitionTime;
    }


    //strStudyDate = pWorklistData->m_ScheduledData.strScheduledProcedureStepStartDate.c_str();
    //strStudyTime = pWorklistData->m_ScheduledData.strScheduledProcedureStepStartTime.c_str();

    strStudyDate = pWorklistData->m_Study.strStudyDate;
    strStudyTime = pWorklistData->m_Study.strStudyTime;

    strSeriesDate = pWorklistData->m_Series.strSeriesDate;
    strSeriesTime = pWorklistData->m_Series.strSeriesTime;


    if (strStudyTime.length()>0)
	{	
        strStudyTime.replace(".", "");
	}

    if(strCreationDate.length()==0)
    {
        strCreationDate = GetCurrentDate();
        strCreationTime = GetCurrentTime();
    }


    if (strStudyDate.length()==0)
	{
		strStudyDate = strCreationDate;
	}

    if (strStudyTime.length()==0)
	{
		strStudyTime = strCreationTime;
	}

    if (strSeriesDate.length()==0)
	{
		strSeriesDate = strStudyDate;
	}

    if (strSeriesTime.length()==0)
	{
		strSeriesTime = strStudyTime;
	}

	PutAndInsertString(pDcmDataset, DCM_StudyDate, strStudyDate);
	PutAndInsertString(pDcmDataset, DCM_StudyTime, strStudyTime);
	PutAndInsertString(pDcmDataset, DCM_SeriesDate, strSeriesDate);
	PutAndInsertString(pDcmDataset, DCM_SeriesTime, strSeriesTime);
	PutAndInsertString(pDcmDataset, DCM_InstanceCreationDate, strCreationDate);
	PutAndInsertString(pDcmDataset, DCM_InstanceCreationTime, strCreationTime);
	PutAndInsertString(pDcmDataset, DCM_ContentDate, strCreationDate);
	PutAndInsertString(pDcmDataset, DCM_ContentTime, strCreationTime);
	PutAndInsertString(pDcmDataset, DCM_AcquisitionDate, strCreationDate);
	PutAndInsertString(pDcmDataset, DCM_AcquisitionTime, strCreationTime);
}

//R=right
//L=left
//U=unpaired
//B=both
void CSDCMImage::WriteLaterality(DcmDataset* pDcmDataset, OFString strLaterality, OFString strImageLaterality)
{
	//Must be set when All image same laterality
	//PutAndInsertString(pDcmDataset, DCM_Laterality, strLaterality);

	//Just Image
	PutAndInsertString(pDcmDataset, DCM_ImageLaterality, strImageLaterality);
}

void CSDCMImage::WriteLaterality(DcmDataset* pDcmDataset, QString strLaterality, QString strImageLaterality)
{
    //Just Image
    PutAndInsertString(pDcmDataset, DCM_ImageLaterality, strImageLaterality);
}

void CSDCMImage::WriteImageType(DcmDataset* pDcmDataset, OFString strImageType)
{
    OFString strData;

	if(strImageType.empty()==true)
	{
		strData = "DERIVED";
		strData += char(0x5c);
		strData += "PRIMARY";	
	}
	else
	{
		strData = strImageType.c_str();
	}

	PutAndInsertString(pDcmDataset, DCM_ImageType, strData);
}

void CSDCMImage::WriteImageType(DcmDataset* pDcmDataset, QString strImageType)
{
    QString strData;

    if(strImageType.isEmpty()==true)
    {
        strData = "DERIVED";
        strData += char(0x5c);
        strData += "PRIMARY";
    }
    else
    {
        strData = strImageType;
    }

    PutAndInsertString(pDcmDataset, DCM_ImageType, strData);
}

void CSDCMImage::WriteDeviceInfo(DcmDataset* pDcmDataset)
{
    CommonData* pCommonData = MainWindow::GetCommonData();
    QString strManufacturer = "Storage Solution for Doctors co,.ltd.";
    QString strManufacturerModelName = "SmartQuadra";
    QString strStationName = pCommonData->GetStationName();
    QString strInstitutionName = pCommonData->GetInstitutionName();

    QString strDeviceSerialNumber = "Device1.2";
    QString strSoftwareVersions = "V2.1";

	//General Equipment Info
    PutAndInsertString(pDcmDataset, DCM_Manufacturer, strManufacturer);
    PutAndInsertString(pDcmDataset, DCM_ManufacturerModelName, strManufacturerModelName);
    PutAndInsertString(pDcmDataset, DCM_StationName, strStationName);
    PutAndInsertString(pDcmDataset, DCM_InstitutionName, strInstitutionName);

	//Device Information
    PutAndInsertString(pDcmDataset, DCM_DeviceSerialNumber, strDeviceSerialNumber);
    PutAndInsertString(pDcmDataset, DCM_SoftwareVersions, strSoftwareVersions);

}

void CSDCMImage::SetTransferSyntax(E_TransferSyntax nTransferSyntax)
{
	m_TransferSyntaxOutput = nTransferSyntax;
}






void CSDCMImage::CharacterSetConversion(DcmDataset* pDcmDataset)
{	
    CommonData* pCommonData = MainWindow::GetCommonData();
    QString strEnc = pCommonData->GetDICOMCharacterSet();

	int i=0;    
	for (i = 0; i<(int)pDcmDataset->card(); i++)
	{
		DcmElement* pElement = NULL;

		OFString strData;
		DcmTagKey dcmKey;
		DcmTag tag;

		pElement = pDcmDataset->getElement(i);
		tag = pElement->getTag();
//		int nGroup = tag.getGroup();
//		int nElement = tag.getElement();

		DcmEVR vr;
		vr = pElement->getVR();

        if(vr==EVR_PN || vr==EVR_LO)
		{
			OFString strData;
			OFString strConv;
			pElement->getOFStringArray(strData);

            //int nRet = 0;
            //nRet = CSDCMStringEncoder::ConvertString(strData, strConv, strEncSystem, strEncDICOM);
            if(strEnc=="EUC-KR")
            {
                //strConv = CharConvert::Convert(strData.data(), strEnc).toStdString().c_str();
                QString strQData = strData.data();
                QByteArray strArray = CharConvert::UTF8toEUCKR(strQData);
                strConv = strArray.data();
                //strConv = strQConv.toStdString().c_str();
                //strConv = strData;
                pElement->putOFStringArray(strConv);

            }
		}
        else if(vr==EVR_SQ)
        {
            //CharacterSetConversion(pElement);

        }
	}    
}


list<OFString>* CSDCMImage::GetListInputFile()
{
	return m_pListInputFile;
}
