How can I get raw data of image from UIPasteboard if it's copied by another app (such as photos, safari, etc..) - ios

Is there a way to get raw data of image from UIPasteboard instead of UIImage if it's copied by another app such as photos or mobile safari?
I'm currently facing wired differences between IOS 6.0 and IOS 6.1(7.0 also)
In IOS 6.0, UIPasteboard's item of the copied image by photos or mobile safari contains raw data of the image.
But In IOS 6.1 and above, it contains UIImage instead of raw data.
In IOS 6.0, copied item of UIPasteboard is below
Printing description of array:
<__NSArrayM 0x8a804c0>(
{
"com.compuserve.gif" = <47494638 39614002 ...... 3b3a2000 3b>;
"public.url" = "url of the image....";
}
)
In IOS 6.1 and above, it contains UIImage instead of raw data.
Printing description of array:
<__NSArrayM 0xa25b7b0>(
{
"com.compuserve.gif" = "<UIImage: 0x9429570>";
"public.url" = "url of the image...";
}
)
If that image format is PNG or JPEG, it's not that bad.
(I still have to compress again if it's JEPG though.)
But when I try to paste animated gif image, it becomes more complicated.
I don't know even it's passible to create animated gif image from normal UIImage.
I can download again from original url, but downloading data that I already have seems not good solution I think.
And also, if it's copied from photos app, there's no such url. (there's some mysterious uri named "com.apple.mobileslideshow.asset-object-id-uri" that is undocumented instead of url)
There seems a workaround, because when I try to do exactly same action between photos and email app, It works properly
Any suggestions?

Well now, I figured it out myself.
You can simply get raw (binary)data of the image form general pasteboard by sending
dataForPasteboardType:(NSSting*)PasteboardType message to general pasteboard, if it's copied from Apple's built-in Mobile Safari or Photos App. (#"com.compuserve.gif" for the pasteboard type in my case)
I myself feel a bit foolish for not having checked all the passible methods sooner. :(
My confusion comes from items property of the UIPasteboard.
I thought that items are containing all of data of current pasteboard. So I try to save that array from pasteboard and want to use it later, but I were totally wrong.
As documented in UIPasteboard Class Reference, the items property contains dictionary with key being the representation type and the "value" the object associated with that type.
At this point of time, The "value" refers really "value" of the representation, not the data of that type. This meaning of the "value" is the same as the value of thesetValue: forPasteboardType: method.
On the other words, you cannot retrieve raw(binary) data of the image from items property, even if you set the image to the pasteboard by sending setData: forPasteboardType: message.(I tested it on IOS 7)
In addition, raw data of the image from items property in IOS 6.0 seems a bug of that OS version. (This may not true, it's just my opinion)

You can get NSData from UIPasteboard if you specify right PasteboardType:
NSData* pasteData = [[UIPasteboard generalPasteboard] dataForPasteboardType:(NSString*)kUTTypeJPEG];
Do not forget to import
<MobileCoreServices/MobileCoreServices.h>

The UIPasteBoard will contain whatever is placed in it. It's up to the app that is copying to the paste board to put the contents in the proper format. The app can place items as raw binary data or as objects such as UIImage in the paste board.
If you're getting something different between iOS versions, you're probably using different versions of the app or it's simply copying things differently.
You're right that you can't represent an animated GIF in a UIImage because a UIImage only contains a single image. Perhaps the app is just copying the first frame's bitmap data in that case?
You can convert a UIImage to raw JPEG data using UIImageJPEGRepresentation.

Related

iOS, Swift, Image Metadata, XMP, DJI Drones

I'm writing an iOS Swift app to fetch metadata from DJI drone images. I'm trying to access the Xmp.drone-dji.X metadata. The iOS/Swift CGImageSource and CGImageMetadata libraries/classes get almost all of the metadata out of the image but not the Xmp.drone-dji. When I get a list of tags, those tag/values are not listed. I know the tags/data are in the images because I've examined the images using exif, exiv2, etc.
Any suggestions?
Here is the code I'm using so far:
result.itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier)
{ data, err in
if let data = data {
let src = CGImageSourceCreateWithData(data as CFData,nil)!
let md = CGImageSourceCopyPropertiesAtIndex(src,0,nil) as! NSDictionary
let md2 = CGImageSourceCopyMetadataAtIndex(src,0,nil)
}
Thanks,
Bobby
So, after a lot of searching, trial and error, I have found an answer.
I was not able to get any of the CGImage swift libraries to extract this info for me.
Adobe has a c++ library that parses xmp/xml data out of images and it purports to support iOS. I didnt want the hassle of building c++ on iOS, importing that into Xcode and then dealing with the fact that thrown errors do not propagate well from c++/objectiveC to Swift.
So, at a high level, I did the following:
get the bytes of the raw image as CFData or Data then cast to a String
then use String.range() to find beginning of XML/XMP data in image
searching for substring <?xpacket begin
use String.range() to find end of XML/XMP data in image
using substring <?xpacket end.*?>
Extract the XML document out of image data String
Use Swift XMLParser class to parse the XML and then copying attributes and
elements as necessary. I just simply added what I wanted to already
existing Exif NSdictionary returned by CGImage classes.
Happy to answer questions on this approach. My code will eventually be uploaded to GitHub under OpenAthenaIOS project.
Bobby

UIImagePNGRepresentation loses its transparency

I am working on an app that connects multiple devices using the networking protocol UPnP.
Among others, I can exchange images and they are files stored inside a folder in my project folder.
For sending the images I am given predefined methods.
if let imageRequested = UIImage(named:"logo.png"){
let fileType = "image/png"
let pngRepresentation = [UInt8](UIImagePNGRepresentation(imageRequested)!)
let fileSize = UInt32(pngRepresentation.count)
writeBegin!(aWriterData, fileSize, fileType)
aWriteResource!(aWriterData, pngRepresentation, fileSize)
aWriteEnd!(aWriterData)
}
However, the receiver gets the image with black background when it is transparent. I know It is not a receiver issue because there is an Android version that sends the same images and they are received with transparency.
any ideas why?
UIImageJPEGRepresentation will convert the resulting image into a JPEG, which doesn't support transparency. Are you sure that you use UIImagePNGRepresentation, not UIImageJPEGRepresentation?
If you use UIImagePNGRepresentation - it's strange, it should work fine, could you provide more details?

Paste a copied image into an AIR iOS app?

Is it possible to paste a copied image from the Safari browser to an Adobe AIR built iOS app?
I tried it with this image but couldn't find a solution yet.
Below is a screenshot of the copy button from the Safari browser on iOS 8:
Yes and no. You can't use the native dialogs or handling, but I believe you can access the data in the clipboard, even if it is an image.
You'll want to use Clipboard#getData() with a format of ClipboardFormats.BITMAP_FORMAT. That will give you access to the raw image data in a BitmapData object. You can then draw that BitmapData to a Bitmap container (or Image/BitmapImage if using Flex). You'll have to include a separate button for instantiating the paste process, but that isn't difficult to do.
Untested, but this should be a good place to start:
pasteButton.addEventListener(MouseEvent.CLICK, this.pasteEventHandler);
function(e:MouseEvent):void {
var clipboard:Clipboard = new Clipboard()
var bd:BitmapData = clipboard.getData(ClipboardFormats.BITMAP_FORMAT);
bitmap.bitmapData = bd;
}
I believe you'll need to handle errors in there as well, since the clipboard could contain text would either throw an error on the getData() line or return null.

iOS saving photo to Camera Roll does not preserve EXIF/GPS metadata

I know a UIImage can be saved into Camera Roll with UIImageWriteToSavedPhotosAlbum, but this approach strips all metadata from the original file (EXIF, GPS data, etc). Is there any way to save the original file, rather than just the image data into the iOS device's Camera Roll?
Edit: I guess I should have been a bit more specific. The aim is to save a duplicate of an existing JPEG file into a user's Camera Roll. What's the most efficient way to do this?
Depending on how you have your image to save you can chose one of the methods provided by the ALAssetsLibrary.
– writeImageDataToSavedPhotosAlbum:metadata:completionBlock:
– writeImageToSavedPhotosAlbum:metadata:completionBlock:
(Depending on if you have the image as an actual UIImage, or as NSData)
http://developer.apple.com/library/ios/#documentation/AssetsLibrary/Reference/ALAssetsLibrary_Class/Reference/Reference.html
Take notice on the fact that you have to have set the correct keys for the dictionary or they might not be saved correctly.
Here is an example for the GPS information:
NSDictionary *gpsDict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:fabs(loc.coordinate.latitude)], kCGImagePropertyGPSLatitude,
((loc.coordinate.latitude >= 0) ? #"N" : #"S"), kCGImagePropertyGPSLatitudeRef,
[NSNumber numberWithFloat:fabs(loc.coordinate.longitude)], kCGImagePropertyGPSLongitude,
((loc.coordinate.longitude >= 0) ? #"E" : #"W"), kCGImagePropertyGPSLongitudeRef,
[formatter stringFromDate:[loc timestamp]], kCGImagePropertyGPSTimeStamp,
[NSNumber numberWithFloat:fabs(loc.altitude)], kCGImagePropertyGPSAltitude,
nil];
And here is a list of the keys:
http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CGImageProperties_Reference/Reference/reference.html#//apple_ref/doc/uid/TP40005103
UIImagePickerControllerDelegate is what you're looking for.
Starting in iOS 4.0, you can save still-image metadata, along with a
still image, to the Camera Roll. To do this, use the
writeImageToSavedPhotosAlbum:metadata:completionBlock: method of the
Assets Library framework. See the description for the
UIImagePickerControllerMediaMetadata key.
UIImagePickerControllerDelegate Protocol Reference
For a Swift solution that uses the Photos API (ALAssetLibrary is deprecated in iOS 9), you can see my solution to this problem here, including sample code.
With the Photos API, the key thing to note is that the .location property of a PHAsset does NOT embed the CLLocation metadata into the file itself, so using an EXIF viewer will not turn up any results.
To get around this, you must embed any metadata changes directly into the Data of the image itself before writing it to the camera roll using the Photos API (or, for iOS versions prior to 9, you must write a temporary file using the Data with the embedded metadata and create the PHAsset from the file's URL).
Also note that the act of converting image Data to a UIImage appears to strip metadata, so be careful with that.

Get copied data from UIPasteboard

i have copied image from UIwebView using clipboard and i want to mail it.For this,I use general pasteboard to get data,but there is a problem in retrieving data.When i check the pasteboard current data,it says the it has Apple Web Archive pasteboard type data,how to read this.here is my code of retriving text.
UIPasteboard* pasteboard = [UIPasteboard generalPasteboard];
NSArray* array = [pasteboard pasteboardTypes];
for (NSString* type in array) {
NSLog(#"%#",type);
}
NSString* item = #"Apple Web Archive pasteboard type";
NSData* val = [pasteboard dataForPasteboardType:item];
I tried to create a UIImage using this data but that didn't work.
I don't understand what you mean by mail it? You can paste the webpage image copy right into the mail app and it will appear as an image.
You can rebuild the data from the Apple Web Archive pasteboard type if you need to manual. It is essentially a XML document with html and the actual image data all within. The html and accompanying images are base64 encoded. If you want to look at an archive example save this, or perhaps a simple webpage in safari as an archive. Open the archive file in something like Text wrangler. Text edit will probably try to render it.
I've written a post on how to make an Apple Web Archive pasteboard type that might help you understand the process.
http://mcmurrym.wordpress.com/2010/08/13/pasting-simplehtml-into-the-mail-app-ios/
I take it you are trying to mail it from within your app and not using the mail app?
If this is the case you will probably have to get the xml from the pasteboard, find the tag that holds the encoded image data, decode it and create an image from the decoded data.

Resources