Encoded string is not working in swift - swift

In my swift App, I need to convert Image as String, then I need to send to Server , i.e POST. Then, if I need to GET, I dont want to decode that. Response having Image file name and path.
ONline Converter:
If I convert the sample image through online converter, HERE. I am getting following string. If I pass this string to API, I can get image successfully.
Output:
iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR.... .....CIBhIIgQRCIIEQSCAQAgmEQAIhkEAIJBAIgQRCIIEQSCAEEgiEQAIhkEAIJCgN/F+AAQAXoGXl+IGgwwAAAABJRU5ErkJggg==
Through My Coding
If I convert the sample image through Coding, I am getting following string. If I pass this string to API, Successfully adding. But, I unable to view that image manually in browser too.
More Over,, Two Output Strings are not same. I dont know why? Kindly guide me, how to solve this?
Code:
var image : UIImage = UIImage(named: "home_recharge.png")!
var imageData = UIImagePNGRepresentation(image)
let base64String = imageData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros)
println("base64String \(base64String)")
Output:
iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAAAXNSR0IArs4c6QAAABxpRE9UAAAAAgAAAAAAAABIAAAAKAAAAEgAAABIAAAKygzM7MwAAAqWSURBVHgB7FwJ0JZDHC9yhJTkLuRMjuQ+opAr5zjGqAwZx...... .......FlIs5ASSDNQLA7EMtYMpBlICaQZKBYHYhlrBtIMpATSDBSLA7GMNQNpBlICaQaKxYFYxpqBNAMpgTQDxeJALGPNQJqBlECagWJxIJaxZiDNQP8B+6MkTad9NtcAAAAASUVORK5CYII=

You use png image representation but server saves the image with .jpg extension so browser tries to read image as JPEG file and fails.
You should replace UIImagePNGRepresentation with UIImageJPEGRepresentation or save image with .png extension.
The reason why browser can open online converter result image despite it has wrong extension is possibly that UIImagePNGRepresentation strips the image of its meta data and online converter not so browser can not figure the real type of image with wrong extension without meta data.

Related

Performance problem with saving images locally and writing to api in Swift 4

We are transforming images to a byte array and then saving them as a string in a JSON file. This happens locally on the file system. When reading this JSON file from the file system or writing it to the API the performance is really bad. For large quantities of images you have to wait >10 sec, before it is loaded in the ViewController. Is there a better way or library (Swift4) to deal with this? We are already compressing the quality to 0.2. Someone told us to use base64, is this the way to go?
We encode the image like this:ImagesBytes : [[UInt8]]? in to a JSON File with some TextField data.
This is the code
public var formImagesBytes : [[UInt8]]? = [] So this is in the model as a field. The model is a form with fields(strings) and an array of images which is an array of UInt8. This will be first saved locally while decoding it like this:
formImagesBytes = try container.decodeIfPresent([[UInt8]].self, forKey: .formImagesBytes)
Then we JSON encode all the data, including values of the form and image array of bytes. Then we add it with the Filemanager to the local storage on the device. We can open this file and it is including the formdata and an array of bytes in this case.
When loading the data from the local storage in the viewcontroller we again read this local file en decode it to a form model. But processing this file is taking too much time. I hope it is clear. My question is not really about the code, but about: is there a best practice or better way to write the image to this JSON file in order to let the app perform better.
Example output:
{"Images":[[255,216,255,224,0,16,74,70,73,70,0,1,1,0,0,144,0,144,0,0,255,225,0,140,69,120,105,102,0,0,77,77,0,42,0,0,0,8,0,5,1,18,0,3,0,0,0,1,0,1,0,0,1,26,0,5,0,0,0,1,0,0,0,74,1,27,0,5,0,0,0,1,0,0,0,82,1,40,0,3,0,0,0,1,0,2,0,0,135,105,0,4,0,0,0,1,0,0,0,90,0,0,0,0,0,0,0,144,0,0,0,1,0,0,0,144,0,0,0,1,0,3,160,1,0,3,0,0,0,1,0,1,0,0,160,2,0,4,0,0,0,1,0,0,1,82,160,3,0,4,0,0,0,1,0,0,0,253,0,0,0,0,255,237,0,56,80,104,111,116,111,115,104,111,112,32,51,46,48,0,56,66,73,77,4,4,0,0,0,0,0,0,56,66,73,77,4,37,0,0,0,0,0,16,212,29,140,217,143,0,178,4,233,128,9,152,236,248,66,126,255,192,0,17,8,0,253,1,82,3,1,34,0,2,17,1,3,17,1,255,196,0,31,0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,16,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,125,1,2,3,0,4,17,5,18,33,49,65,6,19,81,97,7,34,113,20,50,129,145,161,8,35,66,177,193,21,82,209,240,36,51,98,114,130,9,10,22,23,24,25,26,37,38,39,40,41,42,52,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,225,226,227,228,229,230,231,232,233,234,241,242,243,244,245,246,247,248,249,250,255,196,0,31,1,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,255,196,0,181,17,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,119,0,1,2,3,17,4,5,33,49,6,18,65,81,7,97,113,19,34,50,129,8,20,66,145,161,177,193,9,35,51,82,240,21,98,114,209,10,22,36,52,225,37,241,23,24,25,26,38,39,40,41,42,53,54,55,56,57,58,67,68,69,70,71,72,73,74,83,84,85,86,87,88,89,90,99,100,101,102,103,104,105,106,115,116,117,118,119,120,121,122,130,131,132,133,134,135,136,137,138,146,147,148,149,150,151,152,153,154,162,163,164,165,166,167,168,169,170,178,179,180,181,182,183,184,185,186,194,195,196,197,198,199,200,201,202,210,211,212,213,214,215,216,217,218,226,227,228,229,230,231,232,233,234,242,243,244,245,246,247,248,249,250,255,219,0,67,0,28,28,28,28,28,28,48,28,28,48,68,48,48,48,68,92,68,68,68,68,92,116,92,92,92,92,92,116,140,116,116,116,116,116,116,140,140,140,140,140,140,140,140,168,168,168,168,168,168,196,196,196,196,196,220,220,220,220,220,220,220,220,220,220,255,219,0,67,1,34,36,36,56,52,56,96,52,52,96,230,156,128,156,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,255,221,0,4,0,22,255,218,0,12,3,1,0,2,17,3,17,0,63,0,223,162,138,40,16,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,1,255,208,223,162,138,40,16,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,1,255,209,223,162,138,40,16,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,1,255,210,223,162,138,40,16,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0,81,69,20,0]],
Here is a screenshot:
Output of the Image in a ByteArray
The JSON you posted explains why it is taking so long to parse. It probably takes a while to parse these huge arrays.
Instead of having each image as an array of bytes it should just be one base64 encoded string for each image. Something like this:
public var formImagesBase64 : [String]?
Here is some Swift code that might help you:
// Encoding Image
let data = image.jpegData(compressionQuality: 1)
let b64string = data?.base64EncodedString()
// Decoding image
let decodedData = Data(base64Encoded: b64string!)
let decodedImage = UIImage(data: decodedData!)

swift: image is nil after converting to CIImage

I am new to swift and I am trying the CoreML feature using React Native.
I have a source file with URL as string. I convert that string to URL using let imageURL = URL(fileURLWithPath: source) and I tried printing out the source which is of type string and it contains the absolutePath to the file file:///var/mobile/Containers/Data/Application/9C4D58FD-C817-47CB-A418-04BA30863C24/Library/Caches/Camera/133F8168-356A-436C-B7AF-557FA1C4F68F.jpg"
After that, I try to make the CIImage by using let image = CIImage.init(contentsOf: imageURL);
But when I try to print image, it returns nil. I searched a bit and tried using guard but no luck. Any help will be appreciated. Thanks in advance.
The CIImage does not create the image from a server URL. You can achieve this by first downloading the file at local location. And use the local file URL to create CIImage and then set it. The referred question/answer achieves the same, please check Loading/Downloading image from URL on Swift
If you still face issues do let me know. All the best!

UIImage generated base64 is larger than it's referenced (local) base64 image

I am capturing an image via a user's Camera (using a library called CameraManager). The captured image is saved to the file disk (for testing purposes only), and also generates a UIImage, which is then converted to a base64 string via:
cameraManager.capturePictureWithCompletion({ (image, error) -> Void in
let UIImage = UIImageJPEGRepresentation(image!, 0.85)!
let base64Image = UIImage.base64EncodedString(options: .lineLength64Characters)
...
Now when I select the same image (which was saved to the disk) via an image-picker plugin, I am returned a base64 string (of the same image) and it is a little more than 2.5x smaller than the original captured image that it represents.
What could be causing the extra overhead? Could it be something that is being embedded in the UIImage? My other thought was to just save the UIImage to a temp folder, pass the URI to the client, and then have the client worry about converting it to a base64 string to see if it makes the string smaller.

iOS - Should we just save image as local file or as binary data (in Core Data object)? Which way is faster?

I'm currently use binary data saved in Core Data object to generate UIImage as code below.
UIImage * postImage = [UIImage imageWithData:image];
double imageRatio = postImage.size.height / postImage.size.width;
[imageContent setFrame:CGRectMake(imageContent.frame.origin.x, imageContent.frame.origin.y, imageContent.frame.size.width, imageContent.frame.size.height * imageRatio)];
[imageContent setImage:postImage];
However, I found there's a little bit slow when generate image.
Should I save image locally when retrieve data from server instead?
Which way is faster?
Thanks,
Save the image locally (e.g. in the Documents or Caches directory) instead of in the Core Data database. You get no benefit from storing binary data in the database as you will never search or index by this data, and it will just bloat your database. Just store an NSString reference to the filename/path you save the image to.
I imagine the UIImage:imageWithData method is slower when compared with reading an image from file that is already in a suitable image format.
save image locally and in your coreData save the location and name "URL" for that image
save your image locally such as PNG or JPEG instead of NSData.

iPhone how to send a large image along with a JSON file? Should I embed it within the JSON or send separately?

I'm trying to create a way to save the interface of my app in a JSON file. While static elements I can define by their frames and/or center points, the interface does include a single image selected from the photo library. Because some iPhones have 8MP cameras, I can anticipate that some images would be very large.
I would like to be able to save this interface and send it over by email, so another app user can re-open the file and see the same interface with the image included.
Currently I'm using JSONKit to save my data into a JSON object. This means that the email will contain a single JSON file containing both the layout parameters and the image. I've never worked with such large JSON files, so the question is - will having several megs of image data within JSON present parsing issues? Or should I select some other file container that would have : first part JSON file, second part raw image data and then separate that file into a JSON string and a raw data string?
This is what I'm using currently to get a JSON file. After adding NSData to JSON, the convert to json method returns nil
NSString* currentURL = webView.request.mainDocumentURL.absoluteString;
[dictionary setValue:currentURL forKey:#"webViewAddress"];
//this call correctly returns the json string
NSLog(#"%#", [dictionary JSONString]);
NSLog(#"+++++++++++++++++++++++++++++++++++++");
NSData* imageData = UIImagePNGRepresentation(arOverlayView.image);
//after this call, the json returns nil
[dictionary setValue:imageData forKey:kimageData];
NSLog(#"%#", [dictionary JSONString]);
If you are using email as a transport mechanism, your binary data will have to end up as something like Base64 encoded at some point in its life. There is no "raw" format for email, there is only text.
At best you could implement Base85 encoding which is more efficient than Base64
So you are going to have to suck up the large file sizes unless you invent your own transport mechanism - such as a point to point TCP/IP based link.