我必须批量处理多个图像。我必须在特定点(X,Y)放置一些文本。有一个自定义从picturebox派生的控件,允许用户拖动文本并将其放置在所需的位置。为自定义PictureBox控件中的不同尺寸图像转换点(X,Y)
有两种类型的用于我设置PictureBoxSizeMode
不同
垂直图像
我图像集>PictureBoxSizeMode.Zoom;
水平
对于填充在PictureBox水平图像I设定>PictureBoxSizeMode.StretchImage
用户可以选择的位置通过拖动移到该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;
}
我仍然没有得到正确的定位。
我在做什么错?
这就是我想要实现...
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;
这个作品几乎没关系..除了右下角边缘。
在自定义图片框
在主窗体
我我我做错了什么?请指教。
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;
}
请咨询..
嗯..为什么这个问题downvoted?任何意见将是有用的.. – techno
它是一个类?如果是这样,使用ClientSize.Height高度是首选,因为它会允许边界..一个可能的downvote(不是我的)原因可能是缺乏研究,因为这个问题并不完全是新的.. – TaW
@TaW我们可以继续讨论聊天http ://chat.stackoverflow.com/rooms/143591/system-drawing – techno