EDIT 2 :
ImageBrush.Viewbox
. The Viewbox is a Rect
with dimensions [0.0... 1.0] that let you control what used to be the SourceRect. I tested this and it works brilliantly. What I did:
In my Window:
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);
My container for this was a WPF Rectangle called tgtRect whose Rect.Fill
was imgBrush. The zoom and scroll methods were as follows:
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;
}
For your implementation:
protected override void OnRender(DrawingContext drawingContext)
{
drawingContext.DrawRectangle(imgBrush, null, DesRect);
}
You will likely need to maintain a separate imgBrush for each rectangle you want to draw to. I tried the above code (not the OnRender override) in a WPF Window with just a Rectangle whose Rectangle.Fill
was this ImageBrush
and the performance was very good. If you have any troubles, I think we can sort it out, but I think the ImageBrush will end up being the correct implementation. This has been a very interesting project! Thank you for your question.
END EDIT 2
You will need to define the Rect
objects "Window_LeftHalf" and "Window_RightHalf" to be the actual size you want the images to be rendered. For example, if you are zoomed 200%, then the Rect.Width
and Rect.Height
properties will need to be 2x the size of the original ImageSource.
EDIT:
Old method was :
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage(Image, DestRectangle, SrcRectangle, GraphicsUnit);
}
Using '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);
}
Your mouse functions can change the SourceRect. For example:
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);
}
Not sure how the performance will be, but should be better than mapping portions of the bitmap onto new objects each update.
Hope this has helped at all.