ios通過攝像頭獲取特定數據
文字太小可通過command ‘+’調大字體,溫馨提示。
註釋:
由於最近項目需求,需要一個能夠實現對攝像頭圖片獲取其中部分內容的功能,類似於二維碼掃描。但是隻需要獲取特定位置的像素塊進行簡單計算即可,所以聽上去還是很簡單的,但是經過實踐,發現,現實似乎與想象中不一樣,由於攝像頭拍到的數據,采用的是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:
- (UIImage *)image:(UIImage *)image rotation:(UIImageOrientation)orientation { long double rotate = 0.0; CGRect rect; float translateX = 0; float translateY = 0; float scaleX = 1.0; float scaleY = 1.0; switch (orientation) { case UIImageOrientationLeft: 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; case UIImageOrientationRight: 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; case UIImageOrientationDown: 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(); return newPic; }
結論:
這裡的解決方案,就是對底層像素矩陣進行裝換之後,在對裡面數據截取一部分。可以解決截取部分內容的問題。
——————-
2:解決方案二:就是對rect進行裝換,根據數據底層,進行rect的轉換。