I would like to take photos of A4 pieces of paper with writing on. Importantly, I want the text to be readable, but I do not want images with resolutions like 2592x1936 pixel or 3264x2448 pixel as that would be too big. Also, I assume that rescaling the photo after capturing takes extra time, so I would like to avoid this too.
We can choose between the following qualities:
UIImagePickerControllerQualityTypeHigh = 0
UIImagePickerControllerQualityTypeMedium = 1 default value
UIImagePickerControllerQualityTypeLow = 2
UIImagePickerControllerQualityType640x480 = 3,
UIImagePickerControllerQualityTypeIFrame1280x720 = 4,
UIImagePickerControllerQualityTypeIFrame960x540 = 5
If we were using the AVFoundation
, we could choose resolutions from this nice table (under headline "Capturing Still Images").
But is there a similar table for UIImagePickerController
, which for example says that UIImagePickerControllerQualityTypeHigh
equals 1920x1080 on iPhone 3gs?
UIImagepickerController quality is used for video recording (used in UIImagepickerController property "videoQuality").
I guess that if you want to specify what the exact photo resolution should be, you should use the AV Foundation framework instead of the UIImagepickerController. Or as you said, convert the picture afterwards.
To resize it afterwards (found here):
// ==============================================================
// resizedImage
// ==============================================================
// Return a scaled down copy of the image.
UIImage* resizedImage(UIImage *inImage, CGRect thumbRect)
{
CGImageRef imageRef = [inImage CGImage];
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
// There's a wierdness with kCGImageAlphaNone and CGBitmapContextCreate
// see Supported Pixel Formats in the Quartz 2D Programming Guide
// Creating a Bitmap Graphics Context section
// only RGB 8 bit images with alpha of kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst,
// and kCGImageAlphaPremultipliedLast, with a few other oddball image kinds are supported
// The images on input here are likely to be png or jpeg files
if (alphaInfo == kCGImageAlphaNone)
alphaInfo = kCGImageAlphaNoneSkipLast;
// Build a bitmap context that's the size of the thumbRect
CGContextRef bitmap = CGBitmapContextCreate(
NULL,
thumbRect.size.width, // width
thumbRect.size.height, // height
CGImageGetBitsPerComponent(imageRef), // really needs to always be 8
4 * thumbRect.size.width, // rowbytes
CGImageGetColorSpace(imageRef),
alphaInfo
);
// Draw into the context, this scales the image
CGContextDrawImage(bitmap, thumbRect, imageRef);
// Get an image from the context and a UIImage
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* result = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap); // ok if NULL
CGImageRelease(ref);
return result;
}
Hope this helps!
For your Swift 2.1-Project, this is the translation of @marcelosalloum's code:
func scaleAndRotateImage(image: UIImage, kMaxResolution: CGFloat) -> UIImage {
var imageCopy: UIImage = image
if let imgRef: CGImageRef = image.CGImage {
let width = CGFloat(CGImageGetWidth(imgRef))
let height = CGFloat(CGImageGetHeight(imgRef))
var transform = CGAffineTransformIdentity
var bounds = CGRectMake(0, 0, width, height)
if width > kMaxResolution || height > kMaxResolution {
let ratio = width/height
if ratio > 1 {
bounds.size.width = kMaxResolution
bounds.size.height = bounds.size.width / ratio
} else {
bounds.size.height = kMaxResolution
bounds.size.width = bounds.size.height * ratio
}
}
let scaleRatio = bounds.size.width / width
let imageSize = CGSizeMake(width, height)
let boundHeight: CGFloat
let orient: UIImageOrientation = image.imageOrientation
switch orient {
case .Up:
transform = CGAffineTransformIdentity
case .UpMirrored:
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0)
transform = CGAffineTransformScale(transform, -1.0, 1.0)
case .Down:
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height)
transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
case .DownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
case .LeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);
case .Left: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * CGFloat(M_PI) / 2.0);
case .RightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);
case .Right: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, CGFloat(M_PI) / 2.0);
}
UIGraphicsBeginImageContext(bounds.size)
if let context: CGContextRef = UIGraphicsGetCurrentContext() {
if orient == .Right || orient == .Left {
CGContextScaleCTM(context, -scaleRatio, scaleRatio)
CGContextTranslateCTM(context, -height, 0)
} else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio)
CGContextTranslateCTM(context, 0, -height)
}
CGContextConcatCTM(context, transform)
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0,0,width,height), imgRef)
imageCopy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
return imageCopy
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With