123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /*
- * Copyright (C) =USTC= Fu Li
- *
- * Author : Fu Li
- * Create : 2003-4-8
- * Home : http://www.crazy-bit.com/
- * Mail : crazybit@263.net
- * History :
- */
- #ifndef __FOO_OBJECT_SELECTION__2003_04_08__H__
- #define __FOO_OBJECT_SELECTION__2003_04_08__H__
- #include "ObjImage.h"
- #include "PCL_interface_zoom.h"
- //=============================================================================
- /**
- * Selection object (bitmap mask).
- * it's a 8-bit gray image, 0xFF means pixel selected, otherwise unselected.
- */
- class FCObjSelect : public FCObjImage
- {
- public:
- /** handle type. */
- enum RGN_TYPE
- {
- RGN_CREATE=0, /**< create a new selection */
- RGN_ADD=1, /**< add selection into current selection */
- RGN_SUB=2, /**< sub selection from current selection */
- };
- public:
- /**
- * @name Constructor.
- */
- //@{
- /// Create an empty selection.
- FCObjSelect ()
- {
- m_nZoom = ZOOM_UNSCAN ;
- m_nCurAnt = 0 ;
- }
- /// Copy constructor.
- FCObjSelect (const FCObjSelect& sel)
- {
- m_nZoom = ZOOM_UNSCAN ;
- m_nCurAnt = 0 ;
- *this = sel ;
- }
- //@}
- FCObjSelect& operator= (const FCObjSelect& sel)
- {
- if (&sel == this)
- {
- assert(false); return *this;
- }
- __SetSelectionEmpty(); // enable empty copy
- if (sel.HasSelected())
- {
- m_nZoom = sel.m_nZoom;
- m_nCurAnt = sel.m_nCurAnt;
- m_ptEdge = sel.m_ptEdge; // copy the edge point
- FCObjImage::operator=(sel);
- }
- return *this;
- }
- /// Is selection object valid.
- bool HasSelected() const {return IsValidImage();}
- /**
- * Optimize selection.
- * erase un-selected point around. the position of selection will be adjusted automatically.
- */
- void SelectionOptimize()
- {
- if (!HasSelected())
- return ;
- RECT rcBound = {Width(), Height(), 0, 0} ;
- for (int y=0 ; y < Height() ; y++)
- for (int x=0 ; x < Width() ; x++)
- if (*GetBits(x,y) == 0xFF)
- {
- if (x < rcBound.left) rcBound.left = x ;
- if (x > rcBound.right) rcBound.right = x ;
- if (y < rcBound.top) rcBound.top = y ;
- if (y > rcBound.bottom) rcBound.bottom = y ;
- }
- // the selection is open, so we ++
- rcBound.right++ ; rcBound.bottom++ ;
- // the whole selection is empty
- if (IsRectEmpty(&rcBound))
- {
- __SetSelectionEmpty() ;
- return ;
- }
- // the selection can't be optimized
- const RECT rcSel = {0, 0, Width(), Height()} ;
- if (memcmp (&rcSel, &rcBound, sizeof(RECT)) == 0) // rect is equal
- return ;
- // erase == get a sub block
- const POINT ptOldPos = GetGraphObjPos() ;
- FCObjImage imgSub ;
- GetSubBlock (&imgSub, rcBound) ;
- *static_cast<FCObjImage*>(this) = imgSub ;
- SetGraphObjPos (ptOldPos.x+rcBound.left, ptOldPos.y+rcBound.top) ;
- m_ptEdge.clear() ;
- m_nCurAnt = 0 ;
- m_nZoom = ZOOM_UNSCAN ; // force to re-calculate edge
- }
- /**
- * Calculate edge point by nZoom.
- * edge point's coordinate relative to top-left of selection object.
- */
- void RecalculateEdge (int nZoom, bool bForceRecalculate)
- {
- if (!HasSelected())
- {
- m_ptEdge.clear() ;
- m_nCurAnt = 0 ;
- m_nZoom = ZOOM_UNSCAN ;
- return ;
- }
- if (!bForceRecalculate)
- if (m_nZoom == nZoom)
- return ;
- m_ptEdge.clear() ;
- m_nCurAnt = 0 ;
- m_nZoom = nZoom ;
- if ((m_nZoom == ZOOM_UNSCAN) || (m_nZoom == 0))
- return ;
- // search edge point
- FCObjImage EdgeImg (Width(), Height(), 8) ;
- int nEdgeNum = 0 ;
- // is edge point : current is selected around is non-selected
- // brim point must be edge point
- for (int y=0 ; y < Height() ; y++)
- for (int x=0 ; x < Width() ; x++)
- if (*GetBits(x,y) == 0xFF)
- if ((y == 0) || (*GetBits(x,y-1) == 0) || // up
- (y == Height()-1) || (*GetBits(x,y+1) == 0) || // down
- (x == 0) || (*GetBits(x-1,y) == 0) || // left
- (x == Width()-1) || (*GetBits(x+1,y) == 0) || // right
- (*GetBits(x+1,y-1) == 0) || // right-up
- (*GetBits(x+1,y+1) == 0) || // right-down
- (*GetBits(x-1,y+1) == 0) || // left-down
- (*GetBits(x-1,y-1) == 0)) // left-up
- {
- *EdgeImg.GetBits(x,y) = 0xFF ;
- nEdgeNum++ ;
- }
- // no edge point
- if (nEdgeNum == 0)
- return ;
- if (m_nZoom <= -1)
- {
- // deflate, only div
- FCObjImage imgHash (Width()/-m_nZoom+2, Height()/-m_nZoom+2, 8) ;
- for (int y=0 ; y < Height() ; y++)
- for (int x=0 ; x < Width() ; x++)
- if (*EdgeImg.GetBits(x,y) == 0xFF)
- {
- POINT pt = {x/-m_nZoom, y/-m_nZoom} ;
- BYTE * pHash = imgHash.GetBits (pt.x, pt.y) ;
- if (*pHash == 0) // some point --> one point
- {
- *pHash = 0xFF ;
- m_ptEdge.push_back (pt) ;
- }
- }
- }
- else
- {
- // inflate, we should insert some point
- const int nNewW = Width() * m_nZoom,
- nNewH = Height() * m_nZoom ;
- // calculate x/y table
- PCL_array<int> pX (nNewW),
- pY (nNewH) ;
- int x, y ;
- for (y=0 ; y < nNewH ; y++)
- {pY[y] = y / m_nZoom; assert (pY[y] < Height());}
- for (x=0 ; x < nNewW ; x++)
- {pX[x] = x / m_nZoom; assert (pX[x] < Width());}
- // search edge
- for (y=0 ; y < nNewH ; y++)
- for (x=0 ; x < nNewW ; x++)
- if (*EdgeImg.GetBits (pX[x],pY[y]) == 0xFF)
- {
- // still edge point after inflate
- int cr = *GetBits (pX[x],pY[y]) ;
- if ((y == 0) || (*GetBits(pX[x],pY[y-1]) != cr) || // up
- (y == nNewH-1) || (*GetBits(pX[x],pY[y+1]) != cr) || // down
- (x == 0) || (*GetBits(pX[x-1],pY[y]) != cr) || // left
- (x == nNewW-1) || (*GetBits(pX[x+1],pY[y]) != cr)) // right
- // (*(pPixel + 1 + dwPitch) == 0) || // right-up
- // (*(pPixel + 1 - dwPitch) == 0) || // right-down
- // (*(pPixel - 1 - dwPitch) == 0) || // left-down
- // (*(pPixel - 1 + dwPitch) == 0)) // left_up
- {
- POINT pt = {x,y} ;
- m_ptEdge.push_back (pt) ;
- }
- }
- }
- }
- private:
- enum
- {
- ZOOM_UNSCAN = 0x7FFF,
- };
- // internal. set selection empty
- void __SetSelectionEmpty()
- {
- FCObjImage::Destroy() ;
- m_ptEdge.clear() ;
- m_nZoom = ZOOM_UNSCAN ;
- m_nCurAnt = 0 ;
- }
- private:
- int m_nZoom ;
- int m_nCurAnt ; // [0..7]
- std::deque<POINT> m_ptEdge ; // scaled edge point
- friend class FCWin32 ;
- };
- //===================================================================
- // inline implement
- //===================================================================
- #endif
|