Search code examples
c#wpflayoutmeasurescaletransform

WPF LayoutTransform (Scale) throws Exception because DesiredSize of Image is NaN


I am setting the ImageSource of an Image like this:

Stream imageStreamSource = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource,BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
BitmapSource bmSrc = decoder.Frames[0];
bmSrc.Freeze();
ImageSource = bmSrc;

The Image uses a ScaleTransform (LayoutTransform) in a Scrollviewer.
LayoutTransform is needed to update the ScrollViewers content size.
I want to scale the image to the size of the parent of the scrollviewer (bounds):

double horizontalAspectRatio = gridBounds.Width / image.Width;
double verticalAspectRatio = gridBounds.Height / image.Height;

if (horizontalAspectRatio > verticalAspectRatio) {
     scaleTransformImage.ScaleX = scaleTransformImage.ScaleY = verticalAspectRatio;
     MessageBox.Show("to height");
} else {
     scaleTransformImage.ScaleX = scaleTransformImage.ScaleY = horizontalAspectRatio;
     MessageBox.Show("to width");
}

After doing that an InvalidOperationException is thrown and it says that measuring the image's layout requires the DesireSize not to be NaN.
I tried to measure and arrange the image manually like this:

image.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
image.Arrange(new Rect(0d, 0d, gridBounds.Width, gridBounds.Height));

But it doesn't seem to have an effect.
I am just starting out with Transforms and do not have a lot of knowledge yet....


Solution

  • As long as you did not explicitly set the Image control's Width and Height properties, their values will be NaN, and the aspect ratio calculation will fail:

    double horizontalAspectRatio = gridBounds.Width / image.Width;
    double verticalAspectRatio = gridBounds.Height / image.Height;
    

    You may instead use the Image's ActualWidth and ActualHeight, or if it is not yet laid out, the Width and Height of its Source:

    double horizontalAspectRatio = gridBounds.Width / image.Source.Width;
    double verticalAspectRatio = gridBounds.Height / image.Source.Height;