Photos framework checking image type - ios

I have code for fetching the photos from the library and accessing the types. But i have no idea how to check whether the image is PNG or JPEG.? by ALAssetLibrary we can do this easily. I want to implement this by Photos framework. Anyone have any idea.? Any suggestions. Thanks in advance.

Try:
let asset: PHAsset = ...
let opts = PHImageRequestOptions()
// opts.synchronous = true // If you want synchronous callback
opts.version = PHImageRequestOptionsVersion.Original
PHImageManager.defaultManager().requestImageDataForAsset(asset, options: opts) { _, uti, _, _ in
println(uti)
}
I don't know how to do this without fetching actual data.
To convert UTI to MIME-Type:
import MobileCoreServices
let uti = ...
let mime = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType).takeRetainedValue()

Please refer this stack answer using which you can get type of you asset.
https://stackoverflow.com/a/22352132/2098690

Related

How do I grab the UTI or MIME Type from a video asset fetched using PHAsset.fetchAsset?

I've run into an issue where I can't seem to figure out a good way of grabbing the UTI or MIME type from a video asset after fetching it from the photo library.
let assets = PHAsset.fetchAssets(in: someCollection, options: videosOnly)
(iterating over each asset in assets...)
PHImageManager.default().requestAVAsset(forVideo: asset, options: nil) { (AVAsset: avAsset, AVAudioMix: avAudioMix, info) in
(I'm trying to find the UTI/MIME type here...)
}
One iffy solution I found was to grab the pathExtension of the file by casting the avAsset as a AVURLAsset:
guard let avURLAsset = avAsset as? AVURLAsset else { return }
let videoExt = avURLAsset.url.pathExtension
This seems to get the corresponding filetype ('m4v', 'mov', 'mp4') in basic test cases, but I'm worried that this is not a robust enough solution. I saw another post (Finding image type from NSData or UIImage) that details grabbing the image type by looking at the bytes of NSData, but did not touch on video files.
I have also tried the solution suggested at How to get MIME type for image or video in iOS 8 using PHAsset?:
let requestContentEditingOptions = PHContentEditingInputRequestOptions()
asset.requestContentEditingInput(with: requestContentEditingOptions) { (contentEditingInput, contentEditingInfo) in
guard let videoUTI = contentEditingInput?.uniformTypeIdentifier else { completion(nil); return }
}
Unfortunately, the uniformTypeIdentifier property came up as nil when I attempted this. If anyone sees a potential problem with my implementation of this, I'd love to hear it.
Has anyone else run into this before? Would love to hear any ideas or if anyone things the pathExtension is a reasonable option for a production app.

Get PHAsset from iOS Share Extension

I am developing a share extension for photos for my iOS app. Inside the extension, I am able to successfully retrieve the UIImage object from the NSItemProvider.
However, I would like to be able to share the image with my container app, without having to store the entire image data inside my shared user defaults. Is there a way to get the PHAsset of the image that the user has chosen in the share extension (if they have picked from their device)?
The documentation on the photos framework (https://developer.apple.com/library/ios/documentation/Photos/Reference/Photos_Framework/) has a line that says "This architecture makes it easy, safe, and efficient to work with the same assets from multiple threads or multiple apps and app extensions."
That line makes me think there is a way to share the same PHAsset between extension and container app, but I have yet to figure out any way to do that? Is there a way to do that?
This only works if the NSItemProvider gives you a URL with the format:
file:///var/mobile/Media/DCIM/100APPLE/IMG_0007.PNG
which is not always true for all your assets, but if it returns a URL as:
file:///var/mobile/Media/PhotoData/OutgoingTemp/2AB79E02-C977-4B4A-AFEE-60BC1641A67F.JPG
then PHAsset will never find your asset. Further more, the latter is a copy of your file, so if you happen to have a very large image/video, iOS will duplicate it in that OutgoingTemp directory. Nowhere in the documentation says when it's going to be deleted, hopefully soon enough.
I think this is a big gap Apple has left between Sharing Extensions and PHPhotoLibrary framework. Apple should've be creating an API to close it, and soon.
You can get PHAsset if image is shared from Photos app. The item provider will give you a URL that contains the image's filename, you use this to match PHAsset.
/// Assets that handle through handleImageItem:completionHandler:
private var handledAssets = [PHAsset]()
/// Key is the matched asset's original file name without suffix. E.g. IMG_193
private lazy var imageAssetDictionary: [String : PHAsset] = {
let options = PHFetchOptions()
options.includeHiddenAssets = true
let fetchResult = PHAsset.fetchAssetsWithOptions(options)
var assetDictionary = [String : PHAsset]()
for i in 0 ..< fetchResult.count {
let asset = fetchResult[i] as! PHAsset
let fileName = asset.valueForKey("filename") as! String
let fileNameWithoutSuffix = fileName.componentsSeparatedByString(".").first!
assetDictionary[fileNameWithoutSuffix] = asset
}
return assetDictionary
}()
...
provider.loadItemForTypeIdentifier(imageIdentifier, options: nil) { imageItem, _ in
if let image = imageItem as? UIImage {
// handle UIImage
} else if let data = imageItem as? NSData {
// handle NSData
} else if let url = imageItem as? NSURL {
// Prefix check: image is shared from Photos app
if let imageFilePath = imageURL.path where imageFilePath.hasPrefix("/var/mobile/Media/") {
for component in imageFilePath.componentsSeparatedByString("/") where component.containsString("IMG_") {
// photo: /var/mobile/Media/DCIM/101APPLE/IMG_1320.PNG
// edited photo: /var/mobile/Media/PhotoData/Mutations/DCIM/101APPLE/IMG_1309/Adjustments/FullSizeRender.jpg
// cut file's suffix if have, get file name like IMG_1309.
let fileName = component.componentsSeparatedByString(".").first!
if let asset = imageAssetDictionary[fileName] {
handledAssets.append(asset)
imageCreationDate = asset.creationDate
}
break
}
}
}

Copy GIF to UIPasteboard

I'm trying to copy a GIF image to the UIPasteboard in swift, at the moment it only copies the static version of the image and seems to convert it to PNG looking at the file extension when I upload it somewhere.
Wondered if anyone had any idea how to achieve this? All other soltions I've found only seem to work when getting NSData from a URL rather than from an image in the bundle
For anyone who ever encounters this problem I managed to find a solution
let url: NSURL = NSBundle.mainBundle().URLForResource("\(self.imageNames[indexPath.row])", withExtension: ".gif")!
let data: NSData = NSData(contentsOfURL: url)!
UIPasteboard.generalPasteboard().setData(data, forPasteboardType: "com.compuserve.gif")
As it turns out you do need to use a URL and extract the NSData of the GIF from that URL.
Here I am getting the URL of the GIF that is in my bundle, searching for it using the name and extension of the image. I am then setting the data in the pasteboard and bingo we have an animated GIF when pasting the result from the pasteboard
It doesn't look like the image property on the pasteboard supports the GIF type.
The associated array of representation types is UIPasteboardTypeListImage, which includes types kUTTypePNG and kUTTypeJPEG.
You could probably do this using the NSData from the GIF though:
import MobileCoreServices
// ...
var image = UIImage(...)
let data = NSData(bytes: &image, length: sizeof(UIImage))
UIPasteboard.generalPasteboard().setData(data, forPasteboardType: kUTTypeGIF as String)) // com.compuserve.gif

What is equivalent method of ALAsssetsLibrary’s assetForURL:resultBlock:failure in Photos Framework?

I am picking image using UIImagePickerController but I also need image’s name and other metadata information. I could have fetched image asset using ALAsssetsLibrary’s assetForURL:resultBlock:failure method with the help of referenceURL provided by UIImagePickerController after picking image but that method/Framework is deprecated in iOS9. I searched for its equivalent method in Photos Framework but I didn’t find one.
Let me know its equivalent method or any other way to fetch selected image’s metadata using Photos Framework.
Yes you can read metada with Photos Framework like that;
asset.requestContentEditingInputWithOptions(options) { (fooContentEditingInput: PHContentEditingInput!, _) -> Void in
//Get full image
let imageUrl = fooContentEditingInput.fullSizeImageURL
let orientation = fooContentEditingInput.fullSizeImageOrientation
var finalImage = CIImage(contentsOfURL: imageUrl)
finalImage = inputImage.imageByApplyingOrientation(orientation)
for (key, value) in finalImage.properties() {
println("key: \(key)")
println("value: \(value)")
}
}

Get File Extension from a PHAsset in iOS 8?

Is there any way to distinguish a PHAsset's file extension? My app needs to know if the photo is a .GIF or not. I'm not seeing any way to do this.
A better approach would be to use uniformTypeIdentifier. Files can be named anything and may or may not contain a file extension.
[asset valueForKey:#"uniformTypeIdentifier"];
Using valueForKey: you can get the PHAsset file name from that you extract file extension using "pathExtension"
For Example:
PHAsset *selectedAsset = ...
NSString *fileName =[selectedAsset valueForKey:#"filename"];
NSString * fileExtension = [fileName pathExtension];
File names are an implementation detail, and may or may not tell you what the content of a file really is.
When you call requestImageDataForAsset, the dataUTI parameter that Photos passes to your completion handler tells you the Uniform Type Identifier for the image data.
PHAssetResource.uniformTypeIdentifier seems to do the job.
PHAssets can be fetched by using the class function PHAssetResource. assetResources(for:).
An image does NOT mean only there will be only one item in the list, so check out the documentation.
Swift 5 Elegant Solution
extension PHAsset {
func getFileName() -> String? {
return self.value(forKey: "filename") as? String
}
func getExtension() -> String? {
guard let fileName = self.getFileName() else {
return nil
}
return URL(fileURLWithPath: fileName).pathExtension
}
}
In Swift, Use:
URL(fileURLWithPath: (asset.value(forKey: "filename") as! String)).pathExtension

Resources