2009-08-21 2 views
31

Próbuję połączyć tło z obrazem pierwszego planu, na którym obraz pierwszego planu jest przezroczystym obrazem z liniami na nim.zmiksuj dwa obrazki na podstawie alfa/przezroczystości obrazu górnego

Próbuję to zrobić w ten sposób.

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

ale wydaje się nie działać.

Wszelkie sugestie zostaną docenione.

+0

Uwaga techniczna: to odnosi się do "alfa-blending" (compositing dwa obrazy na podstawie kanału alfa w jednym z obrazów), a nie * do korzystania Rdzeń Grafika "tryby mieszania" - wyszukaj ponownie, jeśli tego potrzebujesz. W rzeczywistości, [odpowiedź Erica] (http://stackoverflow.com/a/3188761/199364) pokazuje krótko użycie jednego trybu mieszania; możesz zastąpić tam inny tryb mieszania i usunąć "alpha: 0.Parametr 8 " – ToolmakerSteve

Odpowiedz

0

Można użyć wartości UIImage zamiast CGContextDrawImage (rysują do bieżącego kontekstu). Czy ich użycie daje jakąkolwiek różnicę w wydajności?

Pomocne może być również sprawdzenie, czy wartości UIImage*, które otrzymujesz z numeru imageNamed:, są ważne.

1

Czy możesz podać szczegółowe informacje na temat tego, co masz na myśli przez "to nie działa?" Czy rysuje tylko jeden obraz lub inny obraz? Narysuj czarny? Hałas? Wypadek? Dlaczego wybrałeś kCGBlendModeSourceIn; jaki efekt próbujesz osiągnąć (są dziesiątki sposobów łączenia obrazów)? Czy którekolwiek z twoich zdjęć ma już alfę?

Zakładam, że próbujesz połączyć dwa obrazy tak, aby każdy miał 50% nieprzezroczystości? Zamiast tego użyj CGContextSetAlpha() zamiast CGContextSetBlendMode().

+0

Dziękuję za odpowiedzi .... Oba moje obrazy mają 100% nieprzezroczystości .... kiedy miksuję oba obrazy ... mój kontekst rysuje tylko drugi obraz ... w macosx ... i użyj źródła nad filtrem do złożenia obu obrazów ... a drugi obraz, który chcę złączyć, ma już alfę –

+0

Wierzę, że chcesz wrócić i przestudiować podstawy Rysowania Kwarcem. dezorientacja co do tego, co oznacza narysowanie różnych warstw z ich własną alfa w porównaniu do tego, co to znaczy mieszać (która jest powiązana, ale inna w sposobie jej implementacji) Przejdź do Przewodnika po programowaniu w Quartz 2D, nauczy Cię podstawowej grafiki, której potrzebujesz dzięki czemu możesz robić to, co chcesz, łatwo i z dobrą wydajnością, przewidywalnością i elastycznością 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

Dziękuję za twoje odpowiedzi ... ale nie jest to taki sam jak mając 50% nieprzezroczystości ... może sposób, w jaki sformułowałem moje pytanie jest niewłaściwy ... może i chcę powiedzieć, że chcę scalić 2 UIImages ... a obraz na górze ma wartości alfa. –

+1

Jeśli w pliku png obrazu znajdują się wartości alfa, po prostu pomiń "subView.alpha = 0.5;" i narysuje górny obraz, w tym własne niestandardowe wartości alfa, na wierzchu dolnego obrazu. – Tyler

+0

Pracowałem świetnie, dzięki. – zekel

4

Mieszanie z alfa

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

Proszę wyjaśnić, w jaki sposób jest to poprawa w stosunku do wcześniejszych odpowiedzi/lub w jakich okolicznościach użyłbyś go/lub dlaczego ta alternatywa może być pomocna. Dzięki. – ToolmakerSteve

89

To, co zrobiłem w mojej aplikacji, podobnie jak Tyler - ale bez 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(); 

Jeśli obraz ma już krycie , nie musisz go ustawiać (jak w bottomImage) w przeciwnym razie możesz go ustawić (jak w przypadku image).

+1

Dziękuję bardzo! Rozwiązano 6-godzinne prblem! –

+0

Dziękuję za tę odpowiedź ... Zadziałało jak urok ... Ale chcę zrobić to samo dla dwóch warstw ... – Alfa

+3

Dla wsparcia wyświetlania siatkówki i nie-siatkówki, użyj 'UIGraphicsBeginImageContextWithOptions (newSize, NO, 0.0f); ', która mówi UIKit, aby pobrać i wykorzystać współczynnik skali ekranu głównego urządzenia. –

9

Moja odpowiedź jest oparta na Eric's answer, ale pozwala na @ 2x obrazy zachować ich rozdzielczość po scaleniu obrazu. Proszę zwrócić uwagę na URL REF w moich komentarzach, ponieważ doceniam źródła, które przyczyniły się do mojego rozwoju tej funkcji, z której korzystałem w moich aplikacjach na 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

Funkcja ta zajmie dwa obrazy, a CGSize i powrócić opcjonalnego UIImage. Działa najlepiej, gdy oba obrazy mają ten sam rozmiar. Jeśli twoje najlepsze zdjęcie ma alfa, wyświetli przez nie dolny obraz.

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

Wykorzystanie

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