WPF Bitmapimage resizing is messed up in windows 11 24H2

rakesh kumar 0 Reputation points
2024-10-15T20:43:28.44+00:00

There is a WPF ImageControl that takes local file as source.

Before saving it on server, I am trying to resize the image so that I dont store huge files. I am also trying to reduce the image quality if image size exceeds 12 kb even after resizing.

But in few images, all of a sudden only "a part of image" is getting saved. I cannot reproduce it on my PC but PC that is showing this behaviors have recently being updated to windows 11 24H2.

I wonder if any of the above code is impacted with windows 11 24H2.

private const int MaxHeight = 240;
private const int MaxWidth = 200;
private const long CompressionQuality = 75L;
private const int CompressOnSizeExceeding = 12288;

public static byte[] ProcessBitMapSourceToByteArrayWithCompression(BitmapSource bitmapSource,
    long imageQuality = CompressionQuality, 
    ImageFormat imageFormat = null)
{            
    if (bitmapSource == null) return null;
    var bytes = CompressImageDimensions(bitmapSource);
    if (bytes == null) return null;
    if (bytes.Length < CompressOnSizeExceeding) 
        return bytes;
    if (imageFormat == null)
        imageFormat = ImageFormat.Jpeg;
    return CompressImageQuality(bytes, imageQuality, imageFormat);
}

private static byte[] CompressImageDimensions(BitmapSource bitmapSource,
    int maxHeight = MaxHeight, int newWidth = MaxWidth)
{
    try
    {
        if (bitmapSource == null)
            throw new ArgumentNullException("bitmapSource");

        if (bitmapSource.PixelWidth < newWidth)
        {
            newWidth = bitmapSource.PixelWidth;
        }
        
		int newHeight = bitmapSource.PixelHeight * newWidth / bitmapSource.PixelWidth;
        if (newHeight > maxHeight)
        {
            newWidth = bitmapSource.PixelWidth * maxHeight / bitmapSource.PixelHeight;
            newHeight = maxHeight;
        }

        using (var memStream = new MemoryStream())
        {
            var encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(ResizeImageToBitmapFrame(bitmapSource, newWidth, newHeight, 0));
            encoder.Save(memStream);
            return memStream.ToArray();
        }
    }
    catch (Exception ce)
    {
        Utility.Log(ce);
    }
    return null;
}

private static BitmapFrame ResizeImageToBitmapFrame(ImageSource source, int width, int height, int margin)
{
    try
    {
        var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2);
        var group = new DrawingGroup();
        RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.Fant);
        group.Children.Add(new ImageDrawing(source, rect));
        var drawingVisual = new DrawingVisual();
        using (var drawingContext = drawingVisual.RenderOpen())
            drawingContext.DrawDrawing(group);
        var resizedImage = new RenderTargetBitmap(
            width, height, // Resized dimensions
            96, 96, // Default DPI values
            PixelFormats.Default); // Default pixel format
        resizedImage.Render(drawingVisual);
        return BitmapFrame.Create(resizedImage);
    }
    catch (Exception ce)
    {
        FileLogger.WriteLog(ce);
        throw;
    }
}

private static byte[] CompressImageQuality(byte[] bytes, long imageQuality, ImageFormat imageFormat)
{
    if (bytes == null || bytes.Length == 0) return null;
    try
    {
        var ic = new ImageConverter();
        var sourceImage = (Image) ic.ConvertFrom(bytes);
        var imageQualitysParameter = new EncoderParameter(
            Encoder.Quality, imageQuality);

        var codecParameter = new EncoderParameters(1);
        codecParameter.Param[0] = imageQualitysParameter;
        //Find and choose JPEG codec
        ImageCodecInfo jpegCodec = GetEncoder(imageFormat);
        //Save compressed image
        using (var memoryStream = new MemoryStream())
        {
            sourceImage?.Save(memoryStream, jpegCodec, codecParameter);
            return memoryStream.ToArray();
        }
    }
    catch (Exception ce)
    {
        Utility.Log(ce);
    }
    return null;
}

private static ImageCodecInfo GetEncoder(ImageFormat format)
{
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
    return codecs.FirstOrDefault(codec => codec.FormatID == format.Guid);
}
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,788 questions
Windows 11
Windows 11
A Microsoft operating system designed for productivity, creativity, and ease of use.
10,013 questions
{count} votes

4 answers

Sort by: Most helpful
  1. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

  2. Alexander Magdysyuk 5 Reputation points
    2024-10-21T20:36:12.0233333+00:00

    Looks like I cannot post my solution here with links: I just replaced GDI+ with not free library "MESCIUS Document Solutions for Imaging".

    0 comments No comments

  3. Hongrui Yu-MSFT 2,865 Reputation points Microsoft Vendor
    2024-10-24T05:24:02.3766667+00:00

    Hi,@rakesh kumar.

    This is a known issue in the WIC jpeg encoder (which GDI+ uses). The Windows team is aware, and it has been fixed. It should show up in servicing soon (next month or two most likely).

    Related Documents: https://github.com/dotnet/winforms/issues/12339


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


  4. Deleted

    This answer has been deleted due to a violation of our Code of Conduct. The answer was manually reported or identified through automated detection before action was taken. Please refer to our Code of Conduct for more information.


    Comments have been turned off. Learn more

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.