- 一张图像是像素点的集合,每一个像素都是一个独立明了的颜色RGBA,当成百上千万的像素集合到一起后,就构成了图像。
- 一张白色的图片是由无数个白点的点组成的
- bitmap也是一种文件格式
- 一张白色的bitmap(每个像素点(RGBA) ..... (RGBA)组成的)
- 在iOS里面图片都会转成bitmap然后再交给GPU进行渲染
- 图片文件属性:(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