SDWebImage / SDWebImageSVGCoder

A SVG coder plugin for SDWebImage, using Apple's built-in framework
MIT License
103 stars 34 forks source link

Unable to render SVG image on watchOS #24

Closed loganrockmore closed 4 years ago

loganrockmore commented 4 years ago

Hello! I'm having an issue rendering SVG images on watchOS and I'm wondering if you can help me out.

I'm using SDWebImageSVGCoder along with SDWebImageSwiftUI to try and show SVG images in a watchOS app. I've created an example project that uses Cocoapods to pull in version 1.5.0 of SDWebImageSVGCoder. In that app, I'm doing the following:

struct ContentView: View {
    var body: some View {
        VStack {
            WebImage(url: URL(string: "https://upload.wikimedia.org/wikipedia/commons/8/81/Wikimedia-logo.svg"))
                .resizable()
                .frame(width: 50, height: 50)
                .background(Color.red)
            WebImage(url: URL(string: "https://commons.wikimedia.org/static/images/project-logos/commonswiki.png"))
                .resizable()
                .frame(width: 50, height: 50)
                .background(Color.green)
        }
    }
}

The top image is an SVG and the bottom in a PNG. This is what the app looks like:

Screen Shot 2020-08-10 at 6 40 01 PM

As you can see, the SVG here didn't load. What's interesting is that if I set a breakpoint in SDImageSVGCoder.m at line 124, which is the very end of the decodedImageWithData:options: function, I can see in the debugger that an image is created:

(lldb) po image
<UIImage:0x803349f0 anonymous {1024, 1024}>

The interesting thing is that it is the proper size of the SVG at the URL that I'm passing in, but doing a quicklook of the image in the debugger shows that it's a transparent image:

Screen Shot 2020-08-10 at 6 43 46 PM

Am I doing something incorrect here? Or is there a bug with rendering these SVG images on watchOS? Thanks so much for the help!

dreampiggy commented 4 years ago

watchOS have no UIImageView. AnimatedImage based on UIImageView. Only UIImageView supports Vector SVG.

So, you can not show true vector SVG, PDF, etc on watchOS.

You can only use bitmap rendering. Which means WebImage. See more about this: https://github.com/SDWebImage/SDWebImageSwiftUI/issues/50.

dreampiggy commented 4 years ago

Download your example.

Seems currently for watchOS user, you, as a user, should add the code to use bitmap rendering.

Use code [.thumbnailPixelSize : CGSize.zero] See Example:https://github.com/SDWebImage/SDWebImageSwiftUI/blob/master/Example/SDWebImageSwiftUIDemo/AppDelegate.swift

The framework does not have a special check for watchOS because watchOS does not support UIImageView (Though there is UIImageView in watchOS system framework, not public).

loganrockmore commented 4 years ago

Ah, thanks for the clarification! In some testing, I had seen that using bitmap rendering was working, but I wasn't sure exactly how to enable it. I also found that the code didn't work exactly as you have it in your comment.

In case this helps anybody in the future, here is the SwiftUI code that I was able to use in order to get it working.

WebImage(url: imageURL,
         context: [.imageThumbnailPixelSize : CGSize.zero])

This didn't maintain the image aspect ratio though. In my case, I needed the aspect ratio to remain, so I found it best to just pass in the CGSize that I'm interested in.

WebImage(url: imageURL,
         context: [.imageThumbnailPixelSize : CGSize.init(width: 40, height: 40)])

Thank you so much!

dreampiggy commented 4 years ago

The CGSize.zero, should use SVG's canvas size to render the bitmap version. You means this contains bug ? And you can control to use aspect ratio or not, there exist one options .imagePreserveAspectRatio(defaults to YES). Is this not worked ? Need a fix.

loganrockmore commented 4 years ago

Oh, is that not expected behavior? Yeah, that's what I'm seeing. If I specify CGSize.zero, the aspect ratio is not being maintained.

Here's some example SwiftUI code that I've put together. It uses an SVG image that is taller than it is wide:

HStack(spacing: 10) {
    VStack {
        WebImage(url: URL(string: "https://www.mlbstatic.com/team-logos/team-cap-on-light/137.svg"),
                 context: [.imageThumbnailPixelSize : CGSize.init(width: 70, height: 35)])
            .resizable()
            .frame(width: 70, height: 35)
            .background(Color.gray)
        Text("CGSize.init(width: 50, height: 50)")
    }
    VStack {
        WebImage(url: URL(string: "https://www.mlbstatic.com/team-logos/team-cap-on-light/137.svg"),
                 context: [.imageThumbnailPixelSize : CGSize.zero])
            .resizable()
            .frame(width: 70, height: 35)
            .background(Color.gray)
        Text("CGSize.zero")
    }
}

And here's what it looks like for me on watchOS 6.2:

Simulator Screen Shot - Apple Watch Series 5 - 44mm - 2020-08-11 at 23 05 16

dreampiggy commented 4 years ago

Start debugging.

dreampiggy commented 4 years ago

@loganrockmore Try fix at #25. Use the branch dependency to have a test.

dreampiggy commented 4 years ago

Seems...even I use the old version of SVGCoder, the SVG render still works well 😅

You have wrong code for WebImage. WebImage by default works just as Image, it's not scaledToFit, but instead, depends on UIImage's size and scale up.

You should change your code into

WebImage(url: URL(string: "https://www.mlbstatic.com/team-logos/team-cap-on-light/137.svg"),
         context: [.imageThumbnailPixelSize : CGSize.zero])
    .resizable()
    .scaledToFit() // important
    .frame(width: 70, height: 35)
    .background(Color.gray)
Text("CGSize.zero")
loganrockmore commented 4 years ago

Ah, yes, when I test that out by including .scaledToFit(), I do see that it's working as expected. It seems odd to me that the behavior would sometimes rely on .scaledToFit() to maintain the aspect ratio and that sometimes it's not necessary, but I'm glad that it works. Thanks!

dreampiggy commented 3 years ago

For SVG bitmap image (such as watchOS), new version available in 1.6.0

If you want to keep aspect ratio, and does not know about What's the size of this SVG URL ? this inforamtion. You can provide width or height to 0, which means ignore the limit.

See more complicated rules in README-Render SVG as bitmap image

dreampiggy commented 3 years ago

@loganrockmore Hi. If you still facing this issue. You can have a try with new version.