代码片段iOS俱乐部程序猿阵线联盟-汇总各类技术干货

UIImage的分类:截图功能和修改图片中的指定颜色

2018-01-18  本文已影响92人  李贤立

一,截图一般需要用到两大功能:全屏截图和指定区域截图。
二,拿到一些图片,需要对图片进行合成的时候,外层图片的底色会很讨厌,我们需要把那层讨厌的颜色去掉,换成透明的,或者指定的某种颜色。比如我们代码生成的二维码图片,默认出来就是白色底,但是将该二维码和展示公司形象的图片组合的时候,那张白色底在很显眼,最好是给换成透明的。

全屏截图需要考虑的是当前界面是否有导航栏,指定区域截图需要考虑的是当前手机屏幕对图片的缩放比例。
修改图片的颜色,其实是遍历该image的每个像素点,然后找到对应的ARGB进行值替换。

/**
 *  将图片中的指定颜色转换为透明
 */
- (UIImage *)imageToTransparentWithOriginalColor:(UIColor *)originalColor {
    // 分解原来的颜色
    CGFloat red = 0.0;
    CGFloat green = 0.0;
    CGFloat blue = 0.0;
    CGFloat alpha = 0.0;
    [originalColor getRed:&red green:&green blue:&blue alpha:&alpha];
    
    // 分配内存
    const int imageWidth = self.size.width;
    const int imageHeight = self.size.height;
    size_t bytesPerRow = imageWidth * 4;
    uint32_t *rgbImageBuf = (uint32_t *)malloc(bytesPerRow * imageHeight);
    
    // 创建context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), self.CGImage);
    
    // 遍历像素
    int pixelNum = imageWidth * imageHeight;
    uint32_t* pCurPtr = rgbImageBuf;
    for (int i = 0; i < pixelNum; i++, pCurPtr++) {
        //将像素点转成子节数组来表示---第一个表示透明度即ARGB这种表示方式。ptr[0]:透明度,ptr[1]:R,ptr[2]:G,ptr[3]:B
        //分别取出RGB值后。进行判断需不需要设成透明。
        uint8_t* ptr = (uint8_t *)pCurPtr;
        // NSLog(@"1是%d,2是%d,3是%d",ptr[1],ptr[2],ptr[3]);
        if(ptr[1] == red * 255 || ptr[2] == green * 255 || ptr[3] == blue * 255) {
            ptr[0] = 0;
        }
    }
    
    // 将内存转成image
    CGDataProviderRef dataProvider =CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, nil);
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight,8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast |kCGBitmapByteOrder32Little, dataProvider, NULL, true,kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
    
    // 释放
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    return resultUIImage;
}
/**
 *  将图片中的指定颜色转换为新的颜色
 *
 *  @pram originalColor 原来的颜色
 *  @pram newColor      新的颜色
 */
- (UIImage *)imageOriginalColor:(UIColor *)originalColor toNewColor:(UIColor *)newColor {
    // 分解原来的颜色
    CGFloat red1 = 0.0;
    CGFloat green1 = 0.0;
    CGFloat blue1 = 0.0;
    CGFloat alpha1 = 0.0;
    CGFloat red2 = 0.0;
    CGFloat green2 = 0.0;
    CGFloat blue2 = 0.0;
    CGFloat alpha2 = 0.0;
    [originalColor getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1];
    [newColor getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2];
    
    // 分配内存
    const int imageWidth = self.size.width;
    const int imageHeight = self.size.height;
    size_t bytesPerRow = imageWidth * 4;
    uint32_t *rgbImageBuf = (uint32_t *)malloc(bytesPerRow * imageHeight);
    
    // 创建context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipLast);
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), self.CGImage);
    
    // 遍历像素
    int pixelNum = imageWidth * imageHeight;
    uint32_t* pCurPtr = rgbImageBuf;
    for (int i = 0; i < pixelNum; i++, pCurPtr++) {
        // 将像素点转成子节数组来表示---第一个表示透明度即ARGB这种表示方式。
        // ptr[0]:透明度,ptr[1]:R,ptr[2]:G,ptr[3]:B
        uint8_t* ptr = (uint8_t *)pCurPtr;
        if (ptr[0] == alpha1) ptr[0] = alpha2;
        if (ptr[1] == red1 * 255) ptr[1] = red2 * 255;
        if (ptr[2] == green1 * 255) ptr[2] = green2 * 255;
        if (ptr[3] == blue1 * 255) ptr[3] = blue2 * 255;
    }
    
    // 将内存转成image
    CGDataProviderRef dataProvider =CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, nil);
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight,8, 32, bytesPerRow, colorSpace, kCGImageAlphaLast |kCGBitmapByteOrder32Little, dataProvider, NULL, true,kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
    
    // 释放
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    return resultUIImage;
}
/**
 *  全屏截图
 */
+ (UIImage *)screenShot {
    return  [self screenShotWithRect:[UIApplication sharedApplication].keyWindow.bounds isNavigation:NO];
}
/**
 *  屏幕截图
 *
 *  @pram rect         截图的frame
 *  @pram isNavigation 导航栏是否显示
 */
+ (UIImage *)screenShotWithRect:(CGRect)rect isNavigation:(BOOL)isNavigation {
    // 获取屏幕放大比例
    CGFloat scale = [UIScreen mainScreen].scale;
    CGRect newRect = rect;
    newRect.size.width *= scale;
    newRect.size.height *= scale;
    CGFloat height = 0;
    if (isNavigation) {
        height = NavigationViewHeight;
    }
    newRect.origin.y += height;
    newRect.origin.x *= scale;
    newRect.origin.y *= scale;
    // 设置截屏大小
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(newRect.size.width, newRect.size.height), YES, 0);
    [[UIApplication sharedApplication].keyWindow.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGImageRef imageRef = viewImage.CGImage;
    // 设置截图的区域
    CGImageRef imageRefRect = CGImageCreateWithImageInRect(imageRef, newRect);
    UIImage *sendImage = [[UIImage alloc] initWithCGImage:imageRefRect];
    // 保存图片到照片库
    //    UIImageWriteToSavedPhotosAlbum(sendImage, nil, nil, nil);
    return sendImage;
}
/**
 *  返回截取到的图片数据类型
 */
+ (NSData *)dataWithScreenshot {
    UIImage *image = [self imageWithScreenshot];
    UIGraphicsEndImageContext();
    return UIImagePNGRepresentation(image);
}
/**
 *  截取当前屏幕
 */
+ (UIImage *)imageWithScreenshot {
    CGSize imageSize = CGSizeZero;
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (UIInterfaceOrientationIsPortrait(orientation))
        imageSize = [UIScreen mainScreen].bounds.size;
    else
        imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
        CGContextSaveGState(context);
        CGContextTranslateCTM(context, window.center.x, window.center.y);
        CGContextConcatCTM(context, window.transform);
        CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
        if (orientation == UIInterfaceOrientationLandscapeLeft) {
            CGContextRotateCTM(context, M_PI_2);
            CGContextTranslateCTM(context, 0, -imageSize.width);
        } else if (orientation == UIInterfaceOrientationLandscapeRight) {
            CGContextRotateCTM(context, -M_PI_2);
            CGContextTranslateCTM(context, -imageSize.height, 0);
        } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
            CGContextRotateCTM(context, M_PI);
            CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
        }
        if ([window respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
            [window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
        } else {
            [window.layer renderInContext:context];
        }
        CGContextRestoreGState(context);
    }
    return UIGraphicsGetImageFromCurrentImageContext();
}
上一篇下一篇

猜你喜欢

热点阅读