Update the changelog
[opencv] / apps / HMMDemo / ImageBaseView.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/// ImageBaseView.cpp : implementation file
41 //
42
43 #include "stdafx.h"
44 #include "HMMDemo.h"
45 #include "ImageBaseView.h"
46 #include "HMMDemoDoc.h"
47 #include <math.h>
48
49 #ifdef _DEBUG
50 #define new DEBUG_NEW
51 #undef THIS_FILE
52 static char THIS_FILE[] = __FILE__;
53 #endif
54
55 /////////////////////////////////////////////////////////////////////////////
56 // CImageBaseView
57
58 IMPLEMENT_DYNCREATE(CImageBaseView, CScrollView)
59
60 CImageBaseView::CImageBaseView()
61 {
62     m_canvas.Create( GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 8 );
63     m_rgbcanvas.Create( GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 24 );
64     
65     IplImage* rgb = m_rgbcanvas.GetImage();
66     strcpy( rgb->colorModel, "RGB" );
67     strcpy( rgb->channelSeq, "BGR" );
68
69     IplImage* gray = m_canvas.GetImage();
70     strncpy( gray->colorModel, "GRAY", 4 );
71     strncpy( gray->channelSeq, "GRAY", 4 );
72
73
74     m_base_size = CSize( 100, 120 );
75     m_log_shift = 0;
76     RecalcPictureSize();
77     m_index = -1;
78     m_active = -1;
79     m_pen = CreatePen( PS_SOLID, 3, RGB(255,0,255));
80
81     m_view_mode = 0;
82
83     m_count = 0;
84     m_nx = m_ny = 0;
85 }
86
87 CImageBaseView::~CImageBaseView()
88 {
89     DeleteObject( m_pen );
90 }
91
92
93 BEGIN_MESSAGE_MAP(CImageBaseView, CScrollView)
94     //{{AFX_MSG_MAP(CImageBaseView)
95         ON_WM_SIZE()
96         ON_WM_ERASEBKGND()
97         ON_WM_LBUTTONDOWN()
98         ON_WM_LBUTTONDBLCLK()
99         //}}AFX_MSG_MAP
100 END_MESSAGE_MAP()
101
102 /////////////////////////////////////////////////////////////////////////////
103 // CImageBaseView drawing
104
105 void  CImageBaseView::RefreshView()
106 {
107     CHMMDemoDoc* doc = GetDocument();
108     CSize virt_size = CSize( 10, 10 );
109
110     if( doc )
111     {
112         CRect win_rect;
113         if( m_index < 0 )
114         {
115             m_count = doc->GetFaceBase().GetPersonList().GetCount();
116         }
117         else
118         {
119             CPerson* person = doc->GetFaceBase().GetPerson( m_index );
120             if( !person )
121             {
122                 ASSERT(0);
123                 return;
124             }
125             m_count = person->GetImgList().GetCount();
126         }
127
128         GetClientRect( &win_rect );
129
130         m_margin = CSize((m_pic_delta.cx - m_pic_size.cx)/2,
131                          (m_pic_delta.cy - m_pic_size.cy)/2);
132
133         m_nx = (win_rect.Width() - m_margin.cx +
134                 m_pic_delta.cx - m_pic_size.cx)/m_pic_delta.cx;
135
136         m_nx = MAX( m_nx, 1 );
137
138         if( m_nx != 0 )
139         {
140             m_ny = (m_count + m_nx - 1)/m_nx;
141             virt_size.cx = win_rect.Width();
142             virt_size.cy = MAX( m_ny, 1 )*m_pic_delta.cy;
143         }
144     }
145     SetScrollSizes( MM_TEXT, virt_size );
146     InvalidateRect(0);
147 }
148
149 void CImageBaseView::OnInitialUpdate()
150 {
151     CScrollView::OnInitialUpdate();
152     m_count = m_nx = m_ny = 0;
153     m_active = -1;
154     m_index = -1;
155     RefreshView();
156 }
157
158
159
160 void CImageBaseView::OnDraw(CDC* pDC)
161 {
162     CHMMDemoDoc* doc = GetDocument();
163     if( doc )
164     {
165         CFaceBase& base = doc->GetFaceBase();
166         CRect win_rect;
167         CSize win_size;
168         int y_pos = GetScrollPosition().y;
169         HDC dc;
170
171         dc = ::GetDC( m_hWnd );
172
173         GetClientRect( &win_rect );
174         win_size = CSize( win_rect.Width(), win_rect.Height() );
175
176         m_canvas.Fill( GetSysColor( COLOR_WINDOW ));
177         base.Draw( m_index, m_canvas, win_size, y_pos, m_pic_size, m_pic_delta );
178         
179         if( m_canvas.GetImage() && m_rgbcanvas.GetImage() )
180         {
181             IplImage* src = m_canvas.GetImage();
182             IplImage* dst = m_rgbcanvas.GetImage();
183             CvRect sr = cvGetImageROI( src ), dr = cvGetImageROI( dst );
184
185             cvSetImageROI( src, RectToCvRect( win_rect ));
186             cvSetImageROI( dst, RectToCvRect( win_rect ));
187
188             cvCvtColor( src, dst, CV_GRAY2BGR );
189             cvSetImageROI( src, sr );
190             cvSetImageROI( dst, dr );
191
192             m_rgbcanvas.Show( dc, 0, 0, win_size.cx, win_size.cy, 0, 0 );
193         }
194
195         if( m_active >= 0 )
196         {
197             HGDIOBJ pen = SelectObject( dc, m_pen );
198             CRect rect = GetRectByIndex( m_active );
199             CPoint pt[5];
200
201             pt[0] = CPoint( rect.left, rect.top - y_pos );
202             pt[1] = CPoint( rect.right, rect.top - y_pos );
203             pt[2] = CPoint( rect.right, rect.bottom - y_pos );
204             pt[3] = CPoint( rect.left, rect.bottom - y_pos );
205             pt[4] = pt[0];
206
207             Polyline( dc, pt, 5 );
208             SelectObject( dc, pen );
209         }
210
211         int trained_index = base.GetTrainedIndex(); 
212
213         if( m_index >= 0 && trained_index >= 0 )
214         {
215             CRect rect = GetRectByIndex( trained_index );
216             if( !rect.IsRectEmpty())
217             {
218                 CPerson* person = base.GetPerson( m_index );
219                 ASSERT( person != 0 );
220
221                 CPersonImgList& list = person->GetImgList();
222                 CPersonImage* image = list.GetAt( list.FindIndex(trained_index));
223
224                 ASSERT( image != 0 );
225                 CRect sr, dr;
226                 image->CalcRect( win_size, rect.TopLeft(), m_pic_size, sr, dr );
227
228                 if( !sr.IsRectEmpty() && !dr.IsRectEmpty())
229                 {
230                     SetStretchBltMode( dc, COLORONCOLOR );
231                     base.GetTrainedImage().DrawToHDC( dc, &dr ); 
232                 }
233             }
234         }
235
236         ::ReleaseDC( m_hWnd, dc );
237     }
238 }
239
240 /////////////////////////////////////////////////////////////////////////////
241 // CImageBaseView message handlers
242
243 void  CImageBaseView::RecalcPictureSize()
244 {
245     double scale = pow( sqrt(2), m_log_shift );
246     m_pic_size.cx = (int)(m_base_size.cx*scale + 0.5);
247     m_pic_size.cy = (int)(m_base_size.cy*scale + 0.5);
248     m_pic_delta.cx = m_pic_size.cx*5/4;
249     m_pic_delta.cy = m_pic_size.cy*5/4;
250 }
251
252 void  CImageBaseView::Zoom( bool zoom_in )
253 {
254     if( zoom_in )
255     {
256         m_log_shift = MIN( ZOOM_MAX, m_log_shift + 1 );
257     }
258     else
259     {
260         m_log_shift = MAX( ZOOM_MIN, m_log_shift - 1 );
261     }
262     RecalcPictureSize();
263     RefreshView();
264     InvalidateRect(0);
265 }
266
267
268 void CImageBaseView::OnSize(UINT nType, int cx, int cy) 
269 {
270     CScrollView::OnSize(nType, cx, cy);
271     RefreshView();
272 }
273
274
275 BOOL CImageBaseView::OnEraseBkgnd(CDC* /*pDC*/)
276 {
277     return TRUE;
278 }
279
280
281 CRect CImageBaseView::GetRectByIndex( int index )
282 {
283     CRect rect = CRect(0,0,0,0);
284     if( (unsigned)index >= (unsigned)m_count ) return rect;
285
286     rect.left = index % m_nx;
287     rect.top = index / m_nx;
288
289     rect.left = rect.left*m_pic_delta.cx + m_margin.cx;
290     rect.top = rect.top*m_pic_delta.cy + m_margin.cy;
291
292     rect.right = rect.left + m_pic_size.cx;
293     rect.bottom = rect.top + m_pic_size.cy;
294
295     return rect;
296 }
297
298
299 int  CImageBaseView::GetIndexByPoint( CPoint pt )
300 {
301     int y_pos = GetScrollPosition().y;
302
303     int x = (pt.x - m_margin.cx)/m_pic_delta.cx;
304     int y = (pt.y + y_pos - m_margin.cy)/m_pic_delta.cy;
305     int index;
306
307     if( x >= m_nx || y >= m_ny ) return -1;
308
309     if( pt.x > (x+1)*m_pic_delta.cx - m_margin.cx ||
310         y_pos + pt.y > (y+1)*m_pic_delta.cy - m_margin.cy ) return -1;
311
312     index = y*m_nx + x;
313     if( index >= m_count ) return -1;
314
315     return index;
316 }
317
318
319 void CImageBaseView::OnLButtonDown(UINT nFlags, CPoint point) 
320 {
321         CScrollView::OnLButtonDown(nFlags, point);
322
323     int index = GetIndexByPoint( point );
324     if( index >= 0 )
325     {
326         m_active = index;
327     }
328     InvalidateRect(0);
329 }
330
331
332 void CImageBaseView::SwitchMode( int index, bool to_personal )
333 {
334     CHMMDemoDoc* doc = GetDocument();
335
336     if( doc )
337     {
338         CPerson* person = doc->GetFaceBase().GetPerson( index );
339         if( !person )
340         {
341             ASSERT(0);
342             return;
343         }
344         if( to_personal )
345         {
346             person->LoadRest();
347             m_index = index;
348             m_active = -1;
349             m_view_mode = VIEW_PERSON;
350         }
351         else
352         {
353             if( person->IsModified())
354             {
355                 person->Save();
356             }
357             person->UnloadRest();
358             m_index = -1;
359             m_active = index;
360             m_view_mode = VIEW_BASE;
361         }
362         RefreshView();
363     }
364 }
365
366
367 void CImageBaseView::OnLButtonDblClk(UINT nFlags, CPoint point) 
368 {
369     CScrollView::OnLButtonDblClk(nFlags, point);
370
371     int index = GetIndexByPoint( point );
372     if( index >= 0 && m_index == -1 )
373     {
374         SwitchMode( index, true );
375     }
376     else if( index < 0 && m_index >= 0 )
377     {
378         SwitchMode( m_index, false );
379     }
380 }
381
382 int CImageBaseView::GetMode()
383 {
384     return m_view_mode;
385 }