iOS 对网络图片进行黑白化处理

  先上图片处理的前后效果对比:

处理前:

处理后:

    最近项目需要,图片显示两种状态, 一种是原版彩色的, 另外一种就是黑白的, 可是对于这两种状态我们的服务器端只给我们提供了一套彩色的图片, 我们前端需要根据状态自己处理图片, 于是我就请教了百度, 找到了下面这个方法:

- (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 = (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;

}

  然后我就写了个demo, 用本地图片做了下, 的确好使, 不愧是大神写的, 虽然看不懂, 但是会用就行了, 于是就照搬到我们的项目中去了, 一般事情发展到这里就应该完美结束了, 可是这却是麻烦来临前的平静, 然后在工程中运行时就出现了下面的错误:

访问了坏内存, 如果对于OC来说如果出现这样的问题还能找到些思路, 可是对于C语言对待这样的问题就一头雾水了, 不知道什么地方导致的问题, 所以在当时这个bug使我不知所措呀, 不知道从什么地方下手. 后来经过我重复测试, 得到下面规律:

  1>对本地图片处理不会出现这个问题

  2>对于网络图片都是应用安装(安装模拟器或者真机)后, 第一次运行到该地方时才会出现这个问题, 之后再怎么处理这个图片都不会有问题了.

  问题定位: 最后我把问题点定位在了 图片缓存 上面, 我是通过 SDWebImage 来做图片下载和缓存的, 通过查看代码发现, SDWebImage 在下载完成后作的图片缓存是异步的, 也就是在第一次下载图片的时候, 本地是没有缓存的, 而且处理的图片是在内存里面的, 然后处理图片的时候出现了坏内存访问. 而在第二次处理的时候之前一次已经将图片缓存到本地了, 所以就没有问题了. 虽然我也不知道为什么这个处理方法对没有缓存到本地的图片处理会出现坏内存访问, 不过最终把问题定位到这个地方了.

  解决方案: 在SDWebImage下载完图片后, 先检查本地有没有存在该图片, 如果没有, 则先把下载下来的图片同步缓存到本地, 然后再从本地取得图片进行处理.问题解决!

代码如下:

[[SDWebImageManager sharedManager] downloadImageWithURL:imageUrl options:SDWebImageRetryFailed progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {

NSString* key = [[SDWebImageManager sharedManager] cacheKeyForURL:imageURL];

BOOL result = [[SDImageCache sharedImageCache] diskImageExistsWithKey:key];

NSString* imagePath = [[SDImageCache sharedImageCache] defaultCachePathForKey:key];

if (!result) {

BOOL imageIsPng = ImageDataHasPNGPreffixWithData(nil);

NSData* imageData = nil;

if (imageIsPng) {

imageData = UIImagePNGRepresentation(image);

}

else {

imageData = UIImageJPEGRepresentation(image, (CGFloat)1.0);

}

NSFileManager* _fileManager = [NSFileManager defaultManager];

if (imageData) {

if (![_fileManager fileExistsAtPath:imagePath]) {

[_fileManager createDirectoryAtPath:imagePath withIntermediateDirectories:YES attributes:nil error:NULL];

}

[_fileManager createFileAtPath:imagePath contents:imageData attributes:nil];

}

}

NSData* newData = [NSData dataWithContentsOfFile:imagePath];

UIImage* newImage = [UIImage imageWithData:newData];

UIImage* grayImage = [self grayscale:newImage type:1];

self.imageView.image = grayImage;

}];

时间: 2024-10-06 01:32:08

iOS 对网络图片进行黑白化处理的相关文章

检测SDWebImage有没有缓存图片 IOS 获取网络图片大小

NSURL *url = [NSURL URLWithString:[model.content objectForKey:@"image"]];             //请求网络地址数据的同步方法             //因为这个方法在子线程(全局队列)中执行,所以不需要考虑死线程的问题             SDWebImageManager *manager = [SDWebImageManager sharedManager];              [manag

做一个具有图片读入,写出,灰度化,黑白化的有图形界面的小软件

我们这一次的树莓基础的作业是做一个做一个具有图片读入,写出,灰度化,黑白化的小软件,我采用的是java,因为java有大量性能非常好的接口可用,譬如在图片这块,ImageIO,BufferedImage都是非常好用的,而我这一次作业也是使用这两个包. 首先我们要解决的是界面,界面可以直接用JFrame来打, 非常简单,我的界面有一个菜单栏和一个图片显示区,菜单栏有三个选项:文件,转换,保存,文件菜单有一个子菜单:打开文件,转换菜单有两个子菜单:变成灰度和变成黑白,保存菜单有三个子菜单:jpg,

IOS 获取网络图片的大小 改变 图片色值 灰度什么的方法集合

第一.复制对象的基本概念 复制一个对象为副本,开辟一块新的内存来存储副本对象. 第二.如果一个对象想具备复制的功能,必须实现<NSCopying>协议和<NSMutableCopying>协议 NSObject自带的常用的对象有:NSNumber.NSString.NSArray.NSDictionary.NSMutableArray.NSMutableDictionay.NSMutableString,copy产生的对象时不可变的,mutableCopy产生的对象时可变的 第三.

iOS获取网络图片大小

在iOS开发过程中经常需要通过网络请求加载图片,有时,需要在创建UIImageView或UIButton来显示图片之前需要提前知道图片的尺寸,根据图片尺寸创建对应大小的控件.但是对于网络图片来说,要想通过最优的方法获得尺寸就略微有点困难,大体思路就是下面这种: 如果有使用SDWebImage,则首先检查是否缓存过该图片,如果没有,先通过文件头获取图片大小(针对格式为png.gif.jpg文件获取其尺寸大小),如果获取失败,则下载完整的图片data,然后计算大小,如果有使用SDWebImage,则

Xcode7 低版本iOS系统上下有黑边的问题

在使用Xcode7开发时,默认的启动页改成了 Launch Screen storyboard.通常情况下还是习惯使用 LaunchImage,介绍下Xcode7 下如何改为启动页是LaunchImage. 1:project->target->General->App Icons and Launch Images下面的 Launch Screen File 改为空(默认是launchScreen.storyboard) 2:点击 launchScreen.storyboard,点击右

iOS 获取网络图片的大小

一直都在找关于获取网络图片的大小的方法, 今天找到了一个能解决的办法 ,如下 1, 导入框架 #import <ImageIO/ImageIO.h> 2. 使用此方法得到image的size - (CGSize)getImageSizeWithURL:(NSURL *)url { CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)url, NULL); CGFloat width = 0.0f, height

iOS第三方网络图片加载- SDWebImage笔记(转)

SDWebImage托管在github上.https://github.com/rs/SDWebImage 这个类库提供一个UIImageView类别以支持加载来自网络的远程图片.具有缓存管理.异步下载.同一个URL下载次数控制和优化等特征. 使用示范的代码: UITableView使用UIImageView+WebCache类(基本应用,UIImageView的一个category) 前提#import导入UIImageView+WebCache.h文件,然后在tableview的cellFo

【IOS】相机去黑框(转)

自定义相机的时候,调用系统的相机,由于相机的分辨率,会出现短小的矩形框,总会出现黑色边框,如下图: 如果想实现全屏相机的话,这样做就可以了: 1 CALayer *viewLayer = self.imagePickerController.view.layer; 2 [viewLayer setBounds:CGRectMake(0.0, 0.0, 125.0, 132.0)]; 3 [viewLayer setBackgroundColor:[UIColor blueColor].CGCol

iOS根据网络图片的size大小设置UIImageView的大小

有时候在设置UIImageView的大小时候需要根据UIimage的长宽比来自动设置,不让图片原比例失真. 如果是从本地获取到的图片,[UIImage imageNamed:@""]; 这样就可以拿到image了,从而获取到image的size.但大多数时候我们都是网络请求拿到的图片, 我们需要 NSData *data = [NSData dataWithContentsOfURL:url]; image = [UIImage imageWithData:data]; 这样来得到im