转:ios通过摄像头获取特定数据(http://www.2cto.com/kf/201404/290777.html)

凝视: 因为近期项目需求,须要一个可以实现对摄像头图片获取当中部分内容的功能,类似于二维码扫描。

可是仅仅须要获取特定位置的像素块进行简单计算就可以,所以听上去还是非常easy的。可是经过实践,发现,现实似乎与想象中不一样,因为摄像头拍到的数据,採用的是QZ(也就是CG框架)进行绘制。所以涉及到坐标系与frame的坐标系不一致的问题。

1:尝试直接拿到摄像头数据,先输出看下。 code: 代码略。 

总结: 直接使用摄像头数据再用imageView的方式显示出来的时刻。我们发现,数据是正确的==。所见即所得的方式。 须要注意的是: 当图片是横向拍摄的时刻。我们能够看到。相机会自己主动将图片进行90度旋转,也就是说。系统在你横向拍摄的时刻。会自己主动将图片旋转90度。满足你正常情况下的观看。

所以: 我们使用imageView对拿到的数据进行展示的时刻,数据并没有颠倒的现象。

为了防止出现这个现象的原因是出于imageView的内部实现,我们使用CgimageRef的方式。再次验证 从摄像头拿到的数据真的和我们所示一样吗? 

code:

CGImageRef oldImageRef=image.CGImage;

UIImage* newImage=[UIImage imageWithCGImage:oldImageRef];

凝视: 

在这里,我们仅仅是对拿到的Image对象,先转换成了CGimage。再使用UIImage的方法得到新的Image对象。 

结果:我们发现,得到的图像果然就是旋转90度的图片。而不再是原图了。

UIImage* newImage=[UIImage imageWithCGImage:oldImageRef scale:.1 orientation:UIImageOrientationRight];

使用上面的语句,能够将图像旋转90度变成我们须要的样子。

思考: 

这么简单的变化中,图片会不会丢失数据? ---------

NSData* data=UIImageJPEGRepresentation(image, 0);

NSLog(@"%lu",(unsigned long)data.length);



还好,数据没有丢失。既然数据没有丢失,那么我们应该能够获取到当中特定的一块数据得出。再显示出来才对。 

问题来了: 我们要获取某一块数据的内容,我们应该怎么传递rect呢?由于我们默认的rect与CG的坐标系并不同。是否须要转换呢? 







1:我们先试一下,先把数据转过来。再从里面拿一部分. code:

CGImageRef imageRef=image.CGImage;

CGImageRef newimage=CGImageCreateWithImageInRect(imageRef, rect);

结果发现: 拿到的数据还是倾斜了90度。也就是说,我们上面对数据这种转换事实上根本没有起到作用,数据在底层存储的方式就是使用CG的坐标系存储的。 

经过试验发现,[UIImage imageWithCGImage:oldImageRef scale:.1 orientation:UIImageOrientationRight]中,对orientation的改变。不会对我们的实验结果产生不论什么影响。 也就是说,这种方法,事实上并没有对底层的数据进行操作,而仅仅只是是在初始化新的UIImage的时刻,对底层像素的读取,orientation不同。方向也不同而已。 

思考: 

由于,我们使用上面的方法,并没有操作究竟层的像素矩阵。也就是我。我们假设想要解决问题,有两种方式, 1:将底层数据矩阵转换成我们须要的相应坐标系的内容。

这也就是CTM转换。 将Image对象内部数据进行转换。

code:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-
(UIImage *)image:(UIImage *)image rotation:(UIImageOrientation)orientation
{
    longdoublerotate
=
0.0;
    CGRect
rect;
    floattranslateX
=
0;
    floattranslateY
=
0;
    floatscaleX
=
1.0;
    floatscaleY
=
1.0;
     
    switch(orientation)
{
        caseUIImageOrientationLeft:
            rotate
= M_PI_2;
            rect
= CGRectMake(
0,0,
image.size.height, image.size.width);
            translateX
=
0;
            translateY
= -rect.size.width;
            scaleY
= rect.size.width/rect.size.height;
            scaleX
= rect.size.height/rect.size.width;
            break;
        caseUIImageOrientationRight:
            rotate
=
3*
M_PI_2;
            rect
= CGRectMake(
0,0,
image.size.height, image.size.width);
            translateX
= -rect.size.height;
            translateY
=
0;
            scaleY
= rect.size.width/rect.size.height;
            scaleX
= rect.size.height/rect.size.width;
            break;
        caseUIImageOrientationDown:
            rotate
= M_PI;
            rect
= CGRectMake(
0,0,
image.size.width, image.size.height);
            translateX
= -rect.size.width;
            translateY
= -rect.size.height;
            break;
        default:
            rotate
=
0.0;
            rect
= CGRectMake(
0,0,
image.size.width, image.size.height);
            translateX
=
0;
            translateY
=
0;
            break;
    }
     
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef
context = UIGraphicsGetCurrentContext();
    //做CTM变换
    CGContextTranslateCTM(context,0.0,
rect.size.height);
    CGContextScaleCTM(context,1.0,
-
1.0);
    CGContextRotateCTM(context,
rotate);
    CGContextTranslateCTM(context,
translateX, translateY);
     
    CGContextScaleCTM(context,
scaleX, scaleY);
    //绘制图片
    CGContextDrawImage(context,
CGRectMake(
0,0,
rect.size.width, rect.size.height), image.CGImage);
     
    UIImage
*newPic = UIGraphicsGetImageFromCurrentImageContext();
     
    returnnewPic;
}

结论:

这里的解决方式。就是对底层像素矩阵进行装换之后,在对里面数据截取一部分。

能够解决截取部分内容的问题。

-------------------

2:解决方式二:就是对rect进行装换。依据数据底层,进行rect的转换。

最新文章

  1. webservice 小小例子
  2. 通用easyui查询页面组件
  3. Html5 dataset--自定义属性
  4. 百度站长工具进击site结果页面[SITE特型]
  5. opencv linux
  6. heap(堆)和stack(栈)的区别
  7. dataList中实现用复选框一次删除多行问题
  8. Android开发之使用Handler封装下载图片工具类(源码分享)
  9. Windows 上连接本地 Linux虚拟机上的 mysql 数据库
  10. Magicodes.WeiChat——发送模板消息
  11. DNS到底是干什么用的
  12. nodejs+expressjs+ws实现了websocket即时通讯,服务器和客户端互相通信
  13. JasperReport子报表参数传递
  14. MySQL之数据导入导出
  15. 2017-2018-2 20165312 实验四《Android程序设计》实验报告
  16. Netbeans配置Java SE嵌入式平台(树莓派)
  17. linux桌面与命令模式切换
  18. php安装amqp扩展
  19. SEEprog Serial EEPROM programmer
  20. ubuntu11下安装文件

热门文章

  1. java 判断字符串中是否包含中文并过滤掉中文
  2. ibatis 批量更新(二)
  3. 【Linux】文件夹及作用说明
  4. Mongodb对数据库(DB)的常用操作
  5. chrome配置文件校验初始化隐含參数的逆向
  6. 监听Sms.Content_URI而不是Sms.Inbox.CONTENT_URI
  7. ios中 radioButton和DataPIcker,九宫格封装好使用
  8. 神奇的 Block
  9. winetricks 用WineTricks令你的Wine更完整
  10. TensorFlow 基本概念