So Im trying to upload images from photo library to a server with alamofire post method, the uploading parts is working. However it's when I convert the UIImage to Base64 before uploading that stripes/removes all the exif information from the image.
Before converting the UIImage to Base64 all exif information is there and accessible but after the conversion the exif information is removed. I have tried uploading a Base64 of the same UIImage but converted on a website and that kept the exif information, that proves that the problem is with the swift version of the conversion.
Here is what the converting part of the code looks like:
func imageTobase64(image: UIImage) -> String {
var base64String = ""
let cim = CIImage(image: image)
if (cim != nil) {
let imageData = image.jpegData(compressionQuality: 1.0)
base64String = imageData!.base64EncodedString(options: NSData.Base64EncodingOptions.lineLength64Characters)
}
return base64String
}
Related
I want to encode a UIImage object into Base64 String. Generally, I'm a getting quite a large string and the process is taking a long execustion time as well.
func convertImageToBase64String () -> String {
guard let imageData: Data = UIImage.jpegData()
let imgString = imageData.base64EncodedString(options: .init(rawValue: 0))
return imgString
}
class func convertBase64StringToImage (imageBase64String: String) -> UIImage? {
guard let imageData = Data.init(base64Encoded: imageBase64String, options: .init(rawValue: 0)) else { return nil }
let image = UIImage(data: imageData)
return image
}
Please provide me a li'l help here.
What you want isn't possible. The JPEG data is already a compressed form of the image. And when you convert data to base64 encoding, the result is a string that will be 33% larger than the original data.
So the only way to get a base64 encoded string representation of a JPEG image that is less than 100 characters is to ensure that the original JPEG is less than 66 bytes. I'm pretty sure that even a 1x1 pixel JPEG will be more than 66 bytes.
If the JPEG is a full photograph taken on an iOS device, the resulting data will be a few megabytes. That takes time to submit.
I have an application where user can upload multiple images and all the images will be stored in a server and will be displayed on a web view in my iOS application.
Now everything used to work just about fine till iOS 10 but suddenly we started seeing some pictures/ images not being displayed , after a little debugging we found out that this is the problem caused because of the new image format of apple (HEIC),
I tried changing back to the Native UIImagePicker (picks only one image) and the images are being displayed as Apple I guess is converting the Image from HEIC to JPG when a user picks them, but this is not the case when I use 3rd party libraries as I need to implement multiple image picker.
Though we are hard at work to make the conversion process on the server side to avoid users who have not updated the app to face troubles, I also want to see if there is any way in which I can convert the image format locally in my application.
There's a workaround to convert HEIC photos to JPEG before uploading them to the server :
NSData *jpgImageData = UIImageJPEGRepresentation(image, 0.7);
If you use PHAsset, the, in order to have the image object, you'll need to call this method from PHImageManager:
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;
On server side you also have the ability to use this API or this website directly
I've done it this way,
let newImageSize = Utility.getJpegData(imageData: imageData!, referenceUrl: referenceUrl!)
/**
- Convert heic image to jpeg format
*/
public static func getJpegData(imageData: Data, referenceUrl: NSURL) -> Data {
var newImageSize: Data?
if (try? Data(contentsOf: referenceUrl as URL)) != nil
{
let image: UIImage = UIImage(data: imageData)!
newImageSize = image.jpegData(compressionQuality: 1.0)
}
return newImageSize!
}
In Swift 3, given an input path of an existing HEIF pic and an output path where to save the future JPG file:
func fromHeicToJpg(heicPath: String, jpgPath: String) -> UIImage? {
let heicImage = UIImage(named:heicPath)
let jpgImageData = UIImageJPEGRepresentation(heicImage!, 1.0)
FileManager.default.createFile(atPath: jpgPath, contents: jpgImageData, attributes: nil)
let jpgImage = UIImage(named: jpgPath)
return jpgImage
}
It returns the UIImage of the jpgPath or null if something went wrong.
I have found the existing answers to be helpful but I have decided to post my take on the solution to this problem as well. Hopefully it's a bit clearer and "complete".
This solution saves the image to a file.
private let fileManager: FileManager
func save(asset: PHAsset, to destination: URL) {
let options = PHContentEditingInputRequestOptions()
options.isNetworkAccessAllowed = true
asset.requestContentEditingInput(with: options) { input, info in
guard let input = input, let url = input.fullSizeImageURL else {
return // you might want to handle this case
}
do {
try self.save(input, at: url, to: destination)
// success!
} catch {
// failure, handle the error!
}
}
}
private func copy(
_ input: PHContentEditingInput, at url: URL, to destination: URL
) throws {
let uniformType = input.uniformTypeIdentifier ?? ""
switch uniformType {
case UTType.jpeg.identifier:
// Copy JPEG files directly
try fileManager.copyItem(at: url, to: destination)
default:
// Convert HEIC/PNG and other formats to JPEG and save to file
let image = UIImage(data: try Data(contentsOf: url))
guard let data = image?.jpegData(compressionQuality: 1) else {
return // you might want to handle this case
}
try data.write(to: destination)
}
}
I'm writing a Swift chat app using JSQMessageViewController as well as PubNub. I have no problem getting text messages in real time and display them correctly. But I'm stuck on retrieving image messages, I can send images without any problems but when the receiver gets the image it becomes a NSCFString data. The output of print(message.data.message) in PubNub's didReceiveMessage function is :<UIImage: 0x155d52020>, {256, 342}, And the output of print(message.data) is : { message = "<UIImage: 0x155d52020>, {256, 342}"; subscribedChannel = aUpVlGKxjR; timetoken = 14497691787509050;}
Does anyone know how to convert this data to UIImage?
You need to convert UIImage to base64 encoding and then send to pubnub message and then decode base64 into UIImage.
Encode:
let imageData = UIImagePNGRepresentation(image)
let imageString = imageData.base64EncodedStringWithOptions(.allZeros)
Decode:
let imageData = NSData(base64EncodedString: imageString, options: NSDataBase64DecodingOptions.fromRaw(0)!)
var image = UIImage(data: imageData)
Reference: Convert between UIImage and Base64 string
I'm using UIImageJPEGRepresentation(...) to compress images before I store them on a server. My problem is when I am retrieving them from the server I need a way to decompress them in order to display the image again. How would I go about this using swift?
Thanks!
It's as simple as creating a UIImage from the NSData representing the image
//imageData is the JPEG compressed data retrieved from your server
if let image = UIImage(data: imageData) {
//do something with image
} else {
//image is nil, do something else
}
you might be use below code:
let img = UIImage(data: serverData) // serverdata means get response to server side
This question already has answers here:
Convert between UIImage and Base64 string
(24 answers)
Closed 6 years ago.
A web service echoes a Base64 encoded image as a string. How can one decode and display this encoded image in a Swift project?
Specifically, I would like to take an image, which is already provided by the web service as a string in Base64 format, and understand how to display it in a UIImageView.
The articles I have found thus far describe deprecated techniques or are written in Objective-C, which I am not familiar with. How do you take in a Base64-encoded string and convert it to a UIImage?
Turn your base64 encoded string into an NSData instance by doing something like this:
let encodedImageData = ... get string from your web service ...
let imageData = NSData(base64EncodedString: encodedImageData options: .allZeros)
Then turn the imageData into a UIImage:
let image = UIImage(data: imageData)
You can then set the image on a UIImageView for example:
imageView.image = image
To decode Base64 encoded string to image, you can use the following code in Swift:
let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions.fromRaw(0)!)
var decodedimage = UIImage(data: decodedData)
println(decodedimage)
yourImageView.image = decodedimage as UIImage
Even better, you can check if decodedimage is nil or not before assigning to image view.