iOS开发过程中经常会遇到对UIImage的裁剪、旋转、缩放需求
以下封装了UIImage的这些常用操作
转载请说明出处
- 注:下面代码的
#import "UIImage+TransferImageData.h"
请看这里:Objective-C UIImage和unsigned char 数据相互转换 iOS开发
//
// 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