/* * @(#) linerize.cpp - Image linerizer program for Windows. * (c) 1996 Ivan Maidanski http://ivmai.chat.ru * Freeware program source. All rights reserved. ** * Language: C++ * Tested with: Borland C++ v3.1 * Last modified: 1996-04-29 23:20:00 GMT+04:00 */ // Resource file: linerize.rc #define WIN31 #define STRICT #include #include #include const int BitMapWidth= 700; const int BitMapHeight= 400; const COLORREF Colors[3][16]= {{0x00FFFFFFl,0x00E0E0E0l,0x00C0C0FFl,0x00C0E0FFl, 0x00E0FFFFl,0x00C0FFC0l,0x00FFFFC0l,0x00FFC0C0l, 0x00FFC0FFl,0x000000C0l,0x000040C0l,0x0000C0C0l, 0x0000C000l,0x00C0C000l,0x00C00000l,0x00C000C0l}, {0x00C0C0C0l,0x00404040l,0x008080FFl,0x0080C0FFl, 0x0080FFFFl,0x0080FF80l,0x00FFFF80l,0x00FF8080l, 0x00FF80FFl,0x00000080l,0x00004080l,0x00008080l, 0x00008000l,0x00808000l,0x00800000l,0x00800080l}, {0x00808080l,0x00000000l,0x000000FFl,0x000080FFl, 0x0000FFFFl,0x0000FF00l,0x00FFFF00l,0x00FF0000l, 0x00FF00FFl,0x00000040l,0x00404080l,0x00004040l, 0x00004000l,0x00404000l,0x00400000l,0x00400040l}}; const int ToolCount= 7; const int MenuCount= 4; const int LineCount= 8; const int IconSize= 32; const int LineBarWidth= LineCount*4+6+(1+2+3+4+5+7+9+12); const int LineWidth[LineCount]= {1,2,3,4,5,7,9,12}; _CLASSDEF(TDrawTool) struct TState { PTDrawTool DrawTool; HBITMAP BitMap; int PenSize; COLORREF Foreground,Background; }; typedef TState* PTState; class TDrawTool { protected: HCURSOR Cursor; HICON Icon; PTState State; HWND Window; HPEN Pen; HBRUSH Brush; HDC DC; public: TDrawTool(LPSTR IconName); virtual ~TDrawTool() { DestroyCursor(Cursor); DestroyIcon(Icon); }; void MouseDown(HWND AWindow,int X,int Y,COLORREF Color,PTState AState); void MouseMove(int X,int Y) { DrawTo(X,Y); }; void MouseUp(); virtual void DrawBegin(int X,int Y) {}; // Abstract draw methods will virtual void DrawTo(int X,int Y) {}; // be implemented in derrived classes virtual void DrawEnd() {}; HCURSOR GetCursor() { return Cursor; }; // Classes other than derrived may HICON GetIcon() { return Icon; }; // want access to these member fields }; _CLASSDEF(TPenTool) class TPenTool : public TDrawTool { public: TPenTool(LPSTR IconName) : TDrawTool(IconName) {}; virtual void DrawBegin(int X,int Y); virtual void DrawTo(int X,int Y) { LineTo(DC,X,Y); }; }; _CLASSDEF(TFillTool) class TFillTool : public TDrawTool { public: TFillTool(LPSTR IconName) : TDrawTool(IconName) {}; virtual void DrawBegin(int X,int Y); }; _CLASSDEF(TBoxTool) class TBoxTool : public TDrawTool { protected: BOOL Filled; int X1,Y1,X2,Y2; public: TBoxTool(LPSTR IconName,BOOL AFilled) : TDrawTool(IconName) { Filled=AFilled; }; virtual void DrawBegin(int X,int Y); virtual void DrawTo(int X,int Y); virtual void DrawEnd(); virtual void DrawObject() {}; }; _CLASSDEF(TLineTool) class TLineTool : public TBoxTool { public: TLineTool(LPSTR IconName) : TBoxTool(IconName,False) {}; virtual void DrawObject() { MoveTo(DC,X1,Y1),LineTo(DC,X2,Y2); }; }; _CLASSDEF(TRectTool) class TRectTool : public TBoxTool { public: TRectTool(LPSTR IconName,BOOL AFilled) : TBoxTool(IconName,AFilled) {}; virtual void DrawObject() { Rectangle(DC,X1,Y1,X2,Y2); }; }; _CLASSDEF(TEllipseTool) class TEllipseTool : public TBoxTool { public: TEllipseTool(LPSTR IconName,BOOL AFilled) : TBoxTool(IconName,AFilled) {}; virtual void DrawObject() { Ellipse(DC,X1,Y1,X2,Y2); }; }; _CLASSDEF(TPalette) class TPalette : public TWindow { private: PTState State; public: TPalette(PTWindowsObject AParent,PTState AState); virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); void SelectColor(TMessage& Message,COLORREF& Color); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN] { SelectColor(Message,State->Foreground); }; virtual void WMRButtonDown(TMessage& Message)= [WM_FIRST+WM_RBUTTONDOWN] { SelectColor(Message,State->Background); }; }; _CLASSDEF(TToolBar) class TToolBar : public TWindow { private: PTState State; PTDrawTool Tools[ToolCount]; public: TToolBar(PTWindowsObject AParent,PTState AState); virtual ~TToolBar(); virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; }; _CLASSDEF(TLineBar) class TLineBar : public TWindow { public: TLineBar(PTWindowsObject AParent,PTState AState); virtual void Paint(HDC PaintDC, PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; private: PTState State; void Notch(HDC PaintDC,int X,int W,int Y,int DY); }; _CLASSDEF(TCanvas) class TCanvas : public TWindow { private: PTState State; BOOL Drawing; public: TCanvas(PTWindowsObject AParent,PTState AState); virtual ~TCanvas() { DeleteObject(State->BitMap); }; virtual LPSTR GetClassName() { return "TCanvas"; }; virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; virtual void WMRButtonDown(TMessage& Message)= [WM_FIRST+WM_RBUTTONDOWN]; virtual void WMLButtonUp(TMessage& Message)= [WM_FIRST+WM_LBUTTONUP]; virtual void WMRButtonUp(TMessage& Message)= [WM_FIRST+WM_RBUTTONUP] { WMLButtonUp(Message); }; virtual void WMMouseMove(TMessage& Message)= [WM_FIRST+WM_MOUSEMOVE]; virtual void WMSetCursor(TMessage& Message)= [WM_FIRST+WM_SETCURSOR] { SetCursor(State->DrawTool->GetCursor()); }; HWND GetCanvasWindow() { return (HWindow); }; }; _CLASSDEF(TMenuItem) class TMenuItem { protected: HICON Icon; public: TMenuItem(LPSTR IconName) { Icon=LoadIcon(GetApplicationObject()->hInstance,IconName); }; virtual ~TMenuItem() { DestroyIcon(Icon); }; virtual void Run(PTState State,PTCanvas Canvas) {}; HICON GetIcon() { return Icon; }; }; _CLASSDEF(TClearAll) class TClearAll : public TMenuItem { public: TClearAll(LPSTR IconName) : TMenuItem(IconName) {}; virtual void Run(PTState State,PTCanvas Canvas); }; _CLASSDEF(TClipboardRead) class TClipboardRead : public TMenuItem { public: TClipboardRead(LPSTR IconName) : TMenuItem(IconName) {}; virtual void Run(PTState State,PTCanvas Canvas); }; _CLASSDEF(TReduceImage) class TReduceImage : public TMenuItem { private: BOOL PointTest(int Sw,int p[]); BOOL OneLoop(int Sw,HDC Dest,HDC Src,COLORREF Background); protected: long Step; public: TReduceImage(LPSTR IconName) : TMenuItem(IconName) { Step=0; }; virtual void Run(PTState State,PTCanvas Canvas); }; _CLASSDEF(TReduceImageAll) class TReduceImageAll : public TReduceImage { public: TReduceImageAll(LPSTR IconName) : TReduceImage(IconName) {}; virtual void Run(PTState State,PTCanvas Canvas); }; _CLASSDEF(TMenuBar) class TMenuBar : public TWindow { private: PTState State; PTCanvas Canvas; PTMenuItem Items[MenuCount]; public: TMenuBar(PTWindowsObject AParent,PTState AState,PTCanvas ACanvas); virtual ~TMenuBar(); virtual void Paint(HDC PaintDC,PAINTSTRUCT& PaintInfo); virtual void WMLButtonDown(TMessage& Message)= [WM_FIRST+WM_LBUTTONDOWN]; }; _CLASSDEF(TLinerizerWin) class TLinerizerWin : public TWindow { private: TState State; PTCanvas Canvas; PTPalette Palette; PTToolBar ToolBar; PTLineBar LineBar; PTMenuBar MenuBar; public: TLinerizerWin(PTWindowsObject AParent,LPSTR ATitle); virtual ~TLinerizerWin(); virtual LPSTR GetClassName() { return "TLinerizerWin"; }; virtual void GetWindowClass(WNDCLASS& WndClass); virtual void WMSize(TMessage& Message)= [WM_FIRST+WM_SIZE]; }; class TLinerizeApp : public TApplication { public: TLinerizeApp(LPSTR name,HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmd,int nCmdShow) : TApplication(name,hInstance,hPrevInstance,lpCmd,nCmdShow) {}; virtual void InitMainWindow(void) { MainWindow=new TLinerizerWin(NULL,"Image Linerizer"); }; }; BOOL TReduceImage::PointTest(int Sw,int p[]) { int b=p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+p[8]+p[9]; if (!(b>=2 && b<=6 && !(p[2] && p[4] && (Sw? p[6]:p[8])) && !((Sw? p[4]:p[2]) && p[6] && p[8]))) return FALSE; int i; for (i=2;i<10;i++) if (p[i]) break; if (i>=8) return TRUE; for (i++;i<10;i++) if (!p[i]) break; if (i>=9) return TRUE; for (i++;i<10;i++) if (p[i]) break; if (i==10) return TRUE; for (i++;i<10;i++) if (!p[i]) return FALSE; return p[2]; }; BOOL TReduceImage::OneLoop(int Sw,HDC Dest,HDC Src,COLORREF Background) { BOOL Modified=FALSE; BOOL P[10]; for (int Y=0;YGetCanvasWindow()); HDC MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); Step++; if (!OneLoop((int)(Step%2),MemDC,DC,Colors[0][0])) Step=0; GetClientRect(Canvas->GetCanvasWindow(),&R); BitBlt(DC,0,0,R.right,R.bottom,MemDC,0,0,SRCCOPY); DeleteDC(MemDC); ReleaseDC(Canvas->GetCanvasWindow(),DC); }; void TReduceImageAll::Run(PTState State,PTCanvas Canvas) { Step=0; do TReduceImage::Run(State,Canvas); while (Step); }; TDrawTool::TDrawTool(LPSTR IconName) { char Temp[30]; _fstrcpy(Temp,IconName); strncat(Temp,"Tool",sizeof(Temp)-1); Icon=LoadIcon(GetApplicationObject()->hInstance,Temp); _fstrcpy(Temp,IconName); strncat(Temp,"Cursor",sizeof(Temp)-1); Cursor=LoadCursor(GetApplicationObject()->hInstance,Temp); }; void TDrawTool::MouseDown(HWND AWindow,int X,int Y,COLORREF Color, PTState AState) { Window=AWindow; State=AState; SetCapture(Window); Pen=CreatePen(PS_SOLID,State->PenSize,Color); Brush=CreateSolidBrush(Color); DC=GetDC(Window); DrawBegin(X,Y); }; void TDrawTool::MouseUp() { DrawEnd(); ReleaseCapture(); DeleteObject(Brush); DeleteObject(Pen); ReleaseDC(Window,DC); }; void TPenTool::DrawBegin(int X,int Y) { SelectObject(DC,Pen); MoveTo(DC,X,Y); }; void TFillTool::DrawBegin(int X,int Y) { SelectObject(DC,Brush); ExtFloodFill(DC,X,Y,GetPixel(DC,X,Y),FLOODFILLSURFACE); }; void TBoxTool::DrawBegin(int X,int Y) { X1=X; Y1=Y; X2=X; Y2=Y; SelectObject(DC,GetStockObject(BLACK_PEN)); SelectObject(DC,GetStockObject(NULL_BRUSH)); SetROP2(DC,R2_NOT); DrawObject(); }; void TBoxTool::DrawTo(int X,int Y) { DrawObject(); X2=X; Y2=Y; DrawObject(); }; void TBoxTool::DrawEnd() { DrawObject(); SetROP2(DC,R2_COPYPEN); SelectObject(DC,Pen); if (Filled) SelectObject(DC,Brush); DrawObject(); }; TPalette::TPalette(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; }; void TPalette::Paint(HDC PaintDC,PAINTSTRUCT&) { int X,Y,S; HPEN Pen; HBRUSH Brush; RECT R; GetClientRect(HWindow,&R); S=R.bottom/17; for (Y=0;Y<16;Y++) for (X=0;X<3;X++) { Brush=(HBRUSH)SelectObject(PaintDC,CreateSolidBrush(Colors[X][Y])); Rectangle(PaintDC,X*S,Y*S,(X+1)*S+1,(Y+1)*S+1); DeleteObject(SelectObject(PaintDC,Brush)); } SelectObject(PaintDC,GetStockObject(NULL_BRUSH)); Rectangle(PaintDC,0,S*16,R.right,R.bottom); Pen=(HPEN)SelectObject(PaintDC,CreatePen(PS_SOLID,5,State->Background)); Brush=(HBRUSH)SelectObject(PaintDC,CreateSolidBrush(State->Foreground)); Rectangle(PaintDC,3,S*16+3,R.right-3,R.bottom-3); DeleteObject(SelectObject(PaintDC,Brush)); DeleteObject(SelectObject(PaintDC,Pen)); }; void TPalette::SelectColor(TMessage& Message,COLORREF& Color) { int X,Y,S; RECT R; GetClientRect(HWindow,&R); S=R.bottom/17; X=Message.LP.Lo/S; Y=Message.LP.Hi/S; if ((X<3) && (Y<16)) { Color=Colors[X][Y]; InvalidateRect(HWindow,NULL,FALSE); } }; TToolBar::TToolBar(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; Tools[0]=new TPenTool("Pen"); Tools[1]=new TLineTool("Line"); Tools[2]=new TFillTool("Fill"); Tools[3]=new TRectTool("Rect",FALSE); Tools[4]=new TRectTool("FillRect",TRUE); Tools[5]=new TEllipseTool("Ellipse",FALSE); Tools[6]=new TEllipseTool("FillEllipse",TRUE); State->DrawTool=Tools[0]; }; TToolBar::~TToolBar() { for (int i=0;iGetIcon()); if (Tools[N]==State->DrawTool) { R.top=1; R.left=N*IconSize; R.bottom=R.top+30; R.right=R.left+30; InvertRect(PaintDC,&R); } } }; void TToolBar::WMLButtonDown(TMessage& Message) { int N=Message.LP.Lo/IconSize; if (NDrawTool=Tools[N]; InvalidateRect(HWindow,NULL,FALSE); } }; TLineBar::TLineBar(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { Attr.Style=WS_BORDER | WS_CHILD | WS_VISIBLE; State=AState; }; void TLineBar::Notch(HDC PaintDC,int X,int W,int Y,int DY) { for (int L=3;L>=0;L--) { MoveTo(PaintDC,X+W/2-L,Y); LineTo(PaintDC,X+W/2+L+1,Y); Y+=DY; } }; void TLineBar::Paint(HDC PaintDC,PAINTSTRUCT&) { int I,X,W; RECT R; X=4; for (I=0;IPenSize) { Notch(PaintDC,X,W,0,1); Notch(PaintDC,X,W,29,-1); } X+=W+4; } }; void TLineBar::WMLButtonDown(TMessage& Message) { int I,X,W; X=2; for(I=0;I=X) && (Message.LP.Lo<(X+W+4))) { State->PenSize=W; InvalidateRect(HWindow,NULL,TRUE); return; } X+=W+4; } }; TCanvas::TCanvas(PTWindowsObject AParent,PTState AState) : TWindow(AParent,NULL) { HDC DC,MemDC; Attr.Style=WS_BORDER | WS_CHILD | WS_VISIBLE; State=AState; Drawing=FALSE; DC=GetDC(0); State->BitMap=CreateCompatibleBitmap(DC,BitMapWidth,BitMapHeight); MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); PatBlt(MemDC,0,0,BitMapWidth,BitMapHeight,WHITENESS); DeleteDC(MemDC); ReleaseDC(0,DC); }; void TCanvas::Paint(HDC PaintDC,PAINTSTRUCT&) { RECT R; HDC MemDC=CreateCompatibleDC(PaintDC); SelectObject(MemDC,State->BitMap); GetClientRect(HWindow,&R); BitBlt(PaintDC,0,0,R.right,R.bottom,MemDC,0,0,SRCCOPY); DeleteDC(MemDC); }; void TCanvas::WMLButtonDown(TMessage& Message) { if (!Drawing) { Drawing=TRUE; State->DrawTool->MouseDown(HWindow,Message.LP.Lo,Message.LP.Hi, State->Foreground,State); } }; void TCanvas::WMRButtonDown(TMessage& Message) { if (!Drawing) { Drawing=TRUE; State->DrawTool->MouseDown(HWindow,Message.LP.Lo,Message.LP.Hi, State->Background,State); } }; void TCanvas::WMMouseMove(TMessage& Message) { if (Drawing) State->DrawTool->MouseMove(Message.LP.Lo,Message.LP.Hi); }; void TCanvas::WMLButtonUp(TMessage&) { HDC DC,MemDC; RECT R; if (Drawing) { State->DrawTool->MouseUp(); Drawing=FALSE; DC=GetDC(HWindow); MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); GetClientRect(HWindow,&R); BitBlt(MemDC,0,0,R.right,R.bottom,DC,0,0,SRCCOPY); DeleteDC(MemDC); ReleaseDC(HWindow,DC); } }; void TClearAll::Run(PTState State,PTCanvas Canvas) { HDC DC=GetDC(Canvas->GetCanvasWindow()); HDC MemDC=CreateCompatibleDC(DC); ReleaseDC(Canvas->GetCanvasWindow(),DC); SelectObject(MemDC,State->BitMap); SelectObject(MemDC,GetStockObject(WHITE_PEN)); SelectObject(MemDC,GetStockObject(WHITE_BRUSH)); Rectangle(MemDC,0,0,BitMapWidth-1,BitMapHeight-1); DeleteDC(MemDC); InvalidateRect(Canvas->GetCanvasWindow(),NULL,TRUE); }; void TClipboardRead::Run(PTState State,PTCanvas Canvas) { HANDLE Image; HDC DC=GetDC(Canvas->GetCanvasWindow()); HDC MemDC=CreateCompatibleDC(DC); SelectObject(MemDC,State->BitMap); if (OpenClipboard(Canvas->GetCanvasWindow())) { Image=GetClipboardData(CF_BITMAP); if (Image) { HDC MapDC=CreateCompatibleDC(DC); SelectObject(MapDC,Image); BitBlt(MemDC,0,0,BitMapWidth-1,BitMapHeight-1,MapDC,0,0,SRCCOPY); DeleteDC(MapDC); } CloseClipboard(); } DeleteDC(MemDC); ReleaseDC(Canvas->GetCanvasWindow(),DC); InvalidateRect(Canvas->GetCanvasWindow(),NULL,TRUE); }; TMenuBar::TMenuBar(PTWindowsObject AParent,PTState AState,PTCanvas ACanvas) : TWindow(AParent,NULL) { Attr.Style=WS_CHILD | WS_VISIBLE; State=AState; Canvas=ACanvas; Items[0]=new TClearAll("ClearAll"); Items[1]=new TClipboardRead("ClipboardRead"); Items[2]=new TReduceImageAll("ReduceImageAll"); Items[3]=new TReduceImage("ReduceImage"); }; TMenuBar::~TMenuBar() { for (int i=0;iGetIcon()); }; void TMenuBar::WMLButtonDown(TMessage& Message) { HCURSOR Cursor; int N=Message.LP.Lo/IconSize; if (NRun(State,Canvas); SetCursor(Cursor); } }; TLinerizerWin::TLinerizerWin(PTWindowsObject AParent,LPSTR ATitle) : TWindow(AParent,ATitle) { State.DrawTool=NULL; State.BitMap=0; State.PenSize=LineWidth[3]; State.Background=Colors[0][0]; State.Foreground=0l; Canvas=new TCanvas(this,&State); Palette=new TPalette(this,&State); ToolBar=new TToolBar(this,&State); LineBar=new TLineBar(this,&State); MenuBar=new TMenuBar(this,&State,Canvas); }; TLinerizerWin::~TLinerizerWin() { delete MenuBar; delete LineBar; delete ToolBar; delete Palette; delete Canvas; }; void TLinerizerWin::GetWindowClass(WNDCLASS& WndClass) { TWindow::GetWindowClass(WndClass); WndClass.hbrBackground=(HBRUSH)COLOR_APPWORKSPACE+1; WndClass.hIcon=LoadIcon(GetApplication()->hInstance,"ProgramIcon"); }; void TLinerizerWin::WMSize(TMessage&) { int S; RECT R; GetClientRect(HWindow,&R); S=((R.bottom-8)/17)*3+1; MoveWindow(Palette->HWindow,4,4,S,R.bottom-8,TRUE); MoveWindow(ToolBar->HWindow,S+8,4,ToolCount*IconSize,32,TRUE); MoveWindow(LineBar->HWindow,S+ToolCount*IconSize+14,4, LineBarWidth,32,TRUE); MoveWindow(MenuBar->HWindow,S+ToolCount*IconSize+LineBarWidth+20,4, MenuCount*IconSize,32,TRUE); MoveWindow(Canvas->HWindow,S+8,40,R.right-S-12,R.bottom-44,TRUE); }; int PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpCmd,int nCmdShow) { TLinerizeApp App("Linerizer",hInstance,hPrevInstance,lpCmd,nCmdShow); App.Run(); return (App.Status); }