Cannot Load Texture with MTKTextureLoader

Every time I attempt to load an image using MTKTextureLoader, my app crashes simply saying "Image decoding failed". Here is the relevant code:


let loader = MTKTextureLoader(device: Renderer.main.device)
do {
     texture = try loader.newTexture(name: name,
                                     scaleFactor: Renderer.main.displayLayer.contentsScale,
                                     bundle: Bundle.main,
                                     options: nil)
} catch(let error) {
     fatalError("Error when loading image \"\(name)\": " + error.localizedDescription)
}

(name = "Circle"; Circle is an image in my asset catalog)


This is not an issue of not finding the image, because if I change the "name" variable to something that is not in my asset catalog, I get an error that states the image could not be located. This also does not have to do with the "scaleFactor", because I have tried manually setting that to 1.0, 2.0, and 3.0, with no success. I have checked the .png's properties using the file command, and it gives me this:


PNG image data, 300 x 300, 8-bit/color RGBA, non-interlaced


So clearly the file is not corrupt and certainly is not unusual; it's just your average .png file. Also, this is erroring when run on my iPhone 8 (iOS 12.4; deployment target is iOS 10.3).


Is there some step I'm missing or doing wrong?

Replies

Come on Apple! Loading PNGs doesn't seem to work. Help your developers...

I came to the forum because I have been having the exact same problem. My code is in Objective-C, but I have been trying to use the equivalent method on MTKTextureLoader. I went down the same path as you with . . . odd results.

In my code, I have an array of texture file names that correspond to the texture names in Xcode's image set. I loop through them passing each texture name to [textureLoader newTextureWithName:imageName:scaleFactor:1.0: bundle:nil:options:loaderOptions:error:&error];.

For some of the textures, the code works as expected. For others, I receive the "Image decoding failed" error in my log. I thought there might be an error in the texture name conventions, but I set up a test for that to ensure everything matches. I was also able to load the images that do not load with the MTKTextureLoader using a different framework.

I suspect Xcode's asset catalog is having trouble interfacing with Metal. I was hoping to find a work around, but for the time being, I am loading the textures outside of the asset catalog like so:

Code Block Objective-C
NSURL* img = [[NSBundle mainBundle]URLForResource:imageName withExtension:@"png"];
id<MTLTexture> texture = [textureLoader newTextureWithContentsOfURL:img options:nil error:&error];

This approach is working fine for now, but I would love to use the asset catalog instead.

I ran into this error when trying to load a large image (many tens of megapixels). Resizing the image (in this case to 1080P) resolved the issue.

The OP's issue didn't have to do with large size, but I wanted to share my experience because the error didn't offer lots of detail.

I know this is an old post, but there are still problems it seems even with the latest XCode 14 -- wondering if others can confirm this. I got this same error on a small 16x16 PNG that was just a white antialiased dot in PNG format. The file loaded fine into preview -- there was nothing wrong with it. After much experimentation (different sizes, remaking it) I finally discovered why it would not load -- I simply added some color tinting to the image so it was no longer greyscale and it loaded fine. Thinking there is some odd bug where it cannot handle a greyscale PNG. For my purposes I did not care about the color so it is a decent workaround. If others can confirm this I will try to file a bug report.

  • Yes. I can definitely confirm. If your png has only black or white (plus alpha), it will not load into the textureLoader. I tried messing with using indexed png versus 32-bit png. It doesn't seem to make a difference. I tried with different options to the textureLoader -- no difference.

    But add even one colored pixel, the image will load. So for now, that is my work-around!

  • I just encountered the same issue with a PNG with transparent content - using a normal squared image without any transparency worked out fine.

Add a Comment

Just adding to this, you cannot diffuse a CIImage and you must CGImage.

A UIImage initiated from a CIImage won't work either.

I just hit the same problem/error, with RealityView and a Reality Composer Pro scene driven by a Shader Graph Node. This line was working sometimes, not working others:

let newTexture = try TextureResource.load(named: newValue)

It turns out it was failing on 1024x1024 PNGs that were all grayscale. Adding a tiny red line on each one cured it (done in Preview.app, color model of the PNG is still "Gray").

Xcode 15.3, reproducible on Simulator and on Vision Pro running visionOS 1.2.

Feedback FB13733823.