📄 dicombmpdlg.cpp
字号:
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CDicomBMPDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CDicomBMPDlg::OnModeChanged()
{
UpdateData(); // Get data from UI
AfxGetApp()->WriteProfileInt("Defaults", "Mode", m_nConvertMode);
}
void CDicomBMPDlg::OnConvertFile()
{
int nIndex = 0;
// Pop up the File Dialog for Open
CFileDialog FileDlg( TRUE, NULL, NULL, OFN_ENABLESIZING,
szFilter_in );
FileDlg.m_ofn.nFilterIndex = (DWORD) (m_nConvertMode+1);
if (m_strFileDir.GetLength())
FileDlg.m_ofn.lpstrInitialDir = m_strFileDir.GetBuffer(3);
if( FileDlg.DoModal() == IDOK ){
// Open and store the file name
CString PathName = FileDlg.GetPathName();
PathName.MakeUpper();
m_strFileName = PathName;
m_strFileDir = PathName;
int index;
if (((index = m_strFileDir.ReverseFind('\\')) != -1)
&& (m_strFileDir.GetAt(index-1) != ':'))
m_strFileDir.SetAt(index, '\0');
// Parse the file format
nIndex = (int) FileDlg.m_ofn.nFilterIndex;
// Save directory and file format into the registry
AfxGetApp()->WriteProfileString("Defaults", "Dir", m_strFileDir);
// Start convertsion
switch(m_nConvertMode)
{
case MODE_DICOM2BMP:
ConvertDicomToBMP();
break;
case MODE_BMP2DICOM:
ConvertBmpToDicom();
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CDicomBMPDlg Main Implementation methods
void CDicomBMPDlg::ConvertBmpToDicom()
{
AfxMessageBox("ConvertBmpToDicom() not implemented");
// To do: insert your BMP to DICOM conversion code here.
}
void CDicomBMPDlg::ConvertDicomToBMP()
{
short int nCols = 0, nRows = 0;
short int nBitsAllocated, nSamplesPerPixel = 1;
short int nHighBit = 0;
float fWindowWidth = 0, fWindowCenter = 0 , fRescaleSlope = 1, fRescaleIntercept = 0;
BOOL bIsSigned = FALSE;
int nBytesP = 0;
int nFrameSize = 0;
long int nLength;
const char *pszFileName = m_strFileName.GetBuffer(3);
char szPhotometric[32]="", szTemp[32]="", szTransferSyntaxUID[80]="";
BOOL bImplicitVR = TRUE;
COMPRESSION_MODE nCompressionMode = COMPRESS_NONE;
DATA_ENDIAN nDataEndian = LITTLE_ENDIAN;
int i;
int nBytes;
FILE *fp;
char *pData = 0;
short int gTag, eTag;
int nNumFrames = 1;
fp = fopen(pszFileName, "rb");
if (!fp)
{
AfxMessageBox("Failed to open file for read.");
return;
}
while(fread(&gTag, sizeof(short), 1, fp) == 1)
{
if (nDataEndian == BIG_ENDIAN)
SwapWord((char *) &gTag, 1);
switch(gTag)
{
case 0x0002: // Meta header.
fread(&eTag, sizeof(short), 1, fp);
// Meta header is always in Little Endian Explicit VR syntax.
switch(eTag)
{
case 0x0010: // Transfer syntax UID
readString(fp, szTransferSyntaxUID, FALSE, LITTLE_ENDIAN);
// Check data endian.
if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.2")) // Explicit VR Big Endian
nDataEndian = BIG_ENDIAN; // Big Endian
else
nDataEndian = LITTLE_ENDIAN; // Little Endian
// Check if it is implicit VR or Explicit VR
if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2")) // Implicit VR Little Endian
bImplicitVR = TRUE; // Implicit VR
else
bImplicitVR = FALSE; // Explicit VR
// Parse the encapsulation/compression
if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.50")) // JPEG lossy
nCompressionMode = COMPRESS_JPEGLOSSY;
else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.51")) // JPEG lossy 12bit
nCompressionMode = COMPRESS_JPEGLOSSY12BIT;
else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.70")) // JPEG lossless first order prediction
nCompressionMode = COMPRESS_JPEGLOSSLESS;
else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.4.57")) // JPEG lossless process 14
nCompressionMode = COMPRESS_JPEGLOSSLESS2;
else if (!strcmp(szTransferSyntaxUID, "1.2.840.10008.1.2.5")) // RLE
nCompressionMode = COMPRESS_RLE;
break;
}
break;
case 0x0028: // Image pixel data info group
fread(&eTag, sizeof(short), 1, fp);
if (nDataEndian == BIG_ENDIAN)
SwapWord((char *) &eTag, 1);
switch(eTag)
{
case 0x0010: // Rows
nRows = readUS(fp, nDataEndian);
break;
case 0x0011: // Columns
nCols = readUS(fp, nDataEndian);
break;
case 0x0100: // Bits allocated
nBitsAllocated = readUS(fp, nDataEndian);
break;
case 0x0102: // High bit
nHighBit = readUS(fp, nDataEndian);
break;
case 0x0103: // Is signed?
bIsSigned = readUS(fp, nDataEndian);
break;
case 0x0002: // Samples per Pixel
nSamplesPerPixel = readUS(fp, nDataEndian);
break;
case 0x0004: // Photometric Interpolation
readString(fp, szPhotometric, bImplicitVR, nDataEndian);
break;
case 0x0008: // Number of frames
nNumFrames = readIS(fp, bImplicitVR, nDataEndian);
break;
case 0x1050: // Window Center
fWindowCenter = readDS(fp, bImplicitVR, nDataEndian);
break;
case 0x1051: // Window Width
fWindowWidth = readDS(fp, bImplicitVR, nDataEndian);
break;
case 0x1052: // Rescale intercept
fRescaleIntercept = readDS(fp, bImplicitVR, nDataEndian);
break;
case 0x1053: // Rescale slope
fRescaleSlope = readDS(fp, bImplicitVR, nDataEndian);
break;
default:
// do nothing
break;
}
break;
case 0x7fe0:
fread(&eTag, sizeof(short), 1, fp);
if (nDataEndian == BIG_ENDIAN)
SwapWord((char *) &eTag, 1);
if (eTag == 0x0010)
{
nBytesP = nSamplesPerPixel*nBitsAllocated/8;
nFrameSize = nCols * nRows * nBytesP;
nLength = nNumFrames * nFrameSize;
switch(nCompressionMode)
{
case COMPRESS_NONE:
pData = new char[nLength + 16];
fseek(fp, 4, SEEK_CUR); // Skip 4 bytes (length bytes)
nBytes = fread(pData, 1, nLength, fp);
if (nBytes != nLength)
{
AfxMessageBox("Failed to read all pixel data.");
}
break;
case COMPRESS_RLE:
AfxMessageBox("RLE compression not supported at this moment");
// To do:
// 1. Read the offset table.
// 2. Read and uncompress RLE image frames into either RGB or monochrome format.
// 3. Put frames in the pData buffer, one frame after another.
// Public domain RLE decompression source code is in Papyrus and dcmtk.
break;
case COMPRESS_JPEGLOSSY:
AfxMessageBox("JPEG lossy compression not supported at this moment");
// To do:
// 1. Read the offset table
// 2. Read and uncompress JPEG image frames into either RGB or monochrome format.
// 3. Put frames in the pData buffer, one frame after another.
// Public domain JPEG decompression source code is in Papyrus and dcmtk.
break;
case COMPRESS_JPEGLOSSY12BIT:
AfxMessageBox("JPEG lossy 12-bit compression not supported at this moment");
// To do:
// 1. Read the offset table
// 2. Read and uncompress JPEG image frames into either RGB or monochrome format.
// 3. Put frames in the pData buffer, one frame after another.
// Public domain JPEG decompression source code is in Papyrus and dcmtk.
break;
case COMPRESS_JPEGLOSSLESS:
case COMPRESS_JPEGLOSSLESS2:
AfxMessageBox("JPEG lossless compression not supported at this moment");
// To do:
// 1. Read the offset table
// 2. Read and uncompress JPEG image frames into either RGB or monochrome format.
// 3. Put frames in the pData buffer, one frame after another.
// Public domain JPEG decompression source code is in Papyrus and dcmtk.
break;
}
}
break;
}
if (pData)
break; // We are done.
}
fclose(fp);
if (pData) // Have we got the pixel data?
{
// Need to do byte swap?
if (nDataEndian == BIG_ENDIAN)
{
if (nBitsAllocated > 8)
SwapWord(pData, nLength/2);
}
if (nBitsAllocated > 8)
{
// We need to convert it to 8-bit.
char *pNewData;
pNewData = convertTo8Bit(pData, nLength/2, bIsSigned, nHighBit,
fRescaleSlope, fRescaleIntercept, fWindowCenter, fWindowWidth);
// Use the new 8-bit data.
if (pNewData)
{
delete [] pData;
pData = pNewData;
nBytesP = 1;
nFrameSize /= 2;
nLength /= 2;
}
}
// Write BMP files
for (i = 0; i < nNumFrames; i++)
WriteBMPFile(pData + nFrameSize*i, nFrameSize, nCols, nRows, nBytesP, szPhotometric, i+1);
// Free the memory.
delete [] pData;
AfxMessageBox("Images successfully converted into BMP.");
}
}
// pData is already converted to either 8-bit flat grayscale or 24-bit RGB.
int CDicomBMPDlg::WriteBMPFile(char *pData, int nFrameSize, short nCols, short nRows, int nBytesP, char *pszPhotometric, int nFrameNum)
{
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
int nPaletteSize = sizeof(RGBQUAD)*256;
char szBMPFileName[512], *cc;
FILE *fp;
int i, j, nBytes, nRowPadding, nRowBytes;
unsigned char oneLutSlot[4];
char szPadding[4] = {'\0', '\0', '\0', '\0'};
if (!strncmp(pszPhotometric, "RGB", 3) || !strncmp(pszPhotometric, "YBR", 3))
nPaletteSize = 0;
// Attention:
// 1. BMP image rows need to be 4-byte aligned.
// 2. BMP image is usually bottom up in reverse direction to DICOM images.
nRowBytes = nCols*nBytesP;
nRowPadding = nRowBytes%4;
//here fill in the two info structure
bf.bfType = 0x4D42;
bf.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nPaletteSize + nFrameSize + nRowPadding*nRows;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nPaletteSize;
bi.biSize=sizeof(BITMAPINFOHEADER);
bi.biWidth = nCols;
bi.biHeight = nRows;
bi.biPlanes = 1;
if (nPaletteSize == 0)
{
bi.biBitCount = 24;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
}
else
{
bi.biBitCount = 8;
bi.biClrUsed = 256;
bi.biClrImportant = 256;
}
bi.biCompression = 0;
bi.biSizeImage = nFrameSize;
//
// Resolutions are in pixels per meter. Our IMAGES file uses
// a resolution of 72 pixels per inch, which when multiplied by
// 39.37 inches per meter, gives us 2835 pixels per meter.
//
bi.biXPelsPerMeter = 2835;
bi.biYPelsPerMeter = 2835;
// Make file name and give it a .BMP extension.
strcpy(szBMPFileName, m_strFileName.GetBuffer(3));
if (!(cc = strrchr(szBMPFileName, '.'))) // Find the '.' or end of file name.
cc = szBMPFileName + strlen(szBMPFileName);
sprintf(cc, "_%04d.BMP", nFrameNum); // Append file number and extension.
// Open the file for wirte.
fp = fopen(szBMPFileName, "wb");
if (fp == NULL)
AfxMessageBox("Failed to open file for write.");
// Write the BMP and DIB file headers.
nBytes = fwrite((void *)&bf, 1, sizeof(BITMAPFILEHEADER), fp);
// if (nBytes != sizeof(BITMAPFILEHEADER))
// post your error message here.
nBytes = fwrite((void *)&bi, 1, sizeof(BITMAPINFOHEADER), fp);
// if (nBytes != sizeof(BITMAPINFOHEADER))
// post your error message here.
// Write the color palette if 8-bit
if (nPaletteSize != 0)
for (i = 0; i < 256; i++)
{
oneLutSlot[0] = oneLutSlot[1] = oneLutSlot[2] = i; // Grayscale LUT.
oneLutSlot[3] = 0;
fwrite(oneLutSlot, 1, 4, fp); // Write one color palette slot.
}
// Now write the actual pixel data.
cc = pData + (nRows - 1)*nRowBytes;
if (nPaletteSize != 0) // Grayscale
for (i = 0; i < nRows; i ++)
{
nBytes = fwrite(cc, 1, nRowBytes, fp); // Write a row.
//if (nBytes != nRowBytes)
// post your error message here.
if (nRowPadding) // Pad the row.
fwrite(szPadding, 1, nRowPadding, fp);
cc -= nRowBytes;
}
else
for (i = 0; i < nRows; i ++)
{
for (j = 0; j < nCols; j++, cc += 3)
{
fputc(*(cc + 2), fp); // B
fputc(*(cc + 1), fp); // G
fputc(*cc, fp); // R
}
if (nRowPadding) // Pad the row.
fwrite(szPadding, 1, nRowPadding, fp);
cc -= 2*nRowBytes;
}
fclose(fp);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -