美文网首页
iOS 离屏渲染及图片压缩、滤镜

iOS 离屏渲染及图片压缩、滤镜

作者: cgfloat | 来源:发表于2019-03-19 14:14 被阅读0次

一张图片是像素点的集合,每一个像素都有独立、明了的颜色。图像一般情况下都存储成数组,可以理解为二维数组。
当成千上万个像素集合到一起时,就构成了图像。
表示图形的方式有很多种,最简单的是32位RGBA模式。

图片压缩

png:UIImagePNGRepresentation(image)
jpg:UIImageJPEGRepresentation(image, 1.0)
jpg的压缩效果较png好,且可以设置压缩比例。系统的png压缩方法甚至会发生压缩后的图片大小远远大于压缩前。原因是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;
}

根据上下文绘制后再压缩,结果图片会更小,且不会出现图片大小大于原图的情况

图片过滤

从图片文件中把图片数据的像素拿出来(RGBA),对像素进行转换操作(Bitmap(GPU)),修改完之后还原

- (UIImage *)filterImage:(UIImage *)image {
    
    CGImageRef imageRef = image.CGImage;
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    size_t bits = CGImageGetBitsPerComponent(imageRef);
    size_t bitsPerrow = CGImageGetBitsPerComponent(imageRef);
    
    // 颜色空间
    CGColorSpaceRef colorSpaceRef = CGImageGetColorSpace(imageRef);
    
    // bitmap 数据
    CGDataProviderRef providerRef = CGImageGetDataProvider(imageRef);
    CFDataRef bitmapData = CGDataProviderCopyData(providerRef);
    
    NSInteger pixLength = CFDataGetLength(bitmapData);
    Byte *pixbuf = CFDataGetMutableBytePtr(bitmapData);
    
    for (int i = 0; i < pixLength; i += 4) {
        [self imageFilePixBuf:pixbuf offset:i];
    }
    
    // 绘制图片 bitmap 生成上下文 再通过上下文生成图片
    CGContextRef contextRef = CGBitmapContextCreate(pixbuf, width, height, bits, bitsPerrow, colorSpaceRef, CGImageGetAlphaInfo(imageRef));
    CGImageRef filterImageRef = CGBitmapContextCreateImage(contextRef);
    UIImage *filterImage = [UIImage imageWithCGImage:filterImageRef];
    return filterImage;
}
// RGBA为一个单元 彩色变黑白
- (void)imageFilePixBuf:(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 green = pixBuf[offsetG];
    int blue = pixBuf[offsetB];
//    int alpha = pixBuf[offsetA];
    
    int gray = (red + green + blue) / 3;
    pixBuf[offsetR] = gray;
    pixBuf[offsetG] = gray;
    pixBuf[offsetB] = gray;
}

裁剪图片

- (UIImage *)clipImage:(UIImage *)image {
    
    UIGraphicsBeginImageContext(CGSizeMake(200, 200));
    CGContextRef contexRef = UIGraphicsGetCurrentContext();
    
    // 规则裁剪
    /*
    CGRect rect = CGRectMake(0, 0, 200, 200);
    CGContextAddEllipseInRect(contexRef, rect);
    CGContextClip(contexRef);
    [image drawInRect:CGRectMake(0, 0, 200, 200)];
     */
    
    // 非规则裁剪
    CGMutablePathRef pathRef = CGPathCreateMutable();
    
    CGPoint lines[] = {
        CGPointMake(0, 0),
        CGPointMake(150, 70),
        CGPointMake(200, 200),
        CGPointMake(50, 120),
        CGPointMake(0, 0)
    };
    CGPathAddLines(pathRef, NULL, lines, 5);
    CGContextAddPath(contexRef, pathRef);
    CGContextClip(contexRef);
    [image drawInRect:CGRectMake(0, 0, 200, 200)];
    
    // 这个上下文获取的是传进来的image,非drawInRect处理后的image,所以drawInRect方法应该写在裁剪处理之后才有效果
    UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return clipImage;
}

渲染

- (UIImage *)blendImage:(UIImage *)image {
    
    UIGraphicsBeginImageContext(CGSizeMake(200, 200));
    CGContextRef contexRef = UIGraphicsGetCurrentContext();
    [image drawInRect:CGRectMake(0, 0, 200, 200)];
    
    UIColor *redColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
    CGContextSetFillColorWithColor(contexRef, redColor.CGColor);
    CGContextSetBlendMode(contexRef, kCGBlendModeNormal);
    CGContextFillRect(contexRef, CGRectMake(0, 0, 200, 200));
    CGImageRef imageRef = CGBitmapContextCreateImage(contexRef);
    
    UIImage *backImage = [UIImage imageWithCGImage:imageRef];
    
    UIGraphicsEndImageContext();
    
    return backImage;
}

截屏

- (UIImage *)imageFromFullView {
    
    UIGraphicsBeginImageContext(self.view.frame.size);
    CGContextRef contexRef = UIGraphicsGetCurrentContext();
    [self.view.layer renderInContext:contexRef];
    
    CGImageRef imageRef = CGBitmapContextCreateImage(contexRef);
    UIImage *backImage = [UIImage imageWithCGImage:imageRef];
    UIGraphicsEndImageContext();
    
    return backImage;
}

相关文章

网友评论

      本文标题:iOS 离屏渲染及图片压缩、滤镜

      本文链接:https://www.haomeiwen.com/subject/wuvwmqtx.html