PHIMageManager requestImageDataForAsset:options:resultHandler: does not take into account orientation - ios

I am trying to use this method to then upload imageData to my service but the resulting imageData does not take into account orientation and I am uploading images in the incorrect orientation.
Any suggestions?

I solve the exact same problem using this f°, to get the original image size, you just have to pass size == CGSizeMake (10000000000, 10000000000), hope this help :)
+ (UIImage *)createThumbFromImageIO:(UIImage*)image maxPixelSize:(CGSize)size
{
NSData *imagedata = UIImageJPEGRepresentation(image, 1);
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imagedata, NULL);
if (!imageSource) return nil;
CGSize imageSize = image.size;
imageSize = CGSizeMake(size.width,size.height);
CFDictionaryRef options = (__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageIfAbsent,
(id)[NSNumber numberWithFloat:imageSize.height], (id)kCGImageSourceThumbnailMaxPixelSize,
nil];
CGImageRef imgRef = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options);
image = [UIImage imageWithCGImage:imgRef];
CGImageRelease(imgRef);
CFRelease(imageSource);
return image;
}

Related

How to get width and height of an image loaded from a server in iOS?

How can I get the width and height of an image which was loaded from a server in iOS? I know with NSData we can retrieve the width and height, but it's very slow. Is there any other solution? Thanks
If your image is in a UIImage, you can use:
float width = yourImage.size.width;
float height = yourImage.size.height;
FYI, you can pull an image into a UIImage from NSData using:
UIImage *img = [UIImage imageWithData:yourData];
try with ImageIO framework
#import ImageIO; ...
NSURL *imageURL = yourUrl
CGImageSourceCreateWithURL((__bridge CFURLRef)url, NULL);
NSDictionary* imageProperty = (__bridge_transfer NSDictionary*)
CGImageSourceCopyPropertiesAtIndex(imgSource, 0, NULL);
NSLog(#"%#", imageProperty);
CFRelease(imgSource);

Using Image I/O to create thumbnail from programatically created UIImage

I am trying to use image I/O to create thumbnails from a UIImage that I have created programatically. the problem is that the image that is returned is nil.
-( UIImage *) thumbnailFromImage: ( UIImage *)image
{
CGDataProviderRef dataProvider = CGImageGetDataProvider( image.CGImage );
CGImageSourceRef src = CGImageSourceCreateWithDataProvider( dataProvider, NULL );
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailWithTransform,
(id)kCFBooleanTrue, (id)kCGImageSourceCreateThumbnailFromImageAlways,
(id)[NSNumber numberWithFloat:160.f], (id)kCGImageSourceThumbnailMaxPixelSize,
nil];
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex( src, 0, (__bridge CFDictionaryRef)(options) );
UIImage* smallImage = [UIImage imageWithCGImage:thumbnail scale:1 orientation:UIImageOrientationUp];
return smallImage;
}
Has anybody have any suggestions.
thanks
Reza

iOS easier way to resize image

I'm trying to resize an image on a background thread and the app always crashes after a few low memory warnings. How can I rewrite the code below to fix this?
float max = 1024*1024;
NSData *pngData = UIImagePNGRepresentation(setImage);
while ([pngData length] > max) {
pngData = nil;
CGSize newSize = CGSizeMake(setImage.size.width*.9, setImage.size.height *.9);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSLog(#"scale: %f", (1024.0*1024.0)/((float)[pngData length]));
pngData = UIImagePNGRepresentation(image);
}
NSLog(#"image length: %i",[pngData length]);
[pngData writeToFile:imageLocation atomically:YES];
I have already tried doing this by calculating the scale and replace the .9 in the code with a scale value
float scale = (max)/((float)[pngData length]);
CGSize newSize = CGSizeMake(setImage.size.width*scale, setImage.size.height *scale);
This made the image too small.
The end goal is to take an image from the camera and save it to disk. I originally had to resize the image because I was getting a "Low Memory warning" when loading the image.
Your code causes an infinite loop and creates images until you run out of memory. Try something like this to fix the infinite loop:
float max = 1024*1024;
NSData *pngData = UIImagePNGRepresentation(setImage);
CGSize newSize = setImage.size;
while ([pngData length] > max) {
newSize = CGSizeMake(newSize.width * 0.9, newSize.height * 0.9);
UIGraphicsBeginImageContext(newSize);
[setImage drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSLog(#"scale: %f", (1024.0*1024.0)/((float)[pngData length]));
pngData = UIImagePNGRepresentation(image);
image = nil;
}
NSLog(#"image length: %i",[pngData length]);
[pngData writeToFile:imageLocation atomically:YES];
Is there any reason why you need to do this by hand? If you use a UIImageView and set the image either with initWithImage: or with the image property and then change UIImageView's frame the image will resize accordingly

What is the proper way to handle retina images from resized nsdata?

When a user selects an image from the their photo library, I'm resizing it and then uploading it to my server and then at some other point in the app the user can view all their photos. (I'm simplifying the work flow)
The uiimageview on the "detail" screen is 320 x 320. Based upon the below method should I be using:
UIImage *image = [UIImage imageWithCGImage:img];
or
UIImage *image = [UIImage imageWithCGImage:img scale:[UIScreen mainScreen].scale orientation:img.imageOrientation];
Part B would be when I request download the image (nsdata) should I use imageWithCGIImage or imageWithCGIImage:scale:orientation
- (UIImage *)resizedImageForUpload:(UIImage *)originalImage {
static CGSize __maxSize = {640, 640};
NSMutableData *data = [[NSMutableData alloc] initWithData:UIImageJPEGRepresentation(originalImage, 1.0)];
CFMutableDataRef dataRef = (__bridge CFMutableDataRef)data;
CGImageSourceRef imgSrc = CGImageSourceCreateWithData(dataRef, NULL);
CGFloat width = [originalImage maxDimensionForConstraintSize:__maxSize];
NSNumber *maxWidth = [NSNumber numberWithFloat:width];
NSDictionary *options = #{
(__bridge NSString *)kCGImageSourceCreateThumbnailFromImageAlways : #YES,
(__bridge NSString *)kCGImageSourceCreateThumbnailWithTransform: #YES,
(__bridge NSString *)kCGImageSourceThumbnailMaxPixelSize : maxWidth
};
CFDictionaryRef cfOptions = (__bridge CFDictionaryRef)options;
CGImageRef img = CGImageSourceCreateThumbnailAtIndex(imgSrc, 0, cfOptions);
CFStringRef type = CGImageSourceGetType(imgSrc);
CGImageDestinationRef imgDest = CGImageDestinationCreateWithData(dataRef, type, 1, NULL);
CGImageDestinationAddImage(imgDest, img, NULL);
CGImageDestinationFinalize(imgDest);
UIImage *image = [UIImage imageWithCGImage:img];
CFRelease(imgSrc);
CGImageRelease(img);
CFRelease(imgDest);
return image;
}
It appears I've found the answer to my own question. The resizeImageForUpload shouldn't try to scale based upon the device. Since I'm defining a max size 640,640 (retina size for my 320,320 uiimageview) no other manipulation is necessary. I've added some caching for the images and I'm handing the scaling at that point:
UIImage *image = [UIImage imageWithData:imgData scale:[UIScreen mainScreen].scale];
and then return. The reason why I thought I had messed something up was that I was trying to scale an already scaled image. Lessons learned.

How to compress/resize image on iOS before uploading to a server?

I'm currently uploading an image to a server using Imgur on iOS with the following code:
NSData* imageData = UIImagePNGRepresentation(image);
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* fullPathToFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"SBTempImage.png"];
[imageData writeToFile:fullPathToFile atomically:NO];
[uploadRequest setFile:fullPathToFile forKey:#"image"];
The code works fine when run in the simulator and uploading a file from the simulator's photo library because I'm on a fast ethernet connection. However, the same code times out on the iPhone when selecting an image taken with the iPhone. So, I tried it by saving a small image from the web and attempting to upload that, which worked.
This leads me to believe the large images taken by the iPhone are timing out over the somewhat slow 3G network. Is there any way to compress/resize the image from the iPhone before sending it?
This snippet will resize the image:
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
The variable newSize is a CGSize and can be defined like so:
CGSize newSize = CGSizeMake(100.0f, 100.0f);
A self-contained solution:
- (UIImage *)compressForUpload:(UIImage *)original scale:(CGFloat)scale
{
// Calculate new size given scale factor.
CGSize originalSize = original.size;
CGSize newSize = CGSizeMake(originalSize.width * scale, originalSize.height * scale);
// Scale the original image to match the new size.
UIGraphicsBeginImageContext(newSize);
[original drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *compressedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return compressedImage;
}
Thanks to #Tuan Nguyen.
To complement #Tuan Nguyen, this is maybe the fastest and most elegant way to do that.
To link to John Muchow's post at iphonedevelopertips.com , adding a category to a UIImage is a very very handy way to scale in a very fast fashion.
Just calling
UIImage *_image = [[[UIImage alloc] initWithData:SOME_NSDATA] scaleToSize:CGSizeMake(640.0,480.0)];
returns you a 640x480 representation image of your NSDATA ( that could be an online image ) without any more line of code.
Matt Gemmell's MGImageUtilities are very nice, resizing efficiently and with some effort-reducing methods.
In this code 0.5 means 50% ...
UIImage *original = image;
UIImage *compressedImage = UIImageJPEGRepresentation(original, 0.5f);
use this simple method NSData *data = UIImageJPEGRepresentation(chosenImage, 0.2f);
Swift implementation of Zorayr's function (with a bit of a change to include height or width constraints by actual units not scale):
class func compressForUpload(original:UIImage, withHeightLimit heightLimit:CGFloat, andWidthLimit widthLimit:CGFloat)->UIImage{
let originalSize = original.size
var newSize = originalSize
if originalSize.width > widthLimit && originalSize.width > originalSize.height {
newSize.width = widthLimit
newSize.height = originalSize.height*(widthLimit/originalSize.width)
}else if originalSize.height > heightLimit && originalSize.height > originalSize.width {
newSize.height = heightLimit
newSize.width = originalSize.width*(heightLimit/originalSize.height)
}
// Scale the original image to match the new size.
UIGraphicsBeginImageContext(newSize)
original.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
let compressedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return compressedImage
}
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
+ (UIImage *)resizeImage:(UIImage *)image toResolution:(int)resolution {
NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CFDictionaryRef options = (__bridge CFDictionaryRef) #{
(id) kCGImageSourceCreateThumbnailWithTransform : #YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : #YES,
(id) kCGImageSourceThumbnailMaxPixelSize : #(resolution)
};
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
UIImage *img = [[UIImage alloc]initWithCGImage:thumbnail];
return img;
}
Swift 2.0 version of Jagandeep Singh method but need to convert data to image because NSData? is not converted UIImage automatically.
let orginalImage:UIImage = image
let compressedData = UIImageJPEGRepresentation(orginalImage, 0.5)
let compressedImage = UIImage(data: compressedData!)
NsData *data=UiImageJPEGRepresentation(Img.image,0.2f);
UIImage *image = [UIImage imageNamed:#"image.png"];
NSData *imgData1 = UIImageJPEGRepresentation(image, 1);
NSLog(#"Original --- Size of Image(bytes):%d",[imgData1 length]);
NSData *imgData2 = UIImageJPEGRepresentation(image, 0.5);
NSLog(#"After --- Size of Image(bytes):%d",[imgData2 length]);
image = [UIImage imageWithData:imgData2];
imgTest.image = image;
try to convert JPG by scaling factor. Here I am using 0.5
In my case:
Original --- Size of Image(bytes): 85KB & After --- Size of Image(bytes): 23KB
-(UIImage *) resizeImage:(UIImage *)orginalImage resizeSize:(CGSize)size
{
CGFloat actualHeight = orginalImage.size.height;
CGFloat actualWidth = orginalImage.size.width;
// if(actualWidth <= size.width && actualHeight<=size.height)
// {
// return orginalImage;
// }
float oldRatio = actualWidth/actualHeight;
float newRatio = size.width/size.height;
if(oldRatio < newRatio)
{
oldRatio = size.height/actualHeight;
actualWidth = oldRatio * actualWidth;
actualHeight = size.height;
}
else
{
oldRatio = size.width/actualWidth;
actualHeight = oldRatio * actualHeight;
actualWidth = size.width;
}
CGRect rect = CGRectMake(0.0,0.0,actualWidth,actualHeight);
UIGraphicsBeginImageContext(rect.size);
[orginalImage drawInRect:rect];
orginalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return orginalImage;
}
This is the method calling
UIImage *compimage=[appdel resizeImage:imagemain resizeSize:CGSizeMake(40,40)];
it returns image this image u can display any where...........
You should be able to make a smaller image by doing something like
UIImage *small = [UIImage imageWithCGImage:original.CGImage scale:0.25 orientation:original.imageOrientation];
(for a quarter-size image) then convert the smaller image to a PNG or whatever format you need.

Resources