iOS 图片处理

1.图片横向显示

功能要求需要开启手机的前置摄像头拍摄图片,设置的前置摄像头分辨率是1280 * 720,但是发现显示图片是是1280 * 720,但是图片成90旋转。要想正常显示,需要对图片进行旋转处理。但是为什么会得到横向的图片?

原因

至于为什么图片是方向是反的呢,因为定义的captureOutput是AVCaptureVideoDataOutput类型,如果是AVCaptureStillImageOutput就不存在这个问题。在头文件AVCaptureSession.hAVCaptureVideoOrientation枚举类型定义视频方位的定义。而这个视频默认的方向是AVCaptureVideoOrientationLandscapeRight,所以得到的图片是横向。


typedef NS_ENUM(NSInteger, AVCaptureVideoOrientation) {

AVCaptureVideoOrientationPortrait          = 1,

AVCaptureVideoOrientationPortraitUpsideDown = 2,

AVCaptureVideoOrientationLandscapeRight    = 3,

AVCaptureVideoOrientationLandscapeLeft      = 4,

} NS_AVAILABLE(10_7, 4_0) __TVOS_PROHIBITED;

解决方法

方法一didOutputSampleBuffer回调函数中,对照片进行旋转处理。


Pixel_8888 bgColor = {0,0,0,0};

vImage_Buffer ibuff = {srcBuff,height,width,bytesPerRow};// 原始图片

vImage_Buffer ubuff = {outBuff,height,width,bytesPerRow};// 结果图片

vImage_Error err = vImageRotate90_ARGB8888(&ibuff, &ubuff, 1, bgColor, 0);

方法二 通过设置AVCaptureConnection从根源上解决图片方向问题。


AVCaptureConnection *videoConnection1 = [self connectionWithMediaType:AVMediaTypeVideo fromConnections:[_videoCapture1 connections]];

if ([videoConnection1 isVideoOrientationSupported]){

[videoConnection1 setVideoOrientation:AVCaptureVideoOrientationPortrait];

}

AVCaptureConnection对象有一个属性叫做videoOrientation这是一个AVCaptureVideoOrientation。可以通过这个设置这个改变视频的方向。

2.图片缩放

通过摄像头得到的图片需要放在指定大小,指定位置的区域。这就要对原始图片进行缩放处理。主要有3种情况:

CSImageDrawFrameScaleToFillWidth:在新的边框填充图片,确保不变形,自定义宽度,高度自适应。

CSImageDrawFrameScaleToFillHeight:在新的边框填充图片,确保不变形,自定义高度,宽度自适应。


- (UIImage *)reSizeImage:(NSData *)imgData withSize:(CGSize)size{

// 保证高度 宽度自定义

UIImage *image = [[UIImage alloc] initWithData:imgData];

UIGraphicsBeginImageContext(size);

[image drawInRect:CGRectMake(0, 0, size.width, size.height)];

UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return reSizeImage;

}

图片按比例压缩,客户端的处理是高度自定义,宽度按原比例自适应。但是发现按比例压缩之后的图片较原图片,感觉模糊很多,之前以为是错觉发现完全不是,就是模糊了。这个模糊让人感觉很奇怪,于是review的代码。

感觉代码处理没有什么问题,为什么图片是变模糊呢?


UIKIT_EXTERN void    UIGraphicsBeginImageContext(CGSize size);

UIKIT_EXTERN void    UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) NS_AVAILABLE_IOS(4_0);

原因在于UIGraphicsBeginImageContext中默认scale的系数是为1.0,在iPhone4以上设备就会产生模糊。为什么这个scale系数的设置会对图片产生模糊的效果呢,因为随着设备的分辨的提升,之前scale = 1.0代表当前设备的分辨率是320 * 480(就是iPhone4设备之前的分辨率)而测试的机子是iPhone6它相应的scale = 2.0 (640 * 960)所以图片在上面显示就会出现模糊。因此我们选择一个可以设置scale的函数。为了不产生模糊应该使用UIGraphicsBeginImageContextWithOptions来替代UIGraphicsBeginImageContext

CSImageDrawFrameFillFull:就是不管宽高比例多少,都会对图片进行拉伸,不确保不变形,不确保不压缩,使图片能够充满整个目标区域。

前面两种情况其实就是按某一比例缩放图片,但是只能保证满足宽高的某一个条件,不能够填满全部,但是图片不会变形。第三种,确保图片能够填满整个区域,但是为了适应区域的大小,图片就有可能会被裁剪或者部分被填充。

3.图片剪裁

这里的图片剪裁,主要有矩形区域裁剪和指定路线的裁剪。

矩形区域 :矩形区域的裁剪很简单,给出所需要裁剪的区域坐标就可以了。


- (UIImage*)redrawImage:(UIImage*)image size:(CGSize)size
{
UIGraphicsBeginImageContextWithOptions(size, NO, [[UIScreen mainScreen] scale]);
[image drawInRect:ccr(0, 0, size.width, size.height)];
UIImage* ret = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return ret;
}

指定线路: 指定线路的区域裁剪比矩形裁剪会复杂一点,有点像PS中用磁性套索进行圈图,通过指定一系列的关键点来控制扣出的图片区域,这个需要一个path来绘制这样的线路。将所有的点添加到path中,然后通过CGPathGetBoundingBox获取剪裁区域的边框。其它跟矩形图片剪裁类似。

4.图片格式转换

在定义一个AVCaptureVideoDataOutput的时候是可以设置它的一个输出图片格式,通过属性变量videoSettings设置kCVPixelBufferPixelFormatTypeKey,这个key-value是必须要设置的。其中value的值是非常的多, 这里kCVPixelBufferPixelFormatTypeKey是指解码后图片的格式。怎样选择这个值,因为看文档还有很多其它的选项提供可以选择,但是并非全部都支持。这个值的选择跟机器硬件解码有很大的关系,选择更有效的格式,处理速度更快。现在基本推荐使用的格式都是kCVPixelFormatType_32BGRA,只能说这个值对当前硬件解码是最优最高效的。图片的格式转化大部分用到OpenCV,OpenCV提供了一些接口函数,比如将图片转化成Mat结构(UIImageToMa())

UIImage - > Mat


static void UIImageToMat(const UIImage* image, cv::Mat& m)

{

CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);

CGFloat cols = image.size.width;

CGFloat rows = image.size.height;

m.create(rows, cols, CV_8UC4); // 8 bits per component, 4 channels

CGContextRef contextRef = CGBitmapContextCreate(m.data, m.cols, m.rows, 8,

m.step[0], colorSpace, kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault);

CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);

CGContextRelease(contextRef);

}

Mat - > UIImage


- (UIImage*)getImageFromCVMat:(cv::Mat)cvMat {

NSData* data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];

CGColorSpaceRef colorSpace;

if (cvMat.elemSize() == 1) {

colorSpace = CGColorSpaceCreateDeviceGray();

} else {

colorSpace = CGColorSpaceCreateDeviceRGB();

}

CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

// Creating CGImage from cv::Mat

CGImageRef imageRef = CGImageCreate(

cvMat.cols,  // width

cvMat.rows,  // height

8,  // bits per component

8 * cvMat.elemSize(),  // bits per pixel

cvMat.step[0],  // bytesPerRow

colorSpace,  // colorspace

kCGImageAlphaNone | kCGBitmapByteOrderDefault,  // bitmap info

provider,  // CGDataProviderRef

NULL,  // decode

false,  // should interpolate

kCGRenderingIntentDefault  // intent

);

UIImage* finalImage = [UIImage imageWithCGImage:imageRef];

CGImageRelease(imageRef);

CGDataProviderRelease(provider);

CGColorSpaceRelease(colorSpace);

return finalImage;

}

这是图片格式转化,还有转换图片的色彩空间cv::cvtColor(image, image, CV_BGRA2RGB)文档还有很多种选择输出,找到你需要的即可。



2016.8.11更新

用iPhone前置摄像头拍摄出来的图片跟摄像头看上去是镜像的,找了几种方法,但发现好像不是每个方法都适用,发现最简单的一种方法解决我的问题。


/*

typedef NS_ENUM(NSInteger, UIImageOrientation) {

UIImageOrientationUp,            // default orientation

UIImageOrientationDown,          // 180 deg rotation

UIImageOrientationLeft,          // 90 deg CCW

UIImageOrientationRight,        // 90 deg CW

UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip

UIImageOrientationDownMirrored,  // horizontal flip

UIImageOrientationLeftMirrored,  // vertical flip

UIImageOrientationRightMirrored, // vertical flip

};

*/

UIImage *iamge = [[UIImage alloc] initWithData:imgData];

UIImage *flippedImage = [UIImage imageWithCGImage:imagData.CGImage scale:1.0 orientation:UIImageOrientationUpMirrored];

还有一种更简便的方法,设置AVCaptureConnection参数videoMirrored这个参数。

    [self.captureOutput connectionWithMediaType:AVMediaTypeVideo].videoMirrored = NO;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 一、目录 1> 图片拉伸处理 2> 图片扩展名 3> 大图减小高度,图片拉伸处理 4> 点击大图,Modal出来,...
    iOS_成才录阅读 5,054评论 1 33
  • 最近遇到一个问题,需要对相机拍摄完的照片进行处理,达到一定的标准。所以研究一下图片、位图、像素这些,也找到了一些文...
    艳晓阅读 19,132评论 4 23
  • 我们常用的图片格式可以分为bmp,jpg,png,gif,webp,其中bmp常用语安卓端开发,iOS常用的是jp...
    iOS谢先森阅读 1,121评论 0 2
  • 本篇涵盖图片处理、绘制、美颜滤镜等. 1.iOS CGImageCreateWithImageInRect将若干规...
    守护地中海的花阅读 239评论 0 0
  • 最近公司项目要做图片处理这里总结一下: 1.普通上下文 2.遮罩处理 利用图层 3.剪切遮罩处理(针对图片) 1....
    Cyrill阅读 1,414评论 0 3