iOS之实现图片的压缩、解压缩、模糊、置灰、马赛克、黑白化、调色等处理

举报
Serendipity·y 发表于 2022/02/17 01:57:39 2022/02/17
【摘要】 压缩图片 func imageCompress(targetWidth:CGFloat) -> UIImage { let targetHeight = (targetWidth...

压缩图片

	func imageCompress(targetWidth:CGFloat) -> UIImage {
        let targetHeight = (targetWidth/width)*height
        UIGraphicsBeginImageContext(CGSize(width: targetWidth, height: targetHeight))
        self.draw(in: CGRect(x: 0, y: 0, width: targetWidth, height: targetHeight))
        let newImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return newImage
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

图片强制解压缩

// 图片处理-强制解压缩操作-把元数据绘制到当前的上下文-压缩图片
- (UIImage*)imageDetail:(UIImage *)image {
    // 获取当前图片数据源
    CGImageRef imageRef = image.CGImage;
    // 设置大小改变压缩图片
    NSUInteger width = CGImageGetWidth(imageRef)/3;
    NSUInteger height = CGImageGetHeight(imageRef)/3;
    // 创建颜色空间
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
    /*
     创建绘制当前图片的上下文
     CGBitmapContextCreate(void * __nullable data,
     size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow,
     CGColorSpaceRef cg_nullable space, uint32_t bitmapInfo)
     data:所需要的内存空间 传nil会自动分配
     width/height:当前画布的大小
     bitsPerComponent:每个颜色分量的大小 RGBA 每一个分量占1个字节
     bytesPerRow:每一行使用的字节数 4*width
     bitmapInfo:RGBA绘制的顺序
     */
    CGContextRef contextRef =
    CGBitmapContextCreate(nil,
                          width,
                          height,
                          8,
                          4*width,
                          colorSpace,
                          kCGImageAlphaNoneSkipLast);
    // 根据数据源在上下文(画板)绘制图片
    CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), imageRef);
    
    imageRef = CGBitmapContextCreateImage(contextRef);
    CGContextRelease(contextRef);
    return [UIImage imageWithCGImage:imageRef scale:image.scale orientation:UIImageOrientationUp];
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

模糊图片

	func blurImage(blurValue:NSNumber) -> UIImage {
        let context = CIContext(options: [CIContextOption.useSoftwareRenderer: true])
        let ciImage = CoreImage.CIImage(image: self)
        let blurFilter = CIFilter(name: "CJGaussianBlur")
        blurFilter?.setValue(ciImage, forKey: kCIInputImageKey)
        blurFilter?.setValue(blurValue, forKey: "inputRadius")
        let imageRef = context.createCGImage((blurFilter?.outputImage)!, from: (ciImage?.extent)!)
        let newImage = UIImage(cgImage: imageRef!)
        return newImage
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

图片设置马赛克

  • 马赛克就是让图片看上去模糊不清。将特定区域的像素点设置为同一种颜色,整体就会变得模糊,区域块越大越模糊,越小越接近于原始像素。
  • 同样使用强制解压缩操作,操作像素点,马赛克部分:
    ① 设置区域大小;
    ② 在该区域获取一个像素点(第一个)作为整个区域的取色;
    ③ 将取色设置到区域中;
    ④ 取下一个区域同上去色设置区域。
// 马赛克
 - (UIImage*)mosaicWithImage:(UIImage *)image {
    CGImageRef imageRef = image.CGImage;
    // 获取图片宽高
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetWidth(imageRef);
    // 创建颜色空间
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    // 根据像素点个数创建一个所需要的空间
    UInt32 *imagePiexl = (UInt32 *)calloc(width*height, sizeof(UInt32));
    CGContextRef contextRef = CGBitmapContextCreate(imagePiexl, width, height, 8, 4*width, colorSpaceRef, kCGImageAlphaNoneSkipLast);
    // 根据图片数据源绘制上下文
    CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), imageRef);
    // 获取像素数组
    UInt8 *bitmapPixels = CGBitmapContextGetData(contextRef);
    UInt8 *pixels[4] = {0};
    // 当前的像素点
    NSUInteger currentPixels = 0;
    NSUInteger preCurrentPiexls = 0;
    // 马赛克尺寸
    NSUInteger mosaicSize = 20;
    for (NSUInteger i = 0;  i < height - 1; i++) {
        for (NSUInteger j = 0 ; j < width - 1; j++) {
            currentPixels = i * width + j;
            if (i % mosaicSize == 0) {
                if (j % mosaicSize == 0) {
                    memcpy(pixels, bitmapPixels + 4 * currentPixels, 4);
                } else {
                    memcpy(bitmapPixels + 4 * currentPixels, pixels, 4);
                }
            } else {
                preCurrentPiexls = (i - 1) * width + j;
                memcpy(bitmapPixels + 4 * currentPixels, bitmapPixels + 4 * preCurrentPiexls, 4);
            }
        }
    }
    // 根据上下文创建图片数据源
    CGImageRef finalRef = CGBitmapContextCreateImage(contextRef);
    // 释放用过的内存
    CGContextRelease(contextRef);
    CGColorSpaceRelease(colorSpaceRef);
    free(imagePiexl);
    return [UIImage imageWithCGImage:finalRef scale:image.scale orientation:UIImageOrientationUp];
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • C库函数 - memcpy():
	/*
	* 参数1:指向用于存储复制内容的目标数组;
	* 参数2:指向要复制的数据源;
	* 参数3:要复制的字节数
	*/
	memcpy(void *__dst, const void *__src, size_t __n);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

图片置灰

  • 给imageView加灰色图片
 + (UIImage*)getGrayImage:(UIImage*)sourceImage {
    int width = sourceImage.size.width;
    int height = sourceImage.size.height;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    CGContextRef context = CGBitmapContextCreate (nil,width,height,8,0,colorSpace,kCGImageAlphaNone);
    CGColorSpaceRelease(colorSpace);

    if (context == NULL) {
        return nil;
    }
    CGContextDrawImage(context,CGRectMake(0, 0, width, height), sourceImage.CGImage);
    UIImage *grayImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
    CGContextRelease(context);
    return grayImage;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • image的渲染置灰: imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];这个方法,是给当前的image做一个渲染效果,后面的参数是一个枚举,这个template代表始终使用前景色tintcolor来渲染,接着设置tintcolor,imageview的背景色不会变灰,可以正常设置,而显示的图片是灰色;
- (void)updateUIForFollow:(BOOL)isFollow {
    if (isFollow) {
        self.belowImage.image = [UIImage imageNamed:@"new_room_half_btn_heard"];
    } else {
        UIImage *heartImage = [UIImageimageNamed:@"new_room_half_btn_broken_heard"];
        UIImage *newHeartImage = [heartImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
        [self.belowImv setImage:newHeartImage];
        self.belowImv.tintColor = [UIColor grayColor];
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

图片黑白化

+ (UIImage *)changeColoursImageTograyScaleImage:(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);

    NSInteger 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 0:
                    brightness = (77 * red + 28 * green + 151 * blue) / 256;
                    *(tmp + 0) = brightness;
                    *(tmp + 1) = brightness;
                    *(tmp + 1) = brightness;
                    break;
                case 1:
                    brightness = (77 * red + 28 * green + 151 * blue) / 256;
                    *(tmp + 0) = red;
                    *(tmp + 1) = green * 0.7;
                    *(tmp + 1) = blue *0.4;
                    break;
                case 2:
                    brightness = (77 * red + 28 * green + 151 * blue) / 256;
                    *(tmp + 0) = 255 - red;
                    *(tmp + 1) = 255 - green;
                    *(tmp + 1) = 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;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

获取PNG图片大小

+ (CGSize)getPNGImageSizeWithRequest:(NSMutableURLRequest*)request {
    [request setValue:@"bytes=16-23" forHTTPHeaderField:@"Range"];
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    if(data.length == 8) {
        int w1 = 0, w2 = 0, w3 = 0, w4 = 0;
        [data getBytes:&w1 range:NSMakeRange(0, 1)];
        [data getBytes:&w2 range:NSMakeRange(1, 1)];
        [data getBytes:&w3 range:NSMakeRange(2, 1)];
        [data getBytes:&w4 range:NSMakeRange(3, 1)];
        int w = (w1 << 24) + (w2 << 16) + (w3 << 8) + w4;
        int h1 = 0, h2 = 0, h3 = 0, h4 = 0;
        [data getBytes:&h1 range:NSMakeRange(4, 1)];
        [data getBytes:&h2 range:NSMakeRange(5, 1)];
        [data getBytes:&h3 range:NSMakeRange(6, 1)];
        [data getBytes:&h4 range:NSMakeRange(7, 1)];
        int h = (h1 << 24) + (h2 << 16) + (h3 << 8) + h4;
        return CGSizeMake(w, h);
    }
    return CGSizeZero;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

获取gif图片大小

+ (CGSize)getGIFImageSizeWithRequest:(NSMutableURLRequest*)request {
    [request setValue:@"bytes=6-9" forHTTPHeaderField:@"Range"];
    NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    if(data.length == 4) {
        short w1 = 0, w2 = 0;
        [data getBytes:&w1 range:NSMakeRange(0, 1)];
        [data getBytes:&w2 range:NSMakeRange(1, 1)];
        short w = w1 + (w2 << 8);
        short h1 = 0, h2 = 0;
        [data getBytes:&h1 range:NSMakeRange(2, 1)];
        [data getBytes:&h2 range:NSMakeRange(3, 1)];
        short h = h1 + (h2 << 8);
        return CGSizeMake(w, h);
    }
    return CGSizeZero;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

获取jpg图片大小

+ (CGSize)getJPGImageSizeWithRequest:(NSMutableURLRequest*)request {
    [request setValue:@"bytes=0-209" forHTTPHeaderField:@"Range"];
    NSData* data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
     
    if ([data length] <= 0x58) {
        return CGSizeZero;
    }
     
    if ([data length] < 210) {// 肯定只有一个DQT字段
        short w1 = 0, w2 = 0;
        [data getBytes:&w1 range:NSMakeRange(0x60, 0x1)];
        [data getBytes:&w2 range:NSMakeRange(0x61, 0x1)];
        short w = (w1 << 8) + w2;
        short h1 = 0, h2 = 0;
        [data getBytes:&h1 range:NSMakeRange(0x5e, 0x1)];
        [data getBytes:&h2 range:NSMakeRange(0x5f, 0x1)];
        short h = (h1 << 8) + h2;
        return CGSizeMake(w, h);
    } else {
        short word = 0x0;
        [data getBytes:&word range:NSMakeRange(0x15, 0x1)];
        if (word == 0xdb) {
            [data getBytes:&word range:NSMakeRange(0x5a, 0x1)];
            if (word == 0xdb) {// 两个DQT字段
                short w1 = 0, w2 = 0;
                [data getBytes:&w1 range:NSMakeRange(0xa5, 0x1)];
                [data getBytes:&w2 range:NSMakeRange(0xa6, 0x1)];
                short w = (w1 << 8) + w2;
                short h1 = 0, h2 = 0;
                [data getBytes:&h1 range:NSMakeRange(0xa3, 0x1)];
                [data getBytes:&h2 range:NSMakeRange(0xa4, 0x1)];
                short h = (h1 << 8) + h2;
                return CGSizeMake(w, h);
            } else { // 一个DQT字段
                short w1 = 0, w2 = 0;
                [data getBytes:&w1 range:NSMakeRange(0x60, 0x1)];
                [data getBytes:&w2 range:NSMakeRange(0x61, 0x1)];
                short w = (w1 << 8) + w2;
                short h1 = 0, h2 = 0;
                [data getBytes:&h1 range:NSMakeRange(0x5e, 0x1)];
                [data getBytes:&h2 range:NSMakeRange(0x5f, 0x1)];
                short h = (h1 << 8) + h2;
                return CGSizeMake(w, h);
            }
        } else {
            return CGSizeZero;
        }
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

图片调色

// 调色
- (UIImage *)setRGBImage:(UIImage *)image R:(CGFloat)rk g:(CGFloat)gk b:(CGFloat)bk {
    CGImageRef imageRef = image.CGImage;
    // 获取图片宽高
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetWidth(imageRef);
    // 创建颜色空间
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    // 根据像素点个数创建一个所需要的空间
    UInt32 *imagePiexl = (UInt32 *)calloc(width*height, sizeof(UInt32));
    CGContextRef contextRef = CGBitmapContextCreate(imagePiexl, width, height, 8, 4*width, colorSpaceRef, kCGImageAlphaNoneSkipLast);
    // 根据图片数据源绘制上下文
    CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), imageRef);
    // 将彩色图片像素点重新设置颜色
    // 取平均值 R=G=B=(R+G+B)/3
    for (int y=0; y<height; y++) {
        for (int x=0; x<width; x++) {
            // 操作像素点
            uint8_t *rgbPiexl = (uint8_t *)&imagePiexl[y*width+x];
            // 该色值下不做处理
            if (rgbPiexl[0]>245&&rgbPiexl[1]>245&&rgbPiexl[2]>245) {
                
            } else {
                rgbPiexl[0] = rgbPiexl[0]*rk;
                rgbPiexl[1] = rgbPiexl[1]*gk;
                rgbPiexl[2] = rgbPiexl[2]*bk;
            }   
        }
    }
    // 根据上下文绘制
    CGImageRef finalRef = CGBitmapContextCreateImage(contextRef);
    // 释放用过的内存
    CGContextRelease(contextRef);
    CGColorSpaceRelease(colorSpaceRef);
    free(imagePiexl);
    return [UIImage imageWithCGImage:finalRef scale:image.scale orientation:UIImageOrientationUp];
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

文章来源: blog.csdn.net,作者:Serendipity·y,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/Forever_wj/article/details/108270066

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200