Objective-C UIImage 裁剪、旋转、缩放 iOS开发

iOS开发过程中经常会遇到对UIImage的裁剪、旋转、缩放需求

以下封装了UIImage的这些常用操作

转载请说明出处

//
//  UIImage+ProcessImageData.h
//
//  Created by HW on 2020/4/10.
//


#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (ProcessImageData)

#pragma mark - UIImage图像的裁剪

/// 裁剪图像
/// @param rectCut 裁剪的区域
/// @return 裁剪后的图像
- (UIImage *)cutImageWithRect:(CGRect)rectCut;

#pragma mark - UIImage图像的旋转

/// 上下翻转
/// @return 翻转后的图像
- (UIImage *)rotateImageUpAndDown;

/// 左右翻转
/// @return 翻转后的图像
- (UIImage *)rotateImageeftAndRight;

/// 逆时针旋转90°
/// @return 旋转后的图像
- (UIImage *)rotateImageClockLeft;

/// 顺时针旋转90°
/// @return 旋转后的图像
- (UIImage *)rotateImageClockRight;

#pragma mark - UIImage图像的缩放

/// 按比例缩放图像
/// @param scale 缩放的比例,如:0.5 -> 宽高都缩小一半  2.0 -> 宽高都增加一倍
/// @return 缩放后的图像
- (UIImage *)scaleImageWithScale:(CGFloat)scale;

/// 按比例缩放图像
/// @param scaleWidth 宽缩放的比例,如:0.5 -> 宽缩小一半  2.0 -> 宽增加一倍
/// @param scaleHeight 高缩放的比例,如:0.5 -> 高缩小一半  2.0 -> 高增加一倍
/// @return 缩放后的图像
- (UIImage *)scaleImageWithScaleWidth:(CGFloat)scaleWidth withScaleHeight:(CGFloat)scaleHeight;

@end

NS_ASSUME_NONNULL_END

//
//  UIImage+ProcessImageData.m
//
//  Created by HW on 2020/4/10.
//

#import "UIImage+ProcessImageData.h"
#import "UIImage+TransferImageData.h"

//像素通道
#define TransferImageData_RED   0
#define TransferImageData_GREEN 1
#define TransferImageData_BLUE  2
#define TransferImageData_ALPHA 3


@implementation UIImage (ProcessImageData)

#pragma mark - UIImage图像的裁剪

- (UIImage *)cutImageWithRect:(CGRect)rectCut {
    CGImageRef imageRefCut = CGImageCreateWithImageInRect(self.CGImage, rectCut);
    UIImage *pRetnImage = [[UIImage alloc] initWithCGImage:imageRefCut];
    CGImageRelease(imageRefCut);
    return pRetnImage;
}

#pragma mark - UIImage图像的旋转

- (UIImage *)rotateImageUpAndDown {
    CGSize sizeImage = [self size];
    unsigned char *pOldData = [self transferToRGBAData];
    
    int width = sizeImage.width;
    int height= sizeImage.height;
    
    int bytesPerRow = width * 4;

    unsigned char *pEndData = pOldData + (height - 1) * bytesPerRow;
    unsigned char *pBeginData = pOldData;
    
    int h = height / 2 + 1;
    unsigned char pTemp;
    for (int i = 0; i < h; i++)
    {
        unsigned char *pTemp1 = pBeginData;
        unsigned char *pTemp2 = pEndData;
        for (int j = 0; j < width; j++)
        {
            
            pTemp = pTemp1[TransferImageData_RED];
            pTemp1[TransferImageData_RED] = pTemp2[TransferImageData_RED];
            pTemp2[TransferImageData_RED] = pTemp;
            
            pTemp = pTemp1[TransferImageData_GREEN];
            pTemp1[TransferImageData_GREEN] = pTemp2[TransferImageData_GREEN];
            pTemp2[TransferImageData_GREEN] = pTemp;
            
            pTemp = pTemp1[TransferImageData_BLUE];
            pTemp1[TransferImageData_BLUE] = pTemp2[TransferImageData_BLUE];
            pTemp2[TransferImageData_BLUE] = pTemp;
            
            pTemp1 += 4;
            pTemp2 += 4;
        }
        pBeginData += bytesPerRow;
        pEndData -= bytesPerRow;
    }
    
    UIImage *pRetnImage = [UIImage transferToImageWithRGBAData:pOldData withWidth:width withHeight:height];
    
    if (pOldData) {
        delete [] pOldData;
        pOldData = nullptr;
    }
    
    return pRetnImage;
}

- (UIImage *)rotateImageeftAndRight {
    CGSize sizeImage = [self size];
    unsigned char *pOldData = [self transferToRGBAData];
    
    int width = sizeImage.width;
    int height = sizeImage.height;
    
    int bytesPerRow = width * 4;
    
    unsigned char *pEndData = pOldData + (width - 1) * 4;
    unsigned char *pBeginData = pOldData;
    
    int w = width / 2 + 1;
    unsigned char pTemp;
    for (int i = 0; i < height; i++)
    {
        unsigned char *pTemp1 = pBeginData;
        unsigned char *pTemp2 = pEndData;
        for (int j = 0; j < w; j++)
        {
            
            pTemp = pTemp1[TransferImageData_RED];
            pTemp1[TransferImageData_RED] = pTemp2[TransferImageData_RED];
            pTemp2[TransferImageData_RED] = pTemp;
            
            pTemp = pTemp1[TransferImageData_GREEN];
            pTemp1[TransferImageData_GREEN] = pTemp2[TransferImageData_GREEN];
            pTemp2[TransferImageData_GREEN] = pTemp;
            
            pTemp = pTemp1[TransferImageData_BLUE];
            pTemp1[TransferImageData_BLUE] = pTemp2[TransferImageData_BLUE];
            pTemp2[TransferImageData_BLUE] = pTemp;
            
            
            pTemp1 += 4;
            pTemp2 -= 4;
        }
        pBeginData += bytesPerRow;
        pEndData += bytesPerRow;
    }
    
    UIImage *pRetnImage = [UIImage transferToImageWithRGBAData:pOldData withWidth:width withHeight:height];
    
    if (pOldData) {
        delete [] pOldData;
        pOldData = nullptr;
    }
    
    return pRetnImage;
}

- (UIImage *)rotateImageClockLeft {
    CGSize sizeImage = [self size];
    unsigned char *pOldData = [self transferToRGBAData];
    
    int width = sizeImage.width;
    int height = sizeImage.height;
    
    int bytesPerRow = height * 4;
    
    unsigned char *pOldTemp = pOldData;
    unsigned char *pNewData = new unsigned char[width * height * 4];
    
    long index;
    for (int i = 0; i < height; i++)
    {
        index = (i << 2) + int (width - 1) * bytesPerRow;
        for (int j = 0; j < width; j++)
        {
            pNewData[index + TransferImageData_ALPHA] = pOldTemp[TransferImageData_ALPHA];
            pNewData[index + TransferImageData_RED] = pOldTemp[TransferImageData_RED];
            pNewData[index + TransferImageData_GREEN] = pOldTemp[TransferImageData_GREEN];
            pNewData[index + TransferImageData_BLUE] = pOldTemp[TransferImageData_BLUE];
            
            index -= bytesPerRow;
            pOldTemp += 4;
            
        }
    }
    if (pOldData) {
        delete [] pOldData;
        pOldData = nullptr;
    }
    
    UIImage *pRetnImage = [UIImage transferToImageWithRGBAData:pNewData withWidth:height withHeight:width];
    
    if (pNewData) {
        delete [] pNewData;
        pNewData = nullptr;
    }
    
    return pRetnImage;
}

- (UIImage *)rotateImageClockRight {
    CGSize sizeImage = [self size];
    unsigned char *pOldData = [self transferToRGBAData];
    
    int width = sizeImage.width;
    int height = sizeImage.height;
    
    int bytesPerRow = height * 4;
    
    unsigned char *pOldTemp = pOldData;
    unsigned char *pNewData = new unsigned char[width * height * 4];
    
    long index;
    for (int i = 0; i < height; i++)
    {
        index = ((height - 1 - i) << 2);
        for (int j = 0; j < width; j++)
        {
            pNewData[index + TransferImageData_ALPHA] = pOldTemp[TransferImageData_ALPHA];
            pNewData[index + TransferImageData_RED] = pOldTemp[TransferImageData_RED];
            pNewData[index + TransferImageData_GREEN] = pOldTemp[TransferImageData_GREEN];
            pNewData[index + TransferImageData_BLUE] = pOldTemp[TransferImageData_BLUE];
            
            index += bytesPerRow;
            pOldTemp += 4;
            
        }
    }
    if (pOldData) {
        delete [] pOldData;
        pOldData = nullptr;
    }
    
    UIImage *pRetnImage = [UIImage transferToImageWithRGBAData:pNewData withWidth:height withHeight:width];
    
    if (pNewData) {
        delete [] pNewData;
        pNewData = nullptr;
    }
    
    return pRetnImage;
}

#pragma mark - UIImage图像的缩放

- (UIImage *)scaleImageWithScale:(CGFloat)scale {
    return [self scaleImageWithScaleWidth:scale withScaleHeight:scale];
}

- (UIImage *)scaleImageWithScaleWidth:(CGFloat)scaleWidth withScaleHeight:(CGFloat)scaleHeight {
    CGImageRef imgRef = self.CGImage;
    
    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    CGRect bounds = CGRectMake(0, 0, width, height);
    CGFloat boundHeight;
    
    switch(self.imageOrientation)
    {
        case UIImageOrientationUp:
            transform = CGAffineTransformIdentity;
            break;
        case UIImageOrientationUpMirrored:
            transform = CGAffineTransformMakeTranslation(width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;
        case UIImageOrientationDown:
            transform = CGAffineTransformMakeTranslation(width, height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformMakeTranslation(0.0, height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;
        case UIImageOrientationLeftMirrored:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(height, width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
        case UIImageOrientationLeft:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;
        case UIImageOrientationRightMirrored:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
        case UIImageOrientationRight:
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;
        default:
            transform = CGAffineTransformIdentity;
            [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
            
    }
    CGSize boundSize = bounds.size;
    
    //处理四舍五入情况
    boundSize.width = bounds.size.width * scaleWidth + 0.5f;
    boundSize.height = bounds.size.height * scaleHeight + 0.5f;
    boundSize = CGSizeMake((int)boundSize.width, (int)boundSize.height);

    UIGraphicsBeginImageContext(boundSize);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    if (self.imageOrientation == UIImageOrientationRight || self.imageOrientation == UIImageOrientationLeft) {
        CGContextScaleCTM(context, -scaleWidth, scaleHeight);
        CGContextTranslateCTM(context, -height, 0);
    } else if (self.imageOrientation == UIImageOrientationLeftMirrored || self.imageOrientation == UIImageOrientationRightMirrored) {
        CGContextScaleCTM(context, scaleWidth, -scaleHeight);
        CGContextTranslateCTM(context, 0, -width);
    } else {
        CGContextScaleCTM(context, scaleWidth, -scaleHeight);
        CGContextTranslateCTM(context, 0, -height);
    }
    
    CGRect rectClear = CGRectMake(0, 0, bounds.size.width, bounds.size.height);
    
    //默认将底图刷为白色
    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(context, rectClear);
    
    CGContextConcatCTM(context, transform);
    
    if (boundSize.width * boundSize.height <= bounds.size.width * bounds.size.height) {
        CGContextSetInterpolationQuality(context, kCGInterpolationLow);//缩小的,改为低是为了多保留细节
    } else {
        CGContextSetAllowsAntialiasing(context, YES);
        CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    }
    
    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return imageCopy;
}

@end

发布了8 篇原创文章 · 获赞 0 · 访问量 54

猜你喜欢

转载自blog.csdn.net/q345911572/article/details/105438980