iOS自定義拍照框拍照&裁剪(二)


計算裁剪區域

現在我們已經得到了一個正向的圖片, 如果我們的相機框並非在中心區域,如圖,我們如何得到想要的結果? 我的解決思路是,把拍照框裁剪問題 拆分成三個問題

1.相片旋轉問題,這個在“iOS自定義拍照框拍照&裁剪(一)”已經處理

2.裁剪區域問題。

3.預覽顯示問題。

  • 裁剪區域問題

1.計算出拍照背景框相對於屏幕的區域。假設為(12,193,200,100)

2.計算相對於圖片的區域。如圖(12,120,200,100)

3.根據屏幕旋轉方向計算相對於 修正方向后的圖片的裁剪區域,如果是水平拍攝的圖片,此裁剪區域需要計算轉換。(445,12,100,200)

4.根據屏幕內圖片的裁剪區域,計算相對於原始圖片大小范圍內的裁剪區域。

5.根據裁剪區域使用CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, rect);獲取裁剪后的圖片數據。

圖片名稱
  • 預覽顯示問題

1.使用上述計算中得到的 屏幕內圖片的裁剪區域clipRC,計算預覽圖片是的相機框顯示區域。如果本身是豎直顯示的圖片,則 clipRC 即是 預覽顯示時相機框的預期。如果是橫着顯示的照片,則需要對clipRC進行等比壓縮計算。如下圖

2.根據屏幕旋轉方向獲取預覽顯示拍照框圖片,比如橫着顯示的圖片,拍照框也需要旋轉90度。如下圖

圖片名稱
  • 關鍵代碼實現

計算背景框相對於當前設備大小的CGRect

//根據拍照時手機的方向計算相對於設備大小范圍內的圖片裁剪區域
-(CGRect)calculateClipRectWithImage:(UIImage *)finalImage{
    //設置成圖片大小比例
    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;
    //圖片豎直顯示時,相對於父類的坐標區域
    CGRect portraitRect = CGRectMake(0, ([UIScreen mainScreen].bounds.size.height - imagePortraitHeight)/2, [UIScreen mainScreen].bounds.size.width, imagePortraitHeight);
    
    //裁剪區域 -- 相對於父視圖的坐標區域
    CGRect diyFrameRC = [CTPDIYFrameCameraVideoViewModel transRCFromDIYFrame:self.diyFrame];
    //轉換成相對於圖片imgRC為坐標參考的坐標區域
    CGRect clipRC = [self convertRC:diyFrameRC toCoordinateSpace:portraitRect];
    
    CGRect imageRC = CGRectMake(0, 0, portraitRect.size.width, portraitRect.size.height);
    //根據屏幕方向計算,圖片顯示在當前屏幕范圍內的裁剪區域
    diyFrameRC = [self calculateRect:clipRC contentRC:imageRC];

    return diyFrameRC;
}

/**
坐標轉換,將相機框的坐標轉換成相對於圖片的Rect
相同坐標空間下的兩個RC,將sourceRC轉換成相對於destRC的裁剪區域
*/
-(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;
    //相對於父視圖的交集區域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;
}

/**
 *根據屏幕旋轉方向計算裁剪區域,oldRC必須是基於contentRC坐標系的值
 *oldRC:為轉換前的裁剪區域
 *contentRC:為豎直方向的內容顯示區域
 *返回轉換后的區域。
 */
-(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;
    //裁剪圖片采用的設備坐標系,左上角為原點。注意變換的移動和旋轉方向
    if (self.shootingOrientation == UIDeviceOrientationPortraitUpsideDown) {
        //當前視圖的右下角區域
        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){
        //當前視圖的左下角
        newX = oldRc.origin.y;
        newY = newContentSize.height - newSize.height - oldRc.origin.x;
    }else if(self.shootingOrientation == UIDeviceOrientationLandscapeRight){
        //當前視圖的右上角
        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;
    }
    //前置攝像頭左右轉換。
    if (self.devicePosition == AVCaptureDevicePositionFront) {
        //前置攝像頭在上述計算后的基礎之上沿Y軸翻轉
        newX = newContentSize.width - newSize.width - newX;
    }
    //新的坐標點
    CGRect newRC = CGRectMake(newX, newY, newSize.width, newSize.height);
    return newRC;
}

計算顯示區域

/**
 * 計算拍照完成之后,顯示在屏幕的 裁剪區域
 * clipRC:相對於豎直屏幕根據手機方向旋轉之后的 裁剪區域。
 */
-(CGRect)calculateNewDIYImageFrameWithImage:(UIImage *)finalImage
                                               ClipRC:(CGRect)diyFrameRC{
    
    CGFloat imageWidth = self.photoPreviewImageView.bounds.size.width;
    CGFloat imageHeight = self.photoPreviewImageView.bounds.size.height;
    
    //計算攝像頭豎直拍照時,相對於原圖大小的裁剪區域
    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));
    
    //設置成圖片大小比例
    //裁剪區域 -- 相對於父視圖的坐標區域
    CGFloat newX = self.photoPreviewImageView.frame.origin.x + clipRC.origin.x;
    CGFloat newY = self.photoPreviewImageView.frame.origin.y + clipRC.origin.y;
    //顯示區域
    CGRect newRC = CGRectMake(newX, newY, clipRC.size.width, clipRC.size.height);
    
    return newRC;
}
/**
根據屏幕方向,設置圖片的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軸方向翻轉,
        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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM