//--------------------------------------------------------------------------- #pragma hdrstop #include "ImageVectorizer.h" #include "Main.h" #include "MainMenu.h" #include "MainImage.h" #include "VecDraw.h" #include "Undo_F.h" #include "Undo.h" #include "LogData.h" #pragma package(smart_init) #define IDS_NOT_ADJUST_ERROR1 StringTable[0] #define IDS_NOT_ADJUST_ERROR2 StringTable[1] //--------------------------------------------------------------------------- ImageVectorizer::ImageVectorizer() :bezierCurveApproximator(),progressForm(NULL), processedPixels(0),processedObjects(0),ImageMode(0) { BEGIN_LOG(""); StringTable.Create(DirectoryItem, Language, "ImageVectorizer"); HaveGetColor = false; END_LOG; } //--------------------------------------------------------------------------- ImageVectorizer::~ImageVectorizer() { } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::PlantSeed(const TPoint& point, const int& height, const int& old_color, const int x_left, BYTE*& nex_canvas_line, BYTE*& pre_canvas_line, BYTE*& nex_marking_line, BYTE*& pre_marking_line, bool& span_down, bool& span_up, std::stack& stack) { BEGIN_LOG(""); if(point.y < height - 1) { int color = GetColor(nex_canvas_line, x_left); BYTE mark = *(nex_marking_line + x_left); if(!span_down && color == old_color && mark != ContourMark) { stack.push(Point(x_left, point.y + 1)); span_down = true; } else if(span_down && color != old_color) span_down = false; } if(point.y > 0) { int color = GetColor(pre_canvas_line, x_left); BYTE mark = *(pre_marking_line + x_left); if(!span_up && color == old_color && mark != ContourMark) { stack.push(Point(x_left, point.y - 1)); span_up = true; } else if(span_up && color != old_color) span_up = false; } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::AntiDoubleLineByFloodFill(int X, int Y, const int old_color, TUnionBitmap* marking_bitmap) { BEGIN_LOG(""); Byte *pre_canvas_line, *pre_marking_line; Byte *cur_canvas_line, *cur_marking_line; Byte *nex_canvas_line, *nex_marking_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; TPItemImage* Image = MainImageForm->iMainImage; const int width = Image->uBitmap->Width; const int height = Image->uBitmap->Height; const unsigned int num_of_pixels = width * height; stack stack; stack.push(Point(X, Y)); while(!stack.empty()) { const TPoint point = stack.top(); stack.pop(); cur_canvas_line = Image->uBitmap->GetScanLineN(point.y, cur_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(point.y, cur_line_slot); if(*(cur_marking_line + point.x) == ContourMark) continue; if(point.y < height - 1) { nex_canvas_line = Image->uBitmap->GetScanLineN(point.y + 1, nex_line_slot); nex_marking_line = marking_bitmap->GetScanLineN(point.y + 1, nex_line_slot); } if(point.y > 0) { pre_canvas_line = Image->uBitmap->GetScanLineN(point.y - 1, pre_line_slot); pre_marking_line = marking_bitmap->GetScanLineN(point.y - 1, pre_line_slot); } int x_left = point.x, color; while(x_left >= 0) { color = GetColor(cur_canvas_line, x_left); if(color != old_color) break; --x_left; } ++x_left; bool span_up = false, span_down = false; if(x_left > 0) { PlantSeed(point, height, old_color, x_left - 1, nex_canvas_line, pre_canvas_line, nex_marking_line, pre_marking_line, span_down, span_up, stack); } while(x_left < width) { color = GetColor(cur_canvas_line, x_left); if(color != old_color) break; else{ *(cur_marking_line + x_left) = ContourMark; } ++processedPixels; PlantSeed(point, height, old_color, x_left, nex_canvas_line, pre_canvas_line, nex_marking_line, pre_marking_line, span_down, span_up, stack); ++x_left; } if(x_left + 1 < width) { PlantSeed(point, height, old_color, x_left, nex_canvas_line, pre_canvas_line, nex_marking_line, pre_marking_line, span_down, span_up, stack); } marking_bitmap->PutScanLineN(point.y, cur_line_slot); ProgressForm->Ratio = (double)processedPixels / num_of_pixels; Application->ProcessMessages(); } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::MakeContour(const int min_point) { BEGIN_LOG(""); ProgressForm->Title = "Vectorizing..."; ProgressForm->Ratio = 0; ImageMode = 1; // ¸éµû±â Mode processedPixels = 0, processedObjects = 0; TPItemImage* Image = MainImageForm->iMainImage; int width = Image->uBitmap->Width; int height = Image->uBitmap->Height; bool UndoSw = true; TUnionBitmap* marking_bitmap = new TUnionBitmap; marking_bitmap->Create(Image->uBitmap->Width, Image->uBitmap->Height, 8); marking_bitmap->FillRect(Rect(0,0,Image->uBitmap->Width, Image->uBitmap->Height),0); Image->uBitmap->StartScanLineN(4); marking_bitmap->StartScanLineN(4); processedPixels = 0; processedObjects = 0; //---------- ¸éó¸® CornerDetect ----------// TUnionBitmap* contour_bitmap = new TUnionBitmap; contour_bitmap->Create(Image->uBitmap->Width, Image->uBitmap->Height, Image->uBitmap->BitsPerPixel); for(int y = 0 ; y < height ; ++y) { Byte* canvas_line = Image->uBitmap->GetScanLineN(y, 3); Byte* marking_line = marking_bitmap->GetScanLineN(y, 3); for(int x = 0 ; x < width ; ++x) { int cur_color = GetColor(canvas_line, x); int left_color = GetColor(canvas_line, x - 1); bool is_contour = (x - 1 < 0 ) || (x - 1) >= 0 && cur_color != left_color; if (is_contour && HaveGetColor){ for (int cnt = 0 ; cnt < pColorList->Count ; cnt++){ int bgd_color = *((int*)pColorList->Items[cnt]); if (bgd_color == cur_color){ is_contour = false; break; } } } if(is_contour && *(marking_line + x) != ContourMark) { ProgressForm->Title = "Vectorizing..." + String(processedObjects); Application->ProcessMessages(); if(Image->uBitmap->BitsPerPixel == 8) contour_bitmap->FillRect(Rect(0,0,Image->uBitmap->Width, Image->uBitmap->Height),0); else contour_bitmap->FillRect(Rect(0,0,Image->uBitmap->Width, Image->uBitmap->Height),clWhite); // if (x > 0){ // ¹è°æÀº ¹«Á¶°Ç ¾Èµû°Ô FollowContour(x, y, cur_color, marking_bitmap, contour_bitmap); CallFreeDrawing(cur_color, min_point, UndoSw); // } Application->ProcessMessages(); AntiDoubleLineByFloodFill(x, y, cur_color, marking_bitmap); marking_line = marking_bitmap->GetScanLineN(y, 3); } } if(ProgressForm->isCancelRequested) break; } Image->uBitmap->StopScanLine(); marking_bitmap->StopScanLine(); contour_bitmap->StopScanLine(); delete marking_bitmap; marking_bitmap = NULL; delete contour_bitmap; contour_bitmap = NULL; END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::FollowContour(int X, int Y, const int color, TUnionBitmap* marking_bitmap, TUnionBitmap* contour_bitmap) { BEGIN_LOG(""); Byte *pre_canvas_line, *pre_marking_line; Byte *cur_canvas_line, *cur_marking_line, *cur_contour_line; Byte *nex_canvas_line, *nex_marking_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; int surround[8], mark_sur[8]; TPItemImage* Image = MainImageForm->iMainImage; const int width = Image->uBitmap->Width; const int height = Image->uBitmap->Height; int x = X, y = Y; int pre_position = 3; int Cnt = 0; contour_bitmap->StartScanLine(); CornerPointList.clear(); while(true) { for(int i = 0 ; i < 8 ; ++i) { surround[i] = -1; mark_sur[i] = InitMark; } const bool is_pre_line_exist = (y - 1 >= 0); const bool is_nex_line_exist = (y + 1 < height); const int left = x - 1, right = x + 1; bool is_there_need_to_reread = (pre_position != 4 && pre_position != 0); if(is_there_need_to_reread) { cur_canvas_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); cur_contour_line = contour_bitmap->GetScanLine(y); } if(left >= 0) { surround[4] = GetColor(cur_canvas_line, left); mark_sur[4] = *(cur_marking_line + left); } if(right < width) { surround[0] = GetColor(cur_canvas_line, right); mark_sur[0] = *(cur_marking_line + right); } if(is_pre_line_exist) { if(is_there_need_to_reread) { pre_canvas_line = Image->uBitmap->GetScanLineN(y - 1, pre_line_slot); pre_marking_line = marking_bitmap->GetScanLineN(y - 1, pre_line_slot); } surround[2] = GetColor(pre_canvas_line, x); mark_sur[2] = *(pre_marking_line + x); if(left >= 0) { surround[3] = GetColor(pre_canvas_line, left); mark_sur[3] = *(pre_marking_line + left); } if(right < width) { surround[1] = GetColor(pre_canvas_line, right); mark_sur[1] = *(pre_marking_line + right); } } if(is_nex_line_exist) { if(is_there_need_to_reread) { nex_canvas_line = Image->uBitmap->GetScanLineN(y + 1, nex_line_slot); nex_marking_line = marking_bitmap->GetScanLineN(y + 1, nex_line_slot); } surround[6] = GetColor(nex_canvas_line, x); mark_sur[6] = *(nex_marking_line + x); if(left >= 0) { surround[5] = GetColor(nex_canvas_line, left); mark_sur[5] = *(nex_marking_line + left); } if(right < width) { surround[7] = GetColor(nex_canvas_line, right); mark_sur[7] = *(nex_marking_line + right); } } int i, search_pos; for(i = 0 ; i < 7 ; ++i) { search_pos = (pre_position + i + 2) % 8; if(surround[search_pos] == color)// && mark_sur[search_pos] != ContourMark) break; } if(X != 0 || Y != 0){ int NumberOfColors = 0; for(int cnt = 0 ; cnt < 8 ; ++cnt) { if(surround[cnt] != color){ bool AddEnable = true; for(int cnt2 = 0 ; cnt2 < cnt ; ++cnt2){ if(surround[cnt2] == surround[cnt]){ AddEnable = false; break; } } if(AddEnable) NumberOfColors++; } } if(NumberOfColors > 1){ CornerPointList.push_back(DPOINT(x,y)); } } bezierCurveApproximator.AddPoint(DPOINT(x + 0.5, y + 0.5)); if(Image->uBitmap->BitsPerPixel == 8) *(cur_contour_line + x) = 1; else{ *(cur_contour_line + x*3) = 0; *(cur_contour_line + x*3 + 1) = 0; *(cur_contour_line + x*3 + 2) = 0; } pre_position = (search_pos + 4) % 8; contour_bitmap->PutScanLine(y); switch(search_pos) { case 0: ++x; break; case 1: ++x; --y; break; case 2: --y; break; case 3: --x; --y; break; case 4: --x; break; case 5: --x; ++y; break; case 6: ++y; break; case 7: ++x; ++y; break; } if(i == 7) break; if(x == X && y == Y) { bezierCurveApproximator.AddPoint(DPOINT(x + 0.5, y + 0.5)); if(Image->uBitmap->BitsPerPixel == 8) *(cur_contour_line + x) = 1; else{ *(cur_contour_line + x*3) = 0; *(cur_contour_line + x*3 + 1) = 0; *(cur_contour_line + x*3 + 2) = 0; } contour_bitmap->PutScanLine(y); contour_bitmap->StopScanLine(); int Num_Points = bezierCurveApproximator.freeDrawingPointList.size(); int Num_Corner = CornerPointList.size(); if(Num_Corner > 15) CornerPointList.clear(); // Threshold = 15. Corner°¡ ÀÌ °¹¼ö ³ÑÀ¸¸é µµÇüÀÌ ¾Æ´Ï¶ó Pendant·Î º½ break; } } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::FreeDrawing(const TColor color, const int min_point, bool& UndoSw) { BEGIN_LOG(""); ++processedObjects; int pList_index = 0, additional_count; int point_list_size = bezierCurveApproximator.freeDrawingPointList.size(); int corner_list_size = CornerPointList.size(); TVecData *data = NULL; // Ŭ·¡½º ¸â¹ö º¯¼ö¸¦ »ç¿ëÇÏÁö ¾Êµµ·Ï ÇÔ - by monkman (2009.04.01) list::const_iterator iter_point = bezierCurveApproximator.freeDrawingPointList.begin(); list::const_iterator iter_corner = CornerPointList.begin(); list CornerPointIndex; list::iterator iter_corner2 = CornerPointIndex.begin(); bool EnableAdd; for(int cnt = 0 ; cnt < corner_list_size ; cnt++, iter_corner++){ iter_point = bezierCurveApproximator.freeDrawingPointList.begin(); float corner_x = iter_corner->x, corner_y = iter_corner->y; float point_x = iter_point->x - 0.5, point_y = iter_point->y - 0.5; float pre_deter = (corner_x - point_x)*(corner_x - point_x) + (corner_y - point_y)*(corner_y - point_y); float now_deter; int index = 0; int CornerSize; for(int cnt2 = 0 ; cnt2 < point_list_size ; cnt2++, iter_point++){ corner_x = iter_corner->x, corner_y = iter_corner->y; point_x = iter_point->x - 0.5, point_y = iter_point->y - 0.5; now_deter = (corner_x - point_x)*(corner_x - point_x) + (corner_y - point_y)*(corner_y - point_y); if (pre_deter >= now_deter && sqrt(now_deter) < 2){ // Corner´Â BezierCurvePoint·ÎºÎÅÍ °Å¸®°¡ 2ÀÌÇÏÀ̾î¾ß ÇÔ pre_deter = now_deter; index = cnt2; } } EnableAdd = true; iter_corner2 = CornerPointIndex.begin(); for(int cnt2 = 0 ; cnt2 < CornerPointIndex.size() ; cnt2++ , iter_corner2++){ if(index == *iter_corner2 || abs(index - *iter_corner2) < 3) EnableAdd = false; } if(index > 3 && EnableAdd){ CornerPointIndex.push_back(index); } } CornerPointIndex.sort(); if(CornerPointIndex.size() > 0){ int start = 0; iter_corner2 = CornerPointIndex.begin(); int PointIndexCnt = CornerPointIndex.size(); for(int cnt = 0 ; cnt < PointIndexCnt ; cnt++, iter_corner2++){ bezierCurveApproximator.MakeBezierCurvePointsList(start, (*iter_corner2) + 1); if((*iter_corner2)>0) start = (*iter_corner2) - 1; } bezierCurveApproximator.MakeBezierCurvePointsList(start, point_list_size); } else bezierCurveApproximator.MakeBezierCurvePointsList(0, point_list_size); list::iterator iter = bezierCurveApproximator.bezierCurvePointsList.begin(); int BezierListSize = bezierCurveApproximator.bezierCurvePointsList.size(); int Num_VecData = BezierListSize/341 + 1; if(point_list_size < min_point /* ||BezierListSize > 340 */|| BezierListSize < 2) { bezierCurveApproximator.Reset(); END_LOG; return; } int Cnt_VecData = Num_VecData; while (Cnt_VecData >= 1){ TList *DataList = VecDraw->NVector->DataList; if ((data = new TVecData(MainImageForm->Number))==NULL) { END_LOG; return; } data->Kind = V_CURVE; data->bRound = stCircle; data->Color = color; //data->PenThick = 1; data->PenThick = 3; data->PenStyle = P_SOLID; data->CapStyle[0] = 0; data->CapStyle[1] = 0; double thick = data->PenThick; if (Cnt_VecData > 1){ additional_count = 340; } else if (Cnt_VecData == 1){ additional_count = bezierCurveApproximator.bezierCurvePointsList.size() - 340*(Num_VecData-1); } data->nCount = additional_count; data->pList = (DPOINT*)HeapAlloc(GetProcessHeap(), 0, sizeof(DPOINT)*(data->nCount*3+1)); data->pMask = (BYTE*)HeapAlloc(GetProcessHeap(), 0, (data->nCount * 3 + 1) % 8 == 0 ? (data->nCount * 3 + 1) / 8 : (data->nCount * 3 + 1) / 8 + 1); pList_index = 0; if( Num_VecData > 1) data->bFill = false; else data->bFill = true; data->Brush = color; DataList->Add(data); VecDraw->UndoSave(VU_CREATE, DataList->Count - 1, UndoSw); // Access ¹ß»ý UndoSw = false; int last_end_x = 0 , last_end_y = 0; if (Num_VecData == 1){ FindCloseCornerPoint2(iter->start); FindCloseCornerPoint2(iter->end); int temp_start_x = iter->start.x; int temp_start_y = iter->start.y; data->pList[pList_index++] = iter->start; data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; while(iter != bezierCurveApproximator.bezierCurvePointsList.end()) { FindCloseCornerPoint2(iter->end); if(last_end_x == iter->end.x && last_end_y == iter->end.y){ if((temp_start_x != last_end_x || temp_start_y != last_end_y) && (sqrt(float((temp_start_x - last_end_x) * (temp_start_x - last_end_x) + (temp_start_y - last_end_y) * (temp_start_y - last_end_y))) < 10)) { data->pList[pList_index++] = iter->end; data->pList[pList_index++] = iter->end; data->pList[pList_index++] = DPOINT(temp_start_x, temp_start_y); ++iter; } else{ data->nCount--; ++iter; } } else{ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; } } } else if (Num_VecData > 1){ if (Cnt_VecData > 1) { FindCloseCornerPoint2(iter->start); FindCloseCornerPoint2(iter->end); int temp_start_x = iter->start.x; int temp_start_y = iter->start.y; data->pList[pList_index++] = iter->start; data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; for ( int cnt = 1 ; cnt < 340 ; cnt++) { FindCloseCornerPoint2(iter->end); if(last_end_x == iter->end.x && last_end_y == iter->end.y){ if((temp_start_x != last_end_x || temp_start_y != last_end_y) && (sqrt(float((temp_start_x - last_end_x) * (temp_start_x - last_end_x) + (temp_start_y - last_end_y) * (temp_start_y - last_end_y))) < 10)) { data->pList[pList_index++] = iter->end; data->pList[pList_index++] = iter->end; data->pList[pList_index++] = DPOINT(temp_start_x, temp_start_y); ++iter; } else{ data->nCount--; ++iter; } } else{ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; } } } else if (Cnt_VecData == 1){ FindCloseCornerPoint2(iter->start); FindCloseCornerPoint2(iter->end); int temp_start_x = iter->start.x; int temp_start_y = iter->start.y; data->pList[pList_index++] = iter->start; data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; while(iter != bezierCurveApproximator.bezierCurvePointsList.end()) { FindCloseCornerPoint2(iter->end); if(last_end_x == iter->end.x && last_end_y == iter->end.y){ if((temp_start_x != last_end_x || temp_start_y != last_end_y) && (sqrt(float((temp_start_x - last_end_x) * (temp_start_x - last_end_x) + (temp_start_y - last_end_y) * (temp_start_y - last_end_y))) < 10)) { data->pList[pList_index++] = iter->end; data->pList[pList_index++] = iter->end; data->pList[pList_index++] = DPOINT(temp_start_x, temp_start_y); ++iter; } else{ data->nCount--; ++iter; } } else{ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; } } } } Cnt_VecData--; SET_RECT; } bezierCurveApproximator.Reset(); if (Num_VecData > 1) data->bClosed = false; else if (Num_VecData== 1) data->bClosed = true; END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::ChangeIndexAsBackgroundColor() { /* Byte *cur_canvas_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; TColor bg_color = MainImageForm->Palette->ColorData[1]->Color; TPItemImage* Image = MainImageForm->iMainImage; const int width = Image->uBitmap->Width; const int height = Image->uBitmap->Height; for(int y = 0 ; y < height ; ++y) { cur_canvas_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); for(int x = 0 ; x < width ; ++x) { if (MainImageForm->iMainImage->uBitmap->BitsPerPixel == 8){ // if (MainImageForm->Palette->ColorData[*(cur_canvas_line + x)]->Color == bg_color){ // BgColor_to_int = 1; // *(cur_canvas_line + x) = BgColor_to_int; // } } else { // TColor BgRgb_to_tcolor = ((bg_color << 16) & 0x00ff0000) | (bg_color & 0x0000ff00) | (bg_color >> 16); // BgColor_to_int = BgRgb_to_tcolor; } } Image->uBitmap->PutScanLineN(y, cur_line_slot); } */ } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::Thinning() { BEGIN_LOG(""); ImageMode = 0; // ¼±µû±â Mode int nContinue = 0; // 0 : None, 1 : Continue, 2 : Break Byte *pre_canvas_line, *pre_marking_line, *pre_checkhall_line; Byte *cur_canvas_line, *cur_marking_line, *cur_checkhall_line; Byte *nex_canvas_line, *nex_marking_line, *nex_checkhall_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; int surround[9], mark_sur[8]; int x, y, i; int A,B; int a, end, cnt; int temp1, temp2; bool is_pre_line_exist; bool is_nex_line_exist; bool need_more_thinning; TUnionBitmap *Temporary_bitmap; TUnionBitmap *contour_marking_bitmap; TPItemImage* Image = MainImageForm->iMainImage; TPoint start_point; const int width = Image->uBitmap->Width; const int height = Image->uBitmap->Height; MainImageForm->UndoSave(255, Rect(0, 0, width, height)); TUnionBitmap* marking_bitmap = new TUnionBitmap; marking_bitmap->Create(Image->uBitmap->Width, Image->uBitmap->Height, 8); Image->uBitmap->StartScanLineN(3); marking_bitmap->StartScanLineN(3); bool need_more_thinning_ne = true, need_more_thinning_sw = true, *p_need_more_thinning = &need_more_thinning_ne; int side_index1 = 2, side_index2 = 4, corner_index1 = 0, corner_index2 = 6; bool undoSw = true; //----- Corner È®ÀÎ À§ÇØ txt ÆÄÀÏ Ãâ·Â -----// ofstream f; int Harris_cnt = 0 ; //------------------------------------------// list::const_iterator iter_cross; list::const_iterator iter_corner; threshold = 5; NumberOfCross = 0; // CrossPoint °¹¼ö Harris Á¡ Ãß°¡ Àü int NumberOfCrossLive = 0; // CrossPoint °¹¼ö Harris Á¡ Ãß°¡ µÇ¸é¼­ ½Ç½Ã°£ ¾÷µ¥ÀÌÆ® int NumberOfCornerPoint = 0; // Harris Á¡ °¹¼ö bool AddCornerToCross; // Harris Á¡À» CrossPointList¿¡ Æ÷ÇÔ½ÃųÁö ¸»Áö °áÁ¤ ProgressForm->Title = "Vectorizing Stage 1"; ProgressForm->Ratio = 0; int limit_of_thinning_iteration = 20; int num_of_iteration = 0; // Start : ±¸¸Û ¸Þ¿ì±â Fill_onePointHole(Image->uBitmap); for(y = 0 ; y < height - 1 ; ++y) { cur_checkhall_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); for(x = 1 ; x < width - 1 ; ++x) { try{ if(GetColor(cur_checkhall_line, x - 1) != BgColor_to_int && GetColor(cur_checkhall_line, x) == BgColor_to_int && GetColor(cur_marking_line , x) != 100 ) { NumberOfHoles = Fill_Holes(x, y, Image->uBitmap, marking_bitmap, false); if (NumberOfHoles < threshold && NumberOfHoles > 0) Fill_Holes(x, y, Image->uBitmap, marking_bitmap, true); } } catch(...){ Application->MessageBox(L"À̹ÌÁö¸¦ ´Ý°í ´Ù½Ã Çѹø ½ÃµµÇØ ÁÖ¼¼¿ä", L"Warning", MB_OK); goto fail; } cur_checkhall_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); } ProgressForm->Ratio = 0.1*y/ (height-1); } // End // Start : ¸¶½ºÅ© ¸®¼Â for(y = 0 ; y < height ; ++y) { cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); memset(cur_marking_line, 0, width); marking_bitmap->PutScanLineN(y, cur_line_slot); } // End ProgressForm->Title = "Vectorizing Stage 2"; // Start : Thining // ProgressForm->Title = "Thining"; ProgressForm->Title = "Vectorizing Stage 3"; cnt = 0; while(need_more_thinning_ne || need_more_thinning_sw) { ++num_of_iteration; need_more_thinning = false; for(y = 1 ; y < height - 2 ; ++y) { pre_canvas_line = Image->uBitmap->GetScanLineN(y - 1, pre_line_slot); cur_canvas_line = Image->uBitmap->GetScanLineN(y , cur_line_slot); nex_canvas_line = Image->uBitmap->GetScanLineN(y + 1, nex_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); for(x = 1 ; x < width - 2 ; ++x) { if(GetColor(cur_canvas_line, x) != BgColor_to_int ) { // x ,y ¸ðµÎ ÁÂÇ¥ (1,1)À϶§ºÎÅÍ ¹è°æ»öÀÌ ¾Æ´Ï¶ó¸é ¹«Á¶°Ç ¼±µû±â ¾ÈµÇ°Ô if (x == 1 && y == 1) { // Application->MessageBox("º¤ÅÍ ¼±µû±â¿¡ ÀûÇÕÇÑ ±×¸²ÀÌ ¾Æ´Õ´Ï´Ù ! ", "Warning", MB_OK); Application->MessageBox(IDS_NOT_ADJUST_ERROR1.c_str(), L"Warning", MB_OK); goto fail; } surround[0] = GetColor(pre_canvas_line, x ); surround[1] = GetColor(pre_canvas_line, x + 1); surround[2] = GetColor(cur_canvas_line, x + 1); surround[3] = GetColor(nex_canvas_line, x + 1); surround[4] = GetColor(nex_canvas_line, x ); surround[5] = GetColor(nex_canvas_line, x - 1); surround[6] = GetColor(cur_canvas_line, x - 1); surround[7] = GetColor(pre_canvas_line, x - 1); surround[8] = GetColor(pre_canvas_line, x ); A = 0 , B = 0; for(i = 0 ; i < 8 ; ++i) { if(surround[i] == BgColor_to_int && surround[i + 1] != BgColor_to_int) ++A; if(surround[i] != BgColor_to_int) ++B; } if(B > 1 && B < 7 && A == 1 && (surround[side_index1] == BgColor_to_int || surround[side_index2] == BgColor_to_int || (surround[corner_index1] == BgColor_to_int && surround[corner_index2] == BgColor_to_int) ) ) { *(cur_marking_line + x) = 1; need_more_thinning = true; } } } marking_bitmap->PutScanLineN(y, cur_line_slot); } for(y = 0 ; y < height - 1 ; ++y) { cur_canvas_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); for(x = 0 ; x < width - 1 ; ++x) { if(*(cur_marking_line + x)) PutColor(cur_canvas_line, x, BgColor_to_int); } Image->uBitmap->PutScanLineN(y, cur_line_slot); } if(side_index1 == 2) need_more_thinning_ne = need_more_thinning; else need_more_thinning_sw = need_more_thinning; temp1 = side_index1, temp2 = side_index2; side_index1 = corner_index1; side_index2 = corner_index2; corner_index1 = temp1; corner_index2 = temp2; if (!need_more_thinning) a = side_index1 ; if(num_of_iteration > limit_of_thinning_iteration) { if (nContinue == 0){ if(Application->MessageBox(IDS_NOT_ADJUST_ERROR2.c_str(), L"Warning", MB_RETRYCANCEL) == IDRETRY) { nContinue = 1; } else { nContinue = 2; goto fail; } } limit_of_thinning_iteration *= 2; } if (nContinue != 0) ProgressForm->Ratio = 0.1 + 0.1*(cnt++)/500; // ÀûÀýÇÏÁö ¾ÊÀº ±×¸²Àº iteration Max 500 else ProgressForm->Ratio = 0.1 + 0.1*(cnt++)/100; // ÀûÀýÇÑ ±×¸²Àº iteration Max 100 } // End : Thining ProgressForm->Ratio = 0.2; HarrisOperator(Image->uBitmap); //¸¶½ºÅ©¸®¼Â ProgressForm->Title = "Vectorizing Stage 4"; ProgressForm->Ratio = 0.3; for(y = 0 ; y < height-1 ; ++y) { cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); memset(cur_marking_line, 0, width); marking_bitmap->PutScanLineN(y, cur_line_slot); } //¸¶½ºÅ©¿¡ ±³Â÷Á¡ Ç¥±â ProgressForm->Title = "Vectorizing Stage 5"; for(y = 0 ; y < height - 1 ; ++y) { is_pre_line_exist = (y - 1 >= 0); is_nex_line_exist = (y + 1 < height); if (is_pre_line_exist) pre_canvas_line = Image->uBitmap->GetScanLineN(y - 1, pre_line_slot); cur_canvas_line = Image->uBitmap->GetScanLineN(y , cur_line_slot); if (is_nex_line_exist) nex_canvas_line = Image->uBitmap->GetScanLineN(y + 1, nex_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); for(x = 0 ; x < width - 1 ; ++x) { for(i = 0 ; i < 8 ; ++i) { surround[i] = BgColor_to_int; // ¿ì¼± ¹è°æ»öÀ¸·Î } if(GetColor(cur_canvas_line, x) != BgColor_to_int) { if (is_pre_line_exist){ surround[0] = GetColor(pre_canvas_line, x); if (x < width - 1) surround[1] = GetColor(pre_canvas_line, x + 1); if (x > 0) surround[7] = GetColor(pre_canvas_line, x - 1); surround[8] = GetColor(pre_canvas_line, x); } if (is_nex_line_exist){ if (x < width - 1) surround[3] = GetColor(nex_canvas_line, x + 1); surround[4] = GetColor(nex_canvas_line, x); if (x > 0) surround[5] = GetColor(nex_canvas_line, x - 1); } if (x < width - 1) surround[2] = GetColor(cur_canvas_line, x + 1); if (x > 0) surround[6] = GetColor(cur_canvas_line, x - 1); A = 0; for(i = 0 ; i < 8 ; ++i) { if(surround[i] == BgColor_to_int && surround[i + 1] != BgColor_to_int) ++A; } *(cur_marking_line + x) = A; } } marking_bitmap->PutScanLineN(y, cur_line_slot); } //±³Â÷Á¡ int List »ý¼º //f.open("C:\\VectorCrossPoints.txt"); // Corner È®ÀÎ À§ÇØ txt ÆÄÀÏ Ãâ·Â for(int y = 0 ; y < height - 1 ; ++y) { cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); for(int x = 0 ; x < width - 1 ; ++x) { if(*(cur_marking_line + x) > 2) { DPOINT point; point.x = x; point.y = y; CrossPointList.push_back(point); //f<<"Point: "<x, point_corner.y = iter_corner->y; for(int cnt2 = 0 ; cnt2 < NumberOfCrossLive ; cnt2++, iter_cross++){ point_cross.x = iter_cross->x, point_cross.y = iter_cross->y; if((abs(point_cross.x - point_corner.x) < 5) && (abs(point_cross.y - point_corner.y) < 5)){ AddCornerToCross = false; break; } } if(AddCornerToCross){ CrossPointList.push_back(point_corner); //f<<"Point: "<Title = "Vectorizing Stage 6"; for(y = 0 ; y < height - 1 ; ++y) { cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); cur_canvas_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); for(x = 0 ; x < width - 1 ; ++x) { if(*(cur_marking_line + x) == 1) { PendantEdge(x, y, marking_bitmap, GetFullTColor(GetColor(cur_canvas_line, x)), undoSw); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); } } ProgressForm->Ratio = 0.6 + 0.1*y/(height-1); } // Start : Vectorize ProgressForm->Title = "Vectorizing Stage 7"; Temporary_bitmap = new TUnionBitmap; Temporary_bitmap->Create(Image->uBitmap->Width, Image->uBitmap->Height, 8); Temporary_bitmap->StartScanLineN(3); AntiDoubleLineByFloodFill3(0, 0, marking_bitmap, Temporary_bitmap); Temporary_bitmap->StopScanLine(); delete Temporary_bitmap; end = 0; ProgressForm->Title = "Vectorizing Stage 8"; contour_marking_bitmap = new TUnionBitmap; contour_marking_bitmap->Create(Image->uBitmap->Width, Image->uBitmap->Height, 8); contour_marking_bitmap->FillRect(Rect(0, 0, Image->uBitmap->Width, Image->uBitmap->Height), 0); contour_marking_bitmap->StartScanLineN(3); ProgressForm->Ratio = 0.7; for(y = 0 ; y < height - 1 ; ++y) { cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); cur_canvas_line = Image->uBitmap->GetScanLineN(y, cur_line_slot); for(x = 0 ; x < width - 1 ; ++x) { if(*(cur_marking_line + x - 1) != 0 && *(cur_marking_line + x) == 0) { contour_marking_bitmap->FillRect(Rect(0, 0, Image->uBitmap->Width, Image->uBitmap->Height), 0); start_point = AntiDoubleLineByFloodFill3(x, y, marking_bitmap, contour_marking_bitmap); if(start_point.x < 0) start_point = TPoint(x - 1, y); Is_PendantRing = false; Check_Infi_Loop(contour_marking_bitmap, x-1, y); if (Is_PendantRing) FollowContour3(x - 2, y, contour_marking_bitmap); // ¹«ÇÑ·çÇÁ µµ´Â Á¡À» Áö¿ü´Ù¸é 2Ä­ ¾ÕÀ¸·Î else FollowContour3(x - 1, y, contour_marking_bitmap); //HarrisOperator(contour_marking_bitmap); //FreeDrawing3(0, 1, true, undoSw); FreeDrawing3(GetFullTColor(GetColor(cur_canvas_line, x-1)), 1, true, undoSw); cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); } } ProgressForm->Ratio = 0.7 + 0.3* y / (height-1); } contour_marking_bitmap->StopScanLine(); if(contour_marking_bitmap) delete contour_marking_bitmap; contour_marking_bitmap = NULL; Image->uBitmap->StopScanLine(); marking_bitmap->StopScanLine(); MainImageForm->Undo->UndoRead(); if(marking_bitmap) delete marking_bitmap; marking_bitmap = NULL; CornerPointList.clear(); END_LOG; return; fail: Image->uBitmap->StopScanLine(); marking_bitmap->StopScanLine(); MainImageForm->Undo->UndoRead(); if(marking_bitmap) delete marking_bitmap; marking_bitmap = NULL; CornerPointList.clear(); END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::PendantEdge(int x, int y, TUnionBitmap* marking_bitmap, const TColor vector_color, bool& undoSw) { BEGIN_LOG(""); Byte *pre_marking_line, *cur_marking_line, *nex_marking_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; int mark_sur[8]; TPItemImage* Image = MainImageForm->iMainImage; const int width = Image->uBitmap->Width; const int height = Image->uBitmap->Height; int pre_position = 3; bool Enable_Freedrawing = true; while(true) { const int left = x - 1, right = x + 1; const bool is_pre_line_exist = (y - 1 >= 0); const bool is_nex_line_exist = (y + 1 < height); bool is_there_need_to_reread = (pre_position != 4 && pre_position != 0); for(int i = 0 ; i < 8 ; ++i) { mark_sur[i] = 0; } if(is_there_need_to_reread) { cur_marking_line = marking_bitmap->GetScanLineN(y, cur_line_slot); } if(left >= 0) { mark_sur[4] = *(cur_marking_line + left); } if(right < width) { mark_sur[0] = *(cur_marking_line + right); } if(is_pre_line_exist) { if(is_there_need_to_reread) { pre_marking_line = marking_bitmap->GetScanLineN(y - 1, pre_line_slot); } mark_sur[2] = *(pre_marking_line + x); if(left >= 0) { mark_sur[3] = *(pre_marking_line + left); } if(right < width) { mark_sur[1] = *(pre_marking_line + right); } } if(is_nex_line_exist) { if(is_there_need_to_reread) { nex_marking_line = marking_bitmap->GetScanLineN(y + 1, nex_line_slot); } mark_sur[6] = *(nex_marking_line + x); if(left >= 0) { mark_sur[5] = *(nex_marking_line + left); } if(right < width) { mark_sur[7] = *(nex_marking_line + right); } } int i, search_pos, nex_pos = -1; bool has_junction_pos = false; bool has_whirlwind_junction_pos = false; // Start : ÁÙÀÌ 5°³ ¸ô·Á¼­ A°ªÀÌ 1ÀÌ µÇ´Â ÁöÁ¡. ÆÒ´øÆ® ½ÃÀÛ Æ÷ÀÎÆ®·Î ÀÎ½ÄµÇ¸é ¾ÈµÇ°Ô²û int Num_of_Dots = 0; for ( int i = 0 ; i < 8 ; i++){ if (mark_sur[i] != 0) Num_of_Dots ++; } if (Num_of_Dots >= 7){ *(cur_marking_line + x) = 0; marking_bitmap->PutScanLineN(y ,cur_line_slot); END_LOG; return; } // End // Start : ÆÒ´øÆ®°¡ µÎ°³ ¿¬´Þ¾Æ ºÙ¾î À־ ºÐ¸®½ÃÄÑ¾ß ÇÒ °æ¿ì if ( (mark_sur[2] && mark_sur[3] && mark_sur[4]) || (mark_sur[0] && mark_sur[1] && mark_sur[2]) || (mark_sur[4] && mark_sur[5] && mark_sur[6]) || (mark_sur[0] && mark_sur[6] && mark_sur[7]) ) { *(cur_marking_line + x) = 0; bezierCurveApproximator.AddPoint(DPOINT(x + 0.5, y + 0.5)); if (mark_sur[2] && mark_sur[3] && mark_sur[4]) ++*(pre_marking_line + left); else if (mark_sur[0] && mark_sur[1] && mark_sur[2]) ++*(pre_marking_line + right); else if (mark_sur[4] && mark_sur[5] && mark_sur[6]) ++*(nex_marking_line + left); else if (mark_sur[0] && mark_sur[6] && mark_sur[7]) ++*(nex_marking_line + right); marking_bitmap->PutScanLineN(y ,cur_line_slot); marking_bitmap->PutScanLineN(y-1 ,pre_line_slot); marking_bitmap->PutScanLineN(y+1 ,nex_line_slot); break; } // End int make_odd = 0, make_even = 1; if(pre_position % 2 == 0) { make_odd = 1, make_even = 0; } for(i = 0 ; i < 4 ; ++i) { search_pos = (pre_position + i * 2 + 2 + make_odd) % 8; if(mark_sur[search_pos] != 0) { nex_pos = search_pos; break; } } for(i = 0 ; i < 4 ; ++i) { search_pos = (pre_position + i * 2 + 2 + make_even) % 8; if(mark_sur[search_pos] != 0) { nex_pos = search_pos; break; } } if(nex_pos == -1) break; if(mark_sur[nex_pos] > 2 || mark_sur[nex_pos] == 1) { has_junction_pos = true; } *(cur_marking_line + x) = 0; marking_bitmap->PutScanLineN(y ,cur_line_slot); bezierCurveApproximator.AddPoint(DPOINT(x + 0.5, y + 0.5)); pre_position = (nex_pos + 4) % 8; switch(nex_pos) { case 0: ++x; break; case 1: ++x; --y; break; case 2: --y; break; case 3: --x; --y; break; case 4: --x; break; case 5: --x; ++y; break; case 6: ++y; break; case 7: ++x; ++y; break; default: break; } if(has_junction_pos) { switch(nex_pos) { case 1: case 2: case 3: --*(pre_marking_line + x); marking_bitmap->PutScanLineN(y ,pre_line_slot); break; case 0: case 4: --*(cur_marking_line + x); marking_bitmap->PutScanLineN(y ,cur_line_slot); break; case 5: case 6: case 7: --*(nex_marking_line + x); marking_bitmap->PutScanLineN(y ,nex_line_slot); break; default: break; } bezierCurveApproximator.AddPoint(DPOINT(x + 0.5, y + 0.5)); break; } } FreeDrawing3(vector_color, 1, false, undoSw); END_LOG; } TPoint __fastcall ImageVectorizer::AntiDoubleLineByFloodFill3(int X, int Y, TUnionBitmap* marking_bitmap, TUnionBitmap* contour_marking_bitmap) { BEGIN_LOG(""); TPoint start_point(-1, -1); Byte *pre_contour_line, *pre_marking_line; Byte *cur_contour_line, *cur_marking_line; Byte *nex_contour_line, *nex_marking_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; TPItemImage* Image = MainImageForm->iMainImage; const int width = Image->uBitmap->Width; const int height = Image->uBitmap->Height; stack stack; stack.push(Point(X, Y)); while(!stack.empty()) { const TPoint point = stack.top(); stack.pop(); cur_contour_line = contour_marking_bitmap->GetScanLineN(point.y, cur_line_slot); cur_marking_line = marking_bitmap->GetScanLineN(point.y, cur_line_slot); if(*(cur_marking_line + point.x) == ContourMark) continue; if(point.y < height - 1) { nex_contour_line = contour_marking_bitmap->GetScanLineN(point.y + 1, nex_line_slot); nex_marking_line = marking_bitmap->GetScanLineN(point.y + 1, nex_line_slot); } if(point.y > 0) { pre_contour_line = contour_marking_bitmap->GetScanLineN(point.y - 1, pre_line_slot); pre_marking_line = marking_bitmap->GetScanLineN(point.y - 1, pre_line_slot); } int x_left = point.x, color; while(x_left >= 0) { color = *(cur_marking_line + x_left); if(color != 0) { *(cur_contour_line + x_left) = color; if(point.y > 0 && *(pre_marking_line + x_left) != ContourMark) //°°ÀÌ ÇÏ·Á´Â ÀÌÀ¯°¡ È¿À²¼º? *(pre_contour_line + x_left) = *(pre_marking_line + x_left); if(point.y < height - 1 && *(nex_marking_line + x_left) != ContourMark) *(nex_contour_line + x_left) = *(nex_marking_line + x_left); if(color > 2) start_point = TPoint(x_left, point.y); break; } --x_left; } ++x_left; bool span_up = false, span_down = false; while(x_left < width) { color = *(cur_marking_line + x_left); if(color != 0) { *(cur_contour_line + x_left) = color; if(point.y > 0 && *(pre_marking_line + x_left) != ContourMark) // ContourÀÌµç ¾Æ´Ïµç ¿ì¼± ³Ö°í º»´Ù? *(pre_contour_line + x_left) = *(pre_marking_line + x_left); if(point.y < height - 1 && *(nex_marking_line + x_left) != ContourMark) *(nex_contour_line + x_left) = *(nex_marking_line + x_left); if(color > 2) start_point = TPoint(x_left, point.y); // ¾î¶² ÀǹÌÀÎÁö? break; } else{ *(cur_marking_line + x_left) = ContourMark; } if(point.y < height - 1) { BYTE mark = *(nex_marking_line + x_left); if(!span_down && mark == 0) { stack.push(Point(x_left, point.y + 1)); span_down = true; } else if(span_down && mark != 0) span_down = false; if(mark > 1) *(nex_contour_line + x_left) = mark; } if(point.y > 0) { BYTE mark = *(pre_marking_line + x_left); if(!span_up && mark == 0) { stack.push(Point(x_left, point.y - 1)); span_up = true; } else if(span_up && mark != 0) span_up = false; if(mark > 1) *(pre_contour_line + x_left) = mark; } ++x_left; } contour_marking_bitmap->PutScanLineN(point.y, cur_line_slot); if(point.y > 0) contour_marking_bitmap->PutScanLineN(point.y - 1, pre_line_slot); if(point.y < height - 1) contour_marking_bitmap->PutScanLineN(point.y + 1, nex_line_slot); marking_bitmap->PutScanLineN(point.y, cur_line_slot); } END_LOG; return start_point; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::FollowContour3(int X, int Y, TUnionBitmap* contour_marking_bitmap) { BEGIN_LOG(""); Byte *pre_contour_line, *cur_contour_line, *nex_contour_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; int surround[8]; int x = X, y = Y; int pre_position = 3; int check_already_follow; while(true) { const int width = contour_marking_bitmap->Width; const int height = contour_marking_bitmap->Height; const int left = x - 1, right = x + 1; const bool is_pre_line_exist = (y - 1 >= 0); const bool is_nex_line_exist = (y + 1 < height); bool is_there_need_to_reread = (pre_position != 4 && pre_position != 0); for(int i = 0 ; i < 8 ; ++i) { surround[i] = 0; } if(is_there_need_to_reread) { cur_contour_line = contour_marking_bitmap->GetScanLineN(y, cur_line_slot); } if(left >= 0) { surround[4] = *(cur_contour_line + left); } if(right < width) { surround[0] = *(cur_contour_line + right); } if(is_pre_line_exist) { if(is_there_need_to_reread) { pre_contour_line = contour_marking_bitmap->GetScanLineN(y - 1, pre_line_slot); } surround[2] = *(pre_contour_line + x); if(left >= 0) { surround[3] = *(pre_contour_line + left); } if(right < width) { surround[1] = *(pre_contour_line + right); } } if(is_nex_line_exist) { if(is_there_need_to_reread) { nex_contour_line = contour_marking_bitmap->GetScanLineN(y + 1, nex_line_slot); } surround[6] = *(nex_contour_line + x); if(left >= 0) { surround[5] = *(nex_contour_line + left); } if(right < width) { surround[7] = *(nex_contour_line + right); } } int i, search_pos, nex_pos = -1; int make_odd = 0, make_even = 1; bool is_junction_point = false; contour_marking_bitmap->PutScanLineN(y, cur_line_slot); if(pre_position % 2 == 0) { make_odd = 1, make_even = 0; } for(i = 0 ; i < 6; ++i) { search_pos = (pre_position + i +2)% 8; if(surround[search_pos] != 0) { nex_pos = search_pos; break; } } DPOINT pt = DPOINT(x + 0.5, y + 0.5); bezierCurveApproximator.AddPoint(DPOINT(x + 0.5, y + 0.5)); switch(nex_pos) { case 0: ++x; check_already_follow = *(cur_contour_line + x); break; case 1: ++x; --y; check_already_follow = *(pre_contour_line + x); break; case 2: --y; check_already_follow = *(pre_contour_line + x); break; case 3: --x; --y; check_already_follow = *(pre_contour_line + x); break; case 4: --x; check_already_follow = *(cur_contour_line + x); break; case 5: --x; ++y; check_already_follow = *(nex_contour_line + x); break; case 6: ++y; check_already_follow = *(nex_contour_line + x); break; case 7: ++x; ++y; check_already_follow = *(nex_contour_line + x); break; default: break; } if(nex_pos == -1) break; if(x == X && y == Y) break; pre_position = (nex_pos + 4) % 8; } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::FreeDrawing3(const TColor color, const int min_point, bool Vector_closed, bool& undoSw) { BEGIN_LOG(""); ++processedObjects; int pList_index = 0, additional_count; int point_list_size = bezierCurveApproximator.freeDrawingPointList.size(); int cross_list_size = CrossPointList.size(); TVecData *data = NULL; // Ŭ·¡½º ¸â¹ö º¯¼ö¸¦ »ç¿ëÇÏÁö ¾Êµµ·Ï ÇÔ - by monkman (2009.04.01) list::const_iterator iter_point = bezierCurveApproximator.freeDrawingPointList.begin(); list::const_iterator iter_cross = CrossPointList.begin(); list CrossPointIndex; list::iterator iter_cross2 = CrossPointIndex.begin(); bool EnableAdd; if(Vector_closed){ // Vector_closed 1) false <- Pendant 2) true <- closed contour for(int cnt = 0 ; cnt < cross_list_size ; cnt++, iter_cross++){ iter_point = bezierCurveApproximator.freeDrawingPointList.begin(); float cross_x = iter_cross->x, cross_y = iter_cross->y; float point_x = iter_point->x - 0.5 , point_y = iter_point->y - 0.5; float pre_deter = (cross_x - point_x)*(cross_x - point_x) + (cross_y - point_y)*(cross_y - point_y); float now_deter; int index = 0; int CrossSize; for(int cnt2 = 0 ; cnt2 < point_list_size ; cnt2++, iter_point++){ cross_x = iter_cross->x, cross_y = iter_cross->y; point_x = iter_point->x - 0.5 , point_y = iter_point->y - 0.5; now_deter = (cross_x - point_x)*(cross_x - point_x) + (cross_y - point_y)*(cross_y - point_y); if (pre_deter >= now_deter && sqrt(now_deter) < 2){ // Corner´Â BezierCurvePoint·ÎºÎÅÍ °Å¸®°¡ 2ÀÌÇÏÀ̾î¾ß ÇÔ pre_deter = now_deter; index = cnt2; } } EnableAdd = true; // CrossPointIndex¿¡ ÀÌ¹Ì Á¸ÀçÇÑ´Ù¸é AddÇÏÁö ¸»¾Æ¶ó for(int cnt2 = 0 ; cnt2 < CrossPointIndex.size() ; cnt2++, iter_cross2++){ if(index == *iter_cross2) EnableAdd = false; } if(index > 3 && EnableAdd){ CrossPointIndex.push_back(index); // index°¡ 1,2ÀÌ¸é ³Ê¹« °¡±õ°Ô À§Ä¡ÇØ ÀÖ´Ù. } } CrossPointIndex.sort(); } if(CrossPointIndex.size() > 0){ int start = 0; iter_cross2 = CrossPointIndex.begin(); int PointIndexCnt = CrossPointIndex.size(); for(int cnt = 0 ; cnt < PointIndexCnt ; cnt++, iter_cross2++){ bezierCurveApproximator.MakeBezierCurvePointsList(start, (*iter_cross2) + 1); if((*iter_cross2)>0) start = (*iter_cross2) - 1; } bezierCurveApproximator.MakeBezierCurvePointsList(start, point_list_size); } else bezierCurveApproximator.MakeBezierCurvePointsList(0, point_list_size); list::iterator iter = bezierCurveApproximator.bezierCurvePointsList.begin(); int BezierListSize = bezierCurveApproximator.bezierCurvePointsList.size(); int Num_VecData = BezierListSize/341 + 1; if(point_list_size < min_point || BezierListSize < 1/*|| BezierListSize > 340*/ ) { bezierCurveApproximator.Reset(); END_LOG; return; } int Cnt_VecData = Num_VecData; while (Cnt_VecData >= 1){ TList *DataList = VecDraw->NVector->DataList; if ((data = new TVecData(MainImageForm->Number))==NULL) { END_LOG; return; } data->Kind = V_CURVE; data->bRound = stCircle; data->Color = color;//MainImageForm->Palette->;//color; //data->PenThick = 1; data->PenThick = 3; data->PenStyle = P_SOLID; data->CapStyle[0] = 0; data->CapStyle[1] = 0; double thick = data->PenThick; if (Cnt_VecData > 1){ additional_count = 340; } else if (Cnt_VecData == 1){ additional_count = bezierCurveApproximator.bezierCurvePointsList.size() - 340*(Num_VecData-1); } data->nCount = additional_count; data->pList = (DPOINT*)HeapAlloc(GetProcessHeap(), 0, sizeof(DPOINT)*(data->nCount*3+1)); data->pMask = (BYTE*)HeapAlloc(GetProcessHeap(), 0, (data->nCount * 3 + 1) % 8 == 0 ? (data->nCount * 3 + 1) / 8 : (data->nCount * 3 + 1) / 8 + 1); pList_index = 0; data->bFill = false; data->Brush = color; DataList->Add(data); VecDraw->UndoSave(VU_CREATE, DataList->Count - 1, undoSw); undoSw = false; int last_end_x = 0 , last_end_y = 0; if (Num_VecData == 1){ if(Vector_closed) FindCloseCornerPoint(iter->start); if(Vector_closed) FindCloseCornerPoint(iter->end); int temp_start_x = iter->start.x; int temp_start_y = iter->start.y; data->pList[pList_index++] = iter->start; data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; while(iter != bezierCurveApproximator.bezierCurvePointsList.end()) { if(Vector_closed) FindCloseCornerPoint(iter->end); if(last_end_x == iter->end.x && last_end_y == iter->end.y){ if((temp_start_x != last_end_x || temp_start_y != last_end_y) && (sqrt(float((temp_start_x - last_end_x) * (temp_start_x - last_end_x) + (temp_start_y - last_end_y) * (temp_start_y - last_end_y))) < 10)) { data->pList[pList_index++] = iter->end; data->pList[pList_index++] = iter->end; data->pList[pList_index++] = DPOINT(temp_start_x, temp_start_y); ++iter; } else{ data->nCount--; ++iter; } } else{ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; last_end_x = iter->end.x, last_end_y = iter->end.y; ++iter; } } } else if (Num_VecData > 1){ if (Cnt_VecData > 1){ if(Vector_closed) FindCloseCornerPoint(iter->start); if(Vector_closed) FindCloseCornerPoint(iter->end); data->pList[pList_index++] = iter->start; if(iter->start.x == iter->end.x && iter->start.y == iter->end.y) ++iter; else{ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; ++iter; } for ( int cnt = 1 ; cnt < 340 ; cnt++){ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; if(Vector_closed) FindCloseCornerPoint(iter->end); data->pList[pList_index++] = iter->end; ++iter; } } else if (Cnt_VecData == 1){ if(Vector_closed) FindCloseCornerPoint(iter->start); if(Vector_closed) FindCloseCornerPoint(iter->end); data->pList[pList_index++] = iter->start; if(iter->start.x == iter->end.x && iter->start.y == iter->end.y) ++iter; else{ data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; data->pList[pList_index++] = iter->end; ++iter; } while(iter != bezierCurveApproximator.bezierCurvePointsList.end()) { data->pList[pList_index++] = iter->control1; data->pList[pList_index++] = iter->control2; if(Vector_closed) FindCloseCornerPoint(iter->end); data->pList[pList_index++] = iter->end; ++iter; } } } Cnt_VecData--; SET_RECT; } VecDraw->AddPoint(100,100); bezierCurveApproximator.Reset(); if (Vector_closed){ if (Num_VecData > 1) data->bClosed = false; else if (Num_VecData== 1) data->bClosed = true; } else data->bClosed = false; END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::Check_Infi_Loop(TUnionBitmap* marking_bitmap, const int X, const int Y) { BEGIN_LOG(""); Byte* pre_contour_line, *cur_contour_line, *nex_contour_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; int surround[8]; int x,y; const int Width = marking_bitmap->Width; const int Height = marking_bitmap->Height; for (y = 1 ; y < Height-2 ; ++y){ cur_contour_line = marking_bitmap->GetScanLineN(y, cur_line_slot); pre_contour_line = marking_bitmap->GetScanLineN(y - 1, pre_line_slot); nex_contour_line = marking_bitmap->GetScanLineN(y + 1, nex_line_slot); for (x = 1 ; x < Width-2 ; ++x){ int left = x-1, right = x+1; surround[4] = *(cur_contour_line + left); surround[0] = *(cur_contour_line + right); surround[2] = *(pre_contour_line + x); surround[3] = *(pre_contour_line + left); surround[1] = *(pre_contour_line + right); surround[6] = *(nex_contour_line + x); surround[5] = *(nex_contour_line + left); surround[7] = *(nex_contour_line + right); if (*(cur_contour_line + x) != 0){ if ((surround[1] && surround[2] && surround[4] && surround[5]) || (surround[0] && surround[2] && surround[3] && surround[7]) || (surround[3] && surround[4] && surround[6] && surround[7]) || (surround[0] && surround[1] && surround[5] && surround[6])) { *(cur_contour_line + x) = 0; if (x == X && y == Y) Is_PendantRing = true; } } } marking_bitmap->PutScanLineN(y, cur_line_slot); } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer8::Fill_onePointHole(TUnionBitmap* Image) { BEGIN_LOG(""); Byte* pre_contour_line, *cur_contour_line, *nex_contour_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; const int Width = Image->Width; const int Height = Image->Height; int surround[8]; int x,y; Image->StartScanLineN(3); for (y = 1 ; y < Height-2 ; ++y){ cur_contour_line = Image->GetScanLineN(y, cur_line_slot); pre_contour_line = Image->GetScanLineN(y - 1, pre_line_slot); nex_contour_line = Image->GetScanLineN(y + 1, nex_line_slot); for (x = 1 ; x < Width-2 ; ++x){ int left = x-1, right = x+1; surround[4] = *(cur_contour_line + left); surround[0] = *(cur_contour_line + right); surround[2] = *(pre_contour_line + x); surround[3] = *(pre_contour_line + left); surround[1] = *(pre_contour_line + right); surround[6] = *(nex_contour_line + x); surround[5] = *(nex_contour_line + left); surround[7] = *(nex_contour_line + right); if (*(cur_contour_line + x) == BgColor_to_int){ if ((surround[0] != 1) && (surround[2] != 1) && (surround[4] != 1) && (surround[6] != 1)) *(cur_contour_line + x) = surround[0] ; } } Image->PutScanLineN(y, cur_line_slot); } Image->StopScanLine(); END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer24::Fill_onePointHole(TUnionBitmap* Image) { BEGIN_LOG(""); Byte* pre_contour_line, *cur_contour_line, *nex_contour_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; const int Width = Image->Width; const int Height = Image->Height; int surround[8]; int x,y; Image->StartScanLineN(3); for (y = 1 ; y < Height-2 ; ++y){ cur_contour_line = Image->GetScanLineN(y, cur_line_slot); pre_contour_line = Image->GetScanLineN(y - 1, pre_line_slot); nex_contour_line = Image->GetScanLineN(y + 1, nex_line_slot); for (x = 1 ; x < Width-2 ; ++x){ int left = x-1, right = x+1; surround[4] = GetColor(cur_contour_line , left); surround[0] = GetColor(cur_contour_line , right); surround[2] = GetColor(pre_contour_line , x); surround[3] = GetColor(pre_contour_line , left); surround[1] = GetColor(pre_contour_line , right); surround[6] = GetColor(nex_contour_line , x); surround[5] = GetColor(nex_contour_line , left); surround[7] = GetColor(nex_contour_line , right); if (GetColor(cur_contour_line , x) == BgColor_to_int){ if ((surround[0] != BgColor_to_int) && (surround[2] != BgColor_to_int) && (surround[4] != 1) && (surround[6] != BgColor_to_int)) PutColor(cur_contour_line, x, surround[0]) ; } } Image->PutScanLineN(y, cur_line_slot); } Image->StopScanLine(); END_LOG; } //--------------------------------------------------------------------------- int ImageVectorizer8::Fill_Holes(int X, int Y, TUnionBitmap* Image, TUnionBitmap* marking_bitmap, bool Fill_mode) { BEGIN_LOG(""); Byte *pre_image_line, *pre_marking_line; Byte *cur_image_line, *cur_marking_line; Byte *nex_image_line, *nex_marking_line; Byte *temp_image_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; const int temp_line_slot = 3; const int width = Image->Width; const int height = Image->Height; const int ContourMark = 100; int NumberOfHoles = 0, temp_y; stack stack; stack.push(Point(X, Y)); if (!Fill_mode){ while(!stack.empty()) { const TPoint point = stack.top(); stack.pop(); cur_marking_line = marking_bitmap->GetScanLineN(point.y, cur_line_slot); cur_image_line = Image->GetScanLineN(point.y, cur_line_slot); if(*(cur_marking_line + point.x) == ContourMark) continue; if(point.y < height - 1) { nex_image_line = Image->GetScanLineN(point.y + 1, nex_line_slot); nex_marking_line = marking_bitmap->GetScanLineN(point.y + 1, nex_line_slot); } if(point.y > 0) { pre_image_line = Image->GetScanLineN(point.y - 1, pre_line_slot); pre_marking_line = marking_bitmap->GetScanLineN(point.y - 1, pre_line_slot); } int x_left = point.x, color; while(x_left >= 0) { color = *(cur_image_line + x_left); if(color != BgColor_to_int) break; --x_left; } ++x_left; bool span_up = false, span_down = false; while(x_left < width) { color = *(cur_image_line + x_left); if(color != BgColor_to_int) break; else{ *(cur_marking_line + x_left) = ContourMark; // *(cur_image_line + x_left) = Temp_Color; // Àӽ÷ΠÅ×½ºÆ® Çϱâ À§ÇØ Delete this plz NumberOfHoles++; } if(point.y < height - 1) { BYTE mark = *(nex_image_line + x_left); if(!span_down && mark == BgColor_to_int) { stack.push(Point(x_left, point.y + 1)); span_down = true; } else if(span_down && mark != BgColor_to_int) span_down = false; } if(point.y > 0) { BYTE mark = *(pre_image_line + x_left); if(!span_up && mark == BgColor_to_int) { stack.push(Point(x_left, point.y - 1)); span_up = true; } else if(span_up && mark != BgColor_to_int) span_up = false; } ++x_left; } marking_bitmap->PutScanLineN(point.y, cur_line_slot); if(point.y > 0) marking_bitmap->PutScanLineN(point.y - 1, pre_line_slot); if(point.y < height - 1) marking_bitmap->PutScanLineN(point.y + 1, nex_line_slot); Image->PutScanLineN(point.y, cur_line_slot); } } else if (Fill_mode){ while(!stack.empty()) { const TPoint point = stack.top(); stack.pop(); cur_image_line = Image->GetScanLineN(point.y, cur_line_slot); if(point.y < height - 1) { nex_image_line = Image->GetScanLineN(point.y + 1, nex_line_slot); } if(point.y > 0) { pre_image_line = Image->GetScanLineN(point.y - 1, pre_line_slot); } int x_left = point.x, color; while(x_left >= 0) { color = *(cur_image_line + x_left); if(color != BgColor_to_int) break; --x_left; } ++x_left; bool span_up = false, span_down = false; while(x_left < width) { color = *(cur_image_line + x_left); if(color != BgColor_to_int) break; else{ *(cur_image_line + x_left) = 2; NumberOfHoles++; if (NumberOfHoles > 0 && NumberOfHoles > threshold) break; } if(point.y < height - 1) { BYTE mark = *(nex_image_line + x_left); if(!span_down && mark == BgColor_to_int) { stack.push(Point(x_left, point.y + 1)); span_down = true; } else if(span_down && mark != BgColor_to_int) span_down = false; } if(point.y > 0) { BYTE mark = *(pre_image_line + x_left); if(!span_up && mark == BgColor_to_int) { stack.push(Point(x_left, point.y - 1)); span_up = true; } else if(span_up && mark != BgColor_to_int) span_up = false; } ++x_left; } Image->PutScanLineN(point.y, cur_line_slot); } } END_LOG; return NumberOfHoles; } //--------------------------------------------------------------------------- int ImageVectorizer24::Fill_Holes(int X, int Y, TUnionBitmap* Image, TUnionBitmap* marking_bitmap, bool Fill_mode) { BEGIN_LOG(""); Byte *pre_image_line, *pre_marking_line; Byte *cur_image_line, *cur_marking_line; Byte *nex_image_line, *nex_marking_line; Byte *temp_image_line; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; const int temp_line_slot = 3; const int width = Image->Width; const int height = Image->Height; const int ContourMark = 100; int NumberOfHoles = 0, temp_y; stack stack; stack.push(Point(X, Y)); if (!Fill_mode){ while(!stack.empty()) { const TPoint point = stack.top(); stack.pop(); cur_marking_line = marking_bitmap->GetScanLineN(point.y, cur_line_slot); cur_image_line = Image->GetScanLineN(point.y, cur_line_slot); if(*(cur_marking_line + point.x) == ContourMark) continue; if(point.y < height - 1) { nex_image_line = Image->GetScanLineN(point.y + 1, nex_line_slot); nex_marking_line = marking_bitmap->GetScanLineN(point.y + 1, nex_line_slot); } if(point.y > 0) { pre_image_line = Image->GetScanLineN(point.y - 1, pre_line_slot); pre_marking_line = marking_bitmap->GetScanLineN(point.y - 1, pre_line_slot); } int x_left = point.x, color; while(x_left >= 0) { color = GetColor(cur_image_line, x_left); if(color != BgColor_to_int) break; --x_left; } ++x_left; bool span_up = false, span_down = false; while(x_left < width) { color = GetColor(cur_image_line, x_left); if(color != BgColor_to_int) break; else{ *(cur_marking_line + x_left) = ContourMark; // *(cur_image_line + x_left) = Temp_Color; // Àӽ÷ΠÅ×½ºÆ® Çϱâ À§ÇØ Delete this plz NumberOfHoles++; } if(point.y < height - 1) { int mark = GetColor(nex_image_line, x_left); if(!span_down && mark == BgColor_to_int) { stack.push(Point(x_left, point.y + 1)); span_down = true; } else if(span_down && mark != BgColor_to_int) span_down = false; } if(point.y > 0) { int mark = GetColor(pre_image_line, x_left); if(!span_up && mark == BgColor_to_int) { stack.push(Point(x_left, point.y - 1)); span_up = true; } else if(span_up && mark != BgColor_to_int) span_up = false; } ++x_left; } marking_bitmap->PutScanLineN(point.y, cur_line_slot); if(point.y > 0) marking_bitmap->PutScanLineN(point.y - 1, pre_line_slot); if(point.y < height - 1) marking_bitmap->PutScanLineN(point.y + 1, nex_line_slot); Image->PutScanLineN(point.y, cur_line_slot); } } else if (Fill_mode){ while(!stack.empty()) { const TPoint point = stack.top(); stack.pop(); cur_image_line = Image->GetScanLineN(point.y, cur_line_slot); if(point.y < height - 1) { nex_image_line = Image->GetScanLineN(point.y + 1, nex_line_slot); } if(point.y > 0) { pre_image_line = Image->GetScanLineN(point.y - 1, pre_line_slot); } int x_left = point.x, color; while(x_left >= 0) { color = GetColor(cur_image_line, x_left); if(color != BgColor_to_int) break; --x_left; } ++x_left; int Contour_color = color; bool span_up = false, span_down = false; while(x_left < width) { color = GetColor(cur_image_line, x_left); if(color != BgColor_to_int) break; else{ PutColor(cur_image_line, x_left, Contour_color); NumberOfHoles++; if (NumberOfHoles > 0 && NumberOfHoles > threshold) break; } if(point.y < height - 1) { int mark = GetColor(nex_image_line, x_left); if(!span_down && mark == BgColor_to_int) { stack.push(Point(x_left, point.y + 1)); span_down = true; } else if(span_down && mark != BgColor_to_int) span_down = false; } if(point.y > 0) { int mark = GetColor(pre_image_line, x_left); if(!span_up && mark == BgColor_to_int) { stack.push(Point(x_left, point.y - 1)); span_up = true; } else if(span_up && mark != BgColor_to_int) span_up = false; } ++x_left; } Image->PutScanLineN(point.y, cur_line_slot); } } END_LOG; return NumberOfHoles; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::PutBgdColor(int Color){ BgColor_to_int = Color; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::PutBgdColorList(TList* Color_List){ pColorList = Color_List; HaveGetColor = true; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer8::ConvertToGrayScale(TUnionBitmap* SrcImage, TUnionBitmap* DstImage) { BEGIN_LOG(""); Byte *Src_line, *Dst_line; const int Width = SrcImage->Width; const int Height = SrcImage->Height; int i,j; float grayColor; unsigned char Red, Green, Blue; SrcImage->StartScanLine(); DstImage->StartScanLine(); for(i = 0 ; i < Height ; i++){ Src_line = SrcImage->GetScanLine(i); Dst_line = DstImage->GetScanLine(i); for(j = 0 ; j < Width ; j++){ Red = MainImageForm->Palette->ColorData[*(Src_line+j)]->RGB.rgbRed; Green = MainImageForm->Palette->ColorData[*(Src_line+j)]->RGB.rgbGreen; Blue = MainImageForm->Palette->ColorData[*(Src_line+j)]->RGB.rgbBlue; grayColor =( 0.3*Red + 0.59*Green + 0.11*Blue ); *(Dst_line+j) = (int)grayColor; } DstImage->PutScanLine(i); } SrcImage->StopScanLine(); DstImage->StopScanLine(); END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer24::ConvertToGrayScale(TUnionBitmap* SrcImage, TUnionBitmap* DstImage) { BEGIN_LOG(""); Byte *Src_line,*Dst_line; const int Width = SrcImage->Width; const int Height = SrcImage->Height; int i,j; float grayColor; SrcImage->StartScanLine(); DstImage->StartScanLine(); for(i = 0 ; i < Height ; i++){ Src_line = SrcImage->GetScanLine(i); Dst_line = DstImage->GetScanLine(i); for(j = 0 ; j < Width ; j++){ grayColor =( 0.11*(*(Src_line+3*j))+0.59*(*(Src_line+3*j+1))+0.3*(*(Src_line+3*j+2))); *(Dst_line+j) = (int)(grayColor+0.5); } DstImage->PutScanLine(i); } SrcImage->StopScanLine(); DstImage->StopScanLine(); END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::Mask_2D_Convolution(TUnionBitmap* SrcImage, int** ConvDstArray_dx2, int** ConvDstArray_dy2, int** ConvDstArray_dxy) { BEGIN_LOG(""); Byte *pre_src_line, *cur_src_line, *nex_src_line; const int Width = SrcImage->Width; const int Height = SrcImage->Height; const int pre_line_slot = 0, cur_line_slot = 1, nex_line_slot = 2; int i,j; int x,y; int Ix,Iy,Ixy; int Image[3][3]; const int Mask_dx[3][3] = { {-1 , 0 , 1} , {-1 , 0 , 1} , {-1 , 0 , 1} }; const int Mask_dy[3][3] = { {-1 , -1 , -1} , {0 , 0 , 0} , {1 , 1 , 1} }; SrcImage->StartScanLineN(3); for(y = 0 ; y < Height ; y ++){ cur_src_line = SrcImage->GetScanLineN(y,cur_line_slot); if(y > 0){ pre_src_line = SrcImage->GetScanLineN(y-1,pre_line_slot); } if(y < Height-1){ nex_src_line = SrcImage->GetScanLineN(y+1,nex_line_slot); } for(int row = 0 ; row < 3 ; row++){ for(int column = 0 ; column < 3 ; column++){ Image[row][column] = 255; // ¹è°æ Èò»öÀ¸·Î °¡Á¤ } } for(x = 0 ; x < Width ; x ++){ if(y > 0){ if(x > 0) Image[0][0] = *(pre_src_line + x-1); Image[0][1] = *(pre_src_line + x); if(x < Width-1) Image[0][2] = *(pre_src_line + x+1); } if(x > 0) Image[1][0] = *(cur_src_line + x-1); Image[1][1] = *(cur_src_line + x); if(x < Width-1) Image[1][2] = *(cur_src_line + x+1); if(y < Height-1){ if(x > 0) Image[2][0] = *(nex_src_line + x-1); Image[2][1] = *(nex_src_line + x); if(x < Width-1) Image[2][2] = *(nex_src_line + x+1); } Ix = 0; Iy = 0; for(int cnt1 = 0 ; cnt1 < 3; cnt1++){ for(int cnt2 = 0 ; cnt2 < 3; cnt2++){ Ix += Image[cnt1][cnt2]*Mask_dx[2-cnt1][2-cnt2]; Iy += Image[cnt1][cnt2]*Mask_dy[2-cnt1][2-cnt2]; } } ConvDstArray_dx2[y][x] = Ix*Ix; ConvDstArray_dy2[y][x] = Iy*Iy; ConvDstArray_dxy[y][x] = Ix*Iy; } } SrcImage->StopScanLine(); END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::Gaussian_2D_Convolution(int** ConvDstArray_x, int** ConvDstArray_y, int** ConvDstArray_xy, const int Height, const int Width, float** GaussianDstArray_x, float** GaussianDstArray_y, float** GaussianDstArray_xy) { BEGIN_LOG(""); int row,column; int x,y; float Value_x, Value_y, Value_xy; const float Gaussian_mask[12][12] = { {0 , 0.0001 , 0.0002 , 0.0004 , 0.0007 , 0.0009 , 0.0009 , 0.0007 , 0.0004 , 0.0002 , 0.0001 , 0} , {0.0001 , 0.0003 , 0.0007 , 0.0015 , 0.0024 , 0.0031 , 0.0031 , 0.0024 , 0.0015 , 0.0007 , 0.0003 , 0.0001} , {0.0002 , 0.0007 , 0.0019 , 0.004 , 0.0065 , 0.0084 , 0.0084 , 0.0065 , 0.004 , 0.0019 , 0.0007 , 0.0002} , {0.0004 , 0.0015 , 0.004 , 0.0084 , 0.0138 , 0.0177 , 0.0177 , 0.0138 , 0.0084 , 0.004 , 0.0015 , 0.0004} , {0.0007 , 0.0024 , 0.0065 , 0.0138 , 0.0228 , 0.0293 , 0.0293 , 0.0228 , 0.0138 , 0.0065 , 0.0024 , 0.0007} , {0.0009 , 0.0031 , 0.0084 , 0.0177 , 0.0293 , 0.0376 , 0.0376 , 0.0293 , 0.0177 , 0.0084 , 0.0031 , 0.0009} , {0.0009 , 0.0031 , 0.0084 , 0.0177 , 0.0293 , 0.0376 , 0.0376 , 0.0293 , 0.0177 , 0.0084 , 0.0031 , 0.0009} , {0.0007 , 0.0024 , 0.0065 , 0.0138 , 0.0228 , 0.0293 , 0.0293 , 0.0228 , 0.0138 , 0.0065 , 0.0024 , 0.0007} , {0.0004 , 0.0015 , 0.004 , 0.0084 , 0.0138 , 0.0177 , 0.0177 , 0.0138 , 0.0084 , 0.004 , 0.0015 , 0.0004} , {0.0002 , 0.0007 , 0.0019 , 0.004 , 0.0065 , 0.0084 , 0.0084 , 0.0065 , 0.004 , 0.0019 , 0.0007 , 0.0002} , {0.0001 , 0.0003 , 0.0007 , 0.0015 , 0.0024 , 0.0031 , 0.0031 , 0.0024 , 0.0015 , 0.0007 , 0.0003 , 0.0001} , {0 , 0.0001 , 0.0002 , 0.0004 , 0.0007 , 0.0009 , 0.0009 , 0.0007 , 0.0004 , 0.0002 , 0.0001 , 0} }; for(y = 0 ; y < Height ; y++){ ProgressForm->Ratio = 0.2 + 0.2*(y/Height); for(x = 0 ; x < Width ; x++){ Value_x = 0; Value_y = 0; Value_xy = 0; if(ConvDstArray_x[y][x] == 0 && ConvDstArray_y[y][x] == 0 && ConvDstArray_xy[y][x] == 0){ GaussianDstArray_x[y][x] = 0; GaussianDstArray_y[y][x] = 0; GaussianDstArray_xy[y][x] = 0; continue; } for(row = 0 ; row < 12 ; row++){ if((y-6+row) < 0 || (y-6+row) > Height-1) continue; for(column = 0 ; column < 12 ; column++){ if((x-6+column) < 0 || (x-6+column) > Width-1) continue; Value_x += ConvDstArray_x[y-6+row][x-6+column] * Gaussian_mask[11-row][11-column]; Value_y += ConvDstArray_y[y-6+row][x-6+column] * Gaussian_mask[11-row][11-column]; Value_xy += ConvDstArray_xy[y-6+row][x-6+column] * Gaussian_mask[11-row][11-column]; } } GaussianDstArray_x[y][x] = Value_x; GaussianDstArray_y[y][x] = Value_y; GaussianDstArray_xy[y][x] = Value_xy; } } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::HarrisOperator(TUnionBitmap* SrcImage) { BEGIN_LOG(""); TUnionBitmap *Temporary_Gray; const int Height = SrcImage->Height; const int Width = SrcImage->Width; DPOINT point; ofstream f; // Corner È®ÀÎ À§ÇØ txt ÆÄÀÏ Ãâ·Â Temporary_Gray = new TUnionBitmap; Temporary_Gray->Create(Width, Height, 8); Temporary_Gray->FillRect(Rect(0, 0, Width, Height), 0); int** ConvDstArray_dx = new int*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray_dx[cnt] = new int[Width]; } int** ConvDstArray_dy = new int*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray_dy[cnt] = new int[Width]; } int** ConvDstArray_dx2 = new int*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray_dx2[cnt] = new int[Width]; } int** ConvDstArray_dy2 = new int*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray_dy2[cnt] = new int[Width]; } int** ConvDstArray_dxy = new int*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray_dxy[cnt] = new int[Width]; } float** ConvDstArray2_dx = new float*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray2_dx[cnt] = new float[Width]; } float** ConvDstArray2_dy = new float*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray2_dy[cnt] = new float[Width]; } float** ConvDstArray2_dxy = new float*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ ConvDstArray2_dxy[cnt] = new float[Width]; } float** HarrisArray = new float*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ HarrisArray[cnt] = new float[Width]; } float** AfterOrdfilterArray = new float*[Height]; for(int cnt = 0 ; cnt < Height ; cnt++){ AfterOrdfilterArray[cnt] = new float[Width]; } ConvertToGrayScale(SrcImage, Temporary_Gray); Mask_2D_Convolution(Temporary_Gray, ConvDstArray_dx2, ConvDstArray_dy2, ConvDstArray_dxy); Gaussian_2D_Convolution(ConvDstArray_dx2, ConvDstArray_dy2, ConvDstArray_dxy, Height, Width, ConvDstArray2_dx, ConvDstArray2_dy, ConvDstArray2_dxy); // ProgressForm->Ratio = 0.4; Det_Trace_CalculatedArray(ConvDstArray2_dx, ConvDstArray2_dy, ConvDstArray2_dxy, Height, Width, HarrisArray); OrdfilterArray(HarrisArray, Height, Width, AfterOrdfilterArray); // CornerPointList.clear(); //f.open("C:\\VectorHarris.txt"); // Corner È®ÀÎ À§ÇØ txt ÆÄÀÏ Ãâ·Â // ¿ì¼± ¸ð¼­¸® 2 Çȼ¿¾¿ ¸¸Å­Àº CornerDetect¿¡¼­ »«´Ù. for(int row = 2 ; row < Height-2 ; row++){ for(int column = 2 ; column < Width-2 ; column++){ if(AfterOrdfilterArray[row][column]){ point.x = column; point.y = row; CornerPointList.push_back(point); //f<<"Point: "< max) max = HarrisArray[row][column]; } } for(row = 0 ; row < Height ; row++){ for(column = 0 ; column < Width ; column++){ if(max!=0) HarrisArray[row][column] = (1000/max)*HarrisArray[row][column]; } } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::OrdfilterArray(float** HarrisArray, const int Height, const int Width, float** AfterOrdfilterArray) { BEGIN_LOG(""); int r = 6; int size = 2*r + 1; int row, column; int i,j; // ÇöÀç¹öÀü¿¡¼­´Â ¸éµû±â¿¡¼­ Thrshold Àû¿ë ¾ÈÇÔ. ³ªÁß¿¡ Ȥ½Ã Ç®¶§¸¦ ´ëºñÇÏ¿© // int Thrshold; if(!ImageMode) Thrshold = 500; // ¼±µû±â else Thrshold = 500; // ¸éµû±â int ratio = 3; // ¼±µû±â //int ratio = 13; // ¸éµû±â int cnt = 0; bool out = false; for(row = 0 ; row < Height ; row++){ for(column = 0 ; column < Width ; column++){ AfterOrdfilterArray[row][column] = 0; } } for(row = 0 ; row < Height ; row++){ ProgressForm->Ratio = 0.2 + 0.1*(row/Height); for(column = 0 ; column < Width ; column++){ if(HarrisArray[row][column] == 0) continue; out = false; for(i = 0 ; i < ratio ; i++){ if(row-(ratio/2)+i < 0 || row-(ratio/2)+i > Height-1) continue; if(out) break; for(j = 0 ; j < ratio ; j++){ if(column-(ratio/2)+j < 0 || column-(ratio/2)+j > Width-1) continue; if(HarrisArray[row][column] < HarrisArray[row-(ratio/2)+i][column-(ratio/2)+j]){ out = true; break; } } } if(out) AfterOrdfilterArray[row][column] = 0; else if(HarrisArray[row][column] < Thrshold) AfterOrdfilterArray[row][column] = 0; else AfterOrdfilterArray[row][column] = HarrisArray[row][column] ; } } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::FindCloseCornerPoint(DPOINT& EndPoint) { BEGIN_LOG(""); list::iterator iter_CrossPoint = CrossPointList.begin(); float pre_dis = 100; for(int cnt = 0 ; cnt < NumberOfCross ; cnt++, iter_CrossPoint++){ float dis_square = ((EndPoint.x - iter_CrossPoint->x) * (EndPoint.x - iter_CrossPoint->x) + (EndPoint.y - iter_CrossPoint->y) * (EndPoint.y - iter_CrossPoint->y)); float now_dis = sqrt(dis_square); if(now_dis < 3 && pre_dis > now_dis){ EndPoint.x = iter_CrossPoint->x; EndPoint.y = iter_CrossPoint->y; pre_dis = now_dis; } } END_LOG; } //--------------------------------------------------------------------------- void __fastcall ImageVectorizer::FindCloseCornerPoint2(DPOINT& EndPoint) { BEGIN_LOG(""); list::iterator iter_CornerPoint = CornerPointList.begin(); float pre_dis = 100; int NumberOfCorner = CornerPointList.size(); for(int cnt = 0 ; cnt < NumberOfCorner ; cnt++, iter_CornerPoint++){ float dis_square = ((EndPoint.x - iter_CornerPoint->x) * (EndPoint.x - iter_CornerPoint->x) + (EndPoint.y - iter_CornerPoint->y) * (EndPoint.y - iter_CornerPoint->y)); float now_dis = sqrt(dis_square); if(now_dis < 2.5 && pre_dis > now_dis){ EndPoint.x = iter_CornerPoint->x; EndPoint.y = iter_CornerPoint->y; pre_dis = now_dis; } } END_LOG; } //---------------------------------------------------------------------------