Unplanned
Last Updated: 15 Jan 2025 15:28 by Martin Ivanov
Martin Ivanov
Created on: 15 Jan 2025 15:28
Category: ImageEditor
Type: Bug Report
0
ImageEditor: ArgumentException thrown when using the draw or shape tools

ArgumentException is thrown on mouse up, after using the DrawTool or ShapeTool in RadImageEditor or RadImageEditorUI.

The exception message is: "'∞' is not a valid value for property 'Width'."

The stacktrace is:

System.ArgumentException: '8' is not a valid value for property 'Width'.
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at Telerik.Windows.Media.Imaging.Commands.DrawCommand.Execute(RadBitmap source, Object context)
   at Telerik.Windows.Media.Imaging.History.ImageHistory.Execute(IImageCommand command, Object context)
   at Telerik.Windows.Controls.RadImageEditor.ExecuteCommand(IImageCommand command, Object context)
   at Telerik.Windows.Controls.RadImageEditor.CommitTool(Boolean executeSameToolAfterCommit)
   at Telerik.Windows.Media.Imaging.Tools.DrawToolBase.InvokeEndDraw(Point point)
   at Telerik.Windows.Media.Imaging.Tools.DrawToolBase.DrawingCanvas_MouseLeftButtonUp(Object sender, MouseButtonEventArgs e)

To work this around, you can create a custom DrawCommand based on the code from the default one and then replace it in the ShapeTool and DrawTool.

public class CustomDrawTool : DrawTool
{
    public override IImageCommand GetCommand()
    {
        return new CustomDrawCommand();
    }
}

public class CustomShapeTool : ShapeTool
{
    public override IImageCommand GetCommand()
    {
        return new CustomDrawCommand();
    }
}

public class CustomDrawCommand : IImageCommand
{
    public RadBitmap Execute(RadBitmap source, object context)
    {
        DrawCommandContext drawCommandContext = context as DrawCommandContext;
        if (drawCommandContext == null || drawCommandContext.DrawnPath == null)
        {
            return source;
        }

        Canvas canvas = new Canvas();

        canvas.ClipToBounds = true;
        var dpiXFactor = source.Bitmap.DpiX / 96;
        var dpiYFactor = source.Bitmap.DpiY / 96;

        double imageWidth = source.Width / dpiXFactor;
        if (imageWidth == double.PositiveInfinity)
        {
            imageWidth = source.Width;
        }
        double imageHeight = source.Height/ dpiYFactor;
        if (imageHeight == double.PositiveInfinity)
        {
            imageHeight = source.Height; 
        }

        canvas.Children.Add(new System.Windows.Controls.Image()
        {
            Source = source.Bitmap,
            Width = imageWidth,
            Height = imageHeight,
        });

        Panel parent = drawCommandContext.DrawnPath.Parent as Panel;
        if (parent != null)
        {
            parent.Children.Remove(drawCommandContext.DrawnPath);
            drawCommandContext.DrawnPath.RenderTransform = new ScaleTransform(1 / dpiXFactor, 1 / dpiYFactor);
            canvas.Children.Add(drawCommandContext.DrawnPath);
        }

        RenderOptions.SetBitmapScalingMode(canvas, BitmapScalingMode.NearestNeighbor);
        BitmapSource bitmapSource = this.GetBitmapSource(source.Width, source.Height, canvas, source.Bitmap.DpiX, source.Bitmap.DpiY);
        return new RadBitmap(bitmapSource);
    }

    private BitmapSource GetBitmapSource(int width, int height, Canvas canvas, double dpiX, double dpiY)
    {
        Size size = new Size(width, height);
        canvas.Measure(size);
        canvas.Arrange(new Rect(size));
        RenderTargetBitmap renderBitmap = new RenderTargetBitmap(width, height, dpiX, dpiY, PixelFormats.Pbgra32);
        renderBitmap.Render(canvas);
        return renderBitmap;
    }
}

To use the custom tools in RadImageEditorUI, you will need to use them as CommandParameter in the ImageToolItem.

  <telerik:ImageToolItem ImageKey="Draw" telerik:LocalizationManager.ResourceKey="ImageEditor_Draw" Command="commands:ImageEditorRoutedCommands.ExecuteTool">
      <telerik:ImageToolItem.CommandParameter>
          <local:CustomDrawTool />
      </telerik:ImageToolItem.CommandParameter>
  </telerik:ImageToolItem>

0 comments