问题
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:
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.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