web-dev-qa-db-fra.com

mélanger deux images basées sur l'alpha / transparence de l'image du haut

J'essaie de mélanger un arrière-plan avec une image de premier plan, où l'image de premier plan est une image transparente avec des lignes dessus.

J'essaie de le faire de cette façon.

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

mais ne semble pas fonctionner.

Toute suggestion sera appréciée.

32
saran

Voici ce que j'ai fait dans mon application, similaire à Tyler - mais sans le 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();

Si l'image a déjà l'opacité, vous n'avez pas besoin de la définir (comme dans bottomImage) sinon vous pouvez la définir (comme avec image).

89
Eric
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];
19
Tyler

ma réponse est basée sur la réponse d'Eric , mais permet aux images @ 2x de conserver leur résolution après la fusion de l'image. Veuillez noter l'URL REF dans mes commentaires, car je reconnais les sources qui ont contribué à mon développement de cette fonction que j'ai utilisée dans mes applications 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;
}
9
Jason TEPOORTEN

Mélange avec alpha

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

Swift

Cette fonction prendra deux images et un CGSize et renverra un UIImage facultatif. Cela fonctionne mieux lorsque les deux images sont de la même taille. Si votre image supérieure a alpha, elle montrera l'image inférieure à travers elle.

// 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
}

tilisation

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
        }
    }
}
3
skymook

Pouvez-vous fournir des détails sur ce que vous entendez par "cela ne semble pas fonctionner?" Dessine-t-il une seule image ou l'autre image? Dessiner en noir? Bruit? Crash? Pourquoi avez-vous choisi kCGBlendModeSourceIn; quel effet essayez-vous d'obtenir (il existe des dizaines de façons de mélanger les images)? L'une de vos images contient-elle déjà de l'alpha?

Je suppose que ce que vous essayez de faire est de mélanger deux images de sorte que chacune ait une opacité de 50%? Utilisez CGContextSetAlpha() pour cela plutôt que CGContextSetBlendMode().

1
Rob Napier

Vous pouvez utiliser UIImage's drawInRect: ou drawAtPoint: au lieu de CGContextDrawImage (ils dessinent dans le contexte actuel). Leur utilisation vous donne-t-elle une différence de sortie?

Il peut également être utile de s'assurer que UIImage* valeurs dont vous récupérez imageNamed: sont valides.

0
fbrereto