我想拍下A4纸的照片。重要的是,我希望文本可读,但我不希望像2592x1936像素或3264x2448像素这样的分辨率的图像太大。此外,我认为捕获后重新缩放照片需要额外的时间,所以我也想避免这种情况。
我们可以选择以下品质:
UIImagePickerControllerQualityTypeHigh = 0
UIImagePickerControllerQualityTypeMedium = 1 default value
UIImagePickerControllerQualityTypeLow = 2
UIImagePickerControllerQualityType640x480 = 3,
UIImagePickerControllerQualityTypeIFrame1280x720 = 4,
UIImagePickerControllerQualityTypeIFrame960x540 = 5
如果我们使用AVFoundation
,我们可以选择this nice table的分辨率(标题为“捕捉静止图像”)。
但UIImagePickerController
是否有类似的表格,例如在iPhone 3gs上UIImagePickerControllerQualityTypeHigh
等于1920x1080?
答案 0 :(得分:18)
UIImagepickerController quality用于视频录制(用于UIImagepickerController属性" videoQuality")。
我想如果你想指定确切的照片分辨率应该是什么,你应该使用AV Foundation框架而不是UIImagepickerController。或者如你所说,之后转换图片。
之后调整大小(找到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;
}
希望这有帮助!
答案 1 :(得分:5)
总之:不。
没有“类似的表格”,因为您误解了UIImagePickerControllerQualityTypeHigh
对UIImagePickerController
的使用情况的误解。
如果您使用UIImagePickerController
拍摄静止图像,您将获得相关设备的默认(即最高)质量 - 从8 MP到iPhone 4s到< 1 MP带iPod touch或iPad 2)。
但是,使用AVFoundation,您可以选择,这要归功于您所引用的会话预设。
但与这些AVFoundation会话预设不同,UIImagePickerController
UIImagePickerControllerQualityType
选项仅适用于动态视频,而不适用于静态图像捕捉。
因此,您可以选择使用AVFoundation来控制捕获大小,或者在保存之前重新调整全尺寸图像的大小;但是UIImagePickerController
不能做你想做的事,我害怕。
答案 2 :(得分:2)
Thermometer's answer的问题在于它会影响图像方向。
我发现this solution解决了方向问题并且性能更快:
- (UIImage *)scaleAndRotateImage:(UIImage *)image {
int kMaxResolution = 320; // Or whatever
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat 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;
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //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 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //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 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //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, M_PI / 2.0);
break;
case UIImageOrientationRight: //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, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
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);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
答案 3 :(得分:2)
对于你的Swift 2.1-Project,这是@ marcelosalloum的代码的翻译:
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
}
答案 4 :(得分:2)
marcelosalloum's answer的快速3翻译:
private func scale(image originalImage: UIImage, toLessThan maxResolution: CGFloat) -> UIImage? {
guard let imageReference = originalImage.cgImage else { return nil }
let rotate90 = CGFloat.pi/2.0 // Radians
let rotate180 = CGFloat.pi // Radians
let rotate270 = 3.0*CGFloat.pi/2.0 // Radians
let originalWidth = CGFloat(imageReference.width)
let originalHeight = CGFloat(imageReference.height)
let originalOrientation = originalImage.imageOrientation
var newWidth = originalWidth
var newHeight = originalHeight
if originalWidth > maxResolution || originalHeight > maxResolution {
let aspectRatio: CGFloat = originalWidth / originalHeight
newWidth = aspectRatio > 1 ? maxResolution : maxResolution * aspectRatio
newHeight = aspectRatio > 1 ? maxResolution / aspectRatio : maxResolution
}
let scaleRatio: CGFloat = newWidth / originalWidth
var scale: CGAffineTransform = .init(scaleX: scaleRatio, y: -scaleRatio)
scale = scale.translatedBy(x: 0.0, y: -originalHeight)
var rotateAndMirror: CGAffineTransform
switch originalOrientation {
case .up:
rotateAndMirror = .identity
case .upMirrored:
rotateAndMirror = .init(translationX: originalWidth, y: 0.0)
rotateAndMirror = rotateAndMirror.scaledBy(x: -1.0, y: 1.0)
case .down:
rotateAndMirror = .init(translationX: originalWidth, y: originalHeight)
rotateAndMirror = rotateAndMirror.rotated(by: rotate180 )
case .downMirrored:
rotateAndMirror = .init(translationX: 0.0, y: originalHeight)
rotateAndMirror = rotateAndMirror.scaledBy(x: 1.0, y: -1.0)
case .left:
(newWidth, newHeight) = (newHeight, newWidth)
rotateAndMirror = .init(translationX: 0.0, y: originalWidth)
rotateAndMirror = rotateAndMirror.rotated(by: rotate270)
scale = .init(scaleX: -scaleRatio, y: scaleRatio)
scale = scale.translatedBy(x: -originalHeight, y: 0.0)
case .leftMirrored:
(newWidth, newHeight) = (newHeight, newWidth)
rotateAndMirror = .init(translationX: originalHeight, y: originalWidth)
rotateAndMirror = rotateAndMirror.scaledBy(x: -1.0, y: 1.0)
rotateAndMirror = rotateAndMirror.rotated(by: rotate270)
case .right:
(newWidth, newHeight) = (newHeight, newWidth)
rotateAndMirror = .init(translationX: originalHeight, y: 0.0)
rotateAndMirror = rotateAndMirror.rotated(by: rotate90)
scale = .init(scaleX: -scaleRatio, y: scaleRatio)
scale = scale.translatedBy(x: -originalHeight, y: 0.0)
case .rightMirrored:
(newWidth, newHeight) = (newHeight, newWidth)
rotateAndMirror = .init(scaleX: -1.0, y: 1.0)
rotateAndMirror = rotateAndMirror.rotated(by: CGFloat.pi/2.0)
}
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.concatenate(scale)
context.concatenate(rotateAndMirror)
context.draw(imageReference, in: CGRect(x: 0, y: 0, width: originalWidth, height: originalHeight))
let copy = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return copy
}