Files
yinmeng-ios/xplan-ios/Base/UI/UIImage/UIImage+Utils.m
2023-11-03 14:16:55 +08:00

496 lines
18 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// UIImage+Utils.m
// YYMobileFramework
//
// Created by wuwei on 14/6/20.
// Copyright (c) 2014年 YY Inc. All rights reserved.
//
#import "UIImage+Utils.h"
#import <ImageIO/ImageIO.h>
@implementation UIImage (Utils)
- (UIImage *)grayscaleImage
{
CGFloat width = self.size.width;
CGFloat height = self.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(nil,
width,
height,
8,
0,
colorSpace,
kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(colorSpace);
if (context == NULL) {
return nil;
}
CGContextDrawImage(context, CGRectMake(0, 0, width, height), self.CGImage);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage *grayscaleImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
return grayscaleImage;
}
- (UIImage *)imageBlendInGray {
UIGraphicsBeginImageContext(self.size);
CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextFillRect(context, bounds);
[self drawInRect:bounds blendMode:kCGBlendModeLuminosity alpha:1.0f];
[self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f];
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImg;
}
- (UIImage *)imageWithBlendMode:(CGBlendMode)blendMode {
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);
CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height);
UIRectFill(bounds);
[self drawInRect:bounds blendMode:blendMode alpha:1.0f];
if (blendMode != kCGBlendModeDestinationIn) {
[self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f];
}
UIImage *newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImg;
}
+ (UIImage *)imageWithColor:(UIColor *)color
{
return [self imageWithColor:color size:CGSizeMake(1, 1)];
}
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size {
if (!color || size.width <= 0 || size.height <= 0) return nil;
CGRect rect = CGRectMake(0.0f, 0.0f, size.width + 1, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
+ (UIImage *)fixOrientation:(UIImage *)aImage {
// No-op if the orientation is already correct
if (aImage.imageOrientation == UIImageOrientationUp)
return aImage;
// We need to calculate the proper transformation to make the image upright.
// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
CGAffineTransform transform = CGAffineTransformIdentity;
switch (aImage.imageOrientation) {
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
default:
break;
}
switch (aImage.imageOrientation) {
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
default:
break;
}
// Now we draw the underlying CGImage into a new context, applying the transform
// calculated above.
CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
CGImageGetBitsPerComponent(aImage.CGImage), 0,
CGImageGetColorSpace(aImage.CGImage),
CGImageGetBitmapInfo(aImage.CGImage));
CGContextConcatCTM(ctx, transform);
switch (aImage.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
// Grr...
CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
break;
default:
CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
break;
}
// And now we just create a new UIImage from the drawing context
CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
UIImage *img = [UIImage imageWithCGImage:cgimg];
CGContextRelease(ctx);
CGImageRelease(cgimg);
return img;
}
- (UIImage *)imageWithColor:(UIColor *)color {
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
//异步生成纯色圆角图片
- (void)imageWithSize:(CGSize)size radius:(CGFloat)radius backColor:(UIColor *)backColor completion:(void(^)(UIImage *image))completion {
// 异步绘制裁切
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 利用绘图建立上下文
UIGraphicsBeginImageContextWithOptions(size, true, 0);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
// 填充颜色
[backColor setFill];
UIRectFill(rect);
// // 贝塞尔裁切
// UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
// [path addClip];
// [self drawInRect:rect];
// 获取结果
UIImage *resultImage = [UIGraphicsGetImageFromCurrentImageContext() circularImage];
// 关闭上下文
UIGraphicsEndImageContext();
// 主队列回调
dispatch_async(dispatch_get_main_queue(), ^{
completion(resultImage);
});
});
}
- (UIImage *)circularImage {
// 1. 开启图形上下文
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0);
// 2. 描述路径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.size.width, self.size.height) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii:CGSizeMake(self.size.width, self.size.height)];
// UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
// 3. 添加裁减区域
[path addClip];
// 4. 绘制图片
[self drawAtPoint:CGPointZero];
// 5. 从上下文获取图片
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
// 6. 关闭上下文
UIGraphicsEndImageContext();
// 7. 设置图片
return image;
}
+ (UIImage *)gradientColorImageFromColors:(NSArray<UIColor *> *)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize{
NSMutableArray *ar = [NSMutableArray array];
for(UIColor *c in colors) {
[ar addObject:(id)c.CGColor];
}
UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]);
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL);
CGPoint start;
CGPoint end;
switch (gradientType) {
case GradientTypeTopToBottom:
start = CGPointMake(0.0, 0.0);
end = CGPointMake(0.0, imgSize.height);
break;
case GradientTypeLeftToRight:
start = CGPointMake(0.0, 0.0);
end = CGPointMake(imgSize.width, 0.0);
break;
case GradientTypeUpleftToLowright:
start = CGPointMake(0.0, 0.0);
end = CGPointMake(imgSize.width, imgSize.height);
break;
case GradientTypeUprightToLowleft:
start = CGPointMake(imgSize.width, 0.0);
end = CGPointMake(0.0, imgSize.height);
break;
default:
break;
}
CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGGradientRelease(gradient);
CGContextRestoreGState(context);
CGColorSpaceRelease(colorSpace);
UIGraphicsEndImageContext();
return image;
}
- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size {
//开启图形上下文
UIGraphicsBeginImageContext(size);
//绘制圆角矩形
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
//将Path添加到上下文中
CGContextAddPath(UIGraphicsGetCurrentContext(), path.CGPath);
//裁剪上下文
CGContextClip(UIGraphicsGetCurrentContext());
//将图片绘制到上下文中
[self drawInRect:rect];
//设置绘制模式
CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathStroke);
//获取图片
UIImage *output = UIGraphicsGetImageFromCurrentImageContext();
//关闭上下文
UIGraphicsEndImageContext();
//返回裁剪好的图片
return output;
}
// 给图片添加图片水印
+ (UIImage *)waterImageWithImage:(UIImage *)image waterImage:(UIImage *)waterImage waterImageRect:(CGRect)rect
{
//1.获取图片
//2.开启上下文
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
//3.绘制背景图片
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
//绘制水印图片到当前上下文
[waterImage drawInRect:rect];
//4.从上下文中获取新图片
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
//5.关闭图形上下文
UIGraphicsEndImageContext();
//返回图片
return newImage;
}
+ (CGSize)sizeWithImageOriginSize:(CGSize)originSize
minSize:(CGSize)imageMinSize
maxSize:(CGSize)imageMaxSiz {
CGSize size;
NSInteger imageWidth = originSize.width ,imageHeight = originSize.height;
NSInteger imageMinWidth = imageMinSize.width, imageMinHeight = imageMinSize.height;
NSInteger imageMaxWidth = imageMaxSiz.width, imageMaxHeight = imageMaxSiz.height;
if (imageWidth > imageHeight) //宽图
{
size.height = imageMinHeight; //高度取最小高度
size.width = imageWidth * imageMinHeight / imageHeight;
if (size.width > imageMaxWidth)
{
size.width = imageMaxWidth;
}
}
else if(imageWidth < imageHeight)//高图
{
size.width = imageMinWidth;
size.height = imageHeight *imageMinWidth / imageWidth;
if (size.height > imageMaxHeight){
size.height = imageMaxHeight;
}
}
else//方图
{
if (imageWidth > imageMaxWidth){
size.width = imageMaxWidth;
size.height = imageMaxHeight;
}else if(imageWidth > imageMinWidth){
size.width = imageWidth;
size.height = imageHeight;
}else{
size.width = imageMinWidth;
size.height = imageMinHeight;
}
}
return size;
}
- (UIImage *)cutImage:(CGSize)newSize{
CGFloat scale = newSize.height / self.size.height;
UIImage *scaleImage = [self originImage:self scaleToSize:CGSizeMake(self.size.width*scale, self.size.height*scale)];
//裁剪暂时有问题
return scaleImage;
}
- (UIImage*) originImage:(UIImage *)image scaleToSize:(CGSize)size {
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}
+ (BOOL)isGifWithImageData: (NSData *)data {
if ([[self contentTypeWithImageData:data] isEqualToString:@"gif"]) {
return YES;
}
return NO;
}
+ (NSString *)contentTypeWithImageData: (NSData *)data {
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
case 0xFF:
return @"jpeg";
case 0x89:
return @"png";
case 0x47:
return @"gif";
case 0x49:
case 0x4D:
return @"tiff";
case 0x52:
if ([data length] < 12) {
return nil;
}
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return @"webp";
}
return nil;
}
return nil;
}
//获取gif图片的总时长和循环次数
+ (NSTimeInterval)durationForGifData:(NSData *)data{
//将GIF图片转换成对应的图片源
CGImageSourceRef gifSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
//获取其中图片源个数,即由多少帧图片组成
size_t frameCout = CGImageSourceGetCount(gifSource);
//定义数组存储拆分出来的图片
NSMutableArray* frames = [[NSMutableArray alloc] init];
NSTimeInterval totalDuration = 0;
for (size_t i=0; i<frameCout; i++) {
//从GIF图片中取出源图片
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
//将图片源转换成UIimageView能使用的图片源
UIImage* imageName = [UIImage imageWithCGImage:imageRef];
//将图片加入数组中
[frames addObject:imageName];
NSTimeInterval duration = [UIImage gifImageDeleyTime:gifSource index:i];
totalDuration += duration;
CGImageRelease(imageRef);
}
// //获取循环次数
// NSInteger loopCount;//循环次数
// CFDictionaryRef properties = CGImageSourceCopyProperties(gifSource, NULL);
// if (properties) {
// CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary);
// if (gif) {
// CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount);
// if (loop) {
// //如果loop == NULL表示不循环播放当loopCount == 0时表示无限循环
// CFNumberGetValue(loop, kCFNumberNSIntegerType, &loopCount);
// };
// }
// }
CFRelease(gifSource);
return totalDuration;
}
//获取GIF图片每帧的时长
+ (NSTimeInterval)gifImageDeleyTime:(CGImageSourceRef)imageSource index:(NSInteger)index {
NSTimeInterval duration = 0;
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, NULL);
if (imageProperties) {
CFDictionaryRef gifProperties;
BOOL result = CFDictionaryGetValueIfPresent(imageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties);
if (result) {
const void *durationValue;
if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &durationValue)) {
duration = [(__bridge NSNumber *)durationValue doubleValue];
if (duration < 0) {
if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &durationValue)) {
duration = [(__bridge NSNumber *)durationValue doubleValue];
}
}
}
}
}
return duration;
}
@end