[Insight-users] Image reader problem
Charles Knox
knoxcharles at qwest.net
Fri May 9 18:07:02 EDT 2008
Hi Bill and Luis,
I've written a short test routine, DICOMReaderTest, that duplicates the
behavior I described previously. It is a Windows single-document app
written for Visual Studio 2008. See the listing below.
I had also thought my larger app was stepping on memory somewhere,
trashing the ITK code. However, this shorter test app also misbehaves
in exactly the same way - crashing in an ITK destructor on return from
the ReadDICOMImage() routine. Briefly, the program works as follows:
An ID_FILE_OPEN command is handled by CDICOMReaderTest::OnFileNew, which
opens a CFileDialog to request a file name.
CDICOMReaderTest::ReadDICOMImage is called to retrieve the file. An
error is generated at reader->Update and the program then crashes on the
return from the 'catch' handler.
Regards,
Charles Knox
Bill Lorensen wrote:
> Also, it is possible that your code has a problem elsewhere that has
> only surfaced after switching to the new compiler. You could be
> trashing memory somewhere.
>
> Can you post a small test program that crashes? We could try to run it
> through a memory checker like valgrind.
>
> Bill
>
------------------------------------------------------------------------------------------------------------------
// DICOMReaderTest.h : main header file for the DICOMReaderTest application
//
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
// CDICOMReaderTestApp:
// See DICOMReaderTest.cpp for the implementation of this class
//
class CDICOMReaderTestApp : public CWinApp
{
public:
CDICOMReaderTestApp();
// Overrides
public:
virtual BOOL InitInstance();
// Implementation
afx_msg void OnAppAbout();
DECLARE_MESSAGE_MAP()
};
extern CDICOMReaderTestApp theApp;
------------------------------------------------------------------------------------------------------------------
// DICOMReaderTest.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "DICOMReaderTest.h"
#include "MainFrm.h"
#include <locale>
#include "DICOMReaderTestDoc.h"
#include "DICOMReaderTestView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDICOMReaderTestApp
BEGIN_MESSAGE_MAP(CDICOMReaderTestApp, CWinApp)
ON_COMMAND(ID_APP_ABOUT, &CDICOMReaderTestApp::OnAppAbout)
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
// CDICOMReaderTestApp construction
CDICOMReaderTestApp::CDICOMReaderTestApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CDICOMReaderTestApp object
CDICOMReaderTestApp theApp;
// CDICOMReaderTestApp initialization
BOOL CDICOMReaderTestApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
setlocale(LC_ALL, "English");
CWinApp::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(4); // Load standard INI file options
(including MRU)
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CDICOMReaderTestDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CDICOMReaderTestView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line. Will return
FALSE if
// app was launched with /RegServer, /Register, /Unregserver or
/Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
return TRUE;
}
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// App command to run the dialog
void CDICOMReaderTestApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
// CDICOMReaderTestApp message handlers
------------------------------------------------------------------------------------------------------------------
// DICOMReaderTestDoc.h : interface of the CDICOMReaderTestDoc class
//
using namespace std;
#pragma once
class CDICOMReaderTestDoc : public CDocument
{
protected: // create from serialization only
CDICOMReaderTestDoc();
DECLARE_DYNCREATE(CDICOMReaderTestDoc)
// Attributes
public:
CString m_path; // Complete pathname of the DICOM file read.
BYTE * m_image; // DICOM data
CSize m_imageSize; // x,y size of image
// Operations
public:
BOOL ReadDICOMImage(const LPCTSTR path);
// Overrides
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
// Implementation
public:
virtual ~CDICOMReaderTestDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnFileOpen();
};
------------------------------------------------------------------------------------------------------------------
// DICOMReaderTestDoc.cpp : implementation of the CDICOMReaderTestDoc class
//
#include "stdafx.h"
#include "itkGDCMImageIO.h"
#include "itkImageRegionIterator.h"
#include "itkImageFileReader.h"
#include "DICOMReaderTest.h"
#include "DICOMReaderTestDoc.h"
//#include <string>
//using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDICOMReaderTestDoc
IMPLEMENT_DYNCREATE(CDICOMReaderTestDoc, CDocument)
BEGIN_MESSAGE_MAP(CDICOMReaderTestDoc, CDocument)
ON_COMMAND(ID_FILE_OPEN, &CDICOMReaderTestDoc::OnFileOpen)
END_MESSAGE_MAP()
// CDICOMReaderTestDoc construction/destruction
CDICOMReaderTestDoc::CDICOMReaderTestDoc()
{
m_image = NULL;
}
CDICOMReaderTestDoc::~CDICOMReaderTestDoc()
{
delete [] m_image;
}
BOOL CDICOMReaderTestDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
// CDICOMReaderTestDoc serialization
void CDICOMReaderTestDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
// CDICOMReaderTestDoc diagnostics
#ifdef _DEBUG
void CDICOMReaderTestDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CDICOMReaderTestDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
// CDICOMReaderTestDoc commands
void CDICOMReaderTestDoc::OnFileOpen()
// Gets a file name from the user
{
CFileDialog dlg(TRUE, 0, _T("*.*"));
if (dlg.DoModal() != IDOK)
return;
CString folder = dlg.GetFolderPath() + _T("\\");
CString filename = dlg.GetFileName();
m_path = folder + filename;
// Call the read routine
if (ReadDICOMImage(m_path))
// Signal the view to draw the image
UpdateAllViews(NULL);
}
BOOL CDICOMReaderTestDoc::ReadDICOMImage( const LPCTSTR path)
{
std::string spath((char *)path);
// First check for a DICOM file.
itk::GDCMImageIO::Pointer gdcmIO = itk::GDCMImageIO::New();
if (!gdcmIO->CanReadFile(spath.c_str()))
return FALSE;
delete [] m_image;
m_image = NULL;
typedef signed short PixelType;
// Set dimensions to 3 to have reader return z-value
const UINT Dimension = 3;
typedef itk::Image< PixelType, Dimension > ImageType;
typedef itk::ImageFileReader< ImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(spath.c_str() );
reader->SetImageIO( gdcmIO );
// Return prematurely to invoke 'reader' destructor
//return FALSE;
try {
reader->Update();
} catch (std::exception &err) {
CString msg(err.what());
AfxMessageBox(msg);
return FALSE; // Crashes on return
}
ImageType::Pointer image = reader->GetOutput();
// Image size
ImageType::SizeType size = image->GetLargestPossibleRegion().GetSize();
m_imageSize.cx = size[0];
m_imageSize.cy = size[1];
long bytesPerPixel = sizeof(PixelType);
long nPixels = m_imageSize.cx * m_imageSize.cy;
long nBytes = nPixels * bytesPerPixel;
// Transfer image data into buffer
typedef itk::ImageRegionIterator< ImageType > IteratorType;
IteratorType iter( image, image->GetLargestPossibleRegion() );
PixelType *data = new PixelType[nPixels];
PixelType *row = new PixelType[m_imageSize.cx];
PixelType *pB = data + nPixels - m_imageSize.cx;
iter.GoToBegin();
// get data and mirror y
for (int j = 0; j < m_imageSize.cy; j++) {
for (int i = 0; i < m_imageSize.cx; i++, ++iter)
*(row + i) = iter.Get();
memcpy((void *)pB, (void *)row, m_imageSize.cx * sizeof(PixelType));
pB -= m_imageSize.cx;
}
delete [] row;
m_image = new BYTE[nPixels];
if (sizeof(PixelType) == 1) {
// DICOM data are going to be 2-bpp
// but just in case...
memcpy( m_image, data, nPixels);
delete [] data;
return TRUE;
}
// Convert (possibly) signed pixels to unsigned, rescale
// and save image in member variable m_image.
int i;
PixelType min, max, *pd = data, maxgray = ~0;
for ( i = 0; i < nPixels; pd++, i++) {
if (*pd < min)
min = *pd;
if (*pd > max)
max = *pd;
}
long pixel, offset = min, range = max - min;
for ( i = 0, pd = data; i < nPixels; i++) {
pixel = (((long )*pd++ - offset) * (long)maxgray)/range;
m_image[i] = (BYTE)(pixel >> 8);
}
delete [] data;
return TRUE;
}
------------------------------------------------------------------------------------------------------------------
// DICOMReaderTestView.h : interface of the CDICOMReaderTestView class
//
#include "ImageDC.h"
#pragma once
class CDICOMReaderTestView : public CView
{
protected: // create from serialization only
CDICOMReaderTestView();
DECLARE_DYNCREATE(CDICOMReaderTestView)
// Attributes
public:
CDICOMReaderTestDoc* GetDocument() const;
// Operations
public:
CImageDC m_imageDC;
// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Implementation
public:
virtual ~CDICOMReaderTestView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in DICOMReaderTestView.cpp
inline CDICOMReaderTestDoc* CDICOMReaderTestView::GetDocument() const
{ return reinterpret_cast<CDICOMReaderTestDoc*>(m_pDocument); }
#endif
------------------------------------------------------------------------------------------------------------------
// DICOMReaderTestView.cpp : implementation of the CDICOMReaderTestView
class
//
#include "stdafx.h"
#include "DICOMReaderTest.h"
#include "DICOMReaderTestDoc.h"
#include "DICOMReaderTestView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDICOMReaderTestView
IMPLEMENT_DYNCREATE(CDICOMReaderTestView, CView)
BEGIN_MESSAGE_MAP(CDICOMReaderTestView, CView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
END_MESSAGE_MAP()
// CDICOMReaderTestView construction/destruction
CDICOMReaderTestView::CDICOMReaderTestView()
{
}
CDICOMReaderTestView::~CDICOMReaderTestView()
{
}
BOOL CDICOMReaderTestView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
// CDICOMReaderTestView drawing
void CDICOMReaderTestView::OnDraw(CDC* pDC)
// Draws the image if read
{
CDICOMReaderTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
if (pDoc->m_image == 0)
return;
// Create source device context with bitmap
m_imageDC.Delete();
// Load image data into source device context bitmap
m_imageDC.Create(pDC, pDoc->m_image, pDoc->m_imageSize, 2.2);
m_imageDC.LoadBmp();
pDC->BitBlt(0, 0, pDoc->m_imageSize.cx, pDoc->m_imageSize.cy,
&m_imageDC, 0, 0, SRCCOPY);
}
// CDICOMReaderTestView printing
BOOL CDICOMReaderTestView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CDICOMReaderTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo*
/*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CDICOMReaderTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo*
/*pInfo*/)
{
// TODO: add cleanup after printing
}
// CDICOMReaderTestView diagnostics
#ifdef _DEBUG
void CDICOMReaderTestView::AssertValid() const
{
CView::AssertValid();
}
void CDICOMReaderTestView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CDICOMReaderTestDoc* CDICOMReaderTestView::GetDocument() const //
non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDICOMReaderTestDoc)));
return (CDICOMReaderTestDoc*)m_pDocument;
}
#endif //_DEBUG
// CDICOMReaderTestView message handlers
------------------------------------------------------------------------------------------------------------------
// GrayPalette.h
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// GrayPalette.h : header file
//
#define NGRAYS_8U 256
/////////////////////////////////////////////////////////////////////////////
// CGrayPalette window
class CGrayPalette : public CWnd
{
// Construction
public:
CGrayPalette();
// Attributes
public:
// Operations
public:
// Constructs a linear ramp gray value palette with selectable gamma.
// Adds color red between 'lower' and 'upper' levels with selectable
opacity.
void ThresholdPalette(int lower, int upper,
double opacity, double gamma, RGBQUAD
palette[NGRAYS_8U]);
void RampPalette(int lower, int upper, double gamma, RGBQUAD
palette[NGRAYS_8U]);
void BinaryPalette(int lower, int upper, RGBQUAD palette[NGRAYS_8U]);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGrayPalette)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CGrayPalette();
// Generated message map functions
protected:
//{{AFX_MSG(CGrayPalette)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately
before the previous line.
------------------------------------------------------------------------------------------------------------------
// GrayPalette.cpp : implementation file
//
#include "stdafx.h"
#include "GrayPalette.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGrayPalette
CGrayPalette::CGrayPalette()
{
}
CGrayPalette::~CGrayPalette()
{
}
BEGIN_MESSAGE_MAP(CGrayPalette, CWnd)
//{{AFX_MSG_MAP(CGrayPalette)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGrayPalette message handlers
void CGrayPalette::ThresholdPalette(int lower, int upper,
double opacity, double gamma, RGBQUAD
palette[NGRAYS_8U])
/**
* Makes a gray level palette suitable for use with a DIB section image.
If the 'lower' and 'upper' values are both zero, a gamma-corrected gray
value linear ramp palette is returned. In this case, 'opacity' is
not used.
If either 'lower' or 'upper' is nonzero, the color red is applied to
the range of values 'lower' to 'upper'. 'opacity' of 1.0 gives a
solid color,
whereas, values between 0 and 1.0 give varying degrees of transparency.
'gamma' is typically 1.0 to 2.2.
Return values: An array of NGRAYS_8U (256) RGBQUAD values
*/
{
int i;
double val;
UINT lval;
BYTE maxGray = ~0, red = maxGray;
// Make a gamma corrected gray ramp
for (i = 0; i != NGRAYS_8U; i++) {
val = (double )maxGray * pow((double)i / (double )maxGray, 1 /
gamma) + 0.5;
lval = (UINT )val;
palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = lval;
palette[i].rgbReserved = 0xff;
}
if(lower == 0 && upper == 0)
return;
// If opaque, insert color red in LUT for showing thresholded values
if (opacity >= 1) {
for (i = lower; i <= upper; i++) {
palette[i].rgbRed = red;
palette[i].rgbReserved = maxGray;
palette[i].rgbGreen = palette[i].rgbBlue = 0;
}
// otherwise, blend in the color.
} else if (opacity == 0.5) {
for (i = lower; i <= upper; i++) {
palette[i].rgbGreen >>= 1;
palette[i].rgbBlue >>= 1;
palette[i].rgbRed >>= 1;
palette[i].rgbRed += (red >> 1);
}
} else {
double r, g, b;
for (i = lower; i <= upper; i++) {
r = (double )palette[i].rgbRed * (1 - opacity) + (double
)red * opacity;
g = (double )palette[i].rgbGreen * (1 - opacity);
b = (double )palette[i].rgbBlue * (1 - opacity);
palette[i].rgbRed = (BYTE )r;
palette[i].rgbGreen = (BYTE )g;
palette[i].rgbBlue = (BYTE )b;
}
}
}
void CGrayPalette::RampPalette(int lower, int upper,
double gamma, RGBQUAD
palette[NGRAYS_8U])
{
BYTE maxGray = ~0;
int i;
ZeroMemory((void *)palette, lower * sizeof(RGBQUAD));
for ( i = maxGray; i > upper; i--) {
palette[i].rgbBlue = maxGray;
palette[i].rgbGreen = maxGray;
palette[i].rgbRed = maxGray;
palette[i].rgbReserved = maxGray;
}
// Make a gamma corrected gray ramp between lower and upper
double gVal, d = (double )(upper - lower);
if (d == 0)
d = 1;
for (i = lower; i <= upper; i++) {
gVal = ((double )maxGray * (double )(i - lower)) / d;
gVal = (double )maxGray * pow(gVal / (double )maxGray, 1 /
gamma) + 0.5;
palette[i].rgbBlue = (BYTE )gVal;
palette[i].rgbGreen = (BYTE )gVal;
palette[i].rgbRed = (BYTE )gVal;
palette[i].rgbReserved = maxGray;
}
}
void CGrayPalette::BinaryPalette(int lower, int upper, RGBQUAD
palette[NGRAYS_8U])
{
BYTE maxGray = ~0;
ZeroMemory((void *)palette, 256 * sizeof(RGBQUAD));
for (int i = lower; i <= upper; i++) {
palette[i].rgbBlue = maxGray;
palette[i].rgbGreen = maxGray;
palette[i].rgbRed = maxGray;
palette[i].rgbReserved = maxGray;
}
}
------------------------------------------------------------------------------------------------------------------
// ImageDC.h: interface for the CImageDC class.
// It provides device context with bitmap to draw the image
//
//////////////////////////////////////////////////////////////////////
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//#include "ImageData.h"
class CImageDC : public CDC
{
public:
CImageDC();
virtual ~CImageDC();
// Attach pImage
// Create DC, compatible with pDC
// Create DIB section for pImage and select it into DC
// the initial color table is a linear gray ramp
void Create(CDC* pDC, BYTE* pImage, CSize size, double gamma);
// Copy data from attached image to DIB section
void LoadBmp();
bool HaveBmp() { return m_pBits != NULL; }
void GetBmp(BYTE *pBits);
// Sets the DIB section's color table
void SetColorTable(UINT startIndex, UINT numberColors,
RGBQUAD *colors);
void Delete();
public:
// Attributes
protected:
BITMAPINFO* GetBmpInfo()
{
return (BITMAPINFO *)m_BmpInfoPalette;
}
BITMAPINFOHEADER* GetBmpInfoHeader()
{
return (BITMAPINFOHEADER *)m_BmpInfoPalette;
}
RGBQUAD* GetBmpPalette()
{
return GetBmpInfo()->bmiColors;
}
BOOL SetBmpInfo(void );
void SetGrayPalette();
double m_gamma; // Gamma correction value from Create()
HBITMAP m_hBmp;
BYTE* m_pImg;
BYTE m_BmpInfoPalette[sizeof(BITMAPINFO)+256*sizeof(RGBQUAD)];
BYTE* m_pBits;
CSize m_size;
int m_step; // Number of bytes to step thru rows in
the bitmap
};
------------------------------------------------------------------------------------------------------------------
// ImageDC.cpp: implementation of the CImageDC class.
//
// Creates an 8-bit DIB section of the supplied gray value
// image data.
//
// Use the Create() function to initialize the DIB section.
//
// Call LoadBmp() to load the actual image data into the bitmap.
// Image data are assumed to be 8-bits per pixel.
// The default palette will be set with a linear gray ramp.
//
// Use CDC::BitBlt or CDC::StretchBlt to display the bitmap
// on the device context.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ImageDC.h"
#include "GrayPalette.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CImageDC::CImageDC()
{
m_pImg = NULL;
m_pBits = NULL;
m_hBmp = NULL;
m_gamma = 2.2;
memset(m_BmpInfoPalette, 0,
sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD));
SetGrayPalette();
}
CImageDC::~CImageDC()
{
Delete();
}
void CImageDC::Create(CDC* pDC, BYTE* pImg, CSize size, double gamma)
// Creates a DC, compatible with pDC. A DIB section for pImg
// of size 'size' is then created and selected into the DC.
// The initial color table of the DIB section is a linear gray ramp.
{
ASSERT(pDC);
ASSERT(pImg);
m_pImg = NULL;
m_hBmp = NULL;
m_gamma = gamma;
m_size = size;
// m_step - width in pixels. pixels will be DWORDs and
// width must be rounded up to the next DWORD sized pixel.
m_step = ((m_size.cx + 3) >> 2) << 2;
CreateCompatibleDC(pDC);
if (!SetBmpInfo()) return;
m_pImg = pImg;
m_hBmp = ::CreateDIBSection( GetSafeHdc(), GetBmpInfo(),
DIB_RGB_COLORS, (void **)(&m_pBits), NULL, 0);
ASSERT(m_hBmp);
SelectObject(m_hBmp);
}
void CImageDC::Delete()
// Call this function to delete the DIB section
// from the device context when no longer needed.
{
if (m_hBmp == NULL)
return;
::DeleteObject(m_hBmp);
m_pImg = NULL;
m_pBits = NULL;
m_hBmp = NULL;
DeleteDC();
}
void CImageDC::LoadBmp()
{
if (m_pBits && m_pImg) {
BYTE *q = m_pBits; // Pointer to bitmap
BYTE *p = m_pImg; // and to source image
for (int i = 0; i < m_size.cy; i++) {
// Copy one line at a time
CopyMemory(q, p, m_size.cx);
q += m_step;
p += m_size.cx;
}
}
}
void CImageDC::GetBmp(BYTE *pBits)
{
if (m_pBits) {
BYTE *q = m_pBits; // Pointer to bitmap
for (int i = 0; i < m_size.cy; i++) {
// Copy one line at a time
CopyMemory(pBits, q, m_size.cx);
q += m_step;
pBits += m_size.cx;
}
}
}
BOOL CImageDC::SetBmpInfo( void )
{
BITMAPINFO* bmInfo = GetBmpInfo();
BITMAPINFOHEADER* bi = GetBmpInfoHeader();
bi->biSize = sizeof(BITMAPINFOHEADER);
bi->biWidth = m_step;
bi->biHeight = m_size.cy;
bi->biPlanes = 1;
bi->biCompression = BI_RGB;
bi->biBitCount = 8;
bi->biSizeImage = ((((bi->biWidth * bi->biBitCount) + 31) &
~31) >> 3) * bi->biHeight;
bi->biXPelsPerMeter = 0;
bi->biYPelsPerMeter = 0;
bi->biClrUsed = 256;
bi->biClrImportant = 0;
SetGrayPalette();
return TRUE;
}
void CImageDC::SetGrayPalette()
{
CGrayPalette pal;
RGBQUAD* bmPalette = GetBmpPalette() ;
pal.RampPalette(0, NGRAYS_8U - 1, m_gamma, bmPalette);
}
void CImageDC::SetColorTable(UINT startIndex, UINT numberColors, RGBQUAD
*colors)
// The color table in the DIB section has 256 entries. Call this
// function to alter the current values.
{
if (!m_hBmp)
return;
#ifdef _DEBUG
ASSERT (numberColors <= 256);
#endif
SetDIBColorTable(GetSafeHdc(), startIndex, numberColors, colors);
}
------------------------------------------------------------------------------------------------------------------
// MainFrm.h : interface of the CMainFrame class
//
#pragma once
class CMainFrame : public CFrameWnd
{
protected: // create from serialization only
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
// Attributes
public:
// Operations
public:
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
------------------------------------------------------------------------------------------------------------------
// MainFrm.cpp : implementation of the CMainFrame class
//
#include "stdafx.h"
#include "DICOMReaderTest.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
END_MESSAGE_MAP()
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
// CMainFrame construction/destruction
CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
}
CMainFrame::~CMainFrame()
{
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE
| CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
// TODO: Delete these three lines if you don't want the toolbar to
be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
return 0;
}
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return TRUE;
}
// CMainFrame diagnostics
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
// CMainFrame message handlers
------------------------------------------------------------------------------------------------------------------
// Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by DICOMReaderTest.rc
//
#define IDD_ABOUTBOX 100
#define IDP_OLE_INIT_FAILED 100
#define IDR_MAINFRAME 128
#define IDR_DICOMReaderTestTYPE 129
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 32771
#endif
#endif
------------------------------------------------------------------------------------------------------------------
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once
#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // Exclude rarely-used stuff from
Windows headers
#endif
#include "targetver.h"
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString
constructors will be explicit
// turns off MFC's hiding of some common and often safely ignored
warning messages
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h> // MFC support for Internet Explorer 4
Common Controls
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows
Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
------------------------------------------------------------------------------------------------------------------
// targetver.h
#pragma once
// The following macros define the minimum required platform. The
minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has
the necessary features to run
// your application. The macros work by enabling all features available
on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior
to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for
different platforms.
#ifndef WINVER // Specifies that the minimum
required platform is Windows Vista.
#define WINVER 0x0600 // Change this to the appropriate value
to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Specifies that the minimum required
platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value
to target other versions of Windows.
#endif
#ifndef _WIN32_WINDOWS // Specifies that the minimum required
platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to
target Windows Me or later.
#endif
#ifndef _WIN32_IE // Specifies that the minimum
required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700 // Change this to the appropriate value
to target other versions of IE.
#endif
------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------
More information about the Insight-users
mailing list