iOS自定义拍照框拍照&裁剪(二)
計算裁剪區(qū)域
現(xiàn)在我們已經(jīng)得到了一個正向的圖片, 如果我們的相機框并非在中心區(qū)域,如圖,我們?nèi)绾蔚玫较胍慕Y(jié)果? 我的解決思路是,把拍照框裁剪問題 拆分成三個問題
1.相片旋轉(zhuǎn)問題,這個在“iOS自定義拍照框拍照&裁剪(一)”已經(jīng)處理
2.裁剪區(qū)域問題。
3.預(yù)覽顯示問題。
裁剪區(qū)域問題
1.計算出拍照背景框相對于屏幕的區(qū)域。假設(shè)為(12,193,200,100)
2.計算相對于圖片的區(qū)域。如圖(12,120,200,100)
3.根據(jù)屏幕旋轉(zhuǎn)方向計算相對于 修正方向后的圖片的裁剪區(qū)域,如果是水平拍攝的圖片,此裁剪區(qū)域需要計算轉(zhuǎn)換。(445,12,100,200)
4.根據(jù)屏幕內(nèi)圖片的裁剪區(qū)域,計算相對于原始圖片大小范圍內(nèi)的裁剪區(qū)域。
5.根據(jù)裁剪區(qū)域使用CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, rect);獲取裁剪后的圖片數(shù)據(jù)。
預(yù)覽顯示問題
1.使用上述計算中得到的 屏幕內(nèi)圖片的裁剪區(qū)域clipRC,計算預(yù)覽圖片是的相機框顯示區(qū)域。如果本身是豎直顯示的圖片,則 clipRC 即是 預(yù)覽顯示時相機框的預(yù)期。如果是橫著顯示的照片,則需要對clipRC進行等比壓縮計算。如下圖
2.根據(jù)屏幕旋轉(zhuǎn)方向獲取預(yù)覽顯示拍照框圖片,比如橫著顯示的圖片,拍照框也需要旋轉(zhuǎn)90度。如下圖
關(guān)鍵代碼實現(xiàn)
計算背景框相對于當(dāng)前設(shè)備大小的CGRect
//根據(jù)拍照時手機的方向計算相對于設(shè)備大小范圍內(nèi)的圖片裁剪區(qū)域
-(CGRect)calculateClipRectWithImage:(UIImage *)finalImage{
//設(shè)置成圖片大小比例
CGFloat imageWidth = CGImageGetWidth(finalImage.CGImage);
CGFloat imageHeight = CGImageGetHeight(finalImage.CGImage);
CGFloat maxH = imageWidth < imageHeight ? imageHeight : imageWidth;
CGFloat minW = imageWidth < imageHeight ? imageWidth : imageHeight;
//圖片豎直顯示時候的高度
CGFloat imagePortraitHeight = [UIScreen mainScreen].bounds.size.width * maxH/minW;
//圖片豎直顯示時,相對于父類的坐標區(qū)域
CGRect portraitRect = CGRectMake(0, ([UIScreen mainScreen].bounds.size.height - imagePortraitHeight)/2, [UIScreen mainScreen].bounds.size.width, imagePortraitHeight);
//裁剪區(qū)域 -- 相對于父視圖的坐標區(qū)域
CGRect diyFrameRC = [CTPDIYFrameCameraVideoViewModel transRCFromDIYFrame:self.diyFrame];
//轉(zhuǎn)換成相對于圖片imgRC為坐標參考的坐標區(qū)域
CGRect clipRC = [self convertRC:diyFrameRC toCoordinateSpace:portraitRect];
CGRect imageRC = CGRectMake(0, 0, portraitRect.size.width, portraitRect.size.height);
//根據(jù)屏幕方向計算,圖片顯示在當(dāng)前屏幕范圍內(nèi)的裁剪區(qū)域
diyFrameRC = [self calculateRect:clipRC contentRC:imageRC];
return diyFrameRC;
}
/**
坐標轉(zhuǎn)換,將相機框的坐標轉(zhuǎn)換成相對于圖片的Rect
相同坐標空間下的兩個RC,將sourceRC轉(zhuǎn)換成相對于destRC的裁剪區(qū)域
*/
-(CGRect)convertRC:(CGRect)sourceRC toCoordinateSpace:(CGRect)destRC{
CGRect rc = CGRectMake(0, 0, sourceRC.size.width, sourceRC.size.height);
CGFloat x = sourceRC.origin.x - destRC.origin.x;
CGFloat y = sourceRC.origin.y - destRC.origin.y;
//相對于父視圖的交集區(qū)域RC
// rc = CGRectIntersection(destRC,sourceRC);
// rc.origin.x = x > 0 ? x : 0;
// rc.origin.y = y > 0 ? y : 0;
rc.origin.x = x;
rc.origin.y = y;
return rc;
}
/**
*根據(jù)屏幕旋轉(zhuǎn)方向計算裁剪區(qū)域,oldRC必須是基于contentRC坐標系的值
*oldRC:為轉(zhuǎn)換前的裁剪區(qū)域
*contentRC:為豎直方向的內(nèi)容顯示區(qū)域
*返回轉(zhuǎn)換后的區(qū)域。
*/
-(CGRect)calculateRect:(CGRect)oldRc contentRC:(CGRect)contentRC{
CGSize newSize = CGSizeMake(oldRc.size.height, oldRc.size.width);
CGSize newContentSize = CGSizeMake(contentRC.size.height, contentRC.size.width);
NSInteger newX = 0;
NSInteger newY = 0;
//裁剪圖片采用的設(shè)備坐標系,左上角為原點。注意變換的移動和旋轉(zhuǎn)方向
if (self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown) {
//當(dāng)前視圖的右下角區(qū)域
newSize = oldRc.size;
newContentSize = contentRC.size;
newX = newContentSize.width - newSize.width - oldRc.origin.x;
newY = newContentSize.height - newSize.height - oldRc.origin.y;
}else if (self.shootingOrientation == UIDeviceOrientationLandscapeLeft){
//當(dāng)前視圖的左下角
newX = oldRc.origin.y;
newY = newContentSize.height - newSize.height - oldRc.origin.x;
}else if(self.shootingOrientation == UIDeviceOrientationLandscapeRight){
//當(dāng)前視圖的右上角
newX = newContentSize.width - newSize.width - oldRc.origin.y;
newY = oldRc.origin.x;
}else if(self.shootingOrientation == UIDeviceOrientationPortrait){
//豎直拍照,返回
newSize = oldRc.size;
newContentSize = contentRC.size;
newX = oldRc.origin.x;
newY = oldRc.origin.y;
}
//前置攝像頭左右轉(zhuǎn)換。
if (self.devicePosition == AVCaptureDevicePositionFront) {
//前置攝像頭在上述計算后的基礎(chǔ)之上沿Y軸翻轉(zhuǎn)
newX = newContentSize.width - newSize.width - newX;
}
//新的坐標點
CGRect newRC = CGRectMake(newX, newY, newSize.width, newSize.height);
return newRC;
}
計算顯示區(qū)域
/**
* 計算拍照完成之后,顯示在屏幕的 裁剪區(qū)域
* clipRC:相對于豎直屏幕根據(jù)手機方向旋轉(zhuǎn)之后的 裁剪區(qū)域。
*/
-(CGRect)calculateNewDIYImageFrameWithImage:(UIImage *)finalImage
ClipRC:(CGRect)diyFrameRC{
CGFloat imageWidth = self.photoPreviewImageView.bounds.size.width;
CGFloat imageHeight = self.photoPreviewImageView.bounds.size.height;
//計算攝像頭豎直拍照時,相對于原圖大小的裁剪區(qū)域
CGFloat scale = 1.0;
if (imageWidth > imageHeight) {
//橫向顯示的照片
scale = imageHeight/[UIScreen mainScreen].bounds.size.width;
}
CGRect clipRC = CGRectMake((NSInteger)(diyFrameRC.origin.x * scale), (NSInteger)(diyFrameRC.origin.y * scale), (NSInteger)(diyFrameRC.size.width * scale), (NSInteger)(diyFrameRC.size.height * scale));
//設(shè)置成圖片大小比例
//裁剪區(qū)域 -- 相對于父視圖的坐標區(qū)域
CGFloat newX = self.photoPreviewImageView.frame.origin.x + clipRC.origin.x;
CGFloat newY = self.photoPreviewImageView.frame.origin.y + clipRC.origin.y;
//顯示區(qū)域
CGRect newRC = CGRectMake(newX, newY, clipRC.size.width, clipRC.size.height);
return newRC;
}
/**
根據(jù)屏幕方向,設(shè)置圖片的orientation,獲取方向正確的拍照框圖片。
*/
-(UIImage *)changeImageOrigin{
//拍照框
UIImage *image = self.frameImage;
if (self.shootingOrientation == UIDeviceOrientationLandscapeLeft) {
image = [UIImage imageWithCGImage:self.frameImage.CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationLeft];
}else if (self.shootingOrientation == UIDeviceOrientationLandscapeRight){
image = [UIImage imageWithCGImage:self.frameImage.CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationRight];
}else if (self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown){
image = [UIImage imageWithCGImage:self.frameImage.CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationDown];
}
if (self.devicePosition == AVCaptureDevicePositionFront) {
//前置攝像頭Y軸方向翻轉(zhuǎn),
if (self.shootingOrientation == UIDeviceOrientationLandscapeRight) {
image = [UIImage imageWithCGImage:self.frameImage.CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationLeft];
}
if (self.shootingOrientation == UIDeviceOrientationLandscapeLeft) {
image = [UIImage imageWithCGImage:self.frameImage.CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationRight];
}
}
return image;
}
總結(jié)
以上是生活随笔為你收集整理的iOS自定义拍照框拍照&裁剪(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 白盒测试系列(三)条件覆盖
- 下一篇: 2.0米办公桌多少钱