Problem Statement: After orientation fixed, my image do not show location info on windows machine (OS 10) while it is showing the location info on mac machine (OS Sierra). And if I do not perform orientation fix then image location info is visible on both platform.
In my application I am uploading an image and further that image is used on Windows machine.
Code Details
Friends, here, I am sharing the code segments details. Kindly have a look.
In my application I am capturing image using AVFoundation framework and attaching my EXIF data to the image. See code segment blow:-
// Update the orientation on the still image output video connection before capturing.
let videoOrientation = (self.previewView.layer as!AVCaptureVideoPreviewLayer).connection.videoOrientation
self.stillImageOutput!.connection(withMediaType: AVMediaTypeVideo).videoOrientation = videoOrientation
self.stillImageOutput!.captureStillImageAsynchronously(from: self.stillImageOutput!.connection(withMediaType: AVMediaTypeVideo), completionHandler: { (imageDataSampleBuffer, error) in
if let error = error {
print(error)
} else { let data: Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
if let image = UIImage(data: data) {
let updatedImage = image.fixedOrientation()//Fixed the image orientation
if let updatedData = UIImagePNGRepresentation(updatedImage) {
let source : CGImageSource = CGImageSourceCreateWithData(updatedData as CFData, nil)!
let metaDataInfo :NSDictionary = CGImageSourceCopyPropertiesAtIndex(source,0,nil)!
let mutableMetaDataInfo : NSMutableDictionary = metaDataInfo.mutableCopy() as! NSMutableDictionary
let uti : CFString = CGImageSourceGetType(source)!
let mutable : NSMutableData = NSMutableData()
let destination : CGImageDestination = CGImageDestinationCreateWithData(mutable as CFMutableData,uti,1,nil)!
mutableMetaDataInfo[kCGImagePropertyGPSDictionary] = location.exifMetadata()//Attaching EXIF data
CGImageDestinationAddImageFromSource(destination,source,0, mutableMetaDataInfo as CFDictionary)
let success : Bool = CGImageDestinationFinalize(destination)
if success == true {
FileManager.default.createFile(atPath: imagePath , contents: mutable as Data, attributes: nil)
}
}
}
}
}
Now find the EXIF data info which I am attaching in above code.
extension CLLocation {
func exifMetadata(heading: CLHeading? = nil) -> NSMutableDictionary {
let GPSMetadata = NSMutableDictionary()
let altitudeRef = Int(self.altitude < 0.0 ? 1 : 0)
let latitudeRef = self.coordinate.latitude < 0.0 ? "S" : "N"
let longitudeRef = self.coordinate.longitude < 0.0 ? "W" : "E"
// GPS metadata
GPSMetadata[(kCGImagePropertyGPSLatitude as String)] = abs(self.coordinate.latitude)
GPSMetadata[(kCGImagePropertyGPSLongitude as String)] = abs(self.coordinate.longitude)
GPSMetadata[(kCGImagePropertyGPSLatitudeRef as String)] = latitudeRef
GPSMetadata[(kCGImagePropertyGPSLongitudeRef as String)] = longitudeRef
GPSMetadata[(kCGImagePropertyGPSAltitude as String)] = Int(abs(self.altitude))
GPSMetadata[(kCGImagePropertyGPSAltitudeRef as String)] = altitudeRef
GPSMetadata[(kCGImagePropertyGPSTimeStamp as String)] = self.timestamp.isoTime()
GPSMetadata[(kCGImagePropertyGPSDateStamp as String)] = self.timestamp.isoDate()
GPSMetadata[(kCGImagePropertyGPSVersion as String)] = "2.2.0.0"
if let heading = heading {
GPSMetadata[(kCGImagePropertyGPSImgDirection as String)] = heading.trueHeading
GPSMetadata[(kCGImagePropertyGPSImgDirectionRef as String)] = "T"
}
return GPSMetadata
}
}
And in last the fixed orientation method code:
extension UIImage {
func fixedOrientation() -> UIImage {
if imageOrientation == .up { return self }
var transform:CGAffineTransform = .identity
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height).rotated(by: .pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0).rotated(by: .pi/2)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height).rotated(by: -.pi/2)
default: break
}
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0).scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0).scaledBy(x: -1, y: 1)
default: break
}
let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height),
bitsPerComponent: cgImage!.bitsPerComponent, bytesPerRow: 0,
space: cgImage!.colorSpace!, bitmapInfo: cgImage!.bitmapInfo.rawValue)!
ctx.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.height,height: size.width))
default:
ctx.draw(cgImage!, in: CGRect(x: 0, y: 0, width: size.width,height: size.height))
}
return UIImage(cgImage: ctx.makeImage()!)
}
}
Thats all in terms of code segment what I am using. Kindly assume all the variable and class definition as per the iOS SDK in case if you do not find definition of a variable or class in above code segment.
Although I am amazed to see this strange issues and already tried to many things, I would like to share these conclusions with you people so that we can able to reach on a conclusion:
If we check that image metadata through some online sites on windows machine, we found that location data is present. But why it is not visible on windows machine , we have no clue in that respect.
In simple way if we open the same image through note pad on windows machine we are able to see the location data is there.
If I simply take an image using camera roll on iPad device,(NOT using my app) and mail it to the some windows machine user. In that case too image do not show location info on windows machine. While if I send the same image to the Mac machine user, he/she can able to see location info in the same image. It's really astonishing me.
If we do not perform orientation fixed in my code, we can able to find the location info of image on windows platform too.
In short image is showing the location info on iOS device itself and on mac machine but it is not showing location info on windows machine.
I have also attached an image along with question so that you people can also give a try to check location info on your machines.(Image size is 3.3 MB so I am not upload it directly here,I will share later if it is required to you people)
P.S: I have used Mac OS Sierra, iPad(iOS 10.3.3) and Windows OS 10 during above observations.
In last, Thank you for giving your precious time here. I am very grateful to you.