2017-05-07 53 views
-1

我必須批量處理多個圖像。我必須在特定點(X,Y)放置一些文本。有一個自定義從picturebox派生的控件,允許用戶拖動文本並將其放置在所需的位置。爲自定義PictureBox控件中的不同尺寸圖像轉換點(X,Y)

有兩種類型的用於我設置PictureBoxSizeMode不同

垂直圖像

enter image description here

我圖像集>PictureBoxSizeMode.Zoom;

水平

對於填充在PictureBox水平圖像I設定>PictureBoxSizeMode.StretchImage

enter image description here

用戶可以選擇的位置通過拖動移到該PictureBox的文本control.The原始圖像的尺寸調整爲所述控制放置文本大小(對於水平圖像),用戶將文本拖動到該圖像上。

基於圖片框的SizeMode選定點被轉換使用以下代碼

if (sizemode == 1) 
    { 

    transpoint = TranslateStretchImageMousePosition(new Point(e.X - 20, e.Y -20)); 

    } 

    else if (sizemode == 2) 
    { 
     transpoint = TranslateZoomMousePosition(new Point(e.X - 20, e.Y - 20)); 

    } 

public Point TranslateStretchImageMousePosition(Point coordinates) 
     { 
      // test to make sure our image is not null 
      if (Image == null) return coordinates; 
      // Make sure our control width and height are not 0 
      if (Width == 0 || Height == 0) return coordinates; 
      // First, get the ratio (image to control) the height and width 
      float ratioWidth = (float)Image.Width/Width; 
      //MessageBox.Show(ratioWidth.ToString()); 

      float ratioHeight = (float)Image.Height/Height; 
      // MessageBox.Show(ratioHeight.ToString()); 
      // Scale the points by our ratio 
      float newX = coordinates.X; 
      float newY = coordinates.Y; 
      newX *= ratioWidth; 
      newY *= ratioHeight; 
      return new Point((int)newX, (int)newY); 
     } 

public Point TranslateZoomMousePosition(Point coordinates) 
     { 
      // test to make sure our image is not null 
      if (Image == null) return coordinates; 
      // Make sure our control width and height are not 0 and our 
      // image width and height are not 0 
      if (Width == 0 || Height == 0 || Image.Width == 0 || Image.Height == 0) return coordinates; 
      // This is the one that gets a little tricky. Essentially, need to check 
      // the aspect ratio of the image to the aspect ratio of the control 
      // to determine how it is being rendered 
      float imageAspect = (float)Image.Width/Image.Height; 
      float controlAspect = (float)Width/Height; 
      float newX = coordinates.X; 
      float newY = coordinates.Y; 
      if (imageAspect > controlAspect) 
      { 
       // This means that we are limited by width, 
       // meaning the image fills up the entire control from left to right 
       float ratioWidth = (float)Image.Width/Width; 
       newX *= ratioWidth; 
       float scale = (float)Width/Image.Width; 
       float displayHeight = scale * Image.Height; 
       float diffHeight = Height - displayHeight; 
       diffHeight /= 2; 
       newY -= diffHeight; 
       newY /= scale; 
      } 
      else 
      { 
       // This means that we are limited by height, 
       // meaning the image fills up the entire control from top to bottom 
       float ratioHeight = (float)Image.Height/Height; 
       newY *= ratioHeight; 
       float scale = (float)Height/Image.Height; 
       float displayWidth = scale * Image.Width; 
       float diffWidth = Width - displayWidth; 
       diffWidth /= 2; 
       newX -= diffWidth; 
       newX /= scale; 
      } 
      return new Point((int)newX, (int)newY); 
     } 

現在得到點之後的原始圖像內的點I必須調用主內的另一種方法形式得到近似的文字位置

point= translatemanualpoint(transpoint, img, refimgsize.Width, refimgsize.Height); 

哪裏refimgsize是原始圖像(無標度)的大小,用來放置TE XT。

private Point translatemanualpoint(Point coordinates, Bitmap Image, int Width, int Height) 
     { 

      //--------------------------------- 
      // test to make sure our image is not null 
      if (Image == null) return coordinates; 
      // Make sure our control width and height are not 0 
      if (Width == 0 || Height == 0) return coordinates; 
      // First, get the ratio (image to control) the height and width 
      float ratioWidth = (float)Image.Width/Width; 


      float ratioHeight = (float)Image.Height/Height; 

      // Scale the points by our ratio 
      float newX = coordinates.X; 
      float newY = coordinates.Y; 
      newX *= ratioWidth; 
      newY *= ratioHeight; 
      return new Point((int)newX, (int)newY); 

     } 

的問題是,這種方法並不accurate.When我用水平圖像作爲參考來放置文本,並且當點被轉換爲在垂直圖像的點;所述點的位置是不正確。當我使用垂直圖像作爲參考和翻譯完成水平圖像中的某一點時,會發生這種情況。

我做錯了什麼?請指教。

請讓我知道是否需要發佈控件的完整代碼。

UPDATE:

這是我想achieve.The標誌,並在下面的圖片文字手動placed.You可以看到,如何標識和文字出現在圖像大致相同的位置不同的長寬比。

UPDATE:每@ 爲彈石的意見,我採取了以下方法來找到最接近的2個邊,並使用相應的間距。

void findclosestedges(Point p) 
     {   

      //Xedge=1 -- Left Edge is closer to Point 2--Right Edge 

      //Finding closest Left/Right Edge 
      if (p.X < (ClientSize.Width - p.X)) 
      { 

       LaunchOrigin.Xedge = 1; 
       LaunchOrigin.Xspacing = p.X; 
       LaunchOrigin2.closestedge.Text = " "; 
       LaunchOrigin2.closestedge.Text = LaunchOrigin2.closestedge.Text + " left"; 
      } 
      else 
      { 
       LaunchOrigin.Xedge = 2; 
       LaunchOrigin.Xspacing = (ClientSize.Width - p.X); 
       LaunchOrigin2.closestedge.Text = " "; 
       LaunchOrigin2.closestedge.Text = LaunchOrigin2.closestedge.Text + " right"; 
      } 

      //Finding closest Top/Bottom Edge 

      if (p.Y < (ClientSize.Height - p.Y)) 
      { 
       LaunchOrigin.Yedge = 1; 
       LaunchOrigin.Yspacing =p.Y; 
       LaunchOrigin2.closestedge.Text = LaunchOrigin2.closestedge.Text + " top"; 
      } 
      else 
      { 
       LaunchOrigin.Yedge = 2; 
       LaunchOrigin.Yspacing = (ClientSize.Height - p.Y); 
       LaunchOrigin2.closestedge.Text = LaunchOrigin2.closestedge.Text + " bottom"; 
      } 
      LaunchOrigin.ewidth = Width; 
      LaunchOrigin.eheight = Height; 
     } 

現在在主窗體我做以下

int wratio = img.Width/ewidth; 
    int hratio = img.Height/eheight; 
    if (Xedge == 1) 
    { 

      cpoint.X = Xspacing*wratio; 


    } 
    else 
    { 

     cpoint.X = img.Width - Xspacing * wratio; 



    } 
    if (Yedge == 1) 
    { 

     cpoint.Y = Yspacing * hratio; 




    } 
    else 
    { 


      cpoint.Y = img.Height - Yspacing*hratio; 


    } 

我仍然沒有得到正確的定位。

我在做什麼錯?

這就是我想要實現...

enter image description here enter image description here

UPDATE:

按@ Abion47答案我已經使用以下方法

在定製picturebox控制

Point src = e.Location; 
PointF ratio = new PointF((float)src.X/Width, (float)src.Y/Height); 
LaunchOrigin.ratio = ratio; 
Point origin = new Point((int)(backupbit1.Width * ratio.X), (int)(backupbit1.Height * ratio.Y)); 
LaunchOrigin.origin = origin; 
point.X = src.X - origin.X; 
point.Y = src.Y - origin.Y; 

在主窗口

Point pos2 = new Point((int)(ratio.X * img.Width), (int)(ratio.Y * img.Height)); 
cpoint.X = pos2.X - origin.X; 
cpoint.Y = pos2.Y - origin.Y; 

這個作品幾乎沒關係..除了右下角邊緣。

在自定義圖片框

enter image description here

在主窗體

enter image description here

我我我做錯了什麼?請指教。

UPDATE:

我所做的是計算從PictureBox控件的比例和使用這樣的比例在主要形式,以點

Point origin = new Point((int)(bitmap.Width * textratio.X), (int)(bitmap.Height * textratio.Y)); 
Point pos2 = new Point((int)(textratio.X * img.Width), (int)(textratio.Y * img.Height)); 
cpoint.X = pos2.X - (int)(origin.X); 
cpoint.Y = pos2.Y - (int)(origin.Y); 

徽標翻譯我也是這樣做的

Point origin = new Point((int)(worktag.Width * logoratio.X), (int)(worktag.Height * logoratio.Y)); 
Point logopositionpoint = new Point((int)(logoratio.X * img.Width), (int)(logoratio.Y * img.Height)); 
imgpoint.X = logopositionpoint.X - origin.X; 
imgpoint.Y = logopositionpoint.Y - origin.Y; 

這很好,直到我將文本和標誌緊密放在一起。在自定義圖片框控件中,文本和徽標正確顯示。在主窗口中,對於垂直圖像,它們顯示正常,但對於水平圖像,兩者都重疊...這裏出了什麼問題?請指點..

UPDATE

這工作well.But我如何從主窗口中的點轉換到自定義PictureBox控件(與允許拖動文本)。

我試過下面的代碼。但是,這是不是給精確定位

private Point translatetextpoint(Point mpoint,Bitmap bitmap) 
     { 

      PointF ratio = new PointF((float)LaunchOrigin.cpoint.X /LaunchOrigin.img.Width, (float)LaunchOrigin.cpoint.Y /LaunchOrigin.img.Height); 
      Point origin = new Point((int)(endPointPictureBox1.bit.Width * ratio.X), (int)(endPointPictureBox1.bit.Height * ratio.Y)); 
      Point pos2 = new Point((int)(ratio.X * endPointPictureBox1.Width), (int)(ratio.Y * endPointPictureBox1 
       .Height)); 
      pos2.X = pos2.X - (int)(origin.X); 
      pos2.Y = pos2.Y - (int)(origin.Y); 
      return pos2; 
     } 

請諮詢..

+2

嗯..爲什麼這個問題downvoted?任何意見將是有用的.. – techno

+0

它是一個類?如果是這樣,使用ClientSize.Height高度是首選,因爲它會允許邊界..一個可能的downvote(不是我的)原因可能是缺乏研究,因爲這個問題並不完全是新的.. – TaW

+0

@TaW我們可以繼續討論聊天http ://chat.stackoverflow.com/rooms/143591/system-drawing – techno

回答

2

我無法通過所有的代碼讀取確切地告訴你應該如何編寫這一點,但這裏是一些示例代碼的可能性:

PointF GetReferencePoint(Point absoluteReferencePoint) 
{ 
    PointF referencePointAsRatio = new Point(); 

    referencePointAsRatio.X = (float)absoluteReferencePoint.X/referenceImage.Width; 
    referencePointAsRatio.Y = (float)absoluteReferencePoint.Y/referenceImage.Height; 

    return referencePointAsRatio; 
} 

... 

Point GetTargetPoint(PointF referencePointAsRatio) 
{ 
    Point targetPoint = new Point(); 

    targetPoint.X = (int)(referencePointAsRatio.X * targetImage.Width); 
    targetPoint.Y = (int)(referencePointAsRatio.Y * targetImage.Height); 

    return targetPoint; 
} 

在你的實踐中,你可能還需要做一些抵消以說明邊界厚度或其他。

編輯:

有一件事情你能做爲「正確」的位置是依賴於他們的形象在抵消文本元素的位置。例如,左上角的文本將相對於其自己的左上角進行定位,右下角的文本將定位到其右下角,並且圖像中心的文本將相對於其中心進行定位。

建設關我在樣本項目(在評論中下載鏈接)給的例子,你可以做到這一點,像這樣:

private void PictureBox1_MouseMove(object sender, MouseEventArgs e) 
{ 
    Point src = e.Location; 
    PointF ratio = new PointF((float)src.X/pictureBox1.Width, (float)src.Y/pictureBox1.Height); 
    Point origin = new Point((int)(label1.Width * ratio.X), (int)(label1.Height * ratio.Y)); 

    label1.Left = src.X - origin.X; 
    label1.Top = src.Y - origin.Y; 

    Point pos2 = new Point((int)(ratio.X * pictureBox2.Width), (int)(ratio.Y * pictureBox2.Height)); 
    label2.Left = pos2.X + pictureBox2.Left - origin.X; 
    label2.Top = pos2.Y + pictureBox2.Top - origin.Y; 

    Point pos3 = new Point((int)(ratio.X * pictureBox3.Width), (int)(ratio.Y * pictureBox3.Height)); 
    label3.Left = pos3.X + pictureBox3.Left - origin.X; 
    label3.Top = pos3.Y + pictureBox3.Top - origin.Y; 

    Point pos4 = new Point((int)(ratio.X * pictureBox4.Width), (int)(ratio.Y * pictureBox4.Height)); 
    label4.Left = pos4.X + pictureBox4.Left - origin.X; 
    label4.Top = pos4.Y + pictureBox4.Top - origin.Y; 
} 

enter image description here enter image description here enter image description here

+0

請參閱我的最新更新...進入一個新問題。 – techno

+0

@techno然後你必須做一些[重疊檢測](https://msdn.microsoft.com/en-us/library/y10fyck0(v = vs.110).aspx)並抵消結果的位置。他們不會重疊。 – Abion47

+0

你如何建議我這樣做?請教http://stackoverflow.com/questions/44018201/performing-overlap-detection-of-2-bitmaps – techno