Reputation: 5633
I am capturing InkStrokes and have a need to create a scaled bitmap image of the strokes in the background. The captured images need to be of uniform size regardless of how big the bounding box of the ink.
For example, if original ink stroke is drawn and the bounding box top/left is 100,100 and size is 200,200 on the ink canvas, I want the ink to start at 0,0 of the new rendered bitmap that is 50,50 size (ignore impact of stroke width right now).
I have figured out how to scale the ink strokes (thanks StackOverflow) but not how to move the strokes. Right now, it seems I have to create a bitmap the size of the InkCanvas, render the scaled ink, then crop bigger image to the correct size.
I've tried using the InkStroke.PointTranslate via
var scaleMatrix = Matrix3x2.CreateScale(scale);
scaleMatrix.Translation = -offset; // top/left of ink stroke bounding box
stroke.PointTransform = scaleMatrix;
But the coordinates do not come out correct.
Any help much appreciated.
Upvotes: 2
Views: 512
Reputation: 12993
You can combine transformations by multiplying matrices. This works for me
var strokes = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
var boundingBox = inkCanvas.InkPresenter.StrokeContainer.BoundingRect;
var matrix1 = Matrix3x2.CreateTranslation((float)-boundingBox.X, (float)-boundingBox.Y);
var matrix2 = Matrix3x2.CreateScale(0.5f);
var builder = new InkStrokeBuilder();
var newStrokeList = new List<InkStroke>();
foreach (var stroke in strokes)
{
newStrokeList.Add(builder.CreateStrokeFromInkPoints
(stroke.GetInkPoints(), matrix1 * matrix2));
}
//Add the translated and scaled strokes to the inkcanvas
inkCanvas.InkPresenter.StrokeContainer.AddStrokes(newStrokeList);
Upvotes: 2
Reputation: 5633
Maybe I was still doing something wrong, but it appears you cannot use InkStrokeBuilder.CreateStrokeFromInkPoints with more than one kind of transform. I tried all kinds of combinations/approaches, and just could not get it to work.
Here is my solution...
private static IList<InkStroke> GetScaledAndTransformedStrokes(IList<InkStroke> strokeList, float scale)
{
var builder = new InkStrokeBuilder();
var newStrokeList = new List<InkStroke>();
var boundingBox = strokeList.GetBoundingBox();
foreach (var singleStroke in strokeList)
{
var translateMatrix = new Matrix(1, 0, 0, 1, -boundingBox.X, -boundingBox.Y);
var newInkPoints = new List<InkPoint>();
var originalInkPoints = singleStroke.GetInkPoints();
foreach (var point in originalInkPoints)
{
var newPosition = translateMatrix.Transform(point.Position);
var newInkPoint = new InkPoint(newPosition, point.Pressure, point.TiltX, point.TiltY, point.Timestamp);
newInkPoints.Add(newInkPoint);
}
var newStroke = builder.CreateStrokeFromInkPoints(newInkPoints, new Matrix3x2(scale, 0, 0, scale, 0, 0));
newStrokeList.Add(newStroke);
}
return newStrokeList;
}
I ended up having to apply my own translate transform then use the builder.CreateStrokeFromInkPoints with a scale matrix applied to get the results I wanted. GetBoundingBox is my own extension:
public static class RectExtensions
{
public static Rect CombineWith(this Rect r, Rect rect)
{
var top = (r.Top < rect.Top) ? r.Top : rect.Top;
var left = (r.Left < rect.Left) ? r.Left : rect.Left;
var bottom = (r.Bottom < rect.Bottom) ? rect.Bottom : r.Bottom;
var right = (r.Right < rect.Right) ? rect.Right : r.Right;
var newRect = new Rect(new Point(left, top), new Point(right, bottom));
return newRect;
}
}
Upvotes: 1