Znajdowanie i zamalowanie figury

0

Mam daną dwukolorową bitmapę gdzie jest narysowana jedna, zamknięta figura bez antyaliasingu (przykład), jej linie mogą się przecinać (przykład)
i teraz chcę zakolorować wnętrze tej figury

niestety nie mam pojęcia jak to zrobić - mógłbym zrobić zwykły floodfill ale nie wiem jak wykryć wszystkie wnętrza figury
szukając czegoś w google trafiłem na problem PIP gdzie po spojrzeniu na obrazek wydało mi się że to może działać, ale w praktyce wygląda to tak:

user image

dwa ostatnie przykłady udowadniają że nie da się ocenić czy punkt leży wewnątrz biorąc pod uwagę tylko jedną linię
jakieś pomysły?

0

patrząc na powyższe wpadłem na to żeby zrobić drugi przebieg pionowy i kolorować tylko punkty wspólne
jest już bardzo dobrze ale nadal są drobne błędy:

user image

0

wydaje mi się że byłoby już całkiem dobrze gdyby zrobić jeszcze przebieg od prawej i od dołu i sprawdzać czy czy punkt jest wewnątrz na co najmniej 3 przypadków
ale to już trochę za dużo liczenia dla komputera dla takiej prostej rzeczy

jak to robi na przykład wiekowy ms paint przy jego "Free-form select"?

0

w przypadku painta to inaczej dziala
implementowalem taki algorytm jaki ci trzeba na studiach, nie pamietam nazwy, sprobuje poszperac

0

http://www.mini.pw.edu.pl/~kotowski/Grafika/Wyklady.htm
czesc Filling, masz tam opis algorytmow, moze troche zbyt ogolnie, ale google pomoze znalezc szczegoly

0

cos wyszperalem, dokladnie sie nie przygladalem, po nazwach funkcji sadze ze robi to co bys chcial
kod nie jest moj (ale pewnie bede w stanie pomoc, jesli cos jest nie jacne) i jest w c++ (ale to prawie jak c# ;])

plik .h

#include <windows.h>

class Kontekst
{
public:
	HDC hdc;
	COLORREF Pattern[10][10];
	HBITMAP hBmp;
	PBITMAPINFO pbmi;

	void Filter(HDC hdc, int channel, int func[], RECT rt);
	void Pattern_Print(int x, int y, int height, int width);
	void Flood_Fill(int X,int Y,COLORREF tempKolor,int pattern);
	void Flood_Fill8(int X,int Y,COLORREF tempKolor,int pattern);
	void Boundary_Fill(HWND hWnd, int X,int Y,COLORREF tempKolor,COLORREF tempKolorBorder,int pattern);
	void Boundary_Fill8(HWND hWnd, int X,int Y,COLORREF tempKolor,COLORREF tempKolorBorder,int pattern);
	void Pattern_Fill(int X,int Y,COLORREF tempKolor);
	void Pattern_Fill8(int X,int Y,COLORREF tempKolor);
	void MidPointLine(int p1x, int p1y, int p2x, int p2y, COLORREF color);
	void CreateDibSectionFromDibFile (PTSTR szFileName);
	void CreateBitmapInfoStruct(HWND hwnd);
	void CreateBMPFile(HWND hwnd, LPTSTR pszFile);
};

class Colors
{
public:
	double r,g,b;
	double h,s,l;
	void CalculateHSL();
	void CalculateRGB();
};

plik .cpp

#include "kontekst.h"
#include <stack>

#define RESERVED_RGB RGB(1,1,1)

using namespace std ;

typedef stack<POINT> STACK_POINT;

int MyAbs(int x);
void Invert_Rect(HDC hdc, int x1, int y1, int x2, int y2);

void Kontekst::Filter(HDC hdc, int channel, int func[], RECT rt)
{
	static int i,j,k;
	static Colors col;
	static COLORREF kol;

	if (rt.left>rt.right) { i = rt.left; rt.left = rt.right; rt.right = i; }
	if (rt.top>rt.bottom) { i = rt.top; rt.top = rt.bottom; rt.bottom = i; }

	for(i=rt.left;i<rt.right;i++)
		for(j=rt.top;j<rt.bottom;j++)
		{
			kol = GetPixel(hdc,i,j);
			col.r = (double)GetRValue(kol);
			col.g = (double)GetGValue(kol);
			col.b = (double)GetBValue(kol);
			switch (channel)
			{
			case (0):
				for(k=0;k<256;k++)
					if (abs(col.r-k)<2) 
					{
						col.r = (double)func[k];
						break;
					}
				break;
			case (1):
				for(k=0;k<256;k++)
					if (abs(col.g-k)<2) 
					{
						col.g = (double)func[k];
						break;
					}
				break;
			case (2):
				for(k=0;k<256;k++)
					if (abs(col.b-k)<2) 
					{
						col.b = (double)func[k];
						break;
					}
				break;
			case (3):
				col.CalculateHSL();
				for(k=0;k<256;k++)
					if (abs(col.h-k)<2) 
					{
						col.h = (double)func[k];
						break;
					}
				col.CalculateRGB();
				break;
			case (4):
				col.CalculateHSL();
				for(k=0;k<256;k++)
					if (abs(col.s-k)<2) 
					{
						col.s = (double)func[k];
						break;
					}
				col.CalculateRGB();
				break;
			case (5):
				col.CalculateHSL();
				for(k=0;k<256;k++)
					if (abs(col.l-k)<2) 
					{
						col.l = (double)func[k];
						break;
					}
				col.CalculateRGB();
				break;
			case (6):
				for(k=0;k<256;k++)
					if (abs(col.r-k)<2) 
					{
						col.r = (double)func[k];
						break;
					}
				for(k=0;k<256;k++)
					if (abs(col.g-k)<2) 
					{
						col.g = (double)func[k];
						break;
					}
				for(k=0;k<256;k++)
					if (abs(col.b-k)<2) 
					{
						col.b = (double)func[k];
						break;
					}
				break;
			}
			SetPixel(hdc,i,j,RGB(col.r,col.g,col.b));

		}
}

void Kontekst::Pattern_Print(int x, int y, int height, int width)
{
	static int i,j;

	for(i=0;i<10*height;i++)
		for(j=0;j<10*width;j++)
			if ((i%10==0)||(i%10==9)||(j%10==0)||(j%10==9)) SetPixel(hdc,x+j,y+i,RGB(0,0,0)) ;
				else
					SetPixel(hdc,x+j,y+i,Pattern[j/width][i/height]);
}

void Kontekst::Flood_Fill(int X,int Y,COLORREF tempKolor, int pattern)
{
        STACK_POINT s;
        POINT tempP,tpn;
        COLORREF OldColor = GetPixel(hdc,X,Y);
        tpn.x = X;
		tpn.y = Y;
		s.push(tpn);
        if (pattern==1) tempKolor = RESERVED_RGB;
		while(!s.empty())
        {
                tempP=s.top();
				s.pop();
                if(GetPixel(hdc,tempP.x,tempP.y)==OldColor)
                {

                        SetPixel(hdc,tempP.x,tempP.y,tempKolor);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y;
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y;                        
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y-1;
                        s.push(tpn);
                }
        }
		if (pattern == 1) Pattern_Fill(X,Y,tempKolor);
}

void Kontekst::Flood_Fill8(int X,int Y,COLORREF tempKolor,int pattern)
{
        STACK_POINT s;
        POINT tempP,tpn;
        COLORREF OldColor = GetPixel(hdc,X,Y);
        tpn.x = X;
		tpn.y = Y;
		s.push(tpn);
        if (pattern==1) tempKolor = RESERVED_RGB;
        while(!s.empty())
        {
                tempP=s.top();
				s.pop();
                if(GetPixel(hdc,tempP.x,tempP.y)==OldColor)
                {

                        SetPixel(hdc,tempP.x,tempP.y,tempKolor);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y;
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y;                        
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y-1;
                        s.push(tpn);

						tpn.x = tempP.x+1;
						tpn.y = tempP.y+1;
						s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y-1;                        
						s.push(tpn);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y-1;
                        s.push(tpn);

                }
        }
		if (pattern == 1) Pattern_Fill8(X,Y,tempKolor);
}

void Kontekst::Boundary_Fill(HWND hwnd,int X,int Y,COLORREF tempKolor,COLORREF tempKolorBorder,int pattern)
{

        RECT rt;
		STACK_POINT s;
        POINT tempP,tpn;
        
		if (pattern==1) tempKolor = RESERVED_RGB;
		
		COLORREF KolorPom = tempKolor;
		GetClientRect(hwnd,&rt);

        tpn.x = X;
		tpn.y = Y;
		s.push(tpn);
        

 
        while(!(s.empty()))
        {
				tempP=s.top();
				s.pop();
                
				if((GetPixel(hdc,tempP.x,tempP.y)!=tempKolorBorder)
                && (GetPixel(hdc,tempP.x,tempP.y)!=KolorPom)
                && (tempP.x>0) && (tempP.y>=0)
                && (tempP.x<rt.right) && (tempP.y<rt.bottom))
                {
						SetPixel(hdc,tempP.x,tempP.y,KolorPom);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y;
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y;                        
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y-1;
						s.push(tpn);


                }


        }

		if (pattern == 1) Pattern_Fill(X,Y,tempKolor);

}

void Kontekst::Boundary_Fill8(HWND hwnd, int X,int Y,COLORREF tempKolor,COLORREF tempKolorBorder, int pattern)
{

        RECT rt;
		STACK_POINT s;
        POINT tempP,tpn;
        if (pattern==1) tempKolor = RESERVED_RGB;
        COLORREF KolorPom = tempKolor;
		GetClientRect(hwnd,&rt);

        tpn.x = X;
		tpn.y = Y;
		s.push(tpn);
        


        while(!(s.empty()))
        {
				tempP=s.top();
				s.pop();
                
				if((GetPixel(hdc,tempP.x,tempP.y)!=tempKolorBorder)
                && (GetPixel(hdc,tempP.x,tempP.y)!=KolorPom)
                && (tempP.x>0) && (tempP.y>=0)
                && (tempP.x<rt.right) && (tempP.y<rt.bottom))
                {
						SetPixel(hdc,tempP.x,tempP.y,KolorPom);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y;
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y;                        
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y-1;
						s.push(tpn);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y+1;
						s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y-1;                        
						s.push(tpn);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y-1;
						s.push(tpn);


                }


        }

		if (pattern == 1) Pattern_Fill8(X,Y,tempKolor);

}

void Kontekst::Pattern_Fill(int X,int Y,COLORREF tempKolor)
{
        STACK_POINT s;
        POINT tempP,tpn;
        COLORREF OldColor;

		OldColor=tempKolor;

        tpn.x = X;
		tpn.y = Y;
		s.push(tpn);
        while(!s.empty())
        {
                tempP=s.top();
                s.pop();
                if((GetPixel(hdc,tempP.x,tempP.y)==OldColor)
					&& (GetPixel(hdc,tempP.x,tempP.y)!= Pattern[MyAbs(tempP.x-X)][MyAbs(tempP.y-Y)]))
                {
                        SetPixel(hdc,tempP.x,tempP.y,Pattern[MyAbs(tempP.x-X)][MyAbs(tempP.y-Y)]);

						tpn.x = tempP.x+1;
						tpn.y = tempP.y;
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y;                        
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y-1;
						s.push(tpn);
                }
        }

}
void Kontekst::Pattern_Fill8(int X,int Y,COLORREF tempKolor)
{
        STACK_POINT s;
        POINT tempP,tpn;
        COLORREF OldColor;

		OldColor=tempKolor;

        tpn.x = X;
		tpn.y = Y;
		s.push(tpn);
        while(!s.empty())
        {
                tempP=s.top();
                s.pop();
                if((GetPixel(hdc,tempP.x,tempP.y)==OldColor)
					&& (GetPixel(hdc,tempP.x,tempP.y)!= Pattern[MyAbs(tempP.x-X)][MyAbs(tempP.y-Y)]))
                {
                        SetPixel(hdc,tempP.x,tempP.y,Pattern[MyAbs(tempP.x-X)][MyAbs(tempP.y-Y)]);

						tpn.x = tempP.x+1;
						tpn.y = tempP.y;
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y;                        
						s.push(tpn);
						tpn.x = tempP.x;
						tpn.y = tempP.y-1;
						s.push(tpn);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y+1;
						s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y+1;
                        s.push(tpn);
						tpn.x = tempP.x-1;
						tpn.y = tempP.y-1;                        
						s.push(tpn);
						tpn.x = tempP.x+1;
						tpn.y = tempP.y-1;
						s.push(tpn);
                }
        }

}

void Kontekst::MidPointLine(int p1x, int p1y, int p2x, int p2y, COLORREF color)
{

	int d;
	int pktx, pkty;


	if(p2x<p1x){
		pktx=p2x;
		p2x=p1x;
		p1x=pktx;
		pkty=p2y;
		p2y=p1y;
		p1y=pkty;
	}
	
	int dx=p2x-p1x;
	int dy=p2y-p1y;
	int x=p1x;
	int y=p1y;

	if(dy>=0){
		if(dx>dy){
			d=2*dy-dx;
			int incrE=2*dy;
			int incrNE=2*(dy-dx);
			SetPixel(hdc,x,y,color);
			for(;x<p2x;){
				if(d<0){
					d+=incrE;
					x++;
				}
				else{
					d+=incrNE;
					x++;
					y++;
				}
			SetPixel(hdc,x,y,color);
			}
		}
		else{
			d=2*dx-dy;
			int incrN=2*dx;
			int incrNE=2*(dx-dy);
			SetPixel(hdc,x,y,color);
			for(;y<p2y;){
				if(d<0){
					d+=incrN;
					y++;
				}
				else{
					d+=incrNE;
					x++;
					y++;
				}
			SetPixel(hdc,x,y,color);
			}
		}
	}
	else{
		dy=-dy;
		if(dx>dy){
			d=2*dy-dx;
			int incrE=2*dy;
			int incrSE=2*(dy-dx);
			SetPixel(hdc,x,y,color);
			for(;x<p2x;){
				if(d<0){
					d+=incrE;
					x++;
				}
				else{
					d+=incrSE;
					x++;
					y--;
				}
			SetPixel(hdc,x,y,color);
			}
		}
		else{
			d=2*dx-dy;
			int incrS=2*dx;
			int incrSE=2*(dx-dy);
			SetPixel(hdc,x,y,color);
			for(;y>p2y;){
				if(d<0){
					d+=incrS;
					y--;
				}
				else{
					d+=incrSE;
					x++;
					y--;
				}
			SetPixel(hdc,x,y,color);
			}
		}
	}
}

void Kontekst::CreateDibSectionFromDibFile (PTSTR szFileName)
{
     BITMAPFILEHEADER bmfh ;
     BITMAPINFO     * pbmi ;
     BYTE           * pBits ;
     BOOL             bSuccess ;
     DWORD            dwInfoSize, dwBytesRead ;
     HANDLE           hFile ;

     hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ,
                         NULL, OPEN_EXISTING, 0, NULL) ;

     if (hFile == INVALID_HANDLE_VALUE)
          exit (0);

     bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
                          &dwBytesRead, NULL) ;

     if (!bSuccess || (dwBytesRead != sizeof (BITMAPFILEHEADER))         
                   || (bmfh.bfType != * (WORD *) "BM"))
     {
          CloseHandle (hFile) ;
          exit (0) ;
     }

     dwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ;

     pbmi = (BITMAPINFO *)malloc (dwInfoSize) ;

     bSuccess = ReadFile (hFile, pbmi, dwInfoSize, &dwBytesRead, NULL) ;

     if (!bSuccess || (dwBytesRead != dwInfoSize))
     {
          free (pbmi) ;
          CloseHandle (hFile) ;
          exit (0) ;
     }

     hBmp = CreateDIBSection (NULL, pbmi, DIB_RGB_COLORS, (void **)(&pBits), NULL, 0) ;

     if (hBmp == NULL)
     {
          free (pbmi) ;
          CloseHandle (hFile) ;
          exit (0);
     }

     ReadFile (hFile, pBits, bmfh.bfSize - bmfh.bfOffBits, &dwBytesRead, NULL) ;

     free (pbmi) ;
     CloseHandle (hFile) ;
}

void Kontekst::CreateBitmapInfoStruct(HWND hwnd)
{ 
    BITMAP bmp; 
    WORD    cClrBits; 

    if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
		MessageBox(hwnd,"GetObject","Error",MB_OK);

    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
    if (cClrBits == 1) 
        cClrBits = 1; 
    else if (cClrBits <= 4) 
        cClrBits = 4; 
    else if (cClrBits <= 8) 
        cClrBits = 8; 
    else if (cClrBits <= 16) 
        cClrBits = 16; 
    else if (cClrBits <= 24) 
        cClrBits = 24; 
    else cClrBits = 32; 

     if (cClrBits != 24) 
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                    sizeof(BITMAPINFOHEADER) + 
                    sizeof(RGBQUAD) * (1<< cClrBits)); 

     else 
         pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
                    sizeof(BITMAPINFOHEADER)); 

    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    pbmi->bmiHeader.biWidth = bmp.bmWidth; 
    pbmi->bmiHeader.biHeight = bmp.bmHeight; 
    pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
    if (cClrBits < 24) 
        pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 

    pbmi->bmiHeader.biCompression = BI_RGB; 

    // Compute the number of bytes in the array of color 
    // indices and store the result in biSizeImage. 
    // For Windows NT/2000, the width must be DWORD aligned unless 
    // the bitmap is RLE compressed. This example shows this. 
    // For Windows 95/98, the width must be WORD aligned unless the 
    // bitmap is RLE compressed.
    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
                                  * pbmi->bmiHeader.biHeight; 

     pbmi->bmiHeader.biClrImportant = 0; 
} 

void Kontekst::CreateBMPFile(HWND hwnd, LPTSTR pszFile) 
{ 
    HANDLE hf;       
    BITMAPFILEHEADER hdr;   
    PBITMAPINFOHEADER pbih; 
    LPBYTE lpBits;        
    DWORD dwTotal;
    DWORD cb;   
    BYTE *hp; 
    DWORD dwTmp; 

    pbih = (PBITMAPINFOHEADER) pbmi; 
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

    if (!lpBits) 
         MessageBox(hwnd,"GlobalAlloc","Error",MB_OK);

    if (!GetDIBits(hdc, hBmp, 0, (WORD) pbih->biHeight, lpBits, pbmi, 
        DIB_RGB_COLORS)) 
    {
		MessageBox(hwnd,"GetDIBits","Error",MB_OK);
    }

    hf = CreateFile(pszFile, 
                   GENERIC_READ | GENERIC_WRITE, 
                   (DWORD) 0, 
                    NULL, 
                   CREATE_ALWAYS, 
                   FILE_ATTRIBUTE_NORMAL, 
                   (HANDLE) NULL); 
    if (hf == INVALID_HANDLE_VALUE)
		MessageBox(hwnd,"CreateFile","Error",MB_OK);
    hdr.bfType = 0x4d42;

    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
                 pbih->biSize + pbih->biClrUsed 
                 * sizeof(RGBQUAD) + pbih->biSizeImage); 
    hdr.bfReserved1 = 0; 
    hdr.bfReserved2 = 0; 

    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
                    pbih->biSize + pbih->biClrUsed 
                    * sizeof (RGBQUAD); 

    if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
        (LPDWORD) &dwTmp,  NULL)) 
    {
       MessageBox(hwnd,"WriteFile","Error",MB_OK);
    }

    if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
					+ pbih->biClrUsed * sizeof (RGBQUAD), 
					(LPDWORD) &dwTmp, ( NULL)))
		MessageBox(hwnd,"WriteFile","Error",MB_OK);

    dwTotal = cb = pbih->biSizeImage; 
    hp = lpBits; 
    if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
			MessageBox(hwnd,"WriteFile","Error",MB_OK);

     if (!CloseHandle(hf)) 
		 MessageBox(hwnd,"CloseHandle","Error",MB_OK);

    GlobalFree((HGLOBAL)lpBits);
}
/*
void Colors::CalculateHSL()
{
	double min,max;

	if (r<g) min = min(r,b);
	else min = min(g,b);

	if (r>g) max = max(r,b);
	else max = max(g,b);

	if (max==min)
	{
		h = 0;
		s = 0;
		l = max;
	}
	else
	{
		l = (min+max)/2;

		if (l<0.5) s = (max-min)/(max+min);
		else s = (max-min)/(l-max-min);

		if (r==max) h = 60*(g-b)/(max-min);
		else
		if (g==max) h = 120 + 60*(b-r)/(max-min);
		else
		if (b==max) h = 240 + 60*(r-g)/(max-min);

		h = (h/360)*255;

	}
}

*/
void Colors::CalculateHSL()
{
  double v;
  double m;
  double vm;
  double r2, g2, b2;

  r/=255;
  g/=255;
  b/=255;

  v = max(r,g);
  v = max(v,b);
  m = min(r,g);
  m = min(m,b);

  if ((l = (m + v) / 2.0) <= 0.0) return;
  if ((s = vm = v - m) > 0.0) {
    s /= (l <= 0.5) ? (v + m ) : (2.0 - v - m) ;
  } else return;


  r2 = (v - r) / vm;
  g2 = (v - g) / vm;
  b2 = (v - b) / vm;

  if (r == v)
    h = (g == m ? 5.0 + b2 : 1.0 - g2);
  else if (g == v)
    h = (b == m ? 1.0 + r2 : 3.0 - b2);
  else
    h = (r == m ? 3.0 + g2 : 5.0 - r2);

  h /= 6;

  h *= 255;
  s *= 255;
  l *= 255;
}

void Colors::CalculateRGB()
{
  double v;

  h /= 255;
  s /= 255;
  l /= 255;
  
  v = (l <= 0.5) ? (l * (1.0 + s)) : (l + s - l * s);

  if (v <= 0) {
    r = g = b = 0.0;
  } else {
    double m;
    double sv;
    int sextant;
    double fract, vsf, mid1, mid2;

    m = l + l - v;
    sv = (v - m ) / v;
    h *= 6.0;
    sextant = h;
    fract = h - sextant;
    vsf = v * sv * fract;
    mid1 = m + vsf;
    mid2 = v - vsf;
    switch (sextant) {
      case 0: r = v; g = mid1; b = m; break;
      case 1: r = mid2; g = v; b = m; break;
      case 2: r = m; g = v; b = mid1; break;
      case 3: r = m; g = mid2; b = v; break;
      case 4: r = mid1; g = m; b = v; break;
      case 5: r = v; g = m; b = mid2; break;
    }
  }
  r*=255;
  g*=255;
  b*=255;



}

int MyAbs(int x)
{
    return x>=0?x%10:(10-abs(x%10))%10;
}

void Invert_Rect(HDC hdc, int x1, int y1, int x2, int y2)
{
	int i,r,g,b;
	COLORREF color;

	for(i=min(x1,x2);i<=max(x1,x2);i++)
	{
		color = GetPixel(hdc,i,y1);
		r = 255 - GetRValue(color);
		g = 255 - GetGValue(color);
		b = 255 - GetBValue(color);
		SetPixel(hdc,i,y1,RGB(r,g,b));
		color = GetPixel(hdc,i,y2);
		r = 255 - GetRValue(color);
		g = 255 - GetGValue(color);
		b = 255 - GetBValue(color);
		SetPixel(hdc,i,y2,RGB(r,g,b));
	}
	for(i=min(y1,y2);i<=max(y1,y2);i++)
	{
		color = GetPixel(hdc,x1,i);
		r = 255 - GetRValue(color);
		g = 255 - GetGValue(color);
		b = 255 - GetBValue(color);
		SetPixel(hdc,x1,i,RGB(r,g,b));
		color = GetPixel(hdc,x2,i);
		r = 255 - GetRValue(color);
		g = 255 - GetGValue(color);
		b = 255 - GetBValue(color);
		SetPixel(hdc,x2,i,RGB(r,g,b));
	}
}
0

@dark_astray: przecież to zwykły floodfill... :/ jak pisałem w pierwszym poście problemem nie jest zaimplementowanie floodfilla tylko znalezienie środków figury

@massther: mi właśnie chodzi o to żeby to zrobić najlepiej w ten sam sposób co robi to paint
dzięki wielkie za próby pomocy ale te opisy na podanej stronie nadają się tylko do wielokątów, grafiki wektorowej a pozostałe wymagają podania współrzędnych piksela wewnątrz figury
podane przez Ciebie funkcje też tylko używają zwykłego floodfilla i floodfilla z kolorem krawędzi

może opiszę bliżej po co mi to właściwie jest bo z kolorowaniem to nie ma nic wspólnego:
mam parę bloków - elementów graficznych, w kształtach prostokątów i elips (ale mogą dojść kolejne)
cel: pozwolenie użytkownikowi na zaznaczenie "lassem" elementów z którymi chce coś zrobić

aktualne rozwiązanie:
użytkownik maluje na formie ładną pętle, jednocześnie w pamięci malując drugą figurę na czarnobiałej bitmapie używając LineTo
po puszczenia przycisku myszki następuje wyliczenie które z elementów znajdują się w zaznaczeniu przy pomocy sposobu opisanego wcześniej:

  1. Skanuję bitmapę poziomo zmieniając stan zmiennej bool przy każdym zamalowanym pikselu, zaznaczam piksele które są niezamalowane w nieparzystych regionach
  2. Skanuję bitmapę pionowo robiąc to samo, jednak przy pikselach już uprzednio zaznaczonych, sprawdzam w pętli czy piksel należy do jakiegoś elementu - jeżeli tak to zwiększam przypisaną mu liczbę
  3. W pętli dzielę przypisaną do każdego elementu liczbę przez wyliczone pole powierzchni tego obiektu - jeżeli otrzymana liczba jest większa od 0,5 to oznacza że element w ponad połowie leży w narysowanej pętli

i to już działa, błędy są małe więc teoretycznie rzadko się zdarzy żeby miały wpływ na rezultat działania algorytmu - zwłaszcza że zazwyczaj zaznaczenie będzie zwykłą elipsą przy której błędów praktycznie nie ma
mimo to gryzą mnie sumienie żeby to tak zostawić bo to straszna prowizorka mi się zdaje

mógłbym zamiast rysować figurę w pamięci, zapamiętywać tylko współrzędne początku i końca rysowanych linii, a potem skorzystać z jednego z tych algorytmów na kilkuset-bocznej figurze (przy wolnym ręcznym rysowaniu każdy pixel byłby krawędzią) ale może ktoś podsunie jeszcze jakiś pomysł?

0

patrząc na "Lasso Select" w Paint.NET, wydaje mi się że niektóre rzeczy mogą już być policzone podczas malowania
ale dalej pomysłów brak...

1 użytkowników online, w tym zalogowanych: 0, gości: 1