//.h文件
#pragma once
class dicomRead
{
public:
	dicomRead(void);
	~dicomRead(void);
private:
	const char* PatientName;
	const char* PatientSex;
	long PatientAge;
	long Width;
	long Height;
	long Depth;
	long WindowsLevel;
	long WindowsWidth;
	double space[2];
	double spaceZ;
	double ImagePosition[3];
	double ImageOrientation[6];
	unsigned short* buffer;
public:
	const char* GetPatientName();
	const char* GetPatientSex();
	long GetPatientAge();
	long GetWidth();
	long GetHeight();
	long GetDepth();
	long GetWindowsLevel();
	long GetWindowsWidth();
	double* GetSpace();
	double GetSpaceZ(double orientation[6],double position1[3],double position2[3]);
	double* GetImagePosition();
	double* GetImageOrientation();
	unsigned short* GetBuffer();
	void DicomRead(const char* path);
	void compressionDicom(const char* path,int repType);
	void decompressionDicom(const char* path);
	void readDICOMInfo(const char* path);
};

#include "dicomRead.h"
#include <map>
#include <math.h>
#include <iostream>
#include <string>
#include "dcmtk\config\osconfig.h"
#include "dcmtk\dcmdata\dctk.h"
#include "dcmtk\dcmdata\dcxfer.h"
#include "dcmtk\dcmdata\dctag.h"
#include "dcmtk\dcmdata\dctagkey.h"
#include "dcmtk\dcmdata\dcpxitem.h"
#include "dcmtk\oflog\config.h"
#include "dcmtk\dcmimgle\dcmimage.h"
#include "dcmtk\dcmjpeg\djdecode.h"
#include "dcmtk\dcmjpeg\djdijg12.h"
#include "dcmtk\dcmjpeg\djdijg8.h"
#include "dcmtk\dcmjpeg\djdijg16.h"
#include "dcmtk\dcmjpeg\djencode.h"
#include "dcmtk\dcmjpeg\djrploss.h"
#include "dcmtk\dcmjpeg\djrplol.h"
#include "dcmtk\dcmdata\dcrleerg.h"
#include "dcmtk\dcmdata\dcrledrg.h"
using namespace std;


DcmFileFormat *fileformat;
OFCondition status;
DcmDataset *dicom;

dicomRead::dicomRead(void)
{
}

dicomRead::~dicomRead(void)
{
}

void dicomRead::compressionDicom(const char* path, int repType)
{
	DcmFileFormat *fileformat=new DcmFileFormat();
	OFCondition status = fileformat->loadFile(path);
	DcmDataset *dataset = fileformat->getDataset();
	DcmItem *metaInfo = fileformat->getMetaInfo();
	const char*	transferSyntax;  
	fileformat->getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, transferSyntax);
	string losslessTransUID="1.2.840.10008.1.2.4.70";
	string lossTransUID="1.2.840.10008.1.2.4.51";
	string losslessP14="1.2.840.10008.1.2.4.57";
	string lossyP1="1.2.840.10008.1.2.4.50";
	string lossyRLE="1.2.840.10008.1.2.5";
	if(transferSyntax==losslessTransUID||transferSyntax==lossTransUID||
		transferSyntax==losslessP14||transferSyntax==lossyP1||transferSyntax==lossyRLE)
	{
		return;
	}
	if(repType==(int)EXS_JPEGProcess14SV1||repType==(int)EXS_JPEGProcess2_4||
		repType==(int)EXS_JPEGProcess14||repType==(int)EXS_JPEGProcess1)
	{
		DJEncoderRegistration::registerCodecs();
		dataset->chooseRepresentation((E_TransferSyntax)repType,NULL);
		if (dataset->canWriteXfer((E_TransferSyntax)repType))
		{
			// force the meta-header UIDs to be re-generated when storing the file
			// since the UIDs in the data set may have changed
			delete metaInfo->remove(DCM_MediaStorageSOPClassUID);
			delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID);
			fileformat->saveFile(path, (E_TransferSyntax)repType);
		}
		DJEncoderRegistration::cleanup();
	}
	else if(repType==EXS_RLELossless)
	{
		DcmRLEEncoderRegistration::registerCodecs();
		dataset->chooseRepresentation((E_TransferSyntax)repType, NULL);
		if (dataset->canWriteXfer((E_TransferSyntax)repType))
		{
			// force the meta-header UIDs to be re-generated when storing the file
			// since the UIDs in the data set may have changed
			delete metaInfo->remove(DCM_MediaStorageSOPClassUID);
			delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID);
			fileformat->saveFile(path, (E_TransferSyntax)repType);
		}
		DcmRLEEncoderRegistration::cleanup();
	}
	else
	{
		return;
	}
}

void dicomRead::decompressionDicom(const char* path)
{
	fileformat=new DcmFileFormat();  
	status = fileformat->loadFile(path);
	const char*	transferSyntax=NULL;  
	fileformat->getMetaInfo()->findAndGetString(DCM_TransferSyntaxUID, transferSyntax);
	dicom = fileformat->getDataset();
	string losslessTransUID="1.2.840.10008.1.2.4.70";
	string lossTransUID="1.2.840.10008.1.2.4.51";
	string losslessP14="1.2.840.10008.1.2.4.57";
	string lossyP1="1.2.840.10008.1.2.4.50";
	string lossyRLE="1.2.840.10008.1.2.5";
	if(transferSyntax==losslessTransUID||transferSyntax==lossTransUID||
		transferSyntax==losslessP14||transferSyntax==lossyP1)
	{
		DJDecoderRegistration::registerCodecs();
		dicom->chooseRepresentation(EXS_LittleEndianExplicit,NULL);
		DJDecoderRegistration::cleanup();
	}
	else if(transferSyntax==lossyRLE)
	{
		DcmRLEDecoderRegistration::registerCodecs();
		dicom->chooseRepresentation(EXS_LittleEndianExplicit,NULL);
		DcmRLEDecoderRegistration::cleanup();
	}
	else
		return;
}

void dicomRead::DicomRead(const char* path)
{
	decompressionDicom(path);
	GetPatientName();
	GetPatientSex();
	GetPatientAge();
	GetWidth();
	GetHeight();
	GetDepth();
	GetSpace();
	GetImagePosition();
	GetImageOrientation();
	//GetSpaceZ();
	GetWindowsLevel();
	GetWindowsWidth();
	GetBuffer();
}

void dicomRead::readDICOMInfo(const char* path)
{
	DcmFileFormat fileformat;  
	OFCondition status = fileformat.loadFile(path);  
	if (status.good())  
	{  
		DcmMetaInfo *metainfo = fileformat.getMetaInfo();
		DcmDataset *dataset = fileformat.getDataset();
		DcmObject *pTag=metainfo->nextInContainer(NULL);
		DcmTagKey dtk;
		const char* vmName;
		OFString elementValue;
		string vmOW="OW";
		string vmOB="OB";
		string vmOF="OF";
		do{
			dtk=pTag->getTag().getXTag();
			vmName=pTag->getTag().getVRName();
			if(vmName==vmOW||vmName==vmOB||vmName==vmOF)
			{
				metainfo->findAndGetOFString(dtk,elementValue);
				cout<<setiosflags(ios::left)<<pTag->getTag()<<"\t"<<vmName<<"\t"
					<<const_cast<DcmTag&>(pTag->getTag()).getTagName()<<"\t"<<pTag->getLength()<<"\t"<<"Total Bytes:"<<pTag->getLength()<<endl;
			}
			else
			{
				metainfo->findAndGetOFStringArray(dtk,elementValue);
				cout<<setiosflags(ios::left)<<pTag->getTag()<<"\t"<<vmName<<"\t"
					<<const_cast<DcmTag&>(pTag->getTag()).getTagName()<<"\t"<<pTag->getLength()<<"\t"<<elementValue<<endl;
			}
			pTag=metainfo->nextInContainer(pTag);
		}while(pTag!=NULL);
		pTag=dataset->nextInContainer(NULL);
		do
		{
			dtk=pTag->getTag().getXTag();
			vmName=pTag->getTag().getVRName();
			if(vmName==vmOW||vmName==vmOB||vmName==vmOF)
			{
				dataset->findAndGetOFString(dtk,elementValue);
				cout<<setiosflags(ios::left)<<pTag->getTag()<<"\t"<<vmName<<"\t"
					<<const_cast<DcmTag&>(pTag->getTag()).getTagName()<<"\t"<<pTag->getLength()<<"\t"<<"Total Bytes:"<<pTag->getLength()<<endl;
			}
			else
			{
				dataset->findAndGetOFStringArray(dtk,elementValue);
				cout<<setiosflags(ios::left)<<pTag->getTag()<<"\t"<<vmName<<"\t"
					<<const_cast<DcmTag&>(pTag->getTag()).getTagName()<<"\t"<<pTag->getLength()<<"\t"<<elementValue<<endl;
			}
			pTag=dataset->nextInContainer(pTag);
		}
		while(pTag!=NULL);
	}
}


const char* dicomRead::GetPatientName()
{
	dicom->findAndGetString(DCM_PatientName,PatientName);
	return PatientName;
}

const char* dicomRead::GetPatientSex()
{
	dicom->findAndGetString(DCM_PatientSex,PatientSex);
	return PatientSex;
}

long dicomRead::GetPatientAge()
{
	dicom->findAndGetLongInt(DCM_PatientAge,PatientAge);
	return PatientAge;
}

long dicomRead::GetWidth()
{
	dicom->findAndGetLongInt(DCM_Columns,Width);
	return Width;
}

long dicomRead::GetHeight()
{
	dicom->findAndGetLongInt(DCM_Rows,Height);
	return Height;
}

long dicomRead::GetDepth()
{
	dicom->findAndGetLongInt(DCM_BitsAllocated,Depth);
	Depth/=8;
	return Depth;
}

double* dicomRead::GetSpace()
{
	dicom->findAndGetFloat64(DCM_PixelSpacing,space[0],0);
	dicom->findAndGetFloat64(DCM_PixelSpacing,space[1],1);
	return space;
}

double* dicomRead::GetImagePosition()
{
	dicom->findAndGetFloat64(DCM_ImagePositionPatient,ImagePosition[0],0);
	dicom->findAndGetFloat64(DCM_ImagePositionPatient,ImagePosition[1],1);
	dicom->findAndGetFloat64(DCM_ImagePositionPatient,ImagePosition[2],2);
	return ImagePosition;
}

double* dicomRead::GetImageOrientation()
{
	dicom->findAndGetFloat64(DCM_ImageOrientationPatient,ImageOrientation[0],0);
	dicom->findAndGetFloat64(DCM_ImageOrientationPatient,ImageOrientation[1],1);
	dicom->findAndGetFloat64(DCM_ImageOrientationPatient,ImageOrientation[2],2);
	dicom->findAndGetFloat64(DCM_ImageOrientationPatient,ImageOrientation[3],3);
	dicom->findAndGetFloat64(DCM_ImageOrientationPatient,ImageOrientation[4],4);
	dicom->findAndGetFloat64(DCM_ImageOrientationPatient,ImageOrientation[5],5);
	return ImageOrientation;
}

double dicomRead::GetSpaceZ(double orientation[6],double position1[3],double position2[3])
{
	//dicom->findAndGetFloat64(DCM_SpacingBetweenSlices, spaceZ);
	double vector[3];
	vector[0]=orientation[1]*orientation[5]-orientation[2]*orientation[4];
	vector[1]=orientation[2]*orientation[3]-orientation[0]*orientation[5];
	vector[2]=orientation[0]*orientation[4]-orientation[3]*orientation[1];
	if(vector[0]==0&&vector[1]==0&&vector[2]==0)
	{
		spaceZ=0.0;
	}
	else
	{
		spaceZ=fabs(vector[0]*(position1[0]-position2[0])+vector[1]*(position1[1]-position2[1])+vector[2]*(position1[2]-position2[2]))/sqrt(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]);
	}
	return spaceZ;
}

long dicomRead::GetWindowsLevel()
{
	dicom->findAndGetLongInt(DCM_WindowCenter,WindowsLevel);
	return WindowsLevel;
}

long dicomRead::GetWindowsWidth()
{
	dicom->findAndGetLongInt(DCM_WindowWidth,WindowsWidth);
	return WindowsWidth;
}

unsigned short* dicomRead::GetBuffer()
{
	unsigned long byeCount;
	byeCount=Width*Height*Depth ;
	const unsigned short* uShortPt= (const unsigned short*) new unsigned char[byeCount];
	dicom->findAndGetUint16Array(DCM_PixelData,uShortPt);
	buffer = (unsigned short *)uShortPt;
	return buffer;
}