2009-08-21 5 views
31

J'essaie de fondre un arrière-plan avec une image de premier plan, où l'image de premier plan est une image transparente avec des lignes. J'essaie de faire comme ça.mélange deux uiimages basées sur l'alpha/transparence de l'image supérieure

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.

Toutes les suggestions seront appréciées.

+0

Note technique: cela fait référence à "alpha-blending" (compositing deux images basées sur un canal alpha dans l'une des images), * pas * à l'aide de base Graphiques "modes de fusion" - recherchez à nouveau si c'est ce dont vous avez besoin. En fait, [la réponse d'Eric] (http://stackoverflow.com/a/3188761/199364) montre brièvement l'utilisation d'un mode de fusion; vous pouvez y substituer un mode de fusion différent et supprimer le "alpha: 0".8 "paramètre – ToolmakerSteve

Répondre

0

Vous pouvez utiliser UIImagedrawInRect: ou drawAtPoint: au lieu de CGContextDrawImage (ils dessinent dans le contexte actuel). Est-ce que leur utilisation vous donne une différence de rendement?

Il peut également être utile de vous assurer que les valeurs UIImage* que vous obtenez de imageNamed: sont valides.

1

Pouvez-vous fournir des détails sur ce que vous entendez par «ça ne semble pas fonctionner? Dessine-t-il seulement une image ou l'autre image? Dessiner noir? Bruit? Crash? Pourquoi avez-vous choisi kCGBlendModeSourceIn; quel effet tentez-vous d'atteindre (il existe des dizaines de façons de mélanger les images)? Est-ce que l'une de vos images a déjà un alpha?

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

+0

Merci pour vos réponses .... Mes deux images ont 100% d'opacité .... quand je mélange les deux images ... mon contexte ne dessine que la deuxième image ... dans macosx ... i utiliser la source sur le filtre pour composter à la fois les images .... et la deuxième image que je veux intégrer a déjà –

+0

Je crois que vous voulez revenir en arrière et étudier les bases du dessin à quartz. confusion sur ce que signifie dessiner différentes couches avec leur propre alpha par rapport à ce que cela signifie de mélanger (ce qui est apparenté, mais différent dans la façon dont il est implémenté.) Allez au Guide de programmation 2D Quartz, il vous enseignera les Core Graphics dont vous avez besoin. afin que vous puissiez faire ce que vous voulez facilement et avec de bonnes performances, la prédictibilité et la flexibilité http://developer.apple.com/documentation/graphicsimaging/conceptual/drawingwithquartz2d/ –

19
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]; 
+0

Merci pour vos réponses .... mais ce n'est pas le pareil que avoir 50% d'opacité ... mayb la façon dont j'ai formulé ma question est fausse ... mayb je dirais que je veux fusionner 2 UIImages ... et l'image sur le dessus a des valeurs alpha. –

+1

S'il y a des valeurs alpha dans le fichier png de l'image supérieure, il suffit d'omettre "subView.alpha = 0.5;" ligne, et il dessine l'image supérieure, y compris ses valeurs alpha personnalisées, sur le dessus de l'image du bas. – Tyler

+0

A travaillé super, merci. – zekel

4

Mélangeant 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(); 
+0

Veuillez expliquer en quoi cela constitue une amélioration par rapport aux réponses précédentes/ou dans quelles circonstances vous l'utiliseriez/ou pourquoi cette solution pourrait vous être utile. Merci. – ToolmakerSteve

89

C'est ce que je l'ai fait dans mon application, semblable à Tyler - mais sans 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à une opacité , vous n'avez pas besoin de le définir (comme dans bottomImage) sinon vous pouvez le définir (comme avec image).

+1

Merci beaucoup !!! Résolu un prblem de 6 heures! –

+0

Merci pour cette réponse ... Cela a fonctionné comme charme ... Mais je veux faire la même chose pour deux couches .... – Alfa

+3

Pour la prise en charge de l'affichage rétine et non-rétine, utilisez 'UIGraphicsBeginImageContextWithOptions (newSize, NO, 0.0f), qui indique à UIKit de saisir et d'utiliser le facteur d'échelle de l'écran principal de l'appareil. –

9

ma réponse est basée sur Eric's answer, 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é 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; 
} 
2

Swift 3

Cette fonction prendra deux images, et un CGSize et retourner un UIImage en option. Cela fonctionne mieux lorsque les deux images sont de la même taille. Si votre image supérieure est en alpha, elle affichera l'image du bas.

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

Utilisation

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 
     } 
    } 
} 
Questions connexes