📄 imageview.cpp
字号:
//-----------------------------------------------------------------------------
// (c) 2002 by Basler Vision Technologies
// Section: Vision Components
// Project: BCAM
// $Header: ImageView.cpp, 10, 17.09.2003 17:15:57, Nebelung, H.$
//-----------------------------------------------------------------------------
/**
\file ImageView.cpp
*
* \brief Implementation of CImageRectTracker and CImageView
*
*/
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "RectTracker.h"
#include "imageview.h"
/////////////////////////////////////////////////////////////////////////////
// CImageRectTracker
CImageRectTracker::CImageRectTracker(CImageView& view)
: CRectTracker(CRect(0,0,0,0), solidLine | resizeOutside | hatchedBorder),
m_View(view)
{
m_nHandleSize = 8;
}
void CImageRectTracker::AdjustRect(int nHandle, LPRECT lpRect)
{
// CRectTracker constraints on rectangle dimensions.
CRectTracker::AdjustRect(nHandle, lpRect);
// Enforce rect inside image canvas and adjusted to valid AOI positions and sizes
m_View.AdjustRect(nHandle, lpRect);
}
void CImageRectTracker::AdjustPoint(LPPOINT lpPoint)
{
m_View.AdjustPoint(lpPoint);
}
void CImageRectTracker::OnChangedRect(const CRect& rcOld )
{
m_View.MoveTrackerTo(&m_rect, &rcOld, TRUE);
CRectTracker::OnChangedRect(rcOld);
}
void CImageRectTracker::OnTrackingFinished(BOOL bCancelled )
{
m_View.StopTimer();
if ( ! bCancelled )
{
m_View.SetNewAOI( );
}
else
{
m_View.MoveTrackerTo(m_rect, m_rectSave, TRUE);
m_View.SetNewAOI();
}
CRectTracker::OnTrackingFinished(bCancelled);
}
void CImageRectTracker::LPtoDP(LPPOINT lpPoints, int nCount) const
{
m_View.LPtoDP( lpPoints, nCount);
};
void CImageRectTracker::DPtoLP(LPPOINT lpPoints, int nCount) const
{
m_View.DPtoLP( lpPoints, nCount);
};
/////////////////////////////////////////////////////////////////////////////
// CImageView
const CSize CImageView::s_sizBorder = CSize(10,10);
DWORD CImageView::s_dwDragTimerInterval = 100;
void CImageView::SetSensorSize(CSize SensorSize)
{
if ( m_VideoFormat == DCS_Format7)
{
// we only allow AOI widths which are multiples of 4, so the sensor rect has to be adjusted
m_pCamera->AlignAOI(SensorSize, m_VideoMode);
}
m_SensorSize = SensorSize;
m_SensorRect = CRect(CPoint(0,0), SensorSize);
double ZoomLevel = m_dZoomScale; // SetScrollSize resets the zoom level to 1 -> save current zoom state
SetScrollSize(SensorSize.cx + ( 2 * s_sizBorder.cx ), SensorSize.cy + ( s_sizBorder.cy * 2 ) );
if ( ZoomLevel != 1 )
{ // restore zoom state
SetZoomLevel(ZoomLevel);
UpdateViewPort(NULL);
}
}
void CImageView::ConfigurationChanged(DCSVideoFormat format, DCSVideoMode mode, CSize SensorSize, CSize ImageSize, CPoint Origin)
{
if ( format == DCS_Format7 )
{
m_pCamera->AlignAOI(SensorSize, mode);
}
if ( m_VideoFormat != format || m_VideoMode != mode || m_SensorSize != SensorSize )
{
m_bFit = false;
m_VideoFormat = format;
m_VideoMode = mode;
if ( SensorSize != m_SensorSize )
{
SetSensorSize(SensorSize);
}
m_bScalable = format == DCS_Format7;
if ( m_bScalable )
{
m_SizeInc.cx = lcm(4, m_pCamera->FormatSeven[mode].Size.Inc().cx);
m_SizeInc.cy = m_pCamera->FormatSeven[mode].Size.Inc().cy;
m_PosInc = m_pCamera->FormatSeven[mode].Position.Inc();
m_RectTracker.m_sizeMin = CSize(m_SizeInc.cx, m_SizeInc.cy );
}
}
CRect imageRect = CRect(Origin, ImageSize);
m_RectTracker.m_rect = imageRect;
// if area of interest is not visible -> center viewport on AOI
if ( m_bScalable )
{
CRect client;
GetClientRect(&client);
ClientToLogical(client);
client.IntersectRect(imageRect, client);
if ( client.IsRectEmpty() )
UpdateViewPort(NULL);
}
Invalidate();
UpdateWindow();
ShowAOISize();
}
void CImageView::DoPaint(CDCHandle dc)
{
assert(m_pCamera != NULL );
CBcamBitmap* pBitmap = m_pCamera->GetBitmap();
if ( pBitmap != NULL )
{
// Bitblt bitmap
BitBlt(dc, pBitmap);
// if size of image is less than size of sensor fill the parts of the sensor not
// covered by the image
CRect ImageRect = pBitmap->GetRect(); // image dimension
HBRUSH hBrush = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
if ( ImageRect.left > m_SensorRect.left )
{
RECT rectLeft = m_SensorRect;
rectLeft.right = ImageRect.left;
dc.FillRect(&rectLeft, hBrush);
}
if ( ImageRect.top > m_SensorRect.top )
{
RECT rectTop = m_SensorRect;
rectTop.bottom = ImageRect.top;
dc.FillRect(&rectTop, hBrush);
}
if ( ImageRect.right < m_SensorRect.right )
{
RECT rectRight = m_SensorRect;
rectRight.left = ImageRect.right;
dc.FillRect(&rectRight, hBrush);
}
if ( ImageRect.bottom < m_SensorRect.bottom )
{
RECT rectBottom = m_SensorRect;
rectBottom.top = ImageRect.bottom;
dc.FillRect(&rectBottom, hBrush);
}
}
else
{
// no bitmap available -> fill the whole sensor area
dc.FillRect(&m_SensorRect, (HBRUSH) GetStockObject(LTGRAY_BRUSH));
}
// draw bounding rectangle around sensor area
CRect BorderRect = m_SensorRect;
BorderRect.InflateRect(1,1);
HBRUSH oldBrush = dc.SelectStockBrush(NULL_BRUSH);
dc.Rectangle(&BorderRect);
dc.SelectBrush(oldBrush);
// draw rubber band
if ( m_bScalable )
{
m_RectTracker.Draw(dc);
}
}
void CImageView::ZoomToFit()
{
if ( ! m_bFit )
{
// ensure that actually no scroll bars are visible
m_sizeAll = CSize(0,0);
RecalcBars();
double scale;
bool modifyWidth;
double scaley = (double) ( m_sizeClient.cy - 2 * s_sizBorder.cy ) / (double) m_SensorSize.cy;
double scalex = (double) ( m_sizeClient.cx - 2 * s_sizBorder.cx ) / (double) m_SensorSize.cx;
if ( scalex < scaley )
{
scale = scalex;
modifyWidth = false;
}
else
{
scale = scaley;
modifyWidth = true;
}
SetZoomLevel(scale);
ZoomIn(NULL, 0);
if ( ! ::IsZoomed(GetParent()) )
{
// Adjust window dimension
CRect newRect(CPoint(0,0), m_sizeClient);
// first calculate new client size
if ( modifyWidth )
newRect.right = 2 * s_sizBorder.cx + m_SensorSize.cx * scale;
else
newRect.bottom = 2 * s_sizBorder.cy + m_SensorSize.cy * scale;
// transform client rect to window rect of inner window
AdjustWindowRectEx(&newRect, GetWindowLong(GWL_STYLE), FALSE,GetWindowLong(GWL_EXSTYLE));
// The window rect of the inner window is the desired client rect of the outer window (i.e. the MDI Child window).
// Calculate the window rect of the MDI window from the desired client rect
AdjustWindowRectEx(&newRect, ::GetWindowLong(GetParent(), GWL_STYLE), FALSE, ::GetWindowLong(GetParent(), GWL_EXSTYLE));
// Set the new window rect of the MDI window
CRect oldRect;
::GetWindowRect(GetParent(), &oldRect);
if ( modifyWidth )
::SetWindowPos(GetParent(), NULL, 0, 0, newRect.Width(), oldRect.Height(), SWP_NOMOVE | SWP_NOZORDER );
else
::SetWindowPos(GetParent(), NULL, 0, 0, oldRect.Width(), newRect.Height(), SWP_NOMOVE | SWP_NOZORDER );
}
m_bFit = true;
}
}
void CImageView::BitBlt(CDCHandle dc, CBcamBitmap* pBitmap) {
if ( pBitmap == NULL )
return;
m_CriticalSection.Lock();
PrepareDC(dc);
// determine region of bitmap which has to be blitted
// first get client rect and transform it into the sensor coordinate system
CRect rect;
GetClientRect(rect);
dc.DPtoLP(rect);
rect.InflateRect(1,1);
CRect ImageRect = pBitmap->GetRect(); // image dimensions
rect.IntersectRect(rect, ImageRect);
CDC dcMem;
dcMem.CreateCompatibleDC(dc);
HBITMAP hBmpOld = dcMem.SelectBitmap(*pBitmap);
if ( m_dZoomScale < 1 )
{
dc.SetStretchBltMode(COLORONCOLOR);
}
if ( m_dZoomScale > 1 )
{
// we observed that the performance of StretchBlt may dramatically decrease if the mouse cursor
// is placed outside the bitmap window. To avoid this strange behaviour we do a kind of magic. Selecting a
// clipping region according to the bitmapsize and reducing it by one single pixel will increase the performance
// of StretchBlt
CRgn rgn;
CRect ClipRect = rect;
dc.LPtoDP(ClipRect);
dc.SaveDC();
rgn.CreateRectRgnIndirect(ClipRect);
dc.SelectClipRgn(rgn);
CRect rect2(0, 0, 1, 1);
rect2.OffsetRect(max(ClipRect.left, 0), max(ClipRect.top,0));
CRgn rgn2;
rgn2.CreateRectRgnIndirect(rect2);
dc.SelectClipRgn(rgn2, RGN_DIFF);
}
dc.BitBlt(
rect.left,
rect.top,
rect.Width(),
rect.Height(),
dcMem,
rect.left - ImageRect.left,
rect.top - ImageRect.top,
SRCCOPY
);
if ( m_dZoomScale > 1 )
dc.RestoreDC(-1);
dcMem.SelectBitmap(hBmpOld);
if ( m_bScalable && ! ImageRect.EqualRect(m_RectTracker.m_rect) )
{
m_RectTracker.Draw(dc);
}
m_CriticalSection.Unlock();
}
LRESULT CImageView::OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
assert ( m_pCamera );
CDCHandle dc = (HDC)wParam;
CRect ClientRect;
GetClientRect(&ClientRect);
CPoint pt;
pt.x = m_SensorSize.cx;
pt.y = m_SensorSize.cy;
PrepareDC(dc);
dc.DPtoLP(&ClientRect);
ClientRect.InflateRect(1,1);
if ( ClientRect.left < 0 )
{
RECT ClientRectLeft = ClientRect;
ClientRectLeft.right = 0;
ClientRectLeft.bottom = pt.y;
dc.FillRect(&ClientRectLeft, (HBRUSH) GetStockObject(GRAY_BRUSH));
}
if ( ClientRect.top < 0 )
{
RECT ClientRectTop = ClientRect;
ClientRectTop.bottom = 0;
dc.FillRect(&ClientRectTop, (HBRUSH) GetStockObject(GRAY_BRUSH));
}
if( ClientRect.right > m_SensorSize.cx )
{
RECT ClientRectRight = ClientRect;
ClientRectRight.left = pt.x;
ClientRectRight.bottom = pt.y;
dc.FillRect(&ClientRectRight, (HBRUSH) GetStockObject(GRAY_BRUSH));
}
if( ClientRect.bottom > m_SensorSize.cy )
{
RECT ClientRectBottom = ClientRect;
ClientRectBottom.top = pt.y;
dc.FillRect(&ClientRectBottom, (HBRUSH) GetStockObject(GRAY_BRUSH));
}
return 0;
}
BOOL CImageView::HitTestTrackerBorder()
{
if ( ! m_bScalable )
return FALSE;
CPoint point;
GetCursorPos(&point);
ScreenToClient(&point);
CRect rcTrueRect;
m_RectTracker.GetTrueRect(rcTrueRect);
CRect rcTracker = m_RectTracker.m_rect;
LogicalToClient(rcTracker);
return rcTrueRect.PtInRect(point) && !rcTracker.PtInRect(point);
}
BOOL CImageView::MoveTrackerTo(CRect rcNew, CRect rcOld, BOOL fRepaint)
{
if ( m_bScalable )
{
if (fRepaint)
{
Invalidate();
}
}
return TRUE;
}
void CImageView::AdjustRect(int nHandle, LPRECT lpRect)
{
CRect rc(*lpRect);
CRect rcLimits = m_SensorRect;
if ( nHandle == CRectTracker::hitLeft ||
nHandle == CRectTracker::hitTopLeft ||
nHandle == CRectTracker::hitBottomLeft )
{
int width = m_SizeInc.cx * ( rc.Width() / m_SizeInc.cx );
rc.left = rc.right - width;
if ( rc.left < 0 )
{
rc.left = 0;
rc.right = m_SizeInc.cx * ( rc.right / m_SizeInc.cx );
}
}
if ( nHandle == CRectTracker::hitRight ||
nHandle == CRectTracker::hitTopRight ||
nHandle == CRectTracker::hitBottomRight )
{
int width = m_SizeInc.cx * ( rc.Width() / m_SizeInc.cx );
rc.right = rc.left + width;
if ( rc.right > rcLimits.right )
{
rc.right = rcLimits.right;
rc.left = max(0, rc.right - m_SizeInc.cx * ( rc.Width() / m_SizeInc.cx ));
}
}
if ( nHandle == CRectTracker::hitTopLeft ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -