public override void FloodFill(Bitmap bmp, Point pt)
{
int ctr=timeGetTime();
m_fillcolor=ColorTranslator.ToWin32(m_fillcolorcolor);
m_fillcolor=BGRA(GetB(m_fillcolor),
GetG(m_fillcolor),GetR(m_fillcolor),GetA(m_fillcolor));
//get the bits
BitmapData bmpData=bmp.LockBits(
new Rectangle(0,0,bmp.Width,bmp.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
System.IntPtr Scan0 = bmpData.Scan0;
unsafe
{
byte * scan0=(byte *)(void *)Scan0;
int loc=CoordsToIndex(pt.X,pt.Y,bmpData.Stride);
int color= *((int*)(scan0+loc));
PixelsChecked=new bool[bmpData.Width+1,bmpData.Height+1];
//do the first call to the loop
switch(m_FillStyle)
{
case FloodFillStyle.Linear :
if(m_FillDiagonal)
{
LinearFloodFill8(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}else{
LinearFloodFill4(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}
break;
case FloodFillStyle.Queue :
QueueFloodFill(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
break;
case FloodFillStyle.Recursive :
if(m_FillDiagonal)
{
RecursiveFloodFill8(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}else{
RecursiveFloodFill4(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}
break;
}
}
bmp.UnlockBits(bmpData);
m_TimeBenchmark=timeGetTime()-ctr;
}
unsafe void LinearFloodFill4( byte* scan0, int x, int y,Size bmpsize,
int stride, byte* startcolor)
{
int* p=(int*) (scan0+(CoordsToIndex(x,y, stride)));
//FIND LEFT EDGE OF COLOR AREA
int LFillLoc=x; //the location to check/fill on the left
int* ptr=p; //the pointer to the current location
while(true)
{
ptr[0]=m_fillcolor; //fill with the color
PixelsChecked[LFillLoc,y]=true;
LFillLoc--; //de-increment counter
ptr-=1; //de-increment pointer
if(LFillLoc<=0 ||
!CheckPixel((byte*)ptr,startcolor) ||
(PixelsChecked[LFillLoc,y]))
//exit loop if we're at edge of bitmap or color area
break;
}
LFillLoc++;
int RFillLoc=x; //the location to check/fill on the left
ptr=p;
while(true)
{
ptr[0]=m_fillcolor; //fill with the color
PixelsChecked[RFillLoc,y]=true;
RFillLoc++; //increment counter
ptr+=1; //increment pointer
if(RFillLoc>=bmpsize.Width ||
!CheckPixel((byte*)ptr,startcolor) ||
(PixelsChecked[RFillLoc,y]))
//exit loop if we're at edge of bitmap or color area
break;
}
RFillLoc--;
ptr=(int*)(scan0+CoordsToIndex(LFillLoc,y,stride));
for(int i=LFillLoc;i<=RFillLoc;i++)
{
if(y>0 &&
CheckPixel((byte*)(scan0+CoordsToIndex(i,y-1,stride)),startcolor) &&
(!(PixelsChecked[i,y-1])))
LinearFloodFill4(scan0, i,y-1,bmpsize,stride,startcolor);
if(y<(bmpsize.Height-1) &&
CheckPixel((byte*)(scan0+CoordsToIndex(i,y+1,stride)),startcolor) &&
(!(PixelsChecked[i,y+1])))
LinearFloodFill4(scan0, i,y+1,bmpsize,stride,startcolor);
ptr+=1;
}
}
unsafe bool CheckPixel(byte* px, byte* startcolor)
{
bool ret=true;
for(byte i=0;i<3;i++)
ret&= (px[i]>= (startcolor[i]-m_Tolerance[i])) &&
px[i] <= (startcolor[i]+m_Tolerance[i]);
return ret;
}
{
int ctr=timeGetTime();
m_fillcolor=ColorTranslator.ToWin32(m_fillcolorcolor);
m_fillcolor=BGRA(GetB(m_fillcolor),
GetG(m_fillcolor),GetR(m_fillcolor),GetA(m_fillcolor));
//get the bits
BitmapData bmpData=bmp.LockBits(
new Rectangle(0,0,bmp.Width,bmp.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format32bppArgb);
System.IntPtr Scan0 = bmpData.Scan0;
unsafe
{
byte * scan0=(byte *)(void *)Scan0;
int loc=CoordsToIndex(pt.X,pt.Y,bmpData.Stride);
int color= *((int*)(scan0+loc));
PixelsChecked=new bool[bmpData.Width+1,bmpData.Height+1];
//do the first call to the loop
switch(m_FillStyle)
{
case FloodFillStyle.Linear :
if(m_FillDiagonal)
{
LinearFloodFill8(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}else{
LinearFloodFill4(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}
break;
case FloodFillStyle.Queue :
QueueFloodFill(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
break;
case FloodFillStyle.Recursive :
if(m_FillDiagonal)
{
RecursiveFloodFill8(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}else{
RecursiveFloodFill4(scan0,pt.X,pt.Y,
new Size(bmpData.Width,bmpData.Height),
bmpData.Stride,
(byte*)&color);
}
break;
}
}
bmp.UnlockBits(bmpData);
m_TimeBenchmark=timeGetTime()-ctr;
}
unsafe void LinearFloodFill4( byte* scan0, int x, int y,Size bmpsize,
int stride, byte* startcolor)
{
int* p=(int*) (scan0+(CoordsToIndex(x,y, stride)));
//FIND LEFT EDGE OF COLOR AREA
int LFillLoc=x; //the location to check/fill on the left
int* ptr=p; //the pointer to the current location
while(true)
{
ptr[0]=m_fillcolor; //fill with the color
PixelsChecked[LFillLoc,y]=true;
LFillLoc--; //de-increment counter
ptr-=1; //de-increment pointer
if(LFillLoc<=0 ||
!CheckPixel((byte*)ptr,startcolor) ||
(PixelsChecked[LFillLoc,y]))
//exit loop if we're at edge of bitmap or color area
break;
}
LFillLoc++;
int RFillLoc=x; //the location to check/fill on the left
ptr=p;
while(true)
{
ptr[0]=m_fillcolor; //fill with the color
PixelsChecked[RFillLoc,y]=true;
RFillLoc++; //increment counter
ptr+=1; //increment pointer
if(RFillLoc>=bmpsize.Width ||
!CheckPixel((byte*)ptr,startcolor) ||
(PixelsChecked[RFillLoc,y]))
//exit loop if we're at edge of bitmap or color area
break;
}
RFillLoc--;
ptr=(int*)(scan0+CoordsToIndex(LFillLoc,y,stride));
for(int i=LFillLoc;i<=RFillLoc;i++)
{
if(y>0 &&
CheckPixel((byte*)(scan0+CoordsToIndex(i,y-1,stride)),startcolor) &&
(!(PixelsChecked[i,y-1])))
LinearFloodFill4(scan0, i,y-1,bmpsize,stride,startcolor);
if(y<(bmpsize.Height-1) &&
CheckPixel((byte*)(scan0+CoordsToIndex(i,y+1,stride)),startcolor) &&
(!(PixelsChecked[i,y+1])))
LinearFloodFill4(scan0, i,y+1,bmpsize,stride,startcolor);
ptr+=1;
}
}
unsafe bool CheckPixel(byte* px, byte* startcolor)
{
bool ret=true;
for(byte i=0;i<3;i++)
ret&= (px[i]>= (startcolor[i]-m_Tolerance[i])) &&
px[i] <= (startcolor[i]+m_Tolerance[i]);
return ret;
}
No comments:
Post a Comment