#include "ImgView.h" #include "iScissor.h" ImgView::ImgView(int x, int y, int w, int h, const char *label) : Fl_Double_Window(x,y,w,h,label) { imgBuf = NULL; origImg = NULL; curImg = NULL; curImgChar = NULL; imgBuf = NULL; imgLeft = 0; imgTop = 0; fltDesignUI = new FltDesignUI; fltDesignUI->imgView = this; int i; for (i=0;iimage->value(1); fltDesignUI->selection->value(0); scissorPanelUI = new ScissorPanelUI(); scissorPanelUI->imgView = this; scissorPanelUI->expanded->range(0,0); scissorPanelUI->expanded->value(0); scissorPanelUI->expanded->deactivate(); brushSelection = NULL; brushType = ROUND_BRUSH; brushSize = 20; brushRadius2 = brushSize*brushSize; brushOpacity = 0.5; brushConfigUI = new BrushConfigUI; brushConfigUI->imgView = this; brushConfigUI->round->value(1); brushConfigUI->square->value(0); brushConfigUI->brushSize->range(1,2*brushSize); brushConfigUI->brushSize->value(brushSize); brushConfigUI->brushOpacity->value(brushOpacity); helpPageUI = new HelpPageUI(); char helpInfo[2048]; my_img_filter(helpInfo); helpPageUI->helpText->value(helpInfo); helpPageUI->mainWindow->resizable(helpPageUI->helpText); } void ImgView::FreeBuffer(void) { if (imgBuf) { delete[] origImg; delete[] imgBuf; delete[] brushSelection; delete[] costGraph; delete[] pixelNodes; delete[] viewBuf; delete[] nodeBuf; origImg = NULL; imgBuf = NULL; brushSelection = NULL; costGraph = NULL; pixelNodes = NULL; viewBuf = NULL; nodeBuf = NULL; int i; for (i=0;iFreePtrs(); } contours.FreePtrs(); currentCntr.FreePtrs(); } } void ImgView::HideAll(void) { fltDesignUI->hide(); brushConfigUI->hide(); scissorPanelUI->hide(); } ImgView::~ImgView() { FreeBuffer(); // delete fltDesignUI; delete brushConfigUI; delete helpPageUI; delete scissorPanelUI; } void ImgView::OpenImage(void) { char *filename = fl_file_chooser("choose a targa file", "*.tga", 0); if (filename) { OpenImage(filename); } } void ImgView::OpenImage(const char *filename) { int i,j; FreeBuffer(); CByteImage rick; ReadFile(rick,filename); imgWidth = rick.Shape().width; imgHeight = rick.Shape().height; graphWidth = imgWidth * 3; graphHeight = imgHeight * 3; int numNodes = imgWidth * imgHeight; int imgSize = imgWidth * imgHeight * 3; int graphSize = graphWidth * graphHeight * 3; brushSelection = new unsigned char[numNodes]; memset(brushSelection,0,numNodes*sizeof(unsigned char)); origImg = new unsigned char [imgSize]; curImg = new double [imgSize]; curImgChar = new unsigned char [imgSize]; imgBuf = new unsigned char [imgSize]; costGraph = new unsigned char [graphSize]; pixelNodes = new unsigned char [graphSize]; for (j=0;jw(),this->h()); drawMode = IMAGE_WITH_CONTOUR; scissorPanelUI->contour->value(1); scissorPanelUI->expanded->range(0,imgWidth*imgHeight); scissorPanelUI->expanded->lstep(imgWidth*imgHeight/10); scissorPanelUI->expanded->value(imgWidth*imgHeight); scissorPanelUI->expanded->deactivate(); brushSelPtr = NULL; scissorPanelUI->whole->value(1); UpdateViewBuffer(); redraw(); } void ImgView::SaveContour(void) { char *filename = fl_file_chooser("choose a targa file", "*.tga", 0); if (filename) { SaveContour(filename); } } void ImgView::SaveContour(const char *filename) { CByteImage rick(imgWidth, imgHeight, 3); int i,j; //our buffer is in R, G, B order from top to bottom and from left to right; //Rick's .tga file format is in B,G,R order from bottom to top and from left to right; for (j=0;j *seedEle = contours[k]->GetHeadPtr(); while (!contours[k]->IsSentinel(seedEle)) { Seed *seed = seedEle->Data(); int x = seed->x; int y = imgHeight-1-seed->y; rick.Pixel(x,y,0) = PATH_COLOR[2]; rick.Pixel(x,y,1) = PATH_COLOR[1]; rick.Pixel(x,y,2) = PATH_COLOR[0]; seedEle = seedEle->Next(); } } WriteFile(rick,filename); } void ImgView::SaveMask(void) { char *filename = fl_file_chooser("choose a targa file", "*.tga", 0); if (filename) { SaveMask(filename); } } void ImgView::SaveMask(const char *filename) { CByteImage rick(imgWidth, imgHeight, 3); unsigned char *maskBuf = new unsigned char [3*imgWidth*imgHeight]; memset(maskBuf,0,3*imgWidth*imgHeight*sizeof(unsigned char)); int i,j,k; unsigned char *cntrBuf = new unsigned char [3*imgWidth*imgHeight]; for (k=0;kIsCircular()) { memset(cntrBuf,0,3*imgWidth*imgHeight*sizeof(unsigned char)); CTypedPtrDblElement *seedEle = contours[k]->GetHeadPtr(); Seed *seed = seedEle->Data(); int lastRow = seed->y; int lastCol = seed->x; int bufIndex; seedEle = seedEle->Next(); while (!contours[k]->IsSentinel(seedEle)) { seed = seedEle->Data(); if (lastRowy) { bufIndex = 3*(lastRow*imgWidth+lastCol); cntrBuf[bufIndex+0]++; cntrBuf[bufIndex+1]++; cntrBuf[bufIndex+2]++; lastRow = seed->y; lastCol = seed->x; } else if (lastRow>seed->y) { bufIndex = 3*(seed->y*imgWidth+seed->x); cntrBuf[bufIndex+0]++; cntrBuf[bufIndex+1]++; cntrBuf[bufIndex+2]++; lastRow = seed->y; lastCol = seed->x; } seedEle = seedEle->Next(); } for (j=0;jGetHeadPtr(); while (!contours[k]->IsSentinel(seedEle)) { seed = seedEle->Data(); bufIndex = 3*(seed->y*imgWidth+seed->x); maskBuf[bufIndex+0] = maskBuf[bufIndex+1] = maskBuf[bufIndex+2] = 255; seedEle = seedEle->Next(); } } } delete[] cntrBuf; //our buffer is in R, G, B order from top to bottom and from left to right; //Rick's .tga file format is in B,G,R order from bottom to top and from left to right; for (j=0;jshow(); //cout<<"try filter!"<hide(); //cout<<"stop filter!"<ele0->value(fltKernel[0]); fltDesignUI->ele1->value(fltKernel[1]); fltDesignUI->ele2->value(fltKernel[2]); fltDesignUI->ele3->value(fltKernel[3]); fltDesignUI->ele4->value(fltKernel[4]); fltDesignUI->ele5->value(fltKernel[5]); fltDesignUI->ele6->value(fltKernel[6]); fltDesignUI->ele7->value(fltKernel[7]); fltDesignUI->ele8->value(fltKernel[8]); fltDesignUI->ele9->value(fltKernel[9]); fltDesignUI->ele10->value(fltKernel[10]); fltDesignUI->ele11->value(fltKernel[11]); fltDesignUI->ele12->value(fltKernel[12]); fltDesignUI->ele13->value(fltKernel[13]); fltDesignUI->ele14->value(fltKernel[14]); fltDesignUI->ele15->value(fltKernel[15]); fltDesignUI->ele16->value(fltKernel[16]); fltDesignUI->ele17->value(fltKernel[17]); fltDesignUI->ele18->value(fltKernel[18]); fltDesignUI->ele19->value(fltKernel[19]); fltDesignUI->ele20->value(fltKernel[20]); fltDesignUI->ele21->value(fltKernel[21]); fltDesignUI->ele22->value(fltKernel[22]); fltDesignUI->ele23->value(fltKernel[23]); fltDesignUI->ele24->value(fltKernel[24]); fltDesignUI->scale->value(scale); fltDesignUI->offset->value(offset); } void ImgView::UpdateFilter() { fltKernel[0] = fltDesignUI->ele0->value(); fltKernel[1] = fltDesignUI->ele1->value(); fltKernel[2] = fltDesignUI->ele2->value(); fltKernel[3] = fltDesignUI->ele3->value(); fltKernel[4] = fltDesignUI->ele4->value(); fltKernel[5] = fltDesignUI->ele5->value(); fltKernel[6] = fltDesignUI->ele6->value(); fltKernel[7] = fltDesignUI->ele7->value(); fltKernel[8] = fltDesignUI->ele8->value(); fltKernel[9] = fltDesignUI->ele9->value(); fltKernel[10] = fltDesignUI->ele10->value(); fltKernel[11] = fltDesignUI->ele11->value(); fltKernel[12] = fltDesignUI->ele12->value(); fltKernel[13] = fltDesignUI->ele13->value(); fltKernel[14] = fltDesignUI->ele14->value(); fltKernel[15] = fltDesignUI->ele15->value(); fltKernel[16] = fltDesignUI->ele16->value(); fltKernel[17] = fltDesignUI->ele17->value(); fltKernel[18] = fltDesignUI->ele18->value(); fltKernel[19] = fltDesignUI->ele19->value(); fltKernel[20] = fltDesignUI->ele20->value(); fltKernel[21] = fltDesignUI->ele21->value(); fltKernel[22] = fltDesignUI->ele22->value(); fltKernel[23] = fltDesignUI->ele23->value(); fltKernel[24] = fltDesignUI->ele24->value(); scale = fltDesignUI->scale->value(); offset = fltDesignUI->offset->value(); // printf("update filter\n"); } void ImgView::Filter(void) { if (imgBuf) { unsigned char *range = NULL; if (fltDesignUI->selection->value()) { range = brushSelection; } image_filter(curImg, origImg, range, imgWidth, imgHeight, fltKernel, FLT_WIDTH, FLT_HEIGHT, scale, offset); } } void ImgView::TryBrush(void) { brushConfigUI->show(); } void ImgView::UpdateBrushConfig(void) { if (brushConfigUI->round->value()) { brushType = ROUND_BRUSH; } else if (brushConfigUI->square->value()) { brushType = SQUARE_BRUSH; } brushSize = (int)brushConfigUI->brushSize->value(); brushOpacity = brushConfigUI->brushOpacity->value(); brushRadius2 = brushSize * brushSize; //printf("brush size %d\n",brushSize); if (imgBuf) { UpdateImgBufOpacity(); if (drawMode == IMAGE_ONLY || drawMode == IMAGE_WITH_CONTOUR) { UpdateViewBuffer(); redraw(); } } } void ImgView::CleanBrushSelection(void) { if (imgBuf) { memset(brushSelection,0,imgWidth*imgHeight*sizeof(unsigned char)); UpdateImgBufOpacity(); if (drawMode == IMAGE_ONLY || drawMode == IMAGE_WITH_CONTOUR) { UpdateViewBuffer(); redraw(); } } } void ImgView::BrushSelection(int b) { int invalid_tree = 0; if (!b&&brushSelPtr==brushSelection) { brushSelPtr = NULL; invalid_tree = 1; } else if (b&&brushSelPtr==NULL) { brushSelPtr = brushSelection; invalid_tree = 1; } if (invalid_tree&&imgBuf) { if (currentCntr.GetCount()) { Seed *seed = currentCntr.GetTailPtr()->Data(); int col = seed->x; int row = seed->y; int seedIndex = row*imgWidth+col; if (brushSelPtr==brushSelection && !brushSelection[seedIndex]) { printf("current seed ( %d , %d ) is out of brush selected range!\n",col,row); } int expanded = imgWidth*imgHeight; if (scissorPanelUI->expanded->active()) { expanded = (int)scissorPanelUI->expanded->value(); } LiveWireDP(col, row, nodeBuf, imgWidth, imgHeight, brushSelPtr, expanded); printf("minimun path tree is finished\n"); UpdateViewBuffer(); redraw(); } } } void ImgView::UpdateImgBufOpacity(void) { int i,j; for (j=0;jshow(); } void ImgView::OrigImage(void) { if (drawMode!=IMAGE_ONLY) { if (drawMode == GRAPH_WITH_TREE) { UpdatePathTree(); } drawMode = IMAGE_ONLY; if (imgBuf) { UpdateViewBuffer(); redraw(); } } scissorPanelUI->expanded->deactivate(); } void ImgView::ShowContour(void) { if (drawMode!=IMAGE_WITH_CONTOUR) { if (drawMode == GRAPH_WITH_TREE) { UpdatePathTree(); } drawMode = IMAGE_WITH_CONTOUR; if (imgBuf) { UpdateViewBuffer(); redraw(); } } scissorPanelUI->expanded->deactivate(); } void ImgView::PixelColor(void) { if (drawMode!= GRAPH_WITH_COLOR) { if (drawMode == GRAPH_WITH_TREE) { UpdatePathTree(); } drawMode = GRAPH_WITH_COLOR; if (imgBuf) { UpdateViewBuffer(); redraw(); } } scissorPanelUI->expanded->deactivate(); } void ImgView::CostGraph(void) { if (drawMode!= GRAPH_WITH_COST) { if (drawMode == GRAPH_WITH_TREE) { UpdatePathTree(); } drawMode = GRAPH_WITH_COST; if (imgBuf) { UpdateViewBuffer(); redraw(); } } scissorPanelUI->expanded->deactivate(); } void ImgView::PathTree(void) { if (drawMode!=GRAPH_WITH_TREE) { drawMode = GRAPH_WITH_TREE; if (imgBuf) { PartialExpanding(); } scissorPanelUI->expanded->activate(); } } void ImgView::MinPath(void) { if (drawMode!=GRAPH_WITH_PATH) { if (drawMode == GRAPH_WITH_TREE) { UpdatePathTree(); } drawMode = GRAPH_WITH_PATH; if (imgBuf) { UpdateViewBuffer(); redraw(); } } scissorPanelUI->expanded->deactivate(); } void ImgView::PartialExpanding(void) { int expanded = (int)scissorPanelUI->expanded->value(); if (imgBuf) { if (currentCntr.GetCount()) { Seed *seed = currentCntr.GetTailPtr()->Data(); int col = seed->x; int row = seed->y; int seedIndex = row*imgWidth+col; if (brushSelPtr==brushSelection && !brushSelection[seedIndex]) { printf("current seed ( %d , %d ) is out of brush selected range!\n",col,row); } LiveWireDP(col, row, nodeBuf, imgWidth, imgHeight, brushSelPtr, expanded); freePtX = (x()-zoomPort[0])/zoomFactor+targetPort[0]; freePtX /= 3; freePtY = (y()-zoomPort[2])/zoomFactor+targetPort[2]; freePtY /= 3; printf("minimun path tree is finished\n"); } UpdateViewBuffer(); redraw(); } } void ImgView::UpdatePathTree(void) { if (imgBuf && currentCntr.GetCount()) { Seed *seed = currentCntr.GetTailPtr()->Data(); int col = seed->x; int row = seed->y; int seedIndex = row*imgWidth+col; if (brushSelPtr == brushSelection && !brushSelection[seedIndex]) { printf("current seed ( %d , %d ) is out of brush selected range!\n",col,row); } LiveWireDP(col, row, nodeBuf, imgWidth, imgHeight, brushSelPtr, imgWidth*imgHeight); printf("minimun path tree is finished\n"); } } void ImgView::MarkPath(int col, int row, const unsigned char clr[3]) { if (drawMode == IMAGE_WITH_CONTOUR) { /* CTypedPtrDblList path; MinimumPath(&path,col,row,nodeBuf,imgWidth,imgHeight); path.RemoveHead(); while(path */ int freePtIndex = row * imgWidth + col; Node *node = nodeBuf+freePtIndex; int imgX = col; int imgY = row; if (IsPtInRect(imgX,imgY,targetPort)) { int viewPixelTop = (imgY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (imgX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nprevNode) { node = node->prevNode; imgX = node->column; imgY = node->row; if (IsPtInRect(imgX,imgY,targetPort)) { int viewPixelTop = (imgY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (imgX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nprevNode) { node = node->prevNode; imgX = node->column; imgY = node->row; graphX = 3*imgX+1; graphY = 3*imgY+1; if (IsPtInRect(graphX,graphY,targetPort)) { int viewPixelTop = (graphY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nprevNode) { node = node->prevNode; imgX = node->column; imgY = node->row; imgPixel = imgBuf + 3*(imgY*imgWidth+imgX); if (IsPtInRect(imgX,imgY,targetPort)) { int viewPixelTop = (imgY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (imgX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nprevNode) { node = node->prevNode; imgX = node->column; imgY = node->row; imgPixel = imgBuf + 3*(imgY*imgWidth+imgX); graphX = 3*imgX+1; graphY = 3*imgY+1; if (IsPtInRect(graphX,graphY,targetPort)) { int viewPixelTop = (graphY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;n *cntr, const unsigned char clr[3]) { if (drawMode == IMAGE_WITH_CONTOUR) { CTypedPtrDblElement *seedEle = cntr->GetHeadPtr(); while (!cntr->IsSentinel(seedEle)) { Seed *seed = seedEle->Data(); int imgX = seed->x; int imgY = seed->y; if (IsPtInRect(imgX,imgY,targetPort)) { int viewPixelTop = (imgY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (imgX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nNext(); } } else if (drawMode == GRAPH_WITH_PATH) { CTypedPtrDblElement *seedEle = cntr->GetHeadPtr(); while (!cntr->IsSentinel(seedEle)) { Seed *seed = seedEle->Data(); int imgX = seed->x; int imgY = seed->y; int graphX = 3*imgX+1; int graphY = 3*imgY+1; if (IsPtInRect(graphX,graphY,targetPort)) { int viewPixelTop = (graphY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nNext(); } } } void ImgView::UnMarkPath(const CTypedPtrDblList *cntr) { if (drawMode == IMAGE_WITH_CONTOUR) { CTypedPtrDblElement *seedEle = cntr->GetHeadPtr(); while (!cntr->IsSentinel(seedEle)) { Seed *seed = seedEle->Data(); int imgX = seed->x; int imgY = seed->y; const unsigned char *imgPixel = imgBuf + 3*(imgY*imgWidth+imgX); if (IsPtInRect(imgX,imgY,targetPort)) { int viewPixelTop = (imgY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (imgX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nNext(); } } else if (drawMode == GRAPH_WITH_PATH) { CTypedPtrDblElement *seedEle = cntr->GetHeadPtr(); while (!cntr->IsSentinel(seedEle)) { Seed *seed = seedEle->Data(); int imgX = seed->x; int imgY = seed->y; const unsigned char *imgPixel = imgBuf + 3*(imgY*imgWidth+imgX); int graphX = 3*imgX+1; int graphY = 3*imgY+1; if (IsPtInRect(graphX,graphY,targetPort)) { int viewPixelTop = (graphY-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphX-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nNext(); } } } void ImgView:: MarkCurrentContour(void) { MarkPath(¤tCntr,SELECTED_PATH_COLOR); } void ImgView:: MarkPreviousContour(void) { for (int i=0;iprevNode) if (node->state == EXPANDED || node->state == ACTIVE) { Node *prevNode = node->prevNode; if (prevNode) { int prevNodeCol = prevNode->column; int prevNodeRow = prevNode->row; int graphCol[2], graphRow[2]; if (prevNodeColcolumn) { graphCol[0] = 3*node->column; graphCol[1] = 3*node->column-1; } else if (prevNodeCol>node->column) { graphCol[0] = 3*node->column+2; graphCol[1] = 3*node->column+3; } else { graphCol[0] = 3*node->column+1; graphCol[1] = 3*node->column+1; } if (prevNodeRowrow) { graphRow[0] = 3*node->row; graphRow[1] = 3*node->row-1; } else if (prevNodeRow>node->row) { graphRow[0] = 3*node->row+2; graphRow[1] = 3*node->row+3; } else { graphRow[0] = 3*node->row+1; graphRow[1] = 3*node->row+1; } for (int k = 0; k<2; k++) { if (IsPtInRect(graphCol[k], graphRow[k], targetPort)) { int viewPixelTop = (graphRow[k]-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphCol[k]-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;n>k); viewCol[1] = (TREE_COLOR[1]>>k); viewCol[2] = (TREE_COLOR[2]>>k); viewCol += 3; } viewRow += 3*viewWidth; } } } } int gRow = 3*node->row+1; int gCol = 3*node->column+1; if (IsPtInRect(gCol, gRow, targetPort)) { int viewPixelTop = (gRow-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (gCol-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;nstate == EXPANDED) { viewCol[0] = EXPANDED_COLOR[0]; viewCol[1] = EXPANDED_COLOR[1]; viewCol[2] = EXPANDED_COLOR[2]; } else { viewCol[0] = ACTIVE_COLOR[0]; viewCol[1] = ACTIVE_COLOR[1]; viewCol[2] = ACTIVE_COLOR[2]; } viewCol += 3; } viewRow += 3*viewWidth; } } } } } } void ImgView::MarkPathOnTree(int col, int row) { int nodeIndex = row*imgWidth+col; Node *node = nodeBuf+nodeIndex; while (node->prevNode) { Node *prevNode = node->prevNode; int prevNodeCol = prevNode->column; int prevNodeRow = prevNode->row; int graphCol[2], graphRow[2]; if (prevNodeColcolumn) { graphCol[0] = 3*node->column; graphCol[1] = 3*node->column-1; } else if (prevNodeCol>node->column) { graphCol[0] = 3*node->column+2; graphCol[1] = 3*node->column+3; } else { graphCol[0] = 3*node->column+1; graphCol[1] = 3*node->column+1; } if (prevNodeRowrow) { graphRow[0] = 3*node->row; graphRow[1] = 3*node->row-1; } else if (prevNodeRow>node->row) { graphRow[0] = 3*node->row+2; graphRow[1] = 3*node->row+3; } else { graphRow[0] = 3*node->row+1; graphRow[1] = 3*node->row+1; } for (int k = 0; k<2; k++) { if (IsPtInRect(graphCol[k], graphRow[k], targetPort)) { int viewPixelTop = (graphRow[k]-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphCol[k]-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;n>k); viewCol[1] = (SELECTED_PATH_COLOR[1]>>k); viewCol[2] = (SELECTED_PATH_COLOR[2]>>k); viewCol += 3; } viewRow += 3*viewWidth; } } } node = prevNode; } } void ImgView::UnMarkPathOnTree(int col, int row) { int nodeIndex = row*imgWidth+col; Node *node = nodeBuf+nodeIndex; while (node->prevNode) { Node *prevNode = node->prevNode; int prevNodeCol = prevNode->column; int prevNodeRow = prevNode->row; int graphCol[2], graphRow[2]; if (prevNodeColcolumn) { graphCol[0] = 3*node->column; graphCol[1] = 3*node->column-1; } else if (prevNodeCol>node->column) { graphCol[0] = 3*node->column+2; graphCol[1] = 3*node->column+3; } else { graphCol[0] = 3*node->column+1; graphCol[1] = 3*node->column+1; } if (prevNodeRowrow) { graphRow[0] = 3*node->row; graphRow[1] = 3*node->row-1; } else if (prevNodeRow>node->row) { graphRow[0] = 3*node->row+2; graphRow[1] = 3*node->row+3; } else { graphRow[0] = 3*node->row+1; graphRow[1] = 3*node->row+1; } for (int k = 0; k<2; k++) { if (IsPtInRect(graphCol[k], graphRow[k], targetPort)) { int viewPixelTop = (graphRow[k]-targetPort[2])*zoomFactor+zoomPort[2]; int viewPixelLeft = (graphCol[k]-targetPort[0])*zoomFactor+zoomPort[0]; unsigned char *viewRow = viewBuf + 3*(viewPixelTop*viewWidth+viewPixelLeft); for (int n = 0;n>k); viewCol[1] = (TREE_COLOR[1]>>k); viewCol[2] = (TREE_COLOR[2]>>k); viewCol += 3; } viewRow += 3*viewWidth; } } } node = prevNode; } } void ImgView::AppendCurrentContour(int col,int row) { // unnecessary way, but to check students' codes. CTypedPtrDblList path; MinimumPath(&path,col,row,nodeBuf,imgWidth,imgHeight); if (path.GetCount()>1) { Node *node = path.RemoveTail(); int imgX = node->column; int imgY = node->row; CTypedPtrDblElement *seedEle = currentCntr.AddTail(new Seed(imgX,imgY,1)); while(path.GetCount()>1) { node = path.RemoveTail(); int imgX = node->column; int imgY = node->row; seedEle = currentCntr.AddPrev(seedEle, new Seed(imgX,imgY,0)); } } } void ImgView::FinishCurrentContour(int col,int row) { AppendCurrentContour(col,row); currentCntr.SetCircular(0); } void ImgView::FinishCurrentContour(void) { Seed *seed = currentCntr.GetHeadPtr()->Data(); AppendCurrentContour(seed->x,seed->y); //currentCntr.RemoveTail(); currentCntr.SetCircular(1); } void ImgView::CommitCurrentContour() { CTypedPtrDblList *newCntr = new CTypedPtrDblList ; while(!currentCntr.IsEmpty()) { newCntr->AddTail(currentCntr.RemoveTail()); } newCntr->SetCircular(currentCntr.IsCircular()); contours.AddTail(newCntr); } void ImgView::ChopLastSeed(void) { currentCntr.RemoveTail(); CTypedPtrDblElement *seedEle = currentCntr.GetTailPtr(); while (!currentCntr.IsSentinel(seedEle) && seedEle->Data()->seed == 0) { delete seedEle->Data(); seedEle = seedEle->Prev(); currentCntr.RemoveTail(); } } int ImgView::IsPtAroundContour(int x, int y, const CTypedPtrDblList *cntr) const { CTypedPtrDblElement *seedEle = cntr->GetHeadPtr(); while (!cntr->IsSentinel(seedEle)) { Seed *seed = seedEle->Data(); if (abs(seed->x-x)+abs(seed->y-y)<8) return 1; seedEle = seedEle->Next(); } return 0; } void ImgView::AllocateViewBuffer(int w, int h) { viewWidth = w; viewHeight = h; viewBuf = new unsigned char [w*h*3]; } void ImgView::UpdateViewPort(int bufLeft, int bufTop, int bufWidth, int bufHeight) { int viewPort[4] = { -((viewWidth/2)/zoomFactor), (viewWidth-viewWidth/2)/zoomFactor, -((viewHeight/2)/zoomFactor), (viewHeight-(viewHeight/2))/zoomFactor }; int bufPort[4] = { bufLeft, bufLeft+bufWidth, bufTop, bufTop+bufHeight }; int interPort[4]; RectIntersection(interPort, bufPort, viewPort); targetPort[0] = interPort[0] - bufLeft; targetPort[1] = interPort[1] - bufLeft; targetPort[2] = interPort[2] - bufTop; targetPort[3] = interPort[3] - bufTop; zoomPort[0] = interPort[0] * zoomFactor + viewWidth/2; zoomPort[1] = interPort[1] * zoomFactor + viewWidth/2; zoomPort[2] = interPort[2] * zoomFactor + viewHeight/2; zoomPort[3] = interPort[3] * zoomFactor + viewHeight/2; } void ImgView::UpdateViewBuffer(const unsigned char *origBuf, int bufLeft, int bufTop, int bufWidth, int bufHeight) { if (imgBuf==NULL) return; UpdateViewPort(bufLeft, bufTop, bufWidth, bufHeight); //copy origBuf, targetPort //to viewBuf, zoomPort //each orig Pixel expands by zoomFactor*zoomFactor //other pixels are BK_COLOR; int i,j; unsigned char *zb = viewBuf; if (zoomPort[0]value(info); if (imgBuf) { if (drawMode == IMAGE_WITH_CONTOUR) { int col = (x-zoomPort[0])/zoomFactor+targetPort[0]; int row = (y-zoomPort[2])/zoomFactor+targetPort[2]; if (IsPtInRect(col,row,targetPort)) { if (currentCntr.GetCount()) { UnMarkPath(freePtX,freePtY); MarkAllContour(col, row); freePtX = col; freePtY = row; redraw(); } else { for (int k = 0;k 1) { zoomFactor --; UpdateViewBuffer(); redraw(); } return 1; } else if (Fl::event_key(FL_Enter)) { if (drawMode == IMAGE_WITH_CONTOUR && currentCntr.GetCount()) { int col = (x-zoomPort[0])/zoomFactor+targetPort[0]; int row = (y-zoomPort[2])/zoomFactor+targetPort[2]; if (IsPtInRect(col,row,targetPort)) { UnMarkPath(freePtX,freePtY); if (Fl::get_key(FL_Control_L)||Fl::get_key(FL_Control_R)) { FinishCurrentContour(); } else { FinishCurrentContour(col,row); } CommitCurrentContour(); selectedCntr = contours.GetSize()-1; MarkAllContour(); redraw(); } } return 1; } else if (Fl::event_key(FL_BackSpace)) { if (drawMode == IMAGE_WITH_CONTOUR) { if (currentCntr.GetCount()) { UnMarkPath(freePtX,freePtY); UnMarkCurrentContour(); ChopLastSeed(); if (currentCntr.GetCount()) { Seed *lastSeed = currentCntr.GetTailPtr()->Data(); int col = lastSeed->x; int row = lastSeed->y; int seedIndex = row*imgWidth+col; if (brushSelPtr == brushSelection && !brushSelection[seedIndex]) { printf("current seed ( %d , %d ) is out of brush selected range!\n",col,row); } LiveWireDP(col, row, nodeBuf, imgWidth, imgHeight, brushSelPtr, imgWidth*imgHeight); freePtX = (x-zoomPort[0])/zoomFactor+targetPort[0]; freePtY = (y-zoomPort[2])/zoomFactor+targetPort[2]; printf("minimun path tree is finished\n"); MarkAllContour(freePtX,freePtY); } else { MarkAllContour(); } redraw(); } else { if (0<=selectedCntr && selectedCntr *oldCntr = contours[selectedCntr]; contours[selectedCntr] = contours[contours.GetSize()-1]; contours.RemoveTail(); oldCntr->FreePtrs(); delete oldCntr; selectedCntr = -1; MarkAllContour(); redraw(); } } } return 1; } else return Fl_Double_Window::handle(c); } else { return Fl_Double_Window::handle(c); } } void ImgView::draw(void) { //fl_rectf(0,0,w(),h(),BK_COLOR[0],BK_COLOR[1],BK_COLOR[2]); if (imgBuf) { fl_draw_image(viewBuf, 0, 0, viewWidth, viewHeight, 3, 0); } else { Fl_Window::draw(); } } void ImgView::AboutMe(void) { helpPageUI->show(); }