UIImage generated base64 is larger than it's referenced (local) base64 image - swift
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.
Related
How to generate grayscale bitmap image using HEX data in XML on MacOS (Swift)
I have image source in XML format (the image size is variable therefore I will need to change the image placeholder size). The image source is individual pixel data written in HEX format as string. It is grayscale BMP image data (without header). I would like to know how to work with the data in order to be able to convert the text HEX pixel data into an image to be displayed in MacOS app using Xcode and Swift. I have achieved similar thing years back using Action Script for AIR app. The image source can look like: <Signature t="8209">000200010000000203435A4B03000000C8010205410.... So first thing is to convert the text HEX string into actual binary data, in Action Script I have used this code (part of cycle to read the whole known length of image data): var pixelData:uint = parseInt(imgdata.substr((j-1)*2,2),16); In this example, part of the "signature" XML key is also information about the actual image size, so I would like to be able to change the image size based on that data and be safe not to over/under run the byte stream length needed for the actual image. So the whole looping through the image pixel data and constructing byte array with alpha, red, green, blue values looked like: var bx2:ByteArray = new ByteArray(); if(img2_w!=0){ for (var j:Number = 0; j <imgdata.length / 2; j++) { var pixelData:uint = parseInt(imgdata.substr((j-1)*2,2),16); bx2.writeByte(255); bx2.writeByte(pixelData); bx2.writeByte(pixelData); bx2.writeByte(pixelData); } } then it was about linking the byte array image data to the image itself: var b_image1:ByteArray = new ByteArray(); var bmd_image1:BitmapData = new BitmapData(img1_w,img1_h, false, 0xFFCC00); //getting the parsed XML data off selected item in the displayed grid - P6Grid b_image1 = sigData[P6Grid.selectedIndex].sig1; b_image1.position=0; bmd_image1.setPixels(bmd_image1.rect,b_image1); //reference to the visual component placed on the UI img_sn1.source = bmd_image1; Would anyone know how to do this using Swift and Xcode on MacOS app. Currently I am using sotory boards and figured out how to handle the file drop, check if that is XML document and parse the key values, so I can get to the XML data, but don't know how to turn them into the image. Many thanks for your thoughts, JendaDH
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!)
Encoded string is not working in 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.
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.