[UWP] BitmapEncoder.CreateForTranscodingAsync() throws InvalidCastException when loading heic images taken on iPhone

Mark bryan 6 Reputation points
2022-08-31T08:42:40.263+00:00

The below code throws an InvalidCastException when loading heic taken by an iPhone.
Other heic images and any other image format work as expected.

This behavior could be observed on multiple machines with Windows 11 and with different images.

var decoder = await BitmapDecoder.CreateAsync(imageStream);  
  
var resizedStream = new InMemoryRandomAccessStream();  
  
var encoder = await BitmapEncoder.CreateForTranscodingAsync(resizedStream, decoder);  
  
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Linear;  
  
// ********** InvalidCastException happens here for heic images from iPhones ***********************  
await encoder.FlushAsync();  

I've uploaded a minimal example that demonstrates the issue https://github.com/sperauer/BitmapDecoderTranscodingSample/
An example heic image can be found in the project BitmapDecoderTranscodingSample\App1\TestImage.HEIC

Does the code need any modifying or is this a bug in the framework?

Universal Windows Platform (UWP)
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,905 questions
0 comments No comments
{count} vote

2 answers

Sort by: Most helpful
  1. Roy Li - MSFT 33,091 Reputation points Microsoft Vendor
    2022-09-01T03:12:36.307+00:00

    Hello,

    Welcome to Microsoft Q&A!

    First of all, I've tested the sample you shared. Both of the images will throw exception. The TestImage.heic will throw InvalidCastException exception. The TestImageThatWorks.heic will throw "No suitable transform was found to encode or decode the content" error when calling await wb.SetSourcAsync(resizedStream).

    Does the code need any modifying or is this a bug in the framework?

    Back to the question, I have to say that this behavior is expected. Please take a look at the document for BitmapEncoder Class, in the Remark section, go to the Image formats parts, it is mentioned that the BitmapEncoder could encode the following formats: JPEG, PNG, GIF, TIFF, BMP, JPEG-XR. And you could check BitmapDecoder Class for the formats it supports as well. HEIC is not the format that the BitmapEncoder supports. So you can't use the BitmapEncoder to process the HEIC image.

    Thank you.


    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.

    0 comments No comments

  2. Stefan Perauer 1 Reputation point
    2022-09-01T16:03:41.427+00:00

    Hi Roy,

    Thanks for the thorough reply!

    There are no Image formats on the BitmapEncoder page, your link goes to the BitmapDecoder page which does mention the formats.
    I think the formats section for BitmapDecoder is incomplete, as further down in Version History the HEIF decoder is mentioned as implemented.
    Confusingly, on my system BitmapEncoder has a HeifEncoderId which suggested to me that it's supported for encoding.

    I've done the workaround below that correctly decodes all heif/heic files I have, I've tested on Windows 10 and 11.
    For windows 10 the HEIF and the HEVC extension needs to be installed, on Windows 11 HEIF/HEVC is supported natively.

    Note, that the workaround only uses BitmapDecoder to decode the HEIF/HEIC, for encoding PNG is used.

     var transform = new BitmapTransform  
    {  
        ScaledWidth = scaledWidth,  
        ScaledHeight = scaledHeight,  
        InterpolationMode = interpolationMode  
    };  
    
    stream.Seek(0);  
    
    var pixelData = await decoder.GetPixelDataAsync(  
        BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, transform,  
        ExifOrientationMode.RespectExifOrientation,  
        ColorManagementMode.DoNotColorManage);  
    
    var pixels = pixelData.DetachPixelData();  
    
    var resizedStream = new InMemoryRandomAccessStream();  
    var encoder = await BitmapEncoder.CreateAsync(  
        BitmapEncoder.PngEncoderId, resizedStream);  
    
    encoder.SetPixelData(  
        BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight,  
        scaledWidth, scaledHeight, 96, 96, pixels);  
    
    await encoder.FlushAsync();  
    

    My conclusion is that BitmapDecoder supports HEIF/HEIC decoding, whereas BitmapEncoder only supports HEIF encoding, but not HEIC encoding.

    Thanks!


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.