00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "filterfloodfill.h"
00033 #include "../container/fixedstack.h"
00034 #include <cmath>
00035
00036 FloodFillFilter::FloodFillFilter() : ChannelSelectDotFilter(true)
00037 {
00038 already = 0;
00039 tolerance = 25;
00040 fillcolor = 100;
00041 x0 = y0 = 0;
00042 }
00043
00044 FloodFillFilter::~FloodFillFilter()
00045 {
00046 delete already;
00047 }
00048
00049 void FloodFillFilter::OnMouseEvent(const int button, const int state, int x, int y)
00050 {
00051 if(button!=0)
00052 {
00053 ChannelSelectDotFilter::OnMouseEvent(button, state, x, y);
00054 }
00055 ChannelSelectDotFilter::Normalize(&x,&y);
00056 if(state == 0 && button == 0)
00057 {
00058 x0 = x;
00059 y0 = y;
00060 }
00061 if(state == 1 && button == 0)
00062 {
00063 x0 = x-x0;
00064 y0 = y-y0;
00065 x = x-x0;
00066 y = y-y0;
00067 tolerance = (char)(abs(x0*200.0/ChannelSelectDotFilter::GetWidth()));
00068 if(tolerance < 2)
00069 tolerance = 20;
00070 fillcolor = ChannelSelectDotFilter::GetSelectedColor();
00071 unsigned char color = ChannelSelectDotFilter::Get(x,y);
00072 unsigned char low = tolerance>color ? 0 : color-tolerance;
00073 unsigned char high = tolerance>(255-color) ? 255 : color+tolerance;
00074 unsigned char currentcolor = 0;
00075 already = new Channel<bool>(ChannelSelectDotFilter::GetHeight(),ChannelSelectDotFilter::GetWidth());
00076 for(int x1=0;x1<already->GetWidth();x1++)
00077 for(int y1=0;y1<already->GetHeight();y1++)
00078 already->Set(x1,y1,false);
00079 FixedStack* stack = new FixedStack(already->GetWidth()*already->GetHeight());
00080 already->Set(x,y,true);
00081 stack->Push(x,y);
00082 while(stack->Pop(&x,&y))
00083 {
00084 currentcolor = ChannelSelectDotFilter::Get(x,y);
00085 if(currentcolor >= low && currentcolor <= high)
00086 {
00087 ChannelSelectDotFilter::Set(x,y,fillcolor);
00088 if(x>0 && !already->Get(x-1,y))
00089 {
00090 stack->Push(x-1,y);
00091 already->Set(x-1,y,true);
00092 }
00093 if(x<ChannelSelectDotFilter::GetWidth()-1 && !already->Get(x+1,y))
00094 {
00095 stack->Push(x+1,y);
00096 already->Set(x+1,y,true);
00097 }
00098 if(y>0 && !already->Get(x,y-1))
00099 {
00100 stack->Push(x,y-1);
00101 already->Set(x,y-1,true);
00102 }
00103 if(y<ChannelSelectDotFilter::GetHeight()-1 && !already->Get(x,y+1))
00104 {
00105 stack->Push(x,y+1);
00106 already->Set(x,y+1,true);
00107 }
00108 already->Set(x,y,true);
00109 }
00110 }
00111 delete stack;
00112 delete already;
00113 already = 0;
00114 }
00115 }
00116
00117 ChannelFilter<unsigned char>* FloodFillFilter::EmptyClone()
00118 {
00119 FloodFillFilter *copy = new FloodFillFilter();
00120 copy->SetSubChannel(ChannelSelectDotFilter::GetSubChannel());
00121 return(copy);
00122 }