i will like to pick an images from UIImagepicker, there are PNG and JPG format in camera roll.
and i need to convert it into NSData. However i need to know if this images is UIImageJPEGRepresentation or UIImagePNGRepresentation so i could convert it.
UIImage *orginalImage = [info objectForKey:UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:nil];
NSData *orgData = UIImagePNGRepresentation(orginalImage);
You shouldn't know or care what the internal representation of images in the camera roll is. The methods you mentioned UIImageJPEGRepresentation and UIImagePNGRepresentation return you representations of the camera roll image. It's up to you to pick which representation you want to use.
To summarize:
NSData * pngData = UIImagePNGRepresentation(originalImage);
Will return you the image representation in an NSData object, with the format PNG.
When the delegate method imagePickerController:didFinishPickingMediaWithInfo: for UIImagePickerController is called, you get the asset URL for the particular photo picked.
[info valueForKey:UIImagePickerControllerReferenceURL]
Now this URL can be used to access the asset in the ALAssetsLibrary. Then you would need a ALAssetRepresentation of that accessed asset. From this ALAssetRepresentation we can get the UTI for that image (http://developer.apple.com/library/ios/#DOCUMENTATION/FileManagement/Conceptual/understanding_utis/understand_utis_conc/understand_utis_conc.html)
Maybe the code would make it a bit clearer :
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
if (!(picker.sourceType == UIImagePickerControllerSourceTypeCamera)) {
NSLog(#"User picked image from photo library");
ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease];
[library assetForURL:[info valueForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *repr = [asset defaultRepresentation];
if ([[repr UTI] isEqualToString:#"public.png"]) {
NSLog(#"This image is a PNG image in Photo Library");
} else if ([[repr UTI] isEqualToString:#"public.jpeg"]) {
NSLog(#"This image is a JPEG image in Photo Library");
}
} failureBlock:^(NSError *error) {
NSLog(#"Error getting asset! %#", error);
}];
}
}
As the UTI explains, this should be a sure shot answer to how the image is stored in the photo library.
in Swift 2.2
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
if (!(picker.sourceType == UIImagePickerControllerSourceType.Camera)) {
let assetPath = info[UIImagePickerControllerReferenceURL] as! NSURL
if assetPath.absoluteString.hasSuffix("JPG") {
} else {
}
Related
I am trying to attach an image rendered from UIGraphicsBeginImageContext. As a test, I am adding the image to the photo album as well. It all works perfectly on the simulator, but on the device the correct image get added to the photo album, but will not display in the email attachment correctly. I think it is because it is a big image, and it takes some time on an iPhone 3gs. Which means I have to check if it is done rendering image. Is there a way to to that? Here is my code:
UIGraphicsBeginImageContext(backGround.layer.frame.size);
[backGround.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
UIGraphicsEndImageContext();
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
NSData *imgData = UIImagePNGRepresentation(image);
[mailer addAttachmentData:imgData mimeType:#"image/png" fileName:#"myfilename"];
I am wondering, maybe it is not completely finished with the image, and it still has corrupted data when I am making a PNG Representation of it. Can I somehow check if the UIImage is 'done' ?
Try implementing the completion method and check it. One example is,
UIImageWriteToSavedPhotosAlbum(image, self, #selector(image:didFinishSavingWithError:contextInfo:), NULL);
- (void)image:(UIImage *) image didFinishSavingWithError:(NSError *) error contextInfo: (void *) contextInfo {
NSLog(#"SAVE IMAGE COMPLETE");
if(error != nil) {
NSLog(#"ERROR SAVING:%#", [error localizedDescription]);
}
}
Based on the error message you can debug for the error message. Check UIImageWriteToSavedPhotosAlbum documentation for more details.
I'm interested in uploading a file (image) from an iPhone library/camera roll to a remote web server. I already have a script working that will upload any file from the phone to a web server. However, I assume that to upload an image from the iPhone, I need the PATH to said image. Is there any way this can be done, once the user picks said image from the camera roll? I.e., how do I get the file path of an image selected in the camera roll?
I have tried to no avail.
Thanks!
You will want to look at the ALAssetsLibrary functions - these let you access photos and videos that are stored in your Photos and Videos libraries on your iOS device.
Specifically, something like:
ALAssetsLibrary *assets = [[ALAssetsLibrary alloc] init];
[assets enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
//the ALAsset should be one of your photos - stick it in an array and after this runs, use it however you need
}
}
failureBlock:^(NSError *error) {
//something went wrong, you can't access the photo gallery
}
];
EDIT
If you are using the UIImagePickerController rather than a purely programatical approach, this simplifies it greatly:
In:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *img = [info objectForKey:UIImagePickerControllerEditedImage];
//you can use UIImagePickerControllerOriginalImage for the original image
//Now, save the image to your apps temp folder,
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:#"upload-image.tmp"];
NSData *imageData = UIImagePNGRepresentation(img);
//you can also use UIImageJPEGRepresentation(img,1); for jpegs
[imageData writeToFile:path atomically:YES];
//now call your method
[someClass uploadMyImageToTheWebFromPath:path];
}
In my app I am taking a picture and showing it in an image view.
Now I need the path of that image so I can upload it to a server.
How do I get that path? I try importing ALAsset framework but there is no framework called that my x code (4.2) iOS 5.0
NSData *data = UIImagePNGRepresentation(imagePic.image);
NSString *file = [NSTemporaryDirectory() stringByAppendingPathComponent:#"upload.jpg"];
[data writeToFile:file atomically:YES];
[[EPUploader alloc] initWithURL:[NSURL URLWithString:#"myWebSite"]
filePath:#"file"
delegate:self
doneSelector:#selector(onUploadDone:)
errorSelector:#selector(onUploadError:)];
This is what I am currently trying.
Also what would be a hard coded path to a photo in an iphone camera roll? "iphone/pictures/myPic" ?? so I can try the upload separate from finding the path.
Please and Thank you
EDIT:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Access the uncropped image from info dictionary
image2 = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
// Save image
UIImageWriteToSavedPhotosAlbum(image2, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
imagePic.image = image2;
[picker release];
}
An image view has no path, it's in memory. You'll have to save the path you get when you return from taking the image. In the delegate method imagePickerController:didFinishPickingMediaWithInfo: you can get the NSURL in UIImagePickerControllerMediaURL which points to the image on disk:
NSURL *imageURL = [info valueForKey:UIImagePickerControllerMediaURL];
I am trying to pick an image from the photo library or from the camera.The delegate method:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
Gives me the UIImage object. I need to find the size of the image in bytes for my application.
Is there any way I can get the file type of the image and also the size in the bytes?
Any kind of help would be highly appreciated.
Thanks in advance
Try the following code:
NSData *imageData = [[NSData alloc] initWithData:UIImageJPEGRepresentation((image), 1.0)];
int imageSize = imageData.length;
NSLog(#"SIZE OF IMAGE: %i ", imageSize);
I know this is an old question but creating a NSData object just to get the byte-size of an image can be a really expensive operation. Image can have over 20Mb and creating equally sized object just to get the size of the first one...
I tend to use this category:
UIImage+CalculatedSize.h
#import <UIKit/UIKit.h>
#interface UIImage (CalculatedSize)
-(NSUInteger)calculatedSize;
#end
UIImage+CalculatedSize.m
#import "UIImage+CalculatedSize.h"
#implementation UIImage (CalculatedSize)
-(NSUInteger)calculatedSize
{
return CGImageGetHeight(self.CGImage) * CGImageGetBytesPerRow(self.CGImage);
}
#end
You simply import the UIImage+CalculatedSize.h and use it like this:
NSLog (#"myImage size is: %u",myImage.calculatedSize);
Or, if you want to avoid using categories:
NSUInteger imgSize = CGImageGetHeight(anImage.CGImage) * CGImageGetBytesPerRow(anImage.CGImage);
EDIT:
This calculation of course has nothing to do with JPEG/PNG compression. It relates to underlaying CGimage:
A bitmap (or sampled) image is a rectangular array of pixels, with
each pixel representing a single sample or data point in a source
image.
In a way a size retrieved this way gives you a worst-case scenario information without actually creating an expensive additional object.
From:#fbrereto's answer:
The underlying data of a UIImage can vary, so for the same "image" one can have varying sizes of data. One thing you can do is use UIImagePNGRepresentation or UIImageJPEGRepresentation to get the equivalent NSData constructs for either, then check the size of that.
From:#Meet's answer:
UIImage *img = [UIImage imageNamed:#"sample.png"];
NSData *imgData = UIImageJPEGRepresentation(img, 1.0);
NSLog(#"Size of Image(bytes):%d",[imgData length]);
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)editInfo{
UIImage *image=[editInfo valueForKey:UIImagePickerControllerOriginalImage];
NSURL *imageURL=[editInfo valueForKey:UIImagePickerControllerReferenceURL];
__block long long realSize;
ALAssetsLibraryAssetForURLResultBlock resultBlock=^(ALAsset *asset)
{
ALAssetRepresentation *representation=[asset defaultRepresentation];
realSize=[representation size];
};
ALAssetsLibraryAccessFailureBlock failureBlock=^(NSError *error)
{
NSLog(#"%#", [error localizedDescription]);
};
if(imageURL)
{
ALAssetsLibrary *assetsLibrary=[[[ALAssetsLibrary alloc] init] autorelease];
[assetsLibrary assetForURL:imageURL resultBlock:resultBlock failureBlock:failureBlock];
}
}
What's currently working in my code:
I select a JPG or PNG from the Photo Library (using standard ImagePicker methods), and convert that image to NSData using:
self.myImageData = UIImageJPEGRepresentation(myImage, 0.9);
which I then post to a server using multipart/form-data.
I now want to do the same for a GIF, while retaining the original GIF data (so that an animated GIF going into the library, comes back out still animating).
In didFinishPickingMediaWithInfo, I am able to get the URL of the original GIF using
self.myGIFURL = [info objectForKey:UIImagePickerControllerReferenceURL].
Here's one example of what that might get me:
assets-library://asset/asset.GIF?id=1000000034&ext=GIF
Here are two ways I've tried now to push this GIF into NSData, and each time I myImageData shows (null).
I've tried to use initWithContentsOfURL:
NSData *dataFromGIFURL = [[NSData alloc] initWithContentsOfURL: myGIFURL];
self.myImageData = dataFromGIFURL;
[dataFromGIFURL release];
Then I tried converting the NSURL to a string for initWithContentsOfFile:
NSString *stringFromURL = [NSString stringWithFormat:#"%#", myGIFURL];
NSData *dataFromGIFURL = [[NSData alloc] initWithContentsOfFile: stringFromURL];
self.myImageData = dataFromGIFURL;
[dataFromGIFURL release];
Any suggestions? Thanks.
The UIImagePickerControllerReferenceURL key doesn't appear until iOS 4.1. I therefore take it as implicit in your question that it's fine to use the AssetsLibrary framework, which appeared in iOS only at 4.0. In which case, you can use the following:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL]
resultBlock:^(ALAsset *asset)
{
ALAssetRepresentation *representation = [asset defaultRepresentation];
NSLog(#"size of asset in bytes: %d", [representation size]);
unsigned char bytes[4];
[representation getBytes:bytes fromOffset:0 length:4 error:nil];
NSLog(#"first four bytes: %02x (%c) %02x (%c) %02x (%c) %02x (%c)",
bytes[0], bytes[0],
bytes[1], bytes[1],
bytes[2], bytes[2],
bytes[3], bytes[3]);
[library autorelease];
}
failureBlock:^(NSError *error)
{
NSLog(#"couldn't get asset: %#", error);
[library autorelease];
}
];
}
So, you create an ALAssetsLibrary, ask it to find you the asset with the URL specified (it understands the assets-library:// URL scheme), then when you get the asset you grab its default representation and use that to feed you the bytes. They'll be the actual on-disk bytes, the default representation for an asset from the library being its on-disk form.
For example, selecting a particular GIF I grabbed at random from Google images, from an image picker wired up to a delegate with that method in it gives me the output:
2011-03-03 23:17:37.451
IPTest[1199:307] size of asset in
bytes: 174960
2011-03-03 23:17:37.459
IPTest[1199:307] first four bytes: 47
(G) 49 (I) 46 (F) 38 (8)
So that's the beginning of the standard GIF header. Picking PNGs or JPGs gives the recognisable first four bytes of the PNG and JPG headers.
EDIT: to finish the thought, obviously you can use ALAssetRepresentation to read all of the bytes describing the file into a suitably malloc'd C array, then use NSData +(id)dataWithBytes:length: (or, more likely, +dataWithBytesNoCopy:length:freeWhenDone:) to wrap that into an NSData.
Here's a version that uses the newer Photos framework:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
NSURL * refUrl = [info objectForKey:UIImagePickerControllerReferenceURL];
if (refUrl) {
PHAsset * asset = [[PHAsset fetchAssetsWithALAssetURLs:#[refUrl] options:nil] lastObject];
if (asset) {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.synchronous = YES;
options.networkAccessAllowed = NO;
options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
NSNumber * isError = [info objectForKey:PHImageErrorKey];
NSNumber * isCloud = [info objectForKey:PHImageResultIsInCloudKey];
if ([isError boolValue] || [isCloud boolValue] || ! imageData) {
// fail
} else {
// success, data is in imageData
}
}];
}
}
}
Here's Eli's version using Swift 3:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: Any]) {
guard let imageURL = info[UIImagePickerControllerReferenceURL] as? URL else { return }
guard let asset = PHAsset.fetchAssets(withALAssetURLs: [imageURL], options: nil).lastObject else { return }
if picker.sourceType == .photoLibrary || picker.sourceType == .savedPhotosAlbum {
let options = PHImageRequestOptions()
options.isSynchronous = true
options.isNetworkAccessAllowed = false
options.deliveryMode = .highQualityFormat
PHImageManager.default().requestImageData(for: asset, options: options) { data, uti, orientation, info in
guard let info = info else { return }
if let error = info[PHImageErrorKey] as? Error {
log.error("Cannot fetch data for GIF image: \(error)")
return
}
if let isInCould = info[PHImageResultIsInCloudKey] as? Bool, isInCould {
log.error("Cannot fetch data from cloud. Option for network access not set.")
return
}
// do something with data (it is a Data object)
}
} else {
// do something with media taken via camera
}
}