从UIImage中删除Alpha通道

9
我使用以下方法从文件系统获取未压缩的uiimage。然而,即使UIImageView设置为不透明,当我打开颜色混合层时,UIImageView仍然呈红色。文件系统上的图像没有alpha通道。我尝试设置CGContextSetAlpha(bitmapContext,1),但仍具有混合层。有人知道如何在使用CGContextDrawImage时删除alpha通道吗?
- (UIImage *)decompressedImage
{
    CGImageRef imageRef = self.CGImage;
    CGRect rect = CGRectMake(0.f, 0.f, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef));
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL,
                                                       rect.size.width,
                                                       rect.size.height,
                                                       CGImageGetBitsPerComponent(imageRef),
                                                       CGImageGetBytesPerRow(imageRef),
                                                       CGImageGetColorSpace(imageRef),
                                                       kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little
                                                       );
    // kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little are the bit flags required
    //  so that the main thread doesn't have any conversions to do.

    CGContextDrawImage(bitmapContext, rect, imageRef);

    CGImageRef decompressedImageRef = CGBitmapContextCreateImage(bitmapContext);
    UIImage* decompressedImage = [UIImage imageWithCGImage:decompressedImageRef
                                                     scale:[[UIScreen mainScreen] scale]
                                               orientation:UIImageOrientationUp];
    CGImageRelease(decompressedImageRef);
    CGContextRelease(bitmapContext);

    return decompressedImage;
}
4个回答

8
在上下文选项中,尝试该选项。
kCGImageAlphaNoneSkipLast

或者
kCGImageAlphaNoneSkipFirst

根据你使用的是RGBA还是ARGB

例如:

CGContextRef bitmapContext = CGBitmapContextCreate(NULL,
                                                       rect.size.width,
                                                       rect.size.height,
                                                       CGImageGetBitsPerComponent(imageRef),
                                                       CGImageGetBytesPerRow(imageRef),
                                                       CGImageGetColorSpace(imageRef),
                                                       kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Little
                                                       );

它能够工作。虽然性能没有得到很大的提升,但很高兴看到红色标记消失了。谢谢。 - Jensen
@Jensen 移除 alpha 通道并不能真正提高性能,因为在创建 UIImage 时它们基本上会为您填充。不过,您仍然可以获得更小的压缩图像的优势,因此这仍然是一种很好的优化方式 :) - Jack
我刚发现的另一件事是:如果我使用kCGImageAlphaNoneSkipLast,所有解压缩的图像都会被彩色复制。但是如果使用kCGImageAlphaPremultipliedFirst,则不会被彩色化。难道使用更多内存的原因是kCGImageAlphaNoneSkipLast复制了图像吗? - Jensen
@Jensen 这很有趣,但我不知道可能是什么原因导致的。我觉得它们应该都是复制版本,因为在此过程中创建了一个新的CGImage。可能存在一些我不知道的疯狂优化,抱歉:( - Jack
1
结果发现我使用了错误的标志。使用kCGImageAlphaNoneSkipFirst解决了所有问题。感谢您的帮助:] - Jensen
显示剩余4条评论

8

同样的结果,但代码更少,无需担心太多:

func removeAlpha(from inputImage: UIImage) -> UIImage {
    let format = UIGraphicsImageRendererFormat.init()
    format.opaque = true //Removes Alpha Channel
    format.scale = inputImage.scale //Keeps original image scale.
    let size = inputImage.size
    return UIGraphicsImageRenderer(size: size, format: format).image { _ in
        inputImage.draw(in: CGRect(origin: .zero, size: size))
    }
}

这会使pngData变成nil。 - Ozgur Sahin
当尝试比较表示为数据并从视图中获取的PNG图像以在单元测试中进行比较时,它能够完美运行。只要对于存储的图像的pngData和从ImageView获取的图像的pngData都去除Alpha通道,这就使得测试通过了。感谢Justin! - Repose

1
这是@Justin Ganzer的答案,以可链式调用的扩展格式呈现:
@available(iOS 10.0, *)
extension UIImage {
    func removingAlpha() -> UIImage {
        let format = UIGraphicsImageRendererFormat()
        format.opaque = true // removes Alpha Channel
        format.scale = scale // keeps original image scale
        return UIGraphicsImageRenderer(size: size, format: format).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

-10
-(void)JhagRemoveMethodRepet
{

    switch (Jhagtag)
    {
        case 1:
        {

            if (jhag1.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag1.alpha;
                jhag1.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:0 withObject:@"Mid"];
            }else
            {
            jhag1.alpha=0.0;
            [JRemovetimer invalidate];
             JRemovetimer=nil;
            [Checkjhag replaceObjectAtIndex:0 withObject:@"No"];
            [self checkcompeletewater];
            }

        }
            break;
        case 2:
        {

            if (jhag2.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag2.alpha;
                jhag2.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:1 withObject:@"Mid"];

                if (jhagBrush==YES)
                {
                    BTooth2.alpha=0.0;
                }
            }else
            {
                jhag2.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:1 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 3:
        {

            if (jhag3.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag3.alpha;
                jhag3.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:2 withObject:@"Mid"];
            }else
            {
                jhag3.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:2 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 4:
        {
            if (jhag4.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag4.alpha;
                jhag4.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:3 withObject:@"Mid"];
                if (jhagBrush==YES)
                {
                    BTooth3.alpha=0.0;
                    SpiderMud.alpha=0.0;
                }
            }else
            {
                jhag4.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:3 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 5:
        {

            if (jhag5.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag5.alpha;
                jhag5.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:4 withObject:@"Mid"];
            }else
            {
                jhag5.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:4 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 6:
        {
            if (jhag6.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag6.alpha;
                jhag6.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:5 withObject:@"Mid"];
                if (jhagBrush==YES)
                {
                    GreenMud.alpha=0.0;
                }
            }else
            {
                jhag6.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:5 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 7:
        {
            if (jhag7.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag7.alpha;
                jhag7.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:6 withObject:@"Mid"];
            }else
            {
                jhag7.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:6 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 8:
        {
            if (jhag8.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag8.alpha;
                jhag8.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:7 withObject:@"Mid"];

                if (jhagBrush==YES)
                {
                    BTooth1.alpha=0.0;
                }
            }else
            {
                jhag8.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:7 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 9:
        {
            if (jhag9.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag9.alpha;
                jhag9.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:8 withObject:@"Mid"];
            }
            else
            {
                jhag9.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:8 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 10:
        {
            if (jhag10.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag10.alpha;
                jhag10.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:9 withObject:@"Mid"];
            }else
            {
                jhag10.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:9 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;
        case 11:
        {
            if (jhag11.alpha>0.3)
            {
                float alpha1;
                alpha1=jhag11.alpha;
                jhag11.alpha=alpha1-0.1;
                [Checkjhag replaceObjectAtIndex:10 withObject:@"Mid"];
                if (jhagBrush==YES)
                {
                    Yellowmud.alpha=0.0;
                }
            }else
            {
                jhag11.alpha=0.0;
                [JRemovetimer invalidate];
                JRemovetimer=nil;
                [Checkjhag replaceObjectAtIndex:10 withObject:@"No"];
                [self checkcompeletewater];
            }

        }
            break;

        default:
            break;
    }

}

-(void)checkcompeletewater
{
    NSMutableArray *compeletearr=[NSMutableArray arrayWithObjects:@"No",@"No",@"No",@"No",@"No",@"No",@"No",@"No",@"No",@"No",@"No", nil];


    if ([Checkjhag isEqualToArray:compeletearr] && jhagBrush==YES)
    {
        waterClean=YES;
        [self SoundPlay:@"puzzle_right"];

4
代码需要添加一些注释以及解释。目前它有点混乱。 - fedorqui
1
通常情况下,如果答案包含代码的意图和解决问题的原因,而不会引入其他问题,那么这样的答案会更有帮助。 (此帖子被至少一个用户标记,可能是因为他们认为没有解释的答案应该被删除。在这里我不能完全不同意。) - Nathan Tuggy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接