смешайте два изображения на основе альфа / прозрачности верхнего изображения - PullRequest
32 голосов
/ 21 августа 2009

Я пытаюсь смешать фон с изображением переднего плана, где изображение переднего плана - это прозрачное изображение с линиями на нем.

Я пытаюсь сделать это таким образом.

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();

но, похоже, не работает.

Любые предложения будут оценены.

Ответы [ 7 ]

89 голосов
/ 06 июля 2010

Это то, что я сделал в своем приложении, аналогично Тайлеру, но без 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).

19 голосов
/ 21 августа 2009
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];
9 голосов
/ 12 февраля 2012

мой ответ основан на ответе Эрика , но позволяет @ 2x изображениям сохранять свое разрешение после слияния изображений. Обратите внимание на URL REF в моих комментариях, поскольку я признаю источники, которые помогли мне в разработке этой функции, которую я использовал в своих приложениях для iOS.

- (UIImage*) mergeTwoImages : (UIImage*) topImage : (UIImage*) bottomImage
{
    // URL REF: http://iphoneincubator.com/blog/windows-views/image-processing-tricks
    // URL REF: /923421/smeshaite-dva-izobrazheniya-na-osnove-alfa-prozrachnosti-verhnego-izobrazheniyatab-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 голосов
/ 06 июля 2010

Смешивание с альфа

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();
3 голосов
/ 12 ноября 2016

Swift 3

Эта функция будет принимать два изображения и CGSize и возвращать необязательный UIImage. Это работает лучше всего, когда оба изображения имеют одинаковый размер. Если ваше верхнее изображение имеет альфа, оно покажет нижнее изображение через него.

// 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
        }
    }
}
1 голос
/ 21 августа 2009

Можете ли вы предоставить подробности того, что вы подразумеваете под "это не похоже на работу?" Это рисует только одно изображение или другое изображение? Рисовать черным? Шум? Сбой? Почему вы выбрали kCGBlendModeSourceIn; какого эффекта вы пытаетесь достичь (существуют десятки способов наложения изображений)? У любого из ваших изображений уже есть альфа?

Я предполагаю, что вы пытаетесь смешать два изображения таким образом, чтобы у каждого было 50% непрозрачности? Для этого используйте CGContextSetAlpha(), а не CGContextSetBlendMode().

0 голосов
/ 21 августа 2009

Вы можете использовать UIImage drawInRect: или drawAtPoint: вместо CGContextDrawImage (они рисуют в текущем контексте). Их использование дает вам какую-то разницу в выходе?

Также может быть полезно убедиться, что значения UIImage*, которые вы получаете от imageNamed:, действительны.

...