Introduction
The program loads images (BMP, GIF, JPEG/JPG/EXIF, PNG, TIF, ICON, WMF, EMF), applies some constraints related to window size (best fit, constraint width, constraint height, image original), rotates the image, makes zoom in & out effect and finally navigates through multi-page TIF images. It is useful if you need a image viewer class and image functionality in your C++ application. The problem is that I use GDI+. Developing with GDI+, there is a point most of us must go through.
First, go beyond pointers to GDI+ Image class that block access to every image file I load and view; now only the current loaded is blocked. No more headache with blocked temp image files, we got the key. How to make a big JPEG/JPG/EXIF move fast? I made it, but unfortunately it won't work for a rotation with 180 degrees. Just stretch the image in a hidden window: rotate 90 degrees Graphics::RotateTransform(...) , and display image, don't ask why! It will work to your surprise. I found many programmers that rotated an image with Image class method RotateFlip (and I did it too), instead of Graphics class method RotateTransform. This implies that an image will have negative values along X, Y axis and more ... but will have intact integrity of its internal structure. What I didn't solve is transparent background images management, and what to do to cheat image at a 180 angle rotation.
Background
C/C++ is great, but to know it from the very beginning.
Using the Code
The class that do everything that I discussed earlier is mvImage. So you will need this #include "mvImage.h" in your application. The mvImage class constructor needs a window handle HWND. The rest does the class through this handle. You can use this class in a single / multi document interface or dialog based MFC project. I will try a poor demonstration copying parts of the code here to show you: easier than this doesn't exist !
- Your
CView derived class constructor will be like this:
CDraw1View::CDraw1View() { m_Image = 0x000000 ; }
- 2.1 Initialization of
mvImage pointer comes in OnDraw once per application, the rest is redrawing the window surface.
void CDraw1View::OnDraw(CDC* pDC)
{
CDraw1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if((m_Image == 0x000000) && (this->m_hWnd != 0x000000))
{
m_Image = new mvImage(this->m_hWnd);
} else
{
if(m_Image->mvIsValidImage()) m_Image->mvOnPaint();
}
}
- 2.2 If your application is dialog based, use
OnInitDialog to put this code in:
.....
if((m_Image == 0x000000) && (this->m_hWnd != 0x000000))
{
m_Image = new mvImage(this->m_hWnd);
}
.....
and OnPaint method with this code:
if(m_Image->mvIsValidImage()) m_Image->mvOnPaint() ;
- To load and display an image with 'best fit' propriety, use this:
.....
CFileDialog Fdlg(TRUE) ;
if(Fdlg.DoModal() == IDOK)
{
CString path = Fdlg.GetPathName() ;
m_Image->mvLoadImage(path) ;
}else return ;
if(m_Image->mvIsValidImage()) m_Image->mvConstraintAll();
.....
- Constraint all 'best fit' image in window, proceed like here:
if(m_Image->mvIsValidImage())
{
m_Image->mvConstraintAll();
}
- Constraint height ? like here:
if(m_Image->mvIsValidImage())
m_Image->mvConstraintHeight() ;
- Rotate left:
if(m_Image->mvIsValidImage())
m_Image->mvRotateLeft() ;
- Zoomin:
if(m_Image->mvIsValidImage())
m_Image->mvZoomIn() ;
- Entire vertical scroll function:
void CDraw1View::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if(m_Image->mvIsValidImage())
m_Image->mvOnVScroll(nSBCode, nPos, pScrollBar) ;
CView::OnVScroll(nSBCode, nPos, pScrollBar);
}
- Route
OnSize message like this:
void CDraw1View::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
if((m_Image != 0x000000) && (this->m_hWnd != 0x000000))
{
if(m_Image->mvIsValidImage())
m_Image->mvOnSize(nType, cx, cy) ;
}
}
- Multi-page TIFF navigation:
if(m_Image->mvIsValidImage())
m_Image->mvFrameFirst();
Searching through the source code in draw1View.cpp, you will find all the code you may be interested in.
History
- 27th August, 2006: Initial post