SDWebImage / SDWebImageSVGCoder

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

CoreSVG can not decode base-64 image contains \r (`
`) line feed #52

Closed esilverberg closed 7 months ago

esilverberg commented 7 months ago

My company is trying to render SVG images that contain both vector and rasterized layers. Is this library capable of rendering SVG images like this? So far we have been unsuccessful - this lib only renders the vector portion of our SVG images.

dreampiggy commented 7 months ago

Yes. See readme, using "thumnailPixelSize" option

esilverberg commented 7 months ago

Thank you very much for the quick reply and thank you for all of your work on this very important library! 🙏 ❤️

Let me explain what we are seeing. I am attempting to use the SDImageSVGCoder which seems to be the best choice from what I can tell after reading the Readme.

Here is how I am setting it up:

let SVGCoder = SDImageSVGCoder.shared
SDImageCodersManager.shared.addCoder(SVGCoder)

I then tried to render an SVG in SwiftUI this way:

public struct PSSSVG: UIViewRepresentable {
    public func updateUIView(_ uiView: UIImageView, context: Context) {
    }

    public init() {
    }

    public func makeUIView(context: UIViewRepresentableContext<Self>) -> UIImageView {
        let view = UIImageView()

        view.sd_setImage(
            with: Bundle.main.url(forResource: "demo", withExtension: "svg")!, placeholderImage: nil, context: [.imageThumbnailPixelSize: CGSize(width: 600, height: 400)])
        return view
    }
}

struct ContentView: View {
    var body: some View {
        PSSSVG()
            .background(.red)
            .frame(width: 600, height: 400)
    }
}

I just created a test file in Inkscape; I exported it as an Inkscape SVG.

Here is the file from Inkscape: demo

Here is what it actually looks like in the simulator:

Screenshot 2024-03-23 at 3 21 44 PM

I have not succesfully be able to get any SVG file with a rasterized layer to render on iOS so maybe this is just not possible?

Here is the original Inkscape SVG file as a ZIP; when I attach it directly I think Github is converting it somehow. Inkscape Smaller.svg.zip

dreampiggy commented 7 months ago

Bundle.main.url ?

It seems you're using Assets catalog SVG without that Preserve Vector Data ?

Assets car is a pre-compiled tool, which will turn your image into the format Apple supported, unless you lick Preserve Vector Data.

So I guess you don't load that SVG at all. Your SVG was recognized as a Symbol Image (which is different than SVG actually, even they're all using XML)

dreampiggy commented 7 months ago

Try using without Assets Catalog, use Data to read raw SVG and load into SDWebImge.

You can use any supported way:

  1. Use [NSURL fileURLWithPath:] to create file URL and load into sd_setImageWithURL:
  2. Use [NSURL URLWithString:] with base64 encoded string data:image/svg+xml;base64,abcdefg....
  3. Use [UIImage sd_imageWithData:] to create a spcial UIImage with supportes Vector Image and load through that SDImageSVGCoder, then just set on the UIImageView
  4. Just to be stupid, since you use SwiftUI, why not look at :https://github.com/SDWebImage/SDWebImageSwiftUI, use
WebImage(url: svgURL)
// or 
AniamtedImage(url: svgURL)
// or
AnimatedImage(data: svgData)
dreampiggy commented 7 months ago

Well. Seems I use the SwiftUI demo and it shows as yours.

image

dreampiggy commented 7 months ago

Seems Apple's CoreSVG is unsupported for <image xlink:href=> ?

dreampiggy commented 7 months ago

Can you have a try with Adobe SVG-native parser instead of Apple's CoreSVG ?

https://github.com/SDWebImage/SDWebImageSVGNativeCoder

Since you don't care abot vector inforamtion. Only want bitmap variant. That's better.

dreampiggy commented 7 months ago

After some detail retry, It seems your SVG use embed base64, and it's eval form that Apple's CoreSVG can not detect it.

https://base64.guru/tools/repair report some invalid string character. I don't know whether WebKit (The broswer's SVG engine) has some smart detection and fix-up or not.

image

After fixing, I can extract the original JPEG from it

download.jpeg.zip

dreampiggy commented 7 months ago

After I remove all your original SVG's &#10; characters, it can not displayed in CoreSVG and UIImageView image

Where this &#10; came from ?

dreampiggy commented 7 months ago

https://stackoverflow.com/questions/3025265/what-does-unicode-character-10-represent

Seems &#10; is \r for Windows. The line feed. Mac use UNIX system and only \n for line break. Not \n\r

For now, you need to post-process and remove these thing. Do not add \r on Mac for SVG encoded string

esilverberg commented 7 months ago

Thank you so much! I did not realize that the editor was generating an invalid SVG file because it could be previewed in Xcode. I generated a different SVG file with Affinity designer and it worked great. Thank you for your help on this!