#include "StdAfx.h" #include #include "CornerCut.h" #include "EdgeProc.h" #define CORNERIMAGE_PATEH _T("D:\\Image\\LogCorner") #define USE_ADAPTIVETHRESHOLD 0 #define SAVE_IMAGE const double g_dRatio = 0.2; const int g_nContiCnt = 2; CCornerCut::CCornerCut(void) { ZeroMemory(m_nCornerPoint,sizeof(sCoPoint)*3); m_pInsImg = NULL; m_pOuterLineH = m_pOuterLineV = NULL; m_nOuterCountH = m_nOuterCountV = 0; } CCornerCut::~CCornerCut(void) { if(m_pInsImg != NULL) delete[] m_pInsImg, m_pInsImg=NULL; if(m_pOuterLineH != NULL) delete[] m_pOuterLineH, m_pOuterLineH=NULL; if(m_pOuterLineV != NULL) delete[] m_pOuterLineV, m_pOuterLineV=NULL; } ERRCODE_CORNERCUT CCornerCut::Inspection(LPBYTE pImg,CSize szImg,CRect &rectIns,int iFrame,int nLowThres,int nHighThres,CORNERCUR_DIR nDir, CString strHPanelID,BOOL bSaveImage ,COwnerBuffer &pOrg,double &dResWidth,double &dResHeight) { ZeroMemory(m_nCornerPoint,sizeof(CPoint)*3); dResWidth = dResHeight = 0.; if(pImg == NULL) { return ERR_CO_IMAGENULL; } pOrg.SetSize(szImg.cx,szImg.cy); CopyMemory(pOrg.GetDataAddress(),pImg,pOrg.GetDataSize()); AssertOnFrameRect(rectIns,szImg); if(rectIns.Width()*rectIns.Height() <= 0) { return ERR_CO_INSRECTNULL; } if(bSaveImage == TRUE) { CreateDirectory(CORNERIMAGE_PATEH,NULL); CString strFile; CSISBuffer mosis1(pImg, rectIns.Width(), rectIns.Height()); strFile.Format(_T("%s\\%s_OrgImg_%d.bmp"),CORNERIMAGE_PATEH,strHPanelID, iFrame); CBufferAttach attch1(strFile); if(mosis1.IsValidBuffer() == TRUE) attch1.AttachToFile(mosis1); /*CHMBitmap BmpSave; CString strFile; if(rectIns.Width() > 0 && rectIns.Height() > 0) { BmpSave.SetBitmap(pImg, rectIns.Width(), rectIns.Height()); strFile.Format("%s\\%s_OrgImg_%d.bmp",CORNERIMAGE_PATEH,strHPanelID, iFrame); LPBYTE pBuffer = BmpSave.GetBuffer(); if(pBuffer != NULL) BmpSave.SaveBitmapFile(strFile); }*/ } CSISBuffer pBuf(pImg,szImg.cx,szImg.cy); ThresholdProcLowHigh(pBuf,nLowThres,nHighThres); //CEdgeProc EdgeProc; //EdgeProc.ThresholdByIntegralImage(pImg,szImg.cx,szImg.cy,szImg.cx,10,pImg); //EdgeProc.Adaptive_Binarization(pImg,szImg.cx,szImg.cy,szImg.cx,10,0.2,pImg,rectIns); if(bSaveImage == TRUE) { CSISBuffer mosis2(pImg, rectIns.Width(), rectIns.Height()); CString strFile; strFile.Format(_T("%s\\%s_ThresImg_%d.bmp"),CORNERIMAGE_PATEH,strHPanelID, iFrame); CBufferAttach attch2(strFile); if(mosis2.IsValidBuffer() == TRUE) attch2.AttachToFile(mosis2); /*CHMBitmap BmpSave2; if(rectIns.Width() > 0 && rectIns.Height() > 0) { BmpSave2.SetBitmap(pImg, rectIns.Width(), rectIns.Height()); strFile.Format("%s\\%s_ThresImg_%d.bmp",CORNERIMAGE_PATEH,strHPanelID, iFrame); LPBYTE pBuffer = BmpSave2.GetBuffer(); if(pBuffer != NULL) BmpSave2.SaveBitmapFile(strFile); }*/ } int nVertLine,nHorLine; if(FindVerticalLine(pImg,rectIns,nVertLine,nDir) == FALSE) { return ERR_CO_FINDVERT; } if(FindHorizontalLine(pImg,rectIns,nHorLine,nDir) == FALSE) { return ERR_CO_FINDHOR; } m_nCornerPoint[0].x = nVertLine; m_nCornerPoint[0].y = nHorLine; FindCornerPoint(pImg,rectIns,m_nCornerPoint[0],nDir); FindOuterLine(pImg,rectIns,nDir); if(m_nOuterCountH >= 20 && m_nOuterCountV >= 20) { FindFirstPoint(rectIns); } CalculateLenght(dResWidth,dResHeight); if(m_pOuterLineH != NULL) delete[] m_pOuterLineH, m_pOuterLineH=NULL; if(m_pOuterLineV != NULL) delete[] m_pOuterLineV, m_pOuterLineV=NULL; if(pOrg.IsValidBuffer() == TRUE) { CPoint pointDraw[3]; pointDraw[0] = CPoint((int)m_nCornerPoint[0].x,(int)m_nCornerPoint[0].y); pointDraw[1] = CPoint((int)m_nCornerPoint[1].x,(int)m_nCornerPoint[1].y); pointDraw[2] = CPoint((int)m_nCornerPoint[2].x,(int)m_nCornerPoint[2].y); bresenham_Line(&pOrg,pointDraw[0],pointDraw[1],0); bresenham_Line(&pOrg,pointDraw[2],pointDraw[0],0); SaveMarkImage(pOrg.GetDataAddress(0,0),rectIns); // LPBYTE pBuffer = pOrg.GetDataAddress(0,0); // if(pBuffer != NULL) // { // //SaveMarkImage(pBuffer,rectIns); // } } return ERR_CO_SUCCESS; } void CCornerCut::SaveMarkImage(LPBYTE pBuffer,CRect &rectIns) { int nStartH,nStartV,nEndH,nEndV,x,y; int nDiv = 5,nBright = 128; // 0 Position nStartH = (int)m_nCornerPoint[0].x-nDiv; nEndH = (int)m_nCornerPoint[0].x+nDiv; if(nStartH < 0) nStartH = 0; if(nEndH >= rectIns.Width()) nEndH = rectIns.Width()-1; y=(int)m_nCornerPoint[0].y; for(x=nStartH;x<=nEndH;x++) pBuffer[y*rectIns.Width()+x] = nBright; nStartV = (int)m_nCornerPoint[0].y-nDiv; nEndV = (int)m_nCornerPoint[0].y+nDiv; if(nStartV < 0) nStartV = 0; if(nEndV >= rectIns.Height()) nEndV = rectIns.Height()-1; x=(int)m_nCornerPoint[0].x; for(y=nStartV;y<=nEndV;y++) pBuffer[y*rectIns.Width()+x] = nBright; // 1 Position nStartH = (int)m_nCornerPoint[1].x-nDiv; nEndH = (int)m_nCornerPoint[1].x+nDiv; if(nStartH < 0) nStartH = 0; if(nEndH >= rectIns.Width()) nEndH = rectIns.Width()-1; y=(int)m_nCornerPoint[1].y; for(x=nStartH;x<=nEndH;x++) pBuffer[y*rectIns.Width()+x] = nBright; nStartV = (int)m_nCornerPoint[1].y-nDiv; nEndV = (int)m_nCornerPoint[1].y+nDiv; if(nStartV < 0) nStartV = 0; if(nEndV >= rectIns.Height()) nEndV = rectIns.Height()-1; x=(int)m_nCornerPoint[1].x; for(y=nStartV;y<=nEndV;y++) pBuffer[y*rectIns.Width()+x] = nBright; // 2 Position nStartH = (int)m_nCornerPoint[2].x-nDiv; nEndH = (int)m_nCornerPoint[2].x+nDiv; if(nStartH < 0) nStartH = 0; if(nEndH >= rectIns.Width()) nEndH = rectIns.Width()-1; y=(int)m_nCornerPoint[2].y; for(x=nStartH;x<=nEndH;x++) pBuffer[y*rectIns.Width()+x] = nBright; nStartV = (int)m_nCornerPoint[2].y-nDiv; nEndV = (int)m_nCornerPoint[2].y+nDiv; if(nStartV < 0) nStartV = 0; if(nEndV >= rectIns.Height()) nEndV = rectIns.Height()-1; x=(int)m_nCornerPoint[2].x; for(y=nStartV;y<=nEndV;y++) pBuffer[y*rectIns.Width()+x] = nBright; } void CCornerCut::CalculateLenght(double &dResWidth,double &dResHeight) { dResWidth = sqrt(pow((m_nCornerPoint[0].x-m_nCornerPoint[1].x),2)+pow((m_nCornerPoint[0].y-m_nCornerPoint[1].y),2)); dResHeight = sqrt(pow((m_nCornerPoint[0].x-m_nCornerPoint[2].x),2)+pow((m_nCornerPoint[0].y-m_nCornerPoint[2].y),2)); // dResWidth = fabs(m_nCornerPoint[1].x-m_nCornerPoint[2].x)+1; // dResHeight = fabs(m_nCornerPoint[1].y-m_nCornerPoint[2].y)+1; } BOOL CCornerCut::FindOuterHori(LPBYTE pImg,CRect rectIns,double nYPos,double nStartX,CORNERCUR_DIR nDir) { const int nMargin = 5; BOOL bReverse = FALSE; int nStartY,nEndY; switch(nDir) { case CO_LT: case CO_RT: nStartY = (int)nYPos-nMargin; nEndY = (int)nYPos+nMargin; if(nStartY < 0) nStartY = 0; if(nEndY >= rectIns.Height()) nEndY = rectIns.Height()-1; break; case CO_LB: case CO_RB: bReverse = TRUE; nStartY = (int)nYPos+nMargin; nEndY = (int)nYPos-nMargin; if(nEndY < 0) nEndY = 0; if(nStartY >= rectIns.Height()) nStartY = rectIns.Height()-1; break; } if(nStartX < 0) nStartX = 0; int iX,iY; if(bReverse == FALSE) { switch(nDir) { case CO_LT: case CO_LB: for(iX=(int)nStartX;iX=nEndY;iY--) { if(pImg[iY*rectIns.Width()+iX] == 255) { m_pOuterLineH[m_nOuterCountH].x = iX; m_pOuterLineH[m_nOuterCountH].y = iY; m_nOuterCountH++; break; } } } break; case CO_RT: case CO_RB: for(iX=0;iX<(int)nStartX;iX++) { for(iY=nStartY;iY>=nEndY;iY--) { if(pImg[iY*rectIns.Width()+iX] == 255) { m_pOuterLineH[m_nOuterCountH].x = iX; m_pOuterLineH[m_nOuterCountH].y = iY; m_nOuterCountH++; break; } } } break; } } return TRUE; } BOOL CCornerCut::FindOuterVert(LPBYTE pImg,CRect rectIns,double nYPos,double nXPos,CORNERCUR_DIR nDir) { const int nMargin = 5; BOOL bReverse = FALSE; int nStartX,nEndX; switch(nDir) { case CO_LT: case CO_LB: nStartX = (int)nXPos-nMargin; nEndX = (int)nXPos+nMargin; if(nStartX < 0) nStartX = 0; if(nEndX >= rectIns.Width()) nEndX = rectIns.Width()-1; break; case CO_RT: case CO_RB: bReverse = TRUE; nStartX = (int)nXPos+nMargin; nEndX = (int)nXPos-nMargin; if(nEndX < 0) nEndX = 0; if(nStartX >= rectIns.Width()) nStartX = rectIns.Width()-1; break; } if(nYPos < 0) nYPos = 0; int iX,iY; if(bReverse == FALSE) { switch(nDir) { case CO_LT: case CO_RT: for(iY=(int)nYPos;iY=nEndX;iX--) { if(pImg[iY*rectIns.Width()+iX] == 255) { m_pOuterLineV[m_nOuterCountV].x = iX; m_pOuterLineV[m_nOuterCountV].y = iY; m_nOuterCountV++; break; } } } break; case CO_LB: case CO_RB: for(iY=0;iY<(int)nYPos;iY++) { for(iX=nStartX;iX>=nEndX;iX--) { if(pImg[iY*rectIns.Width()+iX] == 255) { m_pOuterLineV[m_nOuterCountV].x = iX; m_pOuterLineV[m_nOuterCountV].y = iY; m_nOuterCountV++; break; } } } break; } } return TRUE; } BOOL CCornerCut::FindOuterLine(LPBYTE pImg,CRect rectIns,CORNERCUR_DIR nDir) { if(m_pOuterLineH != NULL) delete[] m_pOuterLineH, m_pOuterLineH=NULL; if(m_pOuterLineV != NULL) delete[] m_pOuterLineV, m_pOuterLineV=NULL; m_nOuterCountH = m_nOuterCountV = 0; if(pImg == NULL || rectIns.Width()*rectIns.Height() <= 0) return FALSE; m_pOuterLineH = new sCoPoint[rectIns.Width()+1]; m_pOuterLineV = new sCoPoint[rectIns.Height()+1]; FindOuterHori(pImg,rectIns,m_nCornerPoint[1].y,m_nCornerPoint[1].x,nDir); FindOuterVert(pImg,rectIns,m_nCornerPoint[2].y,m_nCornerPoint[2].x,nDir); return TRUE; } BOOL CCornerCut::FindCornerPoint(LPBYTE pImg,CRect rectIns,sCoPoint point,CORNERCUR_DIR nDir) { switch(nDir) { case CO_LT: DetectLine(pImg,rectIns,point,TRUE,FALSE,nDir,m_nCornerPoint[1]); DetectLine(pImg,rectIns,point,FALSE,FALSE,nDir,m_nCornerPoint[2]); break; case CO_LB: DetectLine(pImg,rectIns,point,TRUE,FALSE,nDir,m_nCornerPoint[1]); DetectLine(pImg,rectIns,point,FALSE,TRUE,nDir,m_nCornerPoint[2]); break; case CO_RT: DetectLine(pImg,rectIns,point,TRUE,TRUE,nDir,m_nCornerPoint[1]); DetectLine(pImg,rectIns,point,FALSE,FALSE,nDir,m_nCornerPoint[2]); break; case CO_RB: DetectLine(pImg,rectIns,point,TRUE,TRUE,nDir,m_nCornerPoint[1]); DetectLine(pImg,rectIns,point,FALSE,TRUE,nDir,m_nCornerPoint[2]); break; } return TRUE; } int CCornerCut::GetVertCount(LPBYTE pImg,int u,sCoPoint point,BOOL bDir,int nWidth,int nHeight,int nSetCount) { int nDetLine = -1; int nCount = 0; int v; if(bDir == FALSE) { for(v=(int)point.y;v= nSetCount) { nDetLine = v-nCount; break; } } } else { for(v=(int)point.y;v>=0;v--) { if(*(pImg+v*nWidth+u) == 255) nCount++; else nCount = 0; if(nCount >= nSetCount) { nDetLine = v+nCount; break; } } } return nDetLine; } int CCornerCut::GetHorCount(LPBYTE pImg,int v,sCoPoint point,BOOL bDir,int nWidth,int nSetCount) { int nDetLine = -1; int nCount = 0; int u; if(bDir == FALSE) { for(u=(int)point.x;u= nSetCount) { nDetLine = u-nCount; break; } } } else { for(u=(int)point.x;u>=0;u--) { if(*(pImg+v*nWidth+u) == 255) nCount++; else nCount = 0; if(nCount >= nSetCount) { nDetLine = u+nCount; break; } } } return nDetLine; } void CCornerCut::GetRegionInfo(sCoPoint point,CORNERCUR_DIR nDir,BOOL bDir,int &nStart,int &nEnd,BOOL &bReverse,int nWidth,int nHeight) { int nSize = g_nContiCnt*2; bReverse = FALSE; if(bDir == TRUE) // Horizontal { switch(nDir) { case CO_LT: case CO_RT: nStart = (int)point.y-nSize*2; nEnd = (int)point.y+nSize; break; case CO_LB: case CO_RB: bReverse = TRUE; nStart = (int)point.y-nSize; nEnd = (int)point.y+nSize*2; break; } if(nStart < 0) nStart = 0; if(nEnd >= nHeight) nEnd = nHeight-1; } else { switch(nDir) { case CO_LT: case CO_LB: nStart = (int)point.x-nSize*2; nEnd = (int)point.x+nSize; break; case CO_RT: case CO_RB: bReverse = TRUE; nStart = (int)point.x-nSize; nEnd = (int)point.x+nSize*2; break; } if(nStart < 0) nStart = 0; if(nEnd >= nWidth) nEnd = nWidth-1; } } int CCornerCut::DetectLine(LPBYTE pImg,CRect rectIns,sCoPoint point,BOOL bDir,BOOL bReverse,CORNERCUR_DIR nDir,sCoPoint &pointResult) { int nWidth = rectIns.Width(); int nHeight = rectIns.Height(); int u,v; int nCount; const int nSetCount = 2; const int nSetDet = 8; int nStart,nEnd,nDetPos,iLoop; BOOL bConvert; CPoint pointDet,pointFirst; CArray nPos; nCount = 0; GetRegionInfo(point,nDir,bDir,nStart,nEnd,bConvert,nWidth,nHeight); if(bDir == TRUE) // Horizontal { if(nStart > nEnd) swapN(nStart,nEnd); if(bConvert == FALSE) { for(v=nEnd;v>=nStart;v--) { nDetPos = GetHorCount(pImg,v,point,bReverse,nWidth,nSetCount); nPos.Add(CPoint(nDetPos,v)); } } else { for(v=nStart;v= nSetDet) { pointResult.x = pointFirst.x; pointResult.y = pointFirst.y; break; } pointFirst = pointDet; } } else { if(nStart > nEnd) swapN(nStart,nEnd); if(bConvert == FALSE) { for(u=nEnd;u>=nStart;u--) { nDetPos = GetVertCount(pImg,u,point,bReverse,nWidth,nHeight,nSetCount); nPos.Add(CPoint(u,nDetPos)); } } else { for(u=nStart;u= nSetDet) { pointResult.x = pointFirst.x; pointResult.y = pointFirst.y; break; } pointFirst = pointDet; } } return 0; } BOOL CCornerCut::FindHorizontalLine(LPBYTE pImg,CRect rectIns,int &nHorLine,CORNERCUR_DIR nDir) { if(rectIns.Height() <= 0) return FALSE; nHorLine = -1; int *pPoint; int u,v; int nMax,nLevel; int nWidth = rectIns.Width(); int nHeight = rectIns.Height(); int nCount; ////////////////////////////////////////////////////////////////////////// // vertical pPoint = new int[nHeight]; ZeroMemory(pPoint,sizeof(int)*nHeight); nMax = INT_MIN; for(v=0;v= nLevel) nCount++; else nCount = 0; if(nCount >= g_nContiCnt) { nHorLine = v-nCount; break; } } break; case CO_LB: case CO_RB: for(v=nHeight-1;v>=0;v--) { if(pPoint[v] >= nLevel) nCount++; else nCount = 0; if(nCount >= g_nContiCnt) { nHorLine = v+nCount; break; } } break; } delete[] pPoint, pPoint=NULL; return TRUE; } BOOL CCornerCut::FindVerticalLine(LPBYTE pImg,CRect rectIns,int &nVertLine,CORNERCUR_DIR nDir) { if(rectIns.Width() <= 0) return FALSE; nVertLine = -1; int *pPoint; int u,v; int nMax,nLevel; int nWidth = rectIns.Width(); int nHeight = rectIns.Height(); int nCount; ////////////////////////////////////////////////////////////////////////// // vertical pPoint = new int[nWidth]; ZeroMemory(pPoint,sizeof(int)*nWidth); nMax = INT_MIN; for(u=0;u= nLevel) nCount++; else nCount = 0; if(nCount >= g_nContiCnt) { nVertLine = u-nCount; break; } } break; case CO_RT: case CO_RB: for(u=nWidth-1;u>=0;u--) { if(pPoint[u] >= nLevel) nCount++; else nCount = 0; if(nCount >= g_nContiCnt) { nVertLine = u+nCount; break; } } break; } delete[] pPoint, pPoint=NULL; return TRUE; } BOOL CCornerCut::CopyEdgeImg(LPBYTE pImg,CSize szImg,CRect &rectIns) { if(m_pInsImg != NULL) delete[] m_pInsImg, m_pInsImg = NULL; m_pInsImg = new BYTE[rectIns.Width()*(rectIns.Height()+1)]; ZeroMemory(m_pInsImg,sizeof(BYTE)*rectIns.Width()*(rectIns.Height()+1)); int v; int dv = 0; for(v=rectIns.top;v szImg.cx) rect.left = szImg.cx-1; if(rect.right < 0) rect.right = 0; if(rect.right > szImg.cx) rect.right = szImg.cx-1; if(rect.left > rect.right) swapN(rect.left,rect.right); if(rect.top < 0) rect.top = 0; if(rect.top > szImg.cy) rect.top = szImg.cy-1; if(rect.bottom < 0) rect.bottom = 0; if(rect.bottom > szImg.cy) rect.bottom = szImg.cy-1; if(rect.top > rect.bottom) swapN(rect.top,rect.bottom); } float CCornerCut::AdaptiveThreshold(BYTE* pImageData, int nWidth, int nHeight, int nStep, int nThresValue) { if (pImageData==NULL) return 0; float fThresValue =(float) nThresValue; float fNewThresValue = 0; for (int i=0; i<1000; i++) { fNewThresValue = GetThresholdValue(pImageData, nWidth, nHeight, nStep, (int)fThresValue); if (fNewThresValue==fThresValue) break; fThresValue = fNewThresValue; } return fNewThresValue; } float CCornerCut::GetThresholdValue(BYTE* pImageData, int nWidth, int nHeight, int nStep, int nThresValue) { if (pImageData==NULL) return 0; ULONG fore = 0; int fore_cnt = 0; ULONG back = 0; int back_cnt = 0; int nIndex; for (int i=0; i nThresValue) { fore += pImageData[nIndex]; fore_cnt++; } else { back += pImageData[nIndex]; back_cnt++; } } } float fore_avg = 0.0f; if (fore_cnt!=0) fore_avg = float(fore) / float(fore_cnt); float back_avg = 0.0f; if (back_cnt!=0) back_avg = float(back) / float(back_cnt); if (fore_cnt==0 || back_cnt==0) { if (nThresValue>=128) return float(nThresValue)/2.0f; else return float(nThresValue)*2.0f; } return (fore_avg+back_avg)/2.0f; } void CCornerCut::ThresholdProcLowHigh(CSISBuffer &pImg,int nLowThres,int nHighThres) { LPBYTE pBuf = pImg.GetDataAddress(); for (int i=0; i= nHighThres) *pBuf = 255; else *pBuf = 0; } } void CCornerCut::ThresholdProcessing(LPBYTE pImg,CSize szImg,int nThres,int nDir) { float fNewThresValue = float(nThres); // threshold and invert int nIndex; int nFinThres = (int)(fNewThresValue); for (int i=0; i nFinThres) { pImg[nIndex] = 255; } else { pImg[nIndex] = 0; } } else { if (pImg[nIndex] < nFinThres) { pImg[nIndex] = 255; } else { pImg[nIndex] = 0; } } } } } // ·Î¹öÆ®ÆÐ³ÊÀÇ ±³Â÷Á¡ ±¸Çϱâ¶ó´Âµ¥.. BOOL CCornerCut::LineInterSection(CPoint p1,CPoint p2,CPoint p3,CPoint p4,double &dInterX,double &dInterY) { double x1 = p1.x; double y1 = p1.y; double x4 = p4.x; double y4 = p4.y; dInterX = dInterY = 0.; double dx1 = p2.x - x1; double dx2 = p3.x - x4; if (!(dx1 || dx2)) return FALSE; double m1 = (p2.y - y1) / dx1; double m2 = (p3.y - y4) / dx2; if (!dx1) { // infinity dInterX = x1; dInterY = m2 * (x1 - x4) + y4; return FALSE; } else if (!dx2) { // infinity dInterX = x4; dInterY = m1 * (x4 - x1) + y1; return FALSE; } dInterX = (-m2 * x4 + y4 + m1 * x1 - y1) / (m1 - m2); dInterY = m1 * (dInterX - x1) + y1; return TRUE; } BOOL CCornerCut::FindFirstPoint(CRect &rectIns) { CPoint HPoint[2],VPoint[2]; int iLoop; int nSetCount = 10; int nSumF,nSumS; double dslope,dAvgF,dAvgS; nSumF = nSumS = 0; for(iLoop=0;iLoopx && samples[i].y == data->y) { return true; } } return false; } void CCornerCut::get_samples (sCoPoint *samples, int no_samples, sCoPoint *data, int no_data) { // µ¥ÀÌÅÍ¿¡¼­ Áߺ¹µÇÁö ¾Ê°Ô N°³ÀÇ ¹«ÀÛÀ§ ¼ÀÇÃÀ» äÃëÇÑ´Ù. for (int i=0; i abs(posEnd.x - posStart.x)); if(steep) { swapLong(posStart.x, posStart.y); swapLong(posEnd.x, posEnd.y); } if(posStart.x > posEnd.x) { swapLong(posStart.x, posEnd.x); swapLong(posStart.y, posEnd.y); } const int dx = posEnd.x - posStart.x; const int dy = abs(posEnd.y - posStart.y); float error = (float)dx / 2.0f; const int ystep = (posStart.y < posEnd.y) ? 1 : -1; int y = (int)posStart.y; const int maxX = (int)posEnd.x; for(int x=(int)posStart.x; xSetPixel(y,x, color); } else { pRes->SetPixel(x,y, color); } error -= dy; if(error < 0) { y += ystep; error += dx; } } }