iOS-UIImageView图片相关

  1. 一张图像是像素点的集合,每一个像素都是一个独立明了的颜色RGBA,当成百上千万的像素集合到一起后,就构成了图像。
  2. 一张白色的图片是由无数个白点的点组成的
  3. bitmap也是一种文件格式
  4. 一张白色的bitmap(每个像素点(RGBA) ..... (RGBA)组成的)
  5. 在iOS里面图片都会转成bitmap然后再交给GPU进行渲染
  6. 图片文件属性:(withd + heigth + 格式)+ 图片内容

一. 图片压缩

1. png或者jpg压缩

图片信息如下:
3.png

使用如下方式压缩“3.png”图片:

_albumImage = [UIImage imageNamed:@"3.jpg"];

//PNG/JPG图片压缩
- (void)imageDataLoad{
    // png  文件属性格式并不会压缩,压缩的是图片内容(像素)
    NSData* pngImageData =  UIImagePNGRepresentation(_albumImage);
    NSData *jpgImageData =  UIImageJPEGRepresentation(_albumImage, 0.1);
    
    _pngImageV.image = [UIImage imageWithData:pngImageData];
    _jpgImageV.image = [UIImage imageWithData:jpgImageData];
    // jpg
    
    NSLog(@"png::%@", [self length:pngImageData.length]);
    NSLog(@"jpg::%@", [self length:jpgImageData.length]);
}

- (NSString*)length:(NSInteger)length{
    if (length > 1024 * 1024) {
        int mb = length/(1024*1024);
        int kb = (length%(1024*1024))/1024;
        return [NSString stringWithFormat:@"%dMb%dKB",mb, kb];
    }else{
        return [NSString stringWithFormat:@"%dKB",length/1024];
    }
}

运行结束,图片大小和内存占用如下图:

图片大小.png
内存占用.png

发现图片变大了,内存占用很多。

2. bitmap压缩

代码如下:

 _albumImage = [self scaleImage:[UIImage imageNamed:@"3.jpg"] size:_pngImageV.frame.size];

//这种压缩方式, 内存占用和图片大小都变小了
// bitmap
- (UIImage*)scaleImage:(UIImage*)image size:(CGSize)imageSize{
    
    UIGraphicsBeginImageContext(imageSize);
    [image drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

运行结果:
bitmap大小.png
bitmap内存.png

发现图片大小和内存都没那么多了。

为什么第一种方式占用图片大小和内存很大呢?

因为从图片从项目中渲染到屏幕上的时候需要转换成bitmap,转换成bitmap的时候需要获取图片文件的宽高位数等信息,然后根据这些信息再渲染到屏幕上来,所以在渲染的时候需要的图片大小和内存就多了。

下面我们可以根据渲染需要的信息,尝试计算渲染的时候图片大小:

// 1 个字节 = 8bit  每行有 17152 每行有17152*8 位
size_t width   = CGImageGetWidth(imageRef);
size_t height  = CGImageGetHeight(imageRef);
size_t bits    = CGImageGetBitsPerComponent(imageRef); // 8位
size_t bitsPerrow = CGImageGetBytesPerRow(imageRef); // 就是width * bits

图片的宽乘以高乘以4个字节:((4288 * 2848 * 4) / 1024) / 1024 = 46.58M 左右,可以看出本来836k的图片,渲染后46M多了,所以我们压缩图片的时候最好不要用PNG或者JPG的压缩方式,最好用上下文重新生成一个图片。

二. 图片处理

1. 图片过滤

原图如下:
原图

代码如下:

self.image =  [UIImage imageNamed:@"3.jpg"];

/*
 从图片文件把 图片数据的像素拿出来(RGBA), 对像素进行操作, 进行一个转换(Bitmap (GPU))
 修改完之后,还原(图片的属性 RGBA,RGBA (宽度,高度,色值空间,拿到宽度和高度,每一个画多少个像素,画多少行))
 //256(11111111)
 */

- (void)filterImage{
    
    CGImageRef imageRef = self.image.CGImage;
    // 1 个字节 = 8bit  每行有 17152 每行有17152*8 位
    size_t width   = CGImageGetWidth(imageRef);
    size_t height  = CGImageGetHeight(imageRef);
    size_t bits    = CGImageGetBitsPerComponent(imageRef); // 8位
    size_t bitsPerrow = CGImageGetBytesPerRow(imageRef); // 就是width * bits
    
    // 颜色空间
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
    // AlphaInfo: RGBA  AGBR  RGB
    CGImageAlphaInfo alpInfo =  CGImageGetAlphaInfo(imageRef); //  AlphaInfo 信息
    
    // bitmap的数据
    CGDataProviderRef providerRef = CGImageGetDataProvider(imageRef);
    CFDataRef bitmapData = CGDataProviderCopyData(providerRef);
    
    NSInteger pixLength = CFDataGetLength(bitmapData);
    // 像素的byte数组
    Byte *pixbuf = CFDataGetMutableBytePtr((CFMutableDataRef)bitmapData);

    // 一个RGBA为一个单元
    for (NSInteger i = 0; i < pixLength; i+=4) {
    
        [self eocImageFiletPixBuf:pixbuf offset:i];
    }
    
    // 准备绘制图片了
    // bitmap 生成一个上下文  再通过上下文生成图片
    CGContextRef contextR = CGBitmapContextCreate(pixbuf, width, height, bits, bitsPerrow, colorSpace, alpInfo);
    
    CGImageRef filterImageRef = CGBitmapContextCreateImage(contextR);
    
    UIImage *filterImage =  [UIImage imageWithCGImage:filterImageRef];
    
    _filterImageV.image = filterImage;
}

// RGBA 为一个单元  彩色照变黑白照
- (void)eocImageFiletPixBuf:(Byte*)pixBuf offset:(int)offset{
    
    int offsetR = offset;
    int offsetG = offset + 1;
    int offsetB = offset + 2;
    int offsetA = offset + 3;
    
    int red = pixBuf[offsetR];
    int gre = pixBuf[offsetG];
    int blu = pixBuf[offsetB];
   // int alp = pixBuf[offsetA];
    
    int gray = (red + gre + blu)/3;
    
    pixBuf[offsetR] = gray;
    pixBuf[offsetG] = gray;
    pixBuf[offsetB] = gray;
}

效果图如下:
效果图.png

2. 截图

代码如下:

#import "ShotScreenImageVC.h"
#import <QuartzCore/QuartzCore.h>
/*
 */
@interface ShotScreenImageVC ()

@end

@implementation ShotScreenImageVC

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationController.navigationBar.translucent = NO;
    self.automaticallyAdjustsScrollViewInsets = NO;
    _scrollerView.contentSize = CGSizeMake(700, 700);
    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"截图" style:UIBarButtonItemStylePlain target:self action:@selector(imageFromFullView)];
}

- (void)imageFromFullView{
    
    //[self shotScreen:nil];
    //[self shotScreenMain];
    //[self noRectClip];
    [self Blend];
}

//截屏
- (void)shotScreenMain {
    UIGraphicsBeginImageContext(self.view.frame.size);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    [self.view.layer renderInContext:context];
    
    CGImageRef imageRef =  CGBitmapContextCreateImage(context);
    
    _eocImageV.image = [UIImage imageWithCGImage:imageRef];
    
    UIGraphicsEndImageContext();
}

// 规则截图
- (void)shotScreen:(id)sender{
    
    UIImage *image = [UIImage imageNamed:@"3.jpg"];
    
    UIGraphicsBeginImageContext(CGSizeMake(200, 200));
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    //先clip
    CGRect rect = CGRectMake(0, 0, 200, 200);
    CGContextAddEllipseInRect(context, rect); // 画了一个路径path
    CGContextClip(context);
    //根据上面的路径, 再draw
    [image drawInRect:CGRectMake(0, 0, 200, 200)];
    
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    _eocImageV.image = clipImage;  
}

// 不规则截图
- (void)noRectClip{
    
    UIGraphicsBeginImageContext(CGSizeMake(200, 200));
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 非规则的path
    CGMutablePathRef pathRef = CGPathCreateMutable();
    CGPoint lines[] = {
        CGPointMake(0, 0),
        CGPointMake(150, 70),
        CGPointMake(200, 200),
        CGPointMake(50, 120),
        CGPointMake(30, 30)
    };
    CGPathAddLines(pathRef, NULL, lines, 5);
    CGContextAddPath(context, pathRef);
    CGContextClip(context);
    //////////
    
    UIImage *imageTwo = [UIImage imageNamed:@"3.jpg"];
    [imageTwo drawInRect:CGRectMake(0, 0, 200, 200)];
    
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    _eocImageV.image = clipImage;
}

// 红色渲染
- (void)Blend{
    
    UIImage *imageTwo = [UIImage imageNamed:@"3.jpg"];
    
    UIGraphicsBeginImageContext(CGSizeMake(200, 200));
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    [imageTwo drawInRect:CGRectMake(0, 0, 200, 200)];
    
    UIColor *redColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
    
    CGContextSetFillColorWithColor(context, redColor.CGColor);
    
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    
    CGContextFillRect(context, CGRectMake(0, 0, 200, 200));
    
    CGImageRef imageRef =  CGBitmapContextCreateImage(context);
    
    _eocImageV.image = [UIImage imageWithCGImage:imageRef];
    
    UIGraphicsEndImageContext();
}
@end

效果图如下:

截屏:

截屏.png

规则截图:

圆形.png

不规则截图:

不规则.png

红色渲染:

红色渲染.png

Demo地址:https://github.com/iamkata/about-imageView

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355