// VD_Core.cpp : Defines the initialization routines for the DLL.
//

#include "stdafx.h"
#include "VD_Core.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif



// CVD_CoreApp

BEGIN_MESSAGE_MAP(CVD_CoreApp, CWinApp)
END_MESSAGE_MAP()

// CVD_CoreApp construction

CVD_CoreApp::CVD_CoreApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}


// The one and only CVD_CoreApp object

CVD_CoreApp theApp;


// CVD_CoreApp initialization

BOOL CVD_CoreApp::InitInstance()
{
	CWinApp::InitInstance();

	return TRUE;
}

void VD_BasOp(BasOp op_index, FIBITMAP *s1_d, FIBITMAP *s2 = 0, BYTE param = 0) 
{
	int width = FreeImage_GetWidth(s1_d);
	int height = FreeImage_GetHeight(s1_d);
	int pitch = FreeImage_GetPitch(s1_d);
	FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(s1_d);

	int width2 = FreeImage_GetWidth(s2);
	int height2 = FreeImage_GetHeight(s2);
	int pitch2 = FreeImage_GetPitch(s2);
	FREE_IMAGE_TYPE image_type2 = FreeImage_GetImageType(s2);


	 
	//if(!result) result = FreeImage_Allocate(width,height,FreeImage_GetBPP(s1_d));		//nefunguje

	int x,y,i,j,mx,my,sum, temp;

	BYTE index_max = 50;
	BYTE *im_pixels;
	BYTE *im_pixels2;
	BYTE *im_pixelsr;

	bool change;

	FreeImage_Unload(result);
	result = FreeImage_Clone(s1_d);

	if(s1_d) im_pixels = (BYTE*)FreeImage_GetBits(s1_d);
	if(s2) im_pixels2 = (BYTE*)FreeImage_GetBits(s2);
	if(result) im_pixelsr = (BYTE*)FreeImage_GetBits(result);

	for(y = 0; y < height; y++)
		for(x = 0; x < width; x++)
			im_pixelsr[y*pitch + x] =0;

	switch (op_index) {
		case F_SUBB:	//rozdil obrazu
			if((image_type == image_type2) && (FreeImage_GetBPP(s1_d) == FreeImage_GetBPP(s2))) {
				for(y = 0; y < height; y++) {
					for(x = 0; x < width; x++) {
						if(im_pixels[x] < im_pixels2[x]) 
							im_pixels[x] = im_pixels2[x] - im_pixels[x];
						else 
							im_pixels[x] = im_pixels[x] - im_pixels2[x];
					}
					im_pixels += pitch;
					im_pixels2 += pitch;
				}
			}
			break;
		case F_THR:	//prahovani
			for(y = 0; y < height; y++) {
					for(x = 0; x < width; x++) {
						if(im_pixels[x] > param) 
							im_pixels[x] = 255;
						else 
							im_pixels[x] = 0;
					}
					im_pixels += pitch;
			}
			break;
		case F_MO:	//moravcuv operator
			for(y = 0; y < height; y++) {
				for(x = 0; x < width; x++) {
					sum = 0;
					for(my = -1;my <= 1; my++) {
						for(mx = -1;mx <= 1; mx++) {
							if(((y+my)>=0) && ((y+my)<height) && ((x+mx)>=0) && ((x+mx)<width)) { 
								temp = ((int) (im_pixels[my*pitch + x + mx] - im_pixels[x]));
								if(temp < 0) sum -= temp;
								else sum += temp;
							}
						}	
					}
					im_pixelsr[x] = (BYTE) (sum / 8);
				}
				im_pixels += pitch;
				im_pixelsr += pitch;
			}
			break;
		case F_REC: // nacte puvodni pixely obrazu pomoci vyprahovaneho snimku
			for(y = 0; y < height; y++) {
				for(x = 0; x < width; x++)
					if(im_pixels[x] > 0) im_pixels[x] = im_pixels2[x];
				im_pixels += pitch;
				im_pixels2 += pitch;
			}
			break;
		case F_IDE:	//identifikace oblasti pomoci cisel         zatim nefunguje
			for(y = 0; y < height-100; y++) {
				for(x = 0; x < width; x++) {
					if(im_pixels[x] > 0) {
						change = false;
						for(my = -2;my <= 2; my++) {
							for(mx = -2;mx <= 2; mx++) {
								if((!change) && ((y+my)>=0) && ((y+my)<height) && ((x+mx)>=0) && ((x+mx)<width)) { 
									if(im_pixelsr[my*pitch + x + mx] > 0) {
										im_pixelsr[x] = im_pixelsr[my*pitch + x + mx];
										change = true;
									}
								}
							}	
						}
						if(!change) {
							index_max+=10;
							im_pixelsr[x] = index_max;
						}
					}
				}
				im_pixels += pitch;
				im_pixelsr += pitch;
			}
			break;
		case F_ERO: //eroze								
			FreeImage_Unload(result);
			result = FreeImage_Clone(s1_d);
			im_pixelsr = (BYTE*)FreeImage_GetBits(result);
			for(y = 0; y < height; y++) {
				for(x = 0; x < width; x++) { 
					temp = 0;
					for(my = -1;my <= 1; my++) {
						for(mx = -1;mx <= 1; mx++) {
							if(((y+my)>=0) && ((y+my)<height) && ((x+mx)>=0) && ((x+mx)<width) && ((mx != 0) || (my != 0))) 
								if(im_pixelsr[my*pitch + x + mx] > 0) temp++;  
						}
					}
					if(temp < param) im_pixels[x] = 0;
					else im_pixels[x] = im_pixelsr[x];
				}
				im_pixels += pitch;
				im_pixelsr += pitch;
			}
			break;
		case F_INTL: //odstraneni pruhu
			for(y = 1; y < height-1; y++) {
				for(x = 0; x < width; x++) 
					if((im_pixels[x] < 20) && (im_pixels[-pitch + x] > 30) && (im_pixels[pitch + x] > 30))
						 im_pixels[x] = (BYTE) ((im_pixels[-pitch + x] + im_pixels[pitch + x]) / 2);
				im_pixels += pitch;
			}
			break;
		case F_BUG:	//brouk hleda hrany
			int startx,starty,actualx,actualy,maxx,minx,maxy,miny,prevx,prevy,dir,length,xp,yp;
			bool contact,change;
			obj_id = 100;
						
			for(y = 0; y < height-150; y++) {		// nepokryva vzdalene casti obrazu
				for(x = 0; x < width; x++) { 
					if((im_pixels[y*pitch + x] == 255) && (im_pixelsr[y*pitch +x] == 0)) {
						length = 0;
						actualx = startx = minx = maxx = prevx = x;
						actualy = starty = miny = maxy = prevy = y;
						dir = 1000;
						
						contact = true;
						do { 
							/*if(prevx) {
								
								TRACE("x%d %d %d %d\n",actualx,actualy,im_pixels[actualy*pitch + actualx],im_pixelsr[actualy*pitch + actualx]);
							}*/
							if(contact) dir--;
							else dir++;
							if(((actualx==0)&&(dir%4 == 2)) || ((actualx==width-1)&&(dir%4 ==0)) || 
								((actualy==0)&&(dir%4 == 1)) || ((actualy==height-1)&&(dir%4 == 3))) dir++;		//zataceni u hranice obrazku
							switch(dir%4) {
								case 0:
									actualx++;
									break;
								case 1:
									actualy--;
									break;
								case 2:
									actualx--;
									break;
								case 3:
									actualy++;
									break;
							}
							/*if(prevx) {
								
								TRACE("xxx%d %d %d %d\n",actualx,actualy,im_pixels[actualy*pitch + actualx],im_pixelsr[actualy*pitch + actualx]);
							}*/
							
							if((im_pixels[actualy*pitch + actualx] > 0) && ((im_pixelsr[actualy*pitch + actualx] == 0) || (im_pixelsr[actualy*pitch + actualx] == obj_id))) {
									contact = true;
									length++;
									im_pixelsr[actualy*pitch + actualx] = obj_id;
									if(actualx < minx) minx = actualx;
									if(actualx > maxx) maxx = actualx;
									if(actualy < miny) miny = actualy;
									if(actualy > maxy) maxy = actualy;
								//}
							}
							else contact = false;
							
							//if a bug have just met his starting position, and object is big enough
							if((actualx == startx) && (actualy == starty)) {
								
								if((length > 200) && ((maxx - minx) > 40) && ((maxy - miny) > 40)) { //jen od urcite velikosti							
									
									if(!list_first) {							//ukladani objektu do seznamu
										list_first = new Car;
										list_p = list_first;
									}
									else {
										list_p->next = new Car;
										list_p = list_p->next;
									}
									list_p->id = obj_id;
									list_p->x = minx;
									list_p->y = miny;
									list_p->x2 = maxx;
									list_p->y2 = maxy;
									list_p->next = NULL;

									for(j = minx; j < maxx-1; j++) {
										if((im_pixelsr[((maxy + miny)/2)*pitch + j] == obj_id) && (im_pixelsr[((maxy + miny)/2)*pitch + j+1] == 0)) { 
											TRACE("%d %d\n",(maxy + miny)/2, j+1);
											Stack_point(j+1,(maxy + miny)/2,true,true);											
											break;
										}
									}
									//if(!point_first) Stack_point((maxx+minx)/2,(maxy + miny)/2,true,true);

									while(point_first) {
										xp = point_first->x;
										yp = point_first->y;
										
										im_pixelsr[yp*pitch + xp] = obj_id;
										if((point_first->up) && (im_pixelsr[(yp+1)*pitch + xp] == 0) && ((yp+1)<maxy))
											Stack_point(xp,yp+1,true,false);
										if((point_first->down) && (im_pixelsr[(yp-1)*pitch + xp] == 0) &&((yp-1)>miny))
											Stack_point(xp,yp-1,false,true);
										i=1;
										while((xp-i >= minx) && (im_pixelsr[yp*pitch + xp - i] == 0)) {
											im_pixelsr[yp*pitch + xp - i] = obj_id;
											if((yp+1)<maxy) {
												if((im_pixelsr[(yp+1)*pitch + xp - i] == obj_id) && (im_pixelsr[(yp+1)*pitch + xp - i+1] == 0))
													Stack_point(xp - i + 1,yp+1,true,false);
												if((im_pixelsr[(yp+1)*pitch + xp - i] == 0) && (im_pixelsr[(yp+1)*pitch + xp - i+1] == obj_id))
													Stack_point(xp - i,yp+1,true,false);
											}
											if((yp-1)>miny) {
												if((im_pixelsr[(yp-1)*pitch + xp - i] == obj_id) && (im_pixelsr[(yp-1)*pitch + xp - i+1] == 0))
													Stack_point(xp - i + 1,yp-1,false,true);
												if((im_pixelsr[(yp-1)*pitch + xp - i] == 0) && (im_pixelsr[(yp-1)*pitch + xp - i+1] == obj_id))
													Stack_point(xp - i,yp-1,false,true);
											}
											i++;
										}
										i=1;
										while(((xp+i) <= maxx) && (im_pixelsr[yp*pitch + xp + i] == 0)) {
											im_pixelsr[yp*pitch + xp + i] = obj_id;
											if((yp+1)<maxy) {
												if((im_pixelsr[(yp+1)*pitch + xp + i] == obj_id) && (im_pixelsr[(yp+1)*pitch + xp + i-1] == 0))
													Stack_point(xp + i - 1,yp+1,true,false);
												if((im_pixelsr[(yp+1)*pitch + xp + i] == 0) && (im_pixelsr[(yp+1)*pitch + xp + i-1] == obj_id))
													Stack_point(xp + i,yp+1,true,false);
											}
											if((yp-1)>miny) {
												if((im_pixelsr[(yp-1)*pitch + xp + i] == obj_id) && (im_pixelsr[(yp-1)*pitch + xp + i-1] == 0))
													Stack_point(xp + i - 1,yp-1,false,true);
												if((im_pixelsr[(yp-1)*pitch + xp + i] == 0) && (im_pixelsr[(yp-1)*pitch + xp + i-1] == obj_id))
													Stack_point(xp + i,yp-1,false,true);
											}
											i++;
										}
										if(yp < 0) TRACE("x%d y%d ax%d ay%d my%d maxy%d\n",xp,yp,actualx,actualy,miny,maxy);
										point_temp = point_first;
										point_first = point_first->next;
		
										delete point_temp;
									}
									
									/*



									do {
										change = false;				//vyplnovani objektu, nutny upravit na seminka
										for(i = miny; i < maxy; i++) {
											for(j = minx; j < maxx; j++) { 
												if(im_pixelsr[i*pitch + j] == obj_id) {
													if(im_pixelsr[i*pitch + j-1] == 0) {
														im_pixelsr[i*pitch + j-1] = obj_id;
														change = true;
													}
													if(im_pixelsr[i*pitch + j+1] == 0) {
														im_pixelsr[i*pitch + j+1] = obj_id;
														change = true;
													}
													if(im_pixelsr[(i-1)*pitch + j] == 0) {
														im_pixelsr[(i-1)*pitch + j] = obj_id;
														change = true;
													}
													if(im_pixelsr[(i+1)*pitch + j] == 0) {
														im_pixelsr[(i+1)*pitch + j] = obj_id;
														change = true;
													}
												}
											}
										}
									} while(change);*/
									obj_id++;
								}
								
								break;			//ukonceni while cyklu
							}
						} while (length < 10000);
					}
					//if(obj_id>101) break;
				}
				//if(obj_id>101) break;			///pro jedno auto
			}



			/*for(y = 0; y < height-150; y++) {		// nepokryva vzdalene casti obrazu
				for(x = 0; x < width; x++) { 
					if((im_pixels[y*pitch + x] > 0) && (im_pixelsr[y*pitch +x] ==0)) {
						length = 0;
						actualx = startx = minx = maxx = prevx = x;
						actualy = starty = miny = maxy = prevy = y;
						dir = 1000;
						contact = true;
						obj_id;
						do { 
							if(contact) dir--;
							else dir++;
							if(((actualx==0)&&(dir%4 == 2)) || ((actualx==width-1)&&(dir%4 ==0)) || 
								((actualy==0)&&(dir%4 == 1)) || ((actualy==height-1)&&(dir%4 == 3))) dir++;		//zataceni u hranice obrazku
							switch(dir%4) {
								case 0:
									actualx++;
									break;
								case 1:
									actualy--;
									break;
								case 2:
									actualx--;
									break;
								case 3:
									actualy++;
									break;
							}
							if(im_pixels[actualy*pitch + actualx] > 0) {
								contact = true;
								length++;
								im_pixelsr[actualy*pitch + actualx] = 255;
								if(actualx < minx) minx = actualx;
								if(actualx > maxx) maxx = actualx;
								if(actualy < miny) miny = actualy;
								if(actualy > maxy) maxy = actualy;
							}
							else contact = false;
							
							//if a bug have just met his starting position, and object is big enough
							if((actualx == startx) && (actualy == starty)) {
								if((length > 200) && ((maxx - minx) > 40) && ((maxy - miny) > 40)) { //jen od urcite velikosti							
									obj_id++;
									if(!list_first) {							//ukladani objektu do seznamu
										list_first = new Car;
										list_p = list_first;
									}
									else {
										list_p->next = new Car;
										list_p = list_p->next;
									}
									list_p->id = obj_id;
									list_p->x = minx;
									list_p->y = miny;
									list_p->x2 = maxx;
									list_p->y2 = maxy;
									list_p->next = NULL;

									for(j = minx; j < maxx; j++) {
										if(im_pixelsr[((maxy + miny)/2)*pitch + j] == 255) { 
											i = 0;
											while(im_pixelsr[((maxy + miny)/2)*pitch + j + i] == 255) i++;
											im_pixelsr[((maxy + miny)/2)*pitch + j + i] = obj_id;
											break;
										}
									}
									do {
										change = false;				//vyplnovani objektu, nutny upravit na seminka
										for(i = miny; i < maxy; i++) {
											for(j = minx; j < maxx; j++) { 
												if(im_pixelsr[i*pitch + j] == obj_id) {
													if(im_pixelsr[i*pitch + j-1] == 0) {
														im_pixelsr[i*pitch + j-1] = obj_id;
														change = true;
													}
													if(im_pixelsr[i*pitch + j+1] == 0) {
														im_pixelsr[i*pitch + j+1] = obj_id;
														change = true;
													}
													if(im_pixelsr[(i-1)*pitch + j] == 0) {
														im_pixelsr[(i-1)*pitch + j] = obj_id;
														change = true;
													}
													if(im_pixelsr[(i+1)*pitch + j] == 0) {
														im_pixelsr[(i+1)*pitch + j] = obj_id;
														change = true;
													}
												}
											}
										}
									} while(change);
								}
								break;
							}
						} while (length < 10000);
					}
				}
			}*/
			break;
		case F_FILLR:		//nefunkcni radkove vyplnovani
			int count;
			bool fill;
			//odstraneni vodorovnych z trojic, celkem slibny, ale zatim nefunguje
			/*for(y = 1; y < height-1; y++) {
				for(x = 1; x < width -1; x++) {
					if(im_pixels[y*pitch + x] == 255) {
						if((im_pixels[y*pitch + x+1] == 0) && (im_pixels[y*pitch + x-1] == 0)) im_pixelsr[y*pitch + x] = 255;
						if((im_pixels[y*pitch + x+1] > 0) && (im_pixels[y*pitch + x-1] == 0)) {
							im_pixelsr[y*pitch + x] = 255;
							if((im_pixels[(y-1)*pitch + x] == 255) || (im_pixels[(y-1)*pitch + x-1] == 255) || (im_pixels[(y-1)*pitch + x+1] == 255))
								prevy = -1;
							if((im_pixels[(y+1)*pitch + x] == 255) || (im_pixels[(y+1)*pitch + x-1] == 255) || (im_pixels[(y+1)*pitch + x+1] == 255))
								prevy = 1;
						}
						if((im_pixels[y*pitch + x+1] == 0) && (im_pixels[y*pitch + x-1] > 0)) {
							if(((im_pixels[(y-1)*pitch + x] == 255) || (im_pixels[(y-1)*pitch + x-1] == 255) || (im_pixels[(y-1)*pitch + x+1] == 255)) && (prevy == -1))
								im_pixelsr[y*pitch + x] = 255;
							if(((im_pixels[(y+1)*pitch + x] == 255) || (im_pixels[(y+1)*pitch + x-1] == 255) || (im_pixels[(y+1)*pitch + x+1] == 255)) && (prevy == 1))
								im_pixelsr[y*pitch + x] = 255;
							prevy = 0;
						}		
						
					}
					else prevy = 0;
					//if((im_pixels[y*pitch + x -1] == 255) && (im_pixels[y*pitch + x +1] == 255)) im_pixelsr[y*pitch + x] = 0;		//pokud sou tri vedle sebe tak prostredni pryc
				}
			}*/
			
			/*for(y = 0; y < height; y++) {
				count = 0;
				fill = false;
				for(x = 0; x < width; x++) 
					if(im_pixelsr[y*pitch + x] == 255) count++;
				if(count >= 2)
					for(x = 0; x < width; x++) { 
						if(im_pixelsr[y*pitch + x] == 255) fill = !fill;
						if(fill) im_pixelsr[y*pitch + x] = 255;
					}
			}	*/		
			break;
		case F_FILLS:
			
			break;
		case F_RECTS:
			list_p = list_first;
			if(FreeImage_GetBPP(s1_d) == 8) {
				while(list_p != NULL) {
					for(x = list_p->x; x <= list_p->x2; x++) {
						im_pixels[list_p->y*pitch + x] = 255;
						im_pixels[list_p->y2*pitch + x] = 255;
					}
					for(y = list_p->y; y <= list_p->y2; y++) {
						im_pixels[y*pitch + list_p->x] = 255;
						im_pixels[y*pitch + list_p->x2] = 255;
					}			
					list_p = list_p->next;
				}
			}
			if(FreeImage_GetBPP(s1_d) == 24) {
				while(list_p != NULL) {
					//drawings of horizontal lines
					im_pixels = FreeImage_GetScanLine(s1_d,list_p->y);
					for(x = list_p->x; x <= list_p->x2; x++)
						im_pixels[x*3 + FI_RGBA_RED] = 255;
					im_pixels = FreeImage_GetScanLine(s1_d,list_p->y+1);
					for(x = list_p->x; x <= list_p->x2; x++)
						im_pixels[x*3 + FI_RGBA_RED] = 255;
					im_pixels = FreeImage_GetScanLine(s1_d,list_p->y2);
					for(x = list_p->x; x <= list_p->x2; x++)
						im_pixels[x*3 + FI_RGBA_RED] = 255;
					im_pixels = FreeImage_GetScanLine(s1_d,list_p->y2-1);
					for(x = list_p->x; x <= list_p->x2; x++)
						im_pixels[x*3 + FI_RGBA_RED] = 255;
					
					im_pixels = FreeImage_GetBits(s1_d);
					for(y = list_p->y; y <= list_p->y2; y++) {				///taady by to slo urcite nejak podobne zrychlit jako nad tim
						
						im_pixels[y*pitch + list_p->x*3+ FI_RGBA_RED] = 255;
						im_pixels[y*pitch + (list_p->x+1)*3+ FI_RGBA_RED] = 255;
						im_pixels[y*pitch + list_p->x2*3 + FI_RGBA_RED] = 255;
						im_pixels[y*pitch + (list_p->x2-1)*3 + FI_RGBA_RED] = 255;
					}			
					list_p = list_p->next;
				}
			}
			break;
		case F_SHRE:	//mely by se prohodit dva parametry, aby se mohla kontrola provadet i bez vyprahovaneho snimku !!!!
			float hi,si,vi, hb,sb,vb;
			float r,g,b,min, max, alfa, beta,th,ts,difh,difs;
			BYTE *im_pixelsb = (BYTE*)FreeImage_GetBits(back_rgb);
			
			beta = 0.9;
			alfa = 0.5;
			th = 0.5;
			ts = 0.4;

			for(y = 0; y < height; y++) {
				im_pixelsb = FreeImage_GetScanLine(back_rgb,y);
				im_pixels2 = FreeImage_GetScanLine(s2,y);
				for(x = 0; x < width; x++) {
					if(im_pixels[x] > 0) {
						r = im_pixels2[FI_RGBA_RED];		//slozky barevneho snimku
						g = im_pixels2[FI_RGBA_GREEN];
						b = im_pixels2[FI_RGBA_BLUE];
					
						//rgb to hsv conversion
						
						if((r == g) && (r == b)) hi = 0;
						if(r >= g) {
							if(r >= b) {
								max = r;
								if(g >= b) min = b;
								else min = g;
								hi = 60 * (g-b)/(max-min);
								
							}
							else {
								max = b;
								min = g;
								hi = 60*(r-g)/(max-min) + 240;
							}
						}
						else {
							if(g >= b) {
								max = g;
								if(r >= b) min = b;
								else min = r;
								hi = 60*(b-r)/(max-min) + 120;
							}
							else {
								max = b;
								min = r;
								hi = 60*(r-g)/(max-min) + 240;
							}
						}
						hi /= 360;
						if(max == 0) si = 0;
						else si = (max-min)/max;
						
						vi = max;
						
						r = im_pixelsb[FI_RGBA_RED];		//slozky pozadi
						g = im_pixelsb[FI_RGBA_GREEN];
						b = im_pixelsb[FI_RGBA_BLUE];

						if((r == g) && (r == b)) hb = 0;
						if(r >= g) {
							if(r >= b) {
								max = r;
								if(g >= b) min = b;
								else min = g;
								hb = 60 * (g-b)/(max-min);
								
							}
							else {
								max = b;
								min = g;
								hb = 60*(r-g)/(max-min) + 240;
							}
						}
						else {
							if(g >= b) {
								max = g;
								if(r >= b) min = b;
								else min = r;
								hb = 60*(b-r)/(max-min) + 120;
							}
							else {
								max = b;
								min = r;
								hb = 60*(r-g)/(max-min) + 240;
							}
						}

						hb /= 360;
						if(max == 0) sb = 0;
						else sb = (max-min)/max;
						
						vb = max;
						//shadow detection
					
						difh = hi-hb;
						if(difh<0) difh = -difh;
						difs = si-sb;
						if(difs<0) difs = -difs;
						if (((vi/vb)>=alfa) && ((vi/vb)<=beta) && (difh<=th) && (difs<=ts)) im_pixels[x] = 0;
						else im_pixels[x] = im_pixels[x];
					}
					
					im_pixels2 +=3;
					im_pixelsb +=3;
				}
				im_pixels += pitch;
			}
			break;
	}
}

void VD_Convol(FIBITMAP* s1_d, int *mask, int param = 0)		//int mask[9] = { 1,1,1,1,-8,1,1,1,1 };
{
	int width = FreeImage_GetWidth(s1_d);
	int height = FreeImage_GetHeight(s1_d);
	int pitch = FreeImage_GetPitch(s1_d);

	int x,y,mx,my,temp;

	result = FreeImage_Clone(s1_d);
	BYTE *im_pixels = (BYTE*)FreeImage_GetBits(s1_d);
	BYTE *im_pixelsr = (BYTE*)FreeImage_GetBits(result);
	for(y = 0; y < height; y++) {
		for(x = 0; x < width; x++) { 
			temp = 0;
			for(my = -1;my <= 1; my++) {
				for(mx = -1;mx <= 1; mx++) {
					if(((y+my)>=0) && ((y+my)<height) && ((x+mx)>=0) && ((x+mx)<width)) 
						temp += ((int) im_pixels[my*pitch + x + mx]) * mask[4 + my*3 + mx];  
				}
			}
			if(param != 0) temp = (int) (temp / param);
			if(temp<=0)
				im_pixelsr[x] = 0;
			else {
				if(temp>=255)
					im_pixelsr[x] = 255;
				else
					im_pixelsr[x] = (BYTE) temp;
			}
		}
		im_pixels += pitch;
		im_pixelsr += pitch;
	}
}	

void VD_BG(FIBITMAP *s1)
{
	int width = FreeImage_GetWidth(s1);
	int height = FreeImage_GetHeight(s1);
	int pitch = FreeImage_GetPitch(s1);

	int x,y,z,i;
	BYTE temp;
	bool change;
	BYTE *pixels;
	BYTE vect[15];
	BYTE *pixelsb;
	double alfa = 0.02;
	
	if(iscount<14) {
		image_set[iscount] = FreeImage_Clone(image_rgb);			//dodelat postupne zatridovani
		iscount++;
		

		return;
	}
	if (iscount == 14){
		image_set[iscount] = FreeImage_Clone(image_rgb);
		iscount++;
	
		if(FreeImage_GetBPP(image_set[0]) == 24) {
			back_rgb = FreeImage_Clone(image_set[0]);
			pixelsb = FreeImage_GetBits(back_rgb);
			for(y = 0; y < height; y++) {
				for(x = 0; x < width; x++) {
					for(z = 0; z < 3; z++) {
						for(i=0;i<iscount;i++) {
							pixels = FreeImage_GetBits(image_set[i]);
							vect[i] = pixels[y*pitch + x*3 + z];
						}
						do {				
							change = false;
							for(i=0;i<(iscount-1);i++) {
								if(vect[i] < vect[i+1]) {
									temp = vect[i];
									vect[i] = vect[i+1];
									vect[i+1] = temp;
									change = true;
								}
							}
						} while(change);			
						
						pixelsb[y*pitch + x*3 + z] = vect[(int) (iscount/2)];
					}
				}
			}
			back_gs = FreeImage_ConvertToGreyscale(back_rgb);
		}
		for(int i=0;i<iscount;i++)
			if(image_set[i]) FreeImage_Unload(image_set[i]);
		return;
	}
	if(iscount > 14) {
		//update pozadi pomoci plovouciho prumeru, nutne upravit pouze pro pixely bez popredi, takze treba pridat vyprahovany snimek do parametru
		pixelsb = FreeImage_GetBits(back_rgb);
		pixels = FreeImage_GetBits(s1);

		for(y = 0; y < height; y++) {
			for(x = 0; x < width; x++) {
				pixelsb[3*x + FI_RGBA_RED] = (BYTE)((1.0-alfa)*pixelsb[3*x + FI_RGBA_RED] + alfa*pixels[3*x + FI_RGBA_RED]);
				pixelsb[3*x + FI_RGBA_GREEN] = (BYTE)((1.0-alfa)*pixelsb[3*x + FI_RGBA_GREEN] + alfa*pixels[3*x + FI_RGBA_GREEN]);
				pixelsb[3*x + FI_RGBA_BLUE] = (BYTE)((1.0-alfa)*pixelsb[3*x + FI_RGBA_BLUE] + alfa*pixels[3*x + FI_RGBA_BLUE]);
			}
			pixels += pitch;
			pixelsb += pitch;
		}
	}
}

void Stack_point(int x, int y, bool up, bool down)
{
	if(!point_first) {
		point_first = new Point;
		point_first->next = NULL;
		point_p = point_first;
	}
	else {
		point_p->next = new Point;
		point_p = point_p->next;
		point_p->next = NULL;
	}

	point_p->x = x;
	point_p->y = y;
	point_p->up = up;
	point_p->down = down;
	
}

void Clean(void) 
{
	while (list_first != NULL) {
		list_p = list_first->next;
		delete list_first;
		list_first = list_p;
	}

	obj_id = 100;
}

extern "C" __declspec(dllexport) FIBITMAP* VD_Core(char *FileName)
{
	if(image_rgb) FreeImage_Unload(image_rgb);
	image_rgb = FreeImage_Load(FIF_JPEG, FileName, JPEG_DEFAULT);
	
	if(image_proc) FreeImage_Unload(image_proc);
	image_proc = FreeImage_ConvertToGreyscale(image_rgb);
	FreeImage_Save(FIF_BMP,image_proc,"vysledek.bmp");

	VD_BG(image_rgb);
	
	if(back_gs) {
		VD_BasOp(F_SUBB,image_proc,back_gs);
		FreeImage_Save(FIF_BMP,image_proc,"vysledek1.bmp");
		
		VD_BasOp(F_THR,image_proc,NULL,20);
		FreeImage_Save(FIF_BMP,image_proc,"vysledek2.bmp");
		
		VD_BasOp(F_SHRE,image_proc,image_rgb);
		FreeImage_Save(FIF_BMP,image_proc,"vysledek3.bmp");

		VD_BasOp(F_ERO,image_proc, 0, 3);
		FreeImage_Save(FIF_BMP, image_proc, "vysledek4.bmp");

		VD_BasOp(F_ERO,image_proc, 0, 3);
		FreeImage_Save(FIF_BMP, image_proc, "vysledek5.bmp");

		VD_BasOp(F_INTL,image_proc);
		FreeImage_Save(FIF_BMP,image_proc,"vysledek6.bmp");

		VD_BasOp(F_BUG,image_proc);
		FreeImage_Save(FIF_BMP,result,"vysledek7.bmp");

		VD_BasOp(F_RECTS,image_rgb);
		
		Clean();
	}

	return image_rgb;

}

int CVD_CoreApp::ExitInstance()
{
	// TODO: Add your specialized code here and/or call the base class
	if(result) FreeImage_Unload(result);

	if(back_gs) FreeImage_Unload(back_gs);
	if(back_rgb) FreeImage_Unload(back_rgb);
	
	return CWinApp::ExitInstance();
}
