The following code does not seem be able to extract depth data from an image (which contains depth information). The code returns nil after the "guard { auxdepthinfo -...)" line. In the following code, the image is a reference to a portrait image stored in the photoAlbum.
struct DepthReader {
var image: UIImage
func depthDataMap() -> CVPixelBuffer? {
//create data from UIImage
guard let imageDat: Data = UIImageJPEGRepresentation(image, 1.0) else {
return nil
}
//create source
guard let source = CGImageSourceCreateWithData(imageDat as CFData, nil) else {
return nil
}
//extract auxData disparity data
guard let auxDataInfo = CGImageSourceCopyAuxiliaryDataInfoAtIndex(source, 0, kCGImageAuxiliaryDataTypeDepth) as? [AnyHashable : Any] else {
return nil
}
// This is the star of the show!
var depthData: AVDepthData
do {
// Get the depth data from the auxiliary data info
depthData = try AVDepthData(fromDictionaryRepresentation: auxDataInfo)
} catch {
return nil
}
// Make sure the depth data is the type we want
if depthData.depthDataType != kCVPixelFormatType_DisparityFloat32 {
depthData = depthData.converting(toDepthDataType: kCVPixelFormatType_DisparityFloat32)
}
return depthData.depthDataMap
}
}
Related
I would like to be able to select a photo from the Photos library using UIImagePicker and copy all the image (with modified Exif metadata) to a new photo which I save in Photos. If I use UIActivityViewController to choose the save option (from copy/save/assign to contact/print/add to shared album/save to file), the input image metadata is not transferred when I create a new UIimage from the loaded image data with the modified metadata. How can get the image with modified metadata attached to the saved photo?
Eventually found out how to do this. The code executed after the image picker is below. The important thing is to create the source from which the metadata is extracted from a URL, not from data from image.jpegData. The jpegData option only includes metadata essential to JPEG operation
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let info = convertFromUIImagePickerControllerInfoKeyDictionary(info)
if let image = info[convertFromUIImagePickerControllerInfoKey(UIImagePickerController.InfoKey.originalImage)] as? UIImage {
let url = info[UIImagePickerController.InfoKey.imageURL.rawValue]
let source = CGImageSourceCreateWithURL(url as! CFURL, nil)
let metadata = CGImageSourceCopyPropertiesAtIndex(source!,0,nil) as? [AnyHashable: Any]
var metadataAsMutable = metadata
//let ImagePropertyExifDictionary = kCGImagePropertyExifDictionary
guard var exif = metadataAsMutable![kCGImagePropertyExifDictionary] as? [String:Any] else {return}
if((exif[kCGImagePropertyExifUserComment as String] == nil))
{
exif[kCGImagePropertyExifUserComment as String] = "Test User Comment"
}
metadataAsMutable![kCGImagePropertyExifDictionary] = exif as CFDictionary
ImagePickerView.contentMode = .scaleAspectFit
let image2 = image.imageWithInsets(insets: UIEdgeInsets.init(top: 0,left: 0,bottom: 300,right: 0))
let data1 = image2!.jpegData(compressionQuality: 1.0)
newData = addImageProperties(imageData: data1!, properties: metadataAsMutable! as CFDictionary)
image3 = UIImage(data:newData)!
ImagePickerView.image = image3
captionButton.isEnabled = true; saveButton.isEnabled = true;
}else {
print("Error")
}
self.dismiss(animated: true, completion: nil)
}
func addImageProperties(imageData: Data, properties: NSMutableDictionary) -> Data? {
if let source = CGImageSourceCreateWithData(imageData as CFData, nil) {
if let uti = CGImageSourceGetType(source) {
let destinationData = NSMutableData()
if let destination = CGImageDestinationCreateWithData(destinationData, uti, 1, nil) {
CGImageDestinationAddImageFromSource(destination, source, 0, properties)
if CGImageDestinationFinalize(destination) == false {
return nil
}
return destinationData as Data
}
}
}
return nil
}
After obtaining newData, the save button IBAction is
#IBAction func shareAction(_ sender: Any) {
self.saveImageDataAsImage(newData)
}
and the function to save the image in the same album as the selected image is
func saveImageDataAsImage(_ data: Data) {
var newImageIdentifier: String!
PHPhotoLibrary.shared().performChanges{
//if #available(iOS 9.0, *) {
let assetRequest = PHAssetCreationRequest.forAsset()
assetRequest.addResource(with: .photo, data: data, options: nil)
newImageIdentifier = assetRequest.placeholderForCreatedAsset!.localIdentifier
// } else {
// // Fallback on earlier versions
// }
} completionHandler: { (success, error) in
DispatchQueue.main.async(execute: {
if success, let newAsset = PHAsset.fetchAssets(withLocalIdentifiers: [newImageIdentifier], options: nil).firstObject {
// ...
} else {
// ...
}
})
}
}
I have a PKCanvas, what i am trying to do is to take the pkcanvas drawing that the user has made ad compare to another image.
However i keep getting nil returned section.
Why is this? my drawing and picture elements are returning nil. but my image2 element is returning the users drawing as expected.
in the code below i am just comparing the drawing the user made against itself (just for testing purposes)
Also "nothing here" does get printed.
//function type for ciimage
func featureprintObservationForImage(_ image: CIImage?) -> VNFeaturePrintObservation? {
guard let ciImage = image else {
print("nothing here")
return nil
}
let requestHandler = VNImageRequestHandler(ciImage: ciImage, options: [:])
let request = VNGenerateImageFeaturePrintRequest()
do {
try requestHandler.perform([request])
return request.results?.first as? VNFeaturePrintObservation
} catch {
print("Vision error: \(error)")
return nil
}
}
#IBAction func finishCalculation(_ sender: Any) {
//geting drawing
UIGraphicsBeginImageContextWithOptions(theCanvasView.bounds.size, false, UIScreen.main.scale)
theCanvasView.drawHierarchy(in: theCanvasView.bounds, afterScreenUpdates: true)
let image2 = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let picture = featureprintObservationForImage(image2?.ciImage)
let drawing = featureprintObservationForImage(image2?.ciImage)
var distance = Float(0)
do {
try picture!.computeDistance(&distance, to: drawing!)
} catch {
print(error)
}
print("picture to drawing")
print(distance)
}
I'm trying to get the UIImage from the local URL, but it doesn't work.
My someURl, where data is NSSecureCoding?: file:///Users/a19468455/Library/Developer/CoreSimulator/Devices/2FA5B725-9266-429C-A036-256D846BC3FA/data/Media/PhotoData/OutgoingTemp/3F73D172-AA12-40AD-A3AB-540543A43330/IMG_0004.JPG
Here's what I've tried (sacrificed code styling for convenience):
guard let inputItems = extensionContext?.inputItems as? [NSExtensionItem else { return }
inputItems.forEach { item in
if let attachments = item.attachments,
!attachments.isEmpty {
attachments.forEach { attachment in
if attachment.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
var image: UIImage?
attachment.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil) { [weak self] data, error in
guard let self = self else { return }
guard error == nil else {
self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
return
}
if let someURl = data as? URL {
do {
let data = try Data(contentsOf: someURl)
image = UIImage(data: data)
} catch {
print("failed to retrieve data")
}
}
if let image = image {
images.append(image)
}
}
}
}
}
}
I also tried tips from here without success:
how to load image from local path ios swift (by path)
how to load image from local image path Ios Swift 4
Loading/Downloading image from URL on Swift
I have no way to get Data from my link, how do I fix it?
Hi I am currently trying to parse a JSON array produced by alamofire as below:
[
{
"UUID": "31ea524c-4d19-46f7-b3ec-c9264f9dbc78"
},
{
"UUID": "d0c89800-bbae-4189-88ab-503c6b68b511"
}
]
I need to take these values and present them as a comma delimited string so they look like this:
"31ea524c-4d19-46f7-b3ec-c9264f9dbc78, d0c89800-bbae-4189-88ab-503c6b68b511"
Alamofire.request(URL_GET_ORDER, method: .post, parameters: parameters).responseJSON
{
response in
//printing response
print(response)
if let result = response.result.value {
let jsonData = result as! NSArray
}
I need to take the data from the above array pass it to a string and then input that sting into this code to produce a QRcode that can then be scanned as part of a click and collect system:
let myString = "*JOINED STRING GOES HERE*"
// Get data from the string
let data = myString.data(using: String.Encoding.ascii)
// Get a QR CIFilter
guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return }
// Input the data
qrFilter.setValue(data, forKey: "inputMessage")
// Get the output image
guard let qrImage = qrFilter.outputImage else { return }
// Scale the image
let transform = CGAffineTransform(scaleX: 10, y: 10)
let scaledQrImage = qrImage.transformed(by: transform)
// Do some processing to get the UIImage
let context = CIContext()
guard let cgImage = context.createCGImage(scaledQrImage, from: scaledQrImage.extent) else { return }
let processedImage = UIImage(cgImage: cgImage)
self.myImageView.image = processedImage
I have already tried a lot of solutions like the following one below:
let stringRepresentation = jsonData.joinWithSeparator("-")
and:
let objCArray = NSMutableArray(array: jsonData)
let swiftArray = objCArray as NSArray as? [String]
print(swiftArray ?? "BrokeAgain!!") // returns nil
let nustr = swiftArray?.joined(separator:",")
The easiest way is to start with Codable data model which represents a single object in your json array.
struct ResponseObject: Codable {
let uuid: String
}
Then you can decode the plain response data into an array of objects – it's easier to work with.
func getUUIDList(_ complection: #escaping (String?) -> Void) {
Alamofire
.request(URL_GET_ORDER, method: .post, parameters: parameters)
.response { response in
guard let data = response.data else {
completion(nil)
return
}
do {
let decoder = JSONDecoder()
let objects = try decoder.decode([ResponseObject].self, from: data)
completion(
objects
.map { $0.uuid }
.joined(separator: ", ")
)
} catch let error {
print(error)
completion(nil)
}
}
}
Finally replace your call Alamofire.request(URL_GET_ORDER, method: .post, parameters: parameters)... with:
// somewhere you call the alamofire
getUUIDList() { responseString in
guard let responseString = responseString else { return }
// Get data from the string
let data = responseString.data(using: String.Encoding.ascii)
// Get a QR CIFilter
guard let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return }
// Input the data
qrFilter.setValue(data, forKey: "inputMessage")
// Get the output image
guard let qrImage = qrFilter.outputImage else { return }
// Scale the image
let transform = CGAffineTransform(scaleX: 10, y: 10)
let scaledQrImage = qrImage.transformed(by: transform)
// Do some processing to get the UIImage
let context = CIContext()
guard let cgImage = context.createCGImage(scaledQrImage, from: scaledQrImage.extent) else { return }
let processedImage = UIImage(cgImage: cgImage)
self.myImageView.image = processedImage
}
Please note, this is just a not testet guideline how you should do it. Do not expect the code will work after copy&paste, but is's a good starting point :)
I ma trying to take an array of type PFFile and convert into an array of type UIImage. I use the below code and no matter what it always returns an empty array. Any help is much appreciated.
userImagesPassed is an array of type PFFile.
func setUserImages() -> Array<UIImage> {
var userImageArray = [UIImage]()
for file2 in userImagesPassed {
file2.getDataInBackground(block: { (imageData2, error) in
if error != nil {
userImageArray = []
} else {
userImageArray.append(UIImage(data: imageData2!)!)
}
})
}
return userImageArray
}
EDIT:
If I print the userImageArray inside the for loop I get the correct output (a populated array of type UIImage). But the returned value is still an empty array.
first of all you shouldn't use return statement for async functions. You should use completion handlers to get your items back. This is the example how I get images from Parse and append to array.
Swift 4.0
public func getImages(_ completion: #escaping (([UIImage]) -> Void)) {
guard let tempImages = self.images else { return }
var images = [UIImage]()
for image in tempImages {
image.getDataInBackground() {
( imageData, error) in
guard error == nil else { return }
guard let imageData = imageData else { return }
guard let image = UIImage(data: imageData) else { return }
images.append(image)
}
}
completion(images) // Its returning your images
}
You can call your getImages function like this;
let images = self.yourObjectArrayInClass[(indexPath).row]
images.getImages() {
(images) in
DispatchQueue.main.async {
// Do something with your images.
}
}