iPhone 6+(比例错误?)
iPhone 6+ (Wrong scale?)
我有一个 iOS 应用程序使用相机拍照。
它使用在屏幕上绘制的路径 (CGPath
)(例如矩形),并在该路径内拍摄照片。该应用程序仅支持纵向。
为此,我使用:AVCaptureSession
、AVCaptureStillImageOutput
、AVCaptureDevice
、AVCaptureVideoPreviewLayer
(我想开发此类应用程序的开发人员都很熟悉)。
我的代码使用 UIScreen.mainScreen().bounds
和 UIScreen.mainScreen().scale
来适应各种设备并完成它的工作。
一切顺利(iPhone 5,iPhone 6),直到我在 iPhone 6+(运行 iOS 9.3.1) 并发现有问题。
拍出来的照片放错地方了
我让某人尝试了 iPhone 6+,通过发送适当的消息,我能够确认 (UIScreen.mainScreen().scale
) 应该是:3.0。
我已经在项目中放置了适当大小的发射图像(640∆×∆960、640∆×∆1136、750∆×∆1334、1242∆×∆2208)。
那么可能是什么问题?
我在一个应用程序中使用下面的代码,它适用于 6+。
代码启动 AVCaptureSession,从设备的相机中提取视频输入。
在这样做的同时,它从 captureOutput 委托函数不断更新 runImage 变量。
当用户想要拍照时,调用takePhoto方法。此方法创建一个临时的 UIImageview 并将 runImage 提供给它。然后使用此临时 UIImageView 将另一个名为 currentImage 的变量绘制到设备的比例。
在我的例子中,currentImage 是方形的,与 previewHolder 框架相匹配,但我想你可以做任何你想要的。
声明这些:
AVCaptureDevice * device;
AVCaptureDeviceInput * input;
AVCaptureVideoDataOutput * output;
AVCaptureSession * session;
AVCaptureVideoPreviewLayer * preview;
AVCaptureConnection * connection;
UIImage * runImage;
加载扫描仪:
-(void)loadScanner
{
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
output = [AVCaptureVideoDataOutput new];
session = [AVCaptureSession new];
[session setSessionPreset:AVCaptureSessionPresetPhoto];
[session addInput:input];
[session addOutput:output];
[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[output setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
preview = [AVCaptureVideoPreviewLayer layerWithSession:session];
preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
preview.frame = previewHolder.bounds;
connection = preview.connection;
[connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
[previewHolder.layer insertSublayer:preview atIndex:0];
}
正在进行图像捕获,更新 runImage 变量。
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
runImage = [self imageForBuffer:sampleBuffer];
}
与上述相关。
-(UIImage *)imageForBuffer:(CMSampleBufferRef)sampleBuffer
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
UIImage *image = [UIImage imageWithCGImage:quartzImage];
CGImageRelease(quartzImage);
UIImage * rotated = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0 orientation:UIImageOrientationRight];
return rotated;
}
拍照时:
-(void)takePhoto
{
UIImageView * temp = [UIImageView new];
temp.frame = previewHolder.frame;
temp.image = runImage;
temp.contentMode = UIViewContentModeScaleAspectFill;
temp.clipsToBounds = true;
[self.view addSubview:temp];
UIGraphicsBeginImageContextWithOptions(temp.bounds.size, NO, [UIScreen mainScreen].scale);
[temp drawViewHierarchyInRect:temp.bounds afterScreenUpdates:YES];
currentImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[temp removeFromSuperview];
//further code...
}
以防其他人遇到同样的问题。以下是让我出错的原因:
我正在命名一个文件:xyz@2x.png。
当 UIScreen.mainScreen().scale == 3.0(iPhone 6+ 的情况)
它必须被命名为:xyz@3x.png.
我有一个 iOS 应用程序使用相机拍照。
它使用在屏幕上绘制的路径 (CGPath
)(例如矩形),并在该路径内拍摄照片。该应用程序仅支持纵向。
为此,我使用:AVCaptureSession
、AVCaptureStillImageOutput
、AVCaptureDevice
、AVCaptureVideoPreviewLayer
(我想开发此类应用程序的开发人员都很熟悉)。
我的代码使用 UIScreen.mainScreen().bounds
和 UIScreen.mainScreen().scale
来适应各种设备并完成它的工作。
一切顺利(iPhone 5,iPhone 6),直到我在 iPhone 6+(运行 iOS 9.3.1) 并发现有问题。 拍出来的照片放错地方了
我让某人尝试了 iPhone 6+,通过发送适当的消息,我能够确认 (UIScreen.mainScreen().scale
) 应该是:3.0。
我已经在项目中放置了适当大小的发射图像(640∆×∆960、640∆×∆1136、750∆×∆1334、1242∆×∆2208)。
那么可能是什么问题?
我在一个应用程序中使用下面的代码,它适用于 6+。
代码启动 AVCaptureSession,从设备的相机中提取视频输入。
在这样做的同时,它从 captureOutput 委托函数不断更新 runImage 变量。
当用户想要拍照时,调用takePhoto方法。此方法创建一个临时的 UIImageview 并将 runImage 提供给它。然后使用此临时 UIImageView 将另一个名为 currentImage 的变量绘制到设备的比例。
在我的例子中,currentImage 是方形的,与 previewHolder 框架相匹配,但我想你可以做任何你想要的。
声明这些:
AVCaptureDevice * device;
AVCaptureDeviceInput * input;
AVCaptureVideoDataOutput * output;
AVCaptureSession * session;
AVCaptureVideoPreviewLayer * preview;
AVCaptureConnection * connection;
UIImage * runImage;
加载扫描仪:
-(void)loadScanner
{
device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
output = [AVCaptureVideoDataOutput new];
session = [AVCaptureSession new];
[session setSessionPreset:AVCaptureSessionPresetPhoto];
[session addInput:input];
[session addOutput:output];
[output setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
[output setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];
preview = [AVCaptureVideoPreviewLayer layerWithSession:session];
preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
preview.frame = previewHolder.bounds;
connection = preview.connection;
[connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
[previewHolder.layer insertSublayer:preview atIndex:0];
}
正在进行图像捕获,更新 runImage 变量。
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
runImage = [self imageForBuffer:sampleBuffer];
}
与上述相关。
-(UIImage *)imageForBuffer:(CMSampleBufferRef)sampleBuffer
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef quartzImage = CGBitmapContextCreateImage(context);
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
UIImage *image = [UIImage imageWithCGImage:quartzImage];
CGImageRelease(quartzImage);
UIImage * rotated = [[UIImage alloc] initWithCGImage:image.CGImage scale:1.0 orientation:UIImageOrientationRight];
return rotated;
}
拍照时:
-(void)takePhoto
{
UIImageView * temp = [UIImageView new];
temp.frame = previewHolder.frame;
temp.image = runImage;
temp.contentMode = UIViewContentModeScaleAspectFill;
temp.clipsToBounds = true;
[self.view addSubview:temp];
UIGraphicsBeginImageContextWithOptions(temp.bounds.size, NO, [UIScreen mainScreen].scale);
[temp drawViewHierarchyInRect:temp.bounds afterScreenUpdates:YES];
currentImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[temp removeFromSuperview];
//further code...
}
以防其他人遇到同样的问题。以下是让我出错的原因:
我正在命名一个文件:xyz@2x.png。
当 UIScreen.mainScreen().scale == 3.0(iPhone 6+ 的情况) 它必须被命名为:xyz@3x.png.