Faster UIImage - Base64 conversion

南楼画角 提交于 2019-12-04 05:43:58

问题


I am doing work where I have to encode and decode between UIImage and Base 64 string). This works great with smaller images, it takes less than 1 second to do the conversion forward and backward, but when I apply it to larger images it takes a long time, almost a minute.

Is there any other way to encode and decode UIImage objects to string to save them in SQLite database? Or if there is no other way to improve this, is there something else I can do to get this job done and I could get rid of the problem?

These are the extension methods I use to do the work:

extension String {
    var toUIImage: UIImage? {
        var img = self
        img = String(img.characters.map({ $0 == "\r" ? " " : $0 }))
        img = String(img.characters.map({ $0 == "\n" ? " " : $0 }))
        img = String(img.characters.map({ $0 == "\r\n" ? " " : $0 }))
        let dataDecoded:NSData? = NSData(base64EncodedString: img, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
        return UIImage(data: dataDecoded!)
    }
}

extension UIImage {
    var toString: String {
        let data = UIImagePNGRepresentation(self)
        let encoded =  data!.base64EncodedDataWithOptions(.Encoding64CharacterLineLength)
        var cadena = String(data: encoded, encoding: NSUTF8StringEncoding)!

        cadena = String(cadena.characters.map({ $0 == "\r" ? " " : $0 }))
        cadena = String(cadena.characters.map({ $0 == "\n" ? " " : $0 }))
        cadena = String(cadena.characters.map({ $0 == "\r\n" ? " " : $0 }))

        return cadena
    }
}

回答1:


With the String extension, you can just use .IgnoreUnknownCharacters and you don't have to do any replacement of \r and \n at all:

extension String {
    var imageFromBase64EncodedString: UIImage? {
        if let data = NSData(base64EncodedString: self, options: .IgnoreUnknownCharacters) {
            return UIImage(data: data)
        }
        return nil
    }
}

Likewise, in your UIImage extension, don't use .Encoding64CharacterLineLength, which introduces the \r and \n, only to then remove them. If you don't use that option, there is no \r and \n to remove:

extension UIImage {
    var base64EncodedString: String? {
        if let data = UIImagePNGRepresentation(self) {
            return data.base64EncodedStringWithOptions([])
        }
        return nil
    }
}

Two observations regarding SQLite:

  1. If you're going to store image in database, just store the NSData SQLite database as blob and be done with it. That not only eliminates this "what do I do with \r and \n characters", but it completely eliminates the base64 encoding/decoding process entirely. It also makes the what you store in the database 25% smaller. It's a lot more efficient.

  2. Even with that, SQLite is notoriously inefficient in storing large objects in database at all. If you want best performance, store images in the file system, and only store relative path references in your database. My rule of thumb is that if I'm dealing with thumbnail images, SQLite blobs are fine, but for anything larger, use the file system.




回答2:


You do not need 'map' code at all. Following code:

img = String(img.characters.map({ $0 == "\r" ? " " : $0 }))
img = String(img.characters.map({ $0 == "\n" ? " " : $0 }))
img = String(img.characters.map({ $0 == "\r\n" ? " " : $0 }))

is useless if you use NSData(base64EncodedString:options:) with IgnoreUnknownCharacters option. Check the description:

IgnoreUnknownCharacters

Modify the decoding algorithm so that it ignores unknown non-Base-64 bytes, including line ending characters.



来源:https://stackoverflow.com/questions/39173048/faster-uiimage-base64-conversion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!