2009-07-11 19 views
21

Chciałbym utworzyć obiekt UIImage z bieżącego kontekstu graficznego. Mówiąc dokładniej, mój przypadek użycia to widok, w którym użytkownik może narysować linie. Mogą rysować przyrostowo. Po ich zakończeniu chciałbym utworzyć UIImage do reprezentowania ich rysunku.Jak utworzyć UIImage z bieżącego kontekstu graficznego?

Oto co drawRect: wygląda jak dla mnie teraz:

- (void)drawRect:(CGRect)rect 
{ 
CGContextRef c = UIGraphicsGetCurrentContext(); 

CGContextSaveGState(c); 
CGContextSetStrokeColorWithColor(c, [UIColor blackColor].CGColor); 
CGContextSetLineWidth(c,1.5f); 

for(CFIndex i = 0; i < CFArrayGetCount(_pathArray); i++) 
{ 
    CGPathRef path = CFArrayGetValueAtIndex(_pathArray, i); 
    CGContextAddPath(c, path); 
} 

CGContextStrokePath(c); 

CGContextRestoreGState(c); 
} 

... gdzie _pathArray jest typu CFArrayRef i jest wypełniana za każdym razem touchesEnded: jest wywoływany. Zauważ również, że drawRect: może być wywoływany kilka razy, jak rysuje użytkownik.

Kiedy użytkownik skończy, chciałbym utworzyć obiekt UIImage, który reprezentuje kontekst graficzny. Wszelkie sugestie, jak to zrobić?

+0

Obie odpowiedzi poniżej pracy. Zauważ, że istnieje różnica funkcjonalna między tymi dwoma, co oznacza, że ​​renderowanie warstwy w kontekście obrazu spowoduje również renderowanie tła warstwy; Wywołanie drawRect: bezpośrednio nie (w moim przypadku to nie ma znaczenia). Przechodzę z podejściem renderowania CALayer ze względu na złożoność wywoływania drawRect: bezpośrednio (szczegóły na stronie http://lists.apple.com/archives/Cocoa-dev/2002/Apr/msg01846.html). Dzięki! – figelwump

Odpowiedz

42

Musisz skonfigurować pierwszy kontekst grafiki:

UIGraphicsBeginImageContext(myView.bounds.size); 
[myView.layer renderInContext:UIGraphicsGetCurrentContext()]; 
viewImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
7

UIImage * image = UIGraphicsGetImageFromCurrentImageContext();

Jeśli musisz zachować image wokół, pamiętaj, aby go zachować!

EDIT: Jeśli chcesz zapisać wyjście drawRect do obrazu, po prostu utwórz kontekst bitmapowy używając UIGraphicsBeginImageContext i wywołaj funkcję drawRect z nowym kontekstem związanym. Łatwiej to zrobić niż zapisać CGContextRef, z którym pracujesz w drawRect - ponieważ ten kontekst może nie zawierać powiązanych z nim informacji bitmapowych.

UIGraphicsBeginImageContext(view.bounds.size); 
[view drawRect: [myView bounds]]; 
UIImage * image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

Można również zastosować podejście, o którym wspomniał Kelvin. Jeśli chcesz utworzyć obraz z bardziej złożonego widoku, takiego jak UIWebView, jego metoda jest szybsza. Rysowanie warstwy widoku nie wymaga odświeżania warstwy, wymaga jedynie przenoszenia danych obrazu z jednego bufora do drugiego!

+0

Dzięki za odpowiedź, jednak nie wydaje się działać. Dodałem wiersz: \t _signatureImage = UIGraphicsGetImageFromCurrentImageContext(); ... gdzie _signatureImage jest własnością zatrzymaną. Zwrócony obiekt jest zerowy. Zgodnie z dokumentami, UIGraphicsGetImageFromCurrentImageContext() jest przeznaczony do użytku tylko wtedy, gdy bieżący kontekst jest kontekstem bitmapowym. W mojej obecnej implementacji drawRect: nie sądzę, żeby tak było. Dokumenty wspominają o użyciu UIGraphicsBeginImageContext(), ale nie jestem pewien jak to ma zastosowanie w moim przypadku, ponieważ drawRect może być wywołany wiele razy. – figelwump

2

Swift Wersja

func createImage(from view: UIView) -> UIImage { 
     UIGraphicsBeginImageContext(view.bounds.size) 
     view.layer.renderInContext(UIGraphicsGetCurrentContext()!) 
     let viewImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 

     return viewImage 
    }