UIImage高效能圓角繪製,壓縮,截圖,幀圖片獲取,修改原有image底色等各種功能持續更新
蒐集一些UIImage的各種使用功能
1.圖片壓縮
- (UIImage *)imageByScalingAndCroppingForSourceImage:(UIImage *)sourceImage targetSize:(CGSize)targetSize
{
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor)
scaleFactor = widthFactor; // scale to fit height
else
scaleFactor = heightFactor; // scale to fit width
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else
if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
UIGraphicsBeginImageContext(targetSize); // this will crop
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
if(newImage == nil) NSLog(@"could not scale image");
//pop the context to get back to the default
UIGraphicsEndImageContext();
return newImage;
}
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size
{
@autoreleasepool {
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context,
color.CGColor);
CGContextFillRect(context, rect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
}
+ (UIImage *)imageFromView:(UIView *)theView
{
UIGraphicsBeginImageContext([theView bounds].size);
CGContextRef context = UIGraphicsGetCurrentContext();
[[theView layer] renderInContext:context];
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return theImage;
}
- (UIImage*)blurredImage:(CGFloat)blurAmount
{
if (blurAmount < 0.0 || blurAmount > 1.0) {
blurAmount = 0.5;
}
int boxSize = (int)(blurAmount * 40);
boxSize = boxSize - (boxSize % 2) + 1;
CGImageRef img = self.CGImage;
vImage_Buffer inBuffer, outBuffer;
vImage_Error error;
void *pixelBuffer;
CGDataProviderRef inProvider = CGImageGetDataProvider(img);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);
inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(img);
outBuffer.height = CGImageGetHeight(img);
outBuffer.rowBytes = CGImageGetBytesPerRow(img);
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (!error) {
error = vImageBoxConvolve_ARGB8888(&outBuffer, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
}
if (error) {
#ifdef DEBUG
NSLog(@"%s error: %zd", __PRETTY_FUNCTION__, error);
#endif
return self;
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
outBuffer.width,
outBuffer.height,
8,
outBuffer.rowBytes,
colorSpace,
(CGBitmapInfo)kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
CFRelease(inBitmapData);
CGImageRelease(imageRef);
return returnImage;
}
+ (UIImage *)screenshot
{
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, [window center].x, [window center].y);
CGContextConcatCTM(context, [window transform]);
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
[[window layer] renderInContext:context];
CGContextRestoreGState(context);
}
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
5.給UIImage替換原有的底色
- (UIImage *)jsq_imageMaskedWithColor:(UIColor *)maskColor
{
NSParameterAssert(maskColor != nil);
CGRect imageRect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);
UIImage *newImage = nil;
UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, self.scale);
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, 1.0f, -1.0f);
CGContextTranslateCTM(context, 0.0f, -(imageRect.size.height));
CGContextClipToMask(context, imageRect, self.CGImage);
CGContextSetFillColorWithColor(context, maskColor.CGColor);
CGContextFillRect(context, imageRect);
newImage = UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();
return newImage;
}
// 圖片疊加
+ (UIImage *)addImage:(UIImage *)image1 withImage:(UIImage *)image2 {
UIGraphicsBeginImageContext(image1.size);
[image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)];
[image2 drawInRect:CGRectMake((image1.size.width - image2.size.width)/2,(image1.size.height - image2.size.height)/2, image2.size.width, image2.size.height)];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
7.獲取視訊播放的某一幀圖片
// 獲取幀圖片
+ (UIImage*) thumbnailImageForVideo:(NSURL *)videoURL atTime:(NSTimeInterval)ts {
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoURL options:nil];
AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
gen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(ts, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *img = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);
return img;
}
8.流暢的tableView優化之非同步處理圓角
- (void)mkj_cornerImageWithSize:(CGSize)size fillColor:(UIColor *)color completion:(block)completionBlock
{
/**
非同步繪製圓角圖片
*/
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSTimeInterval time = CACurrentMediaTime();
// 1.建立上下文 第二個引數就是不透明 第三個引數scale是0,檢視透明會增加GPU的計算
UIGraphicsBeginImageContextWithOptions(size, YES, 0);
CGRect rec = CGRectMake(0, 0, size.width, size.height);
// 2.讓裁減掉的多餘填充部分為白色,不然是黑色的
[color setFill];
UIRectFill(rec);
// 3.BezierPath建立裁減路徑
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:rec];
[path addClip];
// 4.繪製
[self drawInRect:rec];
// 5.從上下文取圖片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 6.關閉上下文
UIGraphicsEndImageContext();
NSLog(@"%lf",CACurrentMediaTime()-time);
// 7.回撥到主執行緒
dispatch_async(dispatch_get_main_queue(), ^{
if (completionBlock) {
completionBlock(image);
}
});
});
}
注意:這裡有個模擬器上的檢視優化知識點
1.螢幕上的每個畫素點的顏色是由當前畫素點上的多層layer(如果存在)共同決定的,GPU會進行計算出混合顏色的RGB值,最終顯示在螢幕上。而這需要讓GPU計算,所以我們要儘量避免設定alpha,這樣GPU會忽略下面所有的layer,節約計算量
如果你兩個檢視,相互遮蓋,上面的檢視如果是由alpha的,那麼開啟這個屬性你的View會是紅色的,而且用傳統的cornerRadius也會是紅色的,綠色是沒有效能問題,紅色有,那麼UILabel比較特殊,沒得玩,其他還是可以改改的
2.蘋果的GPU只解析32bit的顏色格式,記住是32bit
3.不要出現image size與imageView size不同的情況,這樣會觸發反鋸齒計算,增加效能損耗,本地圖片好處理,可以直接看到大小,但是網路圖片載入時可以根據容器的大小傳參獲取,或者下載下來進行壓縮,不然會觸發反鋸齒計算
4.離屏渲染,這個完全不知道是啥,反正就是離屏渲染會導致CPU在後臺儲存一份bitmap,所以會導致CPU多餘運算
當drawInRect或者MaskToBounds會觸發,儘量避免,應該是cell還沒有滑進螢幕的時候進行提前繪製
1.常規做法
imageView.layer.cornerRadius = imageView.bounds.size.width/2;
imageView.layer.masksToBounds = YES;
imageView.image = image;
紅色警告,需要優化
2.非同步做圓角 程式碼在上面
紅色沒了,完美搞定,tableview滑動的時候就不會一直重繪了,絲滑絲滑的
8.微博,糗事百科這一類釋出的長圖片如何壓縮只顯示頂部區域,點開展示大圖
// 開啟圖形上下文 給定一個尺寸框框,無論下面那句話畫出來的新的image是多大,都根據這個尺寸框進行獲取,一般獲取超級長圖頭部圖片的方法
UIGraphicsBeginImageContextWithOptions(CGSizeMake(topic.picFrame.size.width, topic.picFrame.size.height), YES, 0.0);
// 根據大小繪製 這裡給一個圖片壓縮後的尺寸,這個時候是等比例長度縮放的,而且是全尺寸長度的
CGFloat width = topic.picFrame.size.width;
CGFloat height = topic.picFrame.size.width * image.size.height / image.size.width;
[image drawInRect:CGRectMake(0, 0, width, height)];
// 從圖形上下文獲取圖片
self.backImageView.image = UIGraphicsGetImageFromCurrentImageContext();
// 結束圖形上下文
UIGraphicsEndImageContext();
看下實際需求點:
當我們在頭部展示的時候是顯示頂部圖片,然後點開就是全部圖片的展示,不然直接設定圖片的contentMode,大圖的時候顯示位置會有問題
持續更新。。。。。。。。
相關文章
- Image Optimizer for Mac(圖片壓縮工具)Mac
- PS製作圓角圖片
- UIImage 圖片處理:截圖,縮放,設定大小,儲存UI
- 前端的圖片壓縮image-compressor(可在圖片上傳前實現圖片壓縮)前端
- JavaIO 檔案的讀取,寫入,複製,壓縮,解壓等...相關操作,持續更新JavaAI
- BitmapShader繪製圓形圖片
- asp 獲取圖片的 大小 和畫素 ,解析度,以及壓縮圖片
- 通過li-canvas輕鬆實現單圖、多圖、圓角圖繪製,單行文字、多行文字、豎向文字繪製,自動換行,儲存圖片,下載圖片等Canvas
- Glide實現圓角圖片,以及圓形圖片IDE
- 圖片壓縮怎樣操作?分享幾種實用的批次圖片壓縮技巧
- 前端圖片壓縮 - H5&Uni-App圖片壓縮前端H5APP
- iOS 繪製圓角iOS
- ??圖片壓縮CanvasCanvas
- IOS圖片壓縮iOS
- canvas 壓縮圖片Canvas
- iOS圖片設定圓角iOS
- ffmpeg-圖片壓縮旋轉等處理
- 微信小程式開發-canves 圖片壓縮 獲取base64微信小程式
- CSS魔法系列:純CSS繪製基本圖形(圓、橢圓等)CSS
- 圖片壓縮知識梳理(0) 圖片壓縮學習計劃
- canvas 繪製圓角矩形Canvas
- SVG 繪製圓角矩形SVG
- web前端之HTML5壓縮圖片compress image with canvasWeb前端HTMLCanvas
- iOS 圖片壓縮方法iOS
- 前端圖片壓縮方案前端
- [Android] 定製化Toast展示(位置、底色、圓角)AndroidAST
- 各種命令,以及FAQ..持續更新.....
- android 圓角圖片 處理Android
- Android獲取本機各種型別檔案列表(音樂、影片、圖片、文件等)Android型別
- Nginx Image Module圖片縮圖 水印處理模組Nginx
- 【前端】壓縮圖片以及圖片相關概念前端
- vue 上傳圖片進行壓縮圖片Vue
- Android壓縮圖片後再上傳圖片Android
- Nginx網路壓縮 CSS壓縮 圖片壓縮 JSON壓縮NginxCSSJSON
- 在rails中使用sprockets-image_compressor無失真壓縮圖片AI
- 使用java繪圖類Graphics繪製圓圈Java繪圖
- SmallImage for Mac(圖片壓縮工具)Mac
- js上傳圖片壓縮JS