我正在尝试在图像上绘制带有反色的十字准线(“加号”),以显示图像中所选点的位置。我就是这样做的:
private static void DrawInvertedCrosshair(Graphics g, Image img, PointF location, float length, float width)
{
float halfLength = length / 2f;
float halfWidth = width / 2f;
Rectangle absHorizRect = Rectangle.Round(new RectangleF(location.X - halfLength, location.Y - halfWidth, length, width));
Rectangle absVertRect = Rectangle.Round(new RectangleF(location.X - halfWidth, location.Y - halfLength, width, length));
ImageAttributes attributes = new ImageAttributes();
float[][] invertMatrix =
{
new float[] {-1, 0, 0, 0, 0 },
new float[] { 0, -1, 0, 0, 0 },
new float[] { 0, 0, -1, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
new float[] { 1, 1, 1, 0, 1 }
};
ColorMatrix matrix = new ColorMatrix(invertMatrix);
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
g.DrawImage(img, absHorizRect, absHorizRect.X, absHorizRect.Y, absHorizRect.Width, absHorizRect.Height, GraphicsUnit.Pixel, attributes);
g.DrawImage(img, absVertRect, absVertRect.X, absVertRect.Y, absVertRect.Width, absVertRect.Height, GraphicsUnit.Pixel, attributes);
}
它按预期工作,然而,它真的很慢。我希望用户能够使用鼠标移动选定的位置,方法是在移动时将位置设置为光标的位置。不幸的是,在我的计算机上,对于大图像,它每秒只能更新一次。
所以,我正在寻找使用Graphics.DrawImage来反转图像区域的替代方法。有没有办法以选定的区域而不是整个图像区域的速度进行比较?
答案 0 :(得分:7)
听起来我正在关注错误的问题。绘画图像很慢,不画“十字线”。
如果您没有帮助,大图像肯定会非常昂贵。 System.Drawing使非常容易无法帮助。你想要做的两件基本事情是让图像画得更快,速度提高20倍以上是可以实现的:
避免强制图像绘制代码重新缩放图像。而是只做一次,这样可以直接一对一地绘制图像而无需任何重新缩放。这样做的最佳时间是加载图像。可能再次出现在控件的Resize事件处理程序中。
注意图像的像素格式。远射中最快的是像素格式,它与图像需要存储在视频适配器中的方式直接兼容。因此,图像数据可以直接复制到视频RAM,而无需调整每个像素。在99%的现代机器上,这种格式是PixelFormat.Format32bppPArgb。产生巨大差异,比其他所有产品快<10> 倍。
一种简单的辅助方法,可以在不处理宽高比的情况下完成两者:
private static Bitmap Resample(Image img, Size size) {
var bmp = new Bitmap(size.Width, size.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
using (var gr = Graphics.FromImage(bmp)) {
gr.DrawImage(img, new Rectangle(Point.Empty, size));
}
return bmp;
}
答案 1 :(得分:0)
在Graphics g上绘制一次图像,然后直接在Graphics g上绘制十字准线而不是图像。您可以选择跟踪用户点击的位置,以便根据需要将其保存在图像中或其他位置。