【问题标题】:blend two uiimages based on alpha/transparency of top image根据顶部图像的 alpha/透明度混合两个 uiimage
【发布时间】:2018-03-09 22:30:38
【问题描述】:

我正在尝试将背景与前景图像混合,其中前景图像是带有线条的透明图像。

我正在尝试这样做。

UIGraphicsBeginImageContext(CGSizeMake(320, 480));
CGContextRef context = UIGraphicsGetCurrentContext();   

// create rect that fills screen
CGRect bounds = CGRectMake( 0,0, 320, 480);

// This is my bkgnd image
CGContextDrawImage(context, bounds, [UIImage imageNamed:@"bkgnd.jpg"].CGImage);

CGContextSetBlendMode(context, kCGBlendModeSourceIn);

// This is my image to blend in
CGContextDrawImage(context, bounds, [UIImage imageNamed:@"over.png"].CGImage);

UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

UIImageWriteToSavedPhotosAlbum(outputImage, self, nil, nil);
// clean up drawing environment
//
UIGraphicsEndImageContext();

但似乎不起作用。

任何建议将不胜感激。

【问题讨论】:

  • 技术说明:这是指“alpha-blending”(基于其中一个图像中的 alpha 通道合成两个图像),不是使用 Core Graphics “blend模式” - 如果这是您需要的,请再次搜索。实际上,Eric's answer 确实简要展示了一种混合模式的使用;您可以在那里替换不同的混合模式,并删除“alpha:0.8”参数。

标签: iphone alphablending


【解决方案1】:

这是我在我的应用中所做的,类似于 Tyler 的 - 但没有 UIImageView

UIImage *bottomImage = [UIImage imageNamed:@"bottom.png"];
UIImage *image = [UIImage imageNamed:@"top.png"];

CGSize newSize = CGSizeMake(width, height);
UIGraphicsBeginImageContext( newSize );

// Use existing opacity as is
[bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Apply supplied opacity
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.8];

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

如果图像已经具有不透明度,则不需要设置它(如bottomImage),否则您可以设置它(如image)。

【讨论】:

  • 感谢您的回答...它就像魅力一样...但我想对两层做同样的事情...
  • 对于视网膜和非视网膜显示支持,使用UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0f);,它告诉 UIKit 抓取并使用设备主屏幕的比例因子。
【解决方案2】:
UIImage* bottomImage = [UIImage imageNamed:@"bottom.png"];  
UIImage* topImage    = [UIImage imageNamed:@"top.png"];
UIImageView* imageView = [[UIImageView alloc] initWithImage:bottomImage];
UIImageView* subView   = [[UIImageView alloc] initWithImage:topImage];
subView.alpha = 0.5;  // Customize the opacity of the top image.
[imageView addSubview:subView];
UIGraphicsBeginImageContext(imageView.frame.size);
[imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* blendedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[subView release];
[imageView release];

[self doWhateverIWantWith: blendedImage];

【讨论】:

  • 感谢您的回复....但这与 50% 的不透明度相同...可能我表达我的问题的方式是错误的...可能我应该说我想要合并 2 个 UIImages...并且顶部的图像具有 alpha 值。
  • 如果顶部图像的 png 文件中有 alpha 值,只需省略 "subView.alpha = 0.5;"线,它会在底部图像的顶部绘制顶部图像,包括它的自定义 alpha 值。
【解决方案3】:

我的答案基于Eric's answer,但允许@2x 图像在图像合并后保留其分辨率。请注意我的 cmets 中的 URL REF,因为我承认对我在 iOS 应用程序中使用的此功能的开发提供帮助的来源。

- (UIImage*) mergeTwoImages : (UIImage*) topImage : (UIImage*) bottomImage
{
    // URL REF: http://iphoneincubator.com/blog/windows-views/image-processing-tricks
    // URL REF: https://stackoverflow.com/questions/1309757/blend-two-uiimages?answertab=active#tab-top
    // URL REF: http://www.waterworld.com.hk/en/blog/uigraphicsbeginimagecontext-and-retina-display

    int width = bottomImage.size.width;
    int height = bottomImage.size.height;

    CGSize newSize = CGSizeMake(width, height);
    static CGFloat scale = -1.0;

    if (scale<0.0)
    {
        UIScreen *screen = [UIScreen mainScreen];

        if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.0)
        {
            scale = [screen scale];
        }
        else
        {
            scale = 0.0;    // Use the standard API
        }
    }

    if (scale>0.0)
    {
        UIGraphicsBeginImageContextWithOptions(newSize, NO, scale);
    }
    else
    {
        UIGraphicsBeginImageContext(newSize);
    }

    [bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    [topImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:1.0];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

【讨论】:

    【解决方案4】:

    与阿尔法混合

    UIGraphicsBeginImageContext(area.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextRetain(context);
    
    // mirroring context
    CGContextTranslateCTM(context, 0.0, area.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    for (...) {
        CGContextBeginTransparencyLayer(context, nil);
        CGContextSetAlpha( context, alpha );
        CGContextDrawImage(context, area, tempimg.CGImage);
        CGContextEndTransparencyLayer(context);
    }
    
    // get created image
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    CGContextRelease(context);
    UIGraphicsEndImageContext();
    

    【讨论】:

    • 请解释这是对早期答案的改进/或在什么情况下您会使用它/或为什么这种替代方案可能会有所帮助。谢谢。
    【解决方案5】:

    斯威夫特 3

    此函数将获取两个图像和一个CGSize,并返回一个可选的UIImage。当两个图像大小相同时效果最佳。如果您的顶部图像具有 Alpha,它将通过它显示底部图像。

    // composit two images
    func compositeTwoImages(top: UIImage, bottom: UIImage, newSize: CGSize) -> UIImage? {
        // begin context with new size
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        // draw images to context
        bottom.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
        top.draw(in: CGRect(origin: CGPoint.zero, size: newSize))
        // return the new image
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        // returns an optional
        return newImage
    }
    

    用法

    let outputSize = CGSize(width: 100, height: 100)
    if let topImage = UIImage(named: "myTopImage") {
        if let bottomImage = UIImage(named: "myBottomImage") {
            // composite both images
            if let finalImage = compositeTwoImages(top: topImage, bottom: bottomImage, newSize: outputSize) {
                // do something with finalImage
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      您能否详细说明“它似乎不起作用”的含义?它是只画一个图像还是另一个图像?画黑色?噪音?碰撞?为什么选择kCGBlendModeSourceIn;你想达到什么效果(有几十种混合图像的方法)?你的任何一张图片都已经有 Alpha 版了吗?

      我假设你想要做的是混合两个图像,每个图像都有 50% 的不透明度?使用CGContextSetAlpha() 而不是CGContextSetBlendMode()

      【讨论】:

      • 感谢您的回复......我的两个图像都有 100% 的不透明度......当我混合两个图像时......我的上下文只绘制第二个图像......在 macosx 中...... . 我使用源过滤器来合成两个图像....并且我想要混合的第二个图像已经具有 alpha。
      • 相信你想回去学习一下Quartz Drawing的基础知识。我相信您对使用自己的 alpha 绘制各种图层的含义与混合的含义(这是相关的,但在实现方式上有所不同)感到困惑。转到 Quartz 2D 编程指南;它将教您所需的核心图形,以便您可以轻松地做您想做的事,并具有良好的性能、可预测性和灵活性。 developer.apple.com/documentation/graphicsimaging/conceptual/…
      【解决方案7】:

      您可以使用UIImagedrawInRect:drawAtPoint: 代替CGContextDrawImage(它们绘制到当前上下文)。使用它们会给你的输出带来什么不同吗?

      确保您从imageNamed: 返回的UIImage* 值有效也可能会有所帮助。

      【讨论】:

        猜你喜欢
        • 2015-02-03
        • 2015-11-04
        • 2012-04-13
        • 2012-04-12
        • 1970-01-01
        • 1970-01-01
        • 2016-05-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多