您的位置:首页 > 移动开发 > IOS开发

iOS图片的渲染

2016-01-27 20:39 281 查看
最近写项目都要吐了,看见自己的代码就恶心,尽管是自己的心血,但是原本已经写完的代码,但是老板却又改了需求,唉,尽管界面没怎么变,但是你不知道现在是牵一发而动全身吗。牢骚一下,但是还得皱着眉头改啊。

最近收获好大的几个地方,分享一下。以供今后的学习。

1.第一个是改变图片的颜色,我封装了一个类。

这是.h文件

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface AsynNetWorkHandleImage : NSObject

// 定义一个block属性
@property (nonatomic, copy) void(^block)(UIImage *image);

// 定义类方法
+ (instancetype)requestDataForImageWithURLString:(NSString *)urlString block:(void(^)(UIImage *image))block;

@end


这是.m文件

#import "AsynNetWorkHandleImage.h"

@implementation AsynNetWorkHandleImage

- (instancetype)init
{
self = [super init];
if (self) {

}
return self;
}

+ (instancetype)requestDataForImageWithURLString:(NSString *)urlString block:(void(^)(UIImage *image))block
{
AsynNetWorkHandleImage *asyn = [[AsynNetWorkHandleImage alloc] init];
asyn.block = block;

// 先将字符串进行转码
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSArray *array = [urlString componentsSeparatedByString:@"/"];

NSArray *arr =NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
// 拼接最终得到图片的存储路径
NSString *imagePath = [NSString stringWithFormat:@"%@/%@", [arr firstObject], [array lastObject]];

NSFileManager *manager = [NSFileManager defaultManager];

// 如果图片已经存到本地
if ([manager fileExistsAtPath:imagePath]) {

NSData *data = [NSData dataWithContentsOfFile:imagePath];
UIImage *image = [UIImage imageWithData:data];
;
asyn.block([asyn grayscale:image type:1]);

}
// 如果图片没有存到本地, 则进行数据请求
else {

NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"GET";

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

if (error == nil) {
UIImage *image = [UIImage imageWithData:data];
asyn.block([asyn grayscale:image type:1]);
// 同时将数据存入本地
[data writeToFile:imagePath atomically:YES];
}
else {
NSLog(@"图片数据请求失败");
}
}];
// 开始执行任务
[task resume];
}
return asyn;
}

// 渲染图片的方法
- (UIImage *)grayscale:(UIImage *)anImage type:(int)type {

CGImageRef imageRef = anImage.CGImage;
size_t width  = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
bool shouldInterpolate = CGImageGetShouldInterpolate(imageRef);
CGColorRenderingIntent intent = CGImageGetRenderingIntent(imageRef);
CGDataProviderRef dataProvider = CGImageGetDataProvider(imageRef);
CFDataRef data = CGDataProviderCopyData(dataProvider);
UInt8 *buffer = nil;

// 代码保护, 数据存在时执行
if (data) {
buffer = (UInt8*)CFDataGetBytePtr(data);
NSUInteger  x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
UInt8 *tmp;
tmp = buffer + y * bytesPerRow + x * 4;
UInt8 red,green,blue;
red = *(tmp + 0);
green = *(tmp + 1);
blue = *(tmp + 2);
UInt8 brightness;
switch (type) {
case 1:
brightness = (77 * red + 28 * green + 151 * blue) / 256;
*(tmp + 0) = brightness;
*(tmp + 1) = brightness;
*(tmp + 2) = brightness;
break;
case 2:
*(tmp + 0) = red;
*(tmp + 1) = green * 0.7;
*(tmp + 2) = blue * 0.4;
break;
case 3:
*(tmp + 0) = 255 - red;
*(tmp + 1) = 255 - green;
*(tmp + 2) = 255 - blue;
break;
default:
*(tmp + 0) = red;
*(tmp + 1) = green;
*(tmp + 2) = blue;
break;
}
}
}

CFDataRef effectedData = CFDataCreate(NULL, buffer, CFDataGetLength(data));
CGDataProviderRef effectedDataProvider = CGDataProviderCreateWithCFData(effectedData);
CGImageRef effectedCgImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, bitmapInfo, effectedDataProvider, NULL, shouldInterpolate, intent);
UIImage *effectedImage = [[UIImage alloc] initWithCGImage:effectedCgImage];
CGImageRelease(effectedCgImage);
CFRelease(effectedDataProvider);
CFRelease(effectedData);
CFRelease(data);
return effectedImage;
}
return nil;
}

@end


理解:图片渲染的那个方法不是我自己写的,是在网上找到的,在这里要说声谢谢这位神了。首先这个方法渲染的图片必须是本地的图片,我这个方法将图片下载到本地后然后进行渲染的(其实这样说是不准确的,主要是方法中的图片的data不能为空)。之前用的是SDWebImage,但是我发现sd从网络获取图片中,将文件存放到本地是个异步方法的,也就是sd下载图片和存储图片是不同的进程中实现的,这样虽然图片已经显示到界面上,但是你在本地是获取不到图片数据的。这样程序就cash了。大家可以动手体验一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: