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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。