3

我自定义在屏幕上绘制两个放大图像,一个并排。他们每个人都占据了屏幕的一半。

我以前在.net 3.5(我认为)中通过覆盖 OnPaint() 完成了它:

    //using System.Drawing

    /// <summary>
    /// Custom drawing
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPaint(PaintEventArgs e)
    {
        e.Graphics.DrawImage(Image, DestRectangle, SrcRectangle, GraphicsUnit);
    }

DrawImage 方法的描述:“在指定位置以指定大小绘制指定Image的指定部分。” ( MSDN )

我正在尝试使用 .net 4.5 来实现相同的目标。我正在覆盖 OnRender 并使用 DrawingContext 对象来执行我的绘图。基本上这是我的循环:

    //using System.Windows.Media;

    /// <summary>
    /// Overide the OnRender to have access to a lower level of drawing.
    /// </summary>
    /// <param name="drawingContext"></param>
    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawImage(BitmapImage_Left, Window_LeftHalf);
        drawingContext.DrawImage(BitmapImage_Right, Window_RightHalf);
    }

如果我想显示拉伸的图片,它工作得很好。我想要的是显示(在 Window_LeftHalf 和 Window_RightHalf 中)图片的一部分(如放大)。基本上是 graphics.DrawImage (见上图),但使用的是 DrawingContext 对象。

我曾尝试查看 MSDN,但无法提取任何有趣的内容。也许创建一个稍后由 DrawingContext 使用的缓冲区?我几乎可以肯定需要一个中间对象来保存放大的图像。有任何想法吗?

更新:我使用鼠标浏览图像,所以性能重要。例如:

    /// <summary>
    /// Handles the mouse move events.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void MouseMoveEventHandler(RoutedEventArgs e)
    {
        // The size of the crop is always the same
        // but the portion of the picture different.
        crop.X += mouseDelta.X;
        crop.Y += mouseDelta.Y;
    }
4

2 回答 2

3

看看CroppedBitmap课堂。就像您过去可以使用 , 一样e.Graphics.DrawImage()CroppedBitmap您可以只指定您感兴趣的图像部分。

这是一个例子:

protected override void OnRender(System.Windows.Media.DrawingContext dc)
{
    int halfWidth = (int)this.Width / 2;
    int height = (int)this.Height;
    BitmapImage leftImage = new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"));
    BitmapImage rightImage = new BitmapImage(new Uri(@"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"));
    CroppedBitmap leftImageCropped = new CroppedBitmap(leftImage, new Int32Rect(0, 0, halfWidth, height));
    CroppedBitmap rightImageCropped = new CroppedBitmap(rightImage, new Int32Rect(0, 0, halfWidth, height));
    dc.DrawImage(leftImageCropped, new System.Windows.Rect(0, 0, leftImageCropped.Width, height));
    dc.DrawImage(rightImageCropped, new System.Windows.Rect(halfWidth, 0, halfWidth, height));
}
于 2012-12-01T02:15:50.987 回答
0

编辑ImageBrush.Viewbox2 :。 Viewbox 的Rect尺寸为 [0.0...1.0],可让您控制原来的 SourceRect。我对此进行了测试,效果很好。我做了什么:

在我的窗口中:

    protected ImageBrush imgBrush = new ImageBrush(new ImageSource(new Uri("image.png")));
    protected Rect vBox = new Rect(0, 0, 1, 1);
    protected Point lastPosition = new Point(0, 0);

我的容器是一个名为tgtRect的WPF 矩形,它Rect.FillimgBrush。缩放和滚动方法如下:

    protected void tgtRect_MouseWheel(object sender, MouseWheelEventArgs e)
    {
        // Zoom in when Delta is positive, Zoom out when negative
        double exp = -e.Delta / Math.Abs(e.Delta);
        double val = Math.Pow(1.1, exp);
        vBox.Scale(val, val);
        imgBrush.Viewbox = vBox;
    }

    void tgtRect_MouseMove(object sender, MouseEventArgs e)
    {
        Point thisPosition = e.GetPosition(tgtRect);
        if (e.RightButton == MouseButtonState.Pressed)
        {
            double w = tgtRect.ActualWidth;
            double h = tgtRect.ActualHeight;
            Vector offset = lastPosition - thisPosition;
            offset.X /= w;
            offset.Y /= h;
            vBox.Offset(offset);
            imgBrush.Viewbox = vBox;
        }
        lastPosition = thisPosition;
    }

对于您的实施:

    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawRectangle(imgBrush, null, DesRect);
    }

您可能需要为要绘制的每个矩形维护一个单独的 imgBrush。Rectangle.Fill我在 WPF 窗口中尝试了上面的代码(不是 OnRender 覆盖),只有一个 Rectangle ,ImageBrush性能非常好。如果您有任何问题,我认为我们可以解决,但我认为 ImageBrush 最终会成为正确的实现。这是一个非常有趣的项目!谢谢你的问题。

结束编辑 2

您需要将Rect对象“Window_LeftHalf”和“Window_RightHalf”定义为您希望渲染图像的实际大小。例如,如果您缩放 200%,则Rect.WidthandRect.Height属性将需要是原始 ImageSource 大小的 2 倍。

编辑

旧方法是:

protected override void OnPaint(PaintEventArgs e)
{
    e.Graphics.DrawImage(Image, DestRectangle, SrcRectangle, GraphicsUnit);
}

使用 'BitmapImage.SourceRect` :

protected override void OnRender(DrawingContext drawingContext)
{
    BitmapImage_Left.SourceRect = SrcRectangleLeft;
    drawingContext.DrawImage(BitmapImage_Left, Window_LeftHalf);
    BitmapImage_Right.SourceRect = SrcRectangleRight;
    drawingContext.DrawImage(BitmapImage_Right, Window_RightHalf);
}

您的鼠标功能可以更改 SourceRect。例如:

private static void MouseMoveEventHandler(RoutedEventArgs e)
{
    // The size of the crop is always the same
    // but the portion of the picture different.
    SrcRectangleLeft = new Int32Rect(SrcRectangleLeft.X + mouseDelta.X, 
        SrcRectangleLeft.Y + mouseDelta.Y,
        SrcRectangleLeft.Width, SrcRectangleLeft.Height);
}

不确定性能如何,但应该比每次更新时将位图的一部分映射到新对象上要好。

希望这有帮助。

于 2012-12-01T00:04:25.707 回答