2017-05-07 54 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