Czy ktoś wie, dlaczego CGContextDrawImage
miałbym rysować mój obraz do góry nogami? Ładuję obraz z mojej aplikacji:
UIImage *image = [UIImage imageNamed:@"testImage.png"];
A potem po prostu poproś podstawową grafikę, aby narysowała ją w moim kontekście:
CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);
Renderuje się we właściwym miejscu i wymiarach, ale obraz jest odwrócony. Muszę tu przegapić coś naprawdę oczywistego?
ios
cocoa-touch
core-graphics
cgcontextdrawimage
rustyshelf
źródło
źródło
Nawet po zastosowaniu wszystkiego, o czym wspomniałem, wciąż miałem dramaty z obrazami. Ostatecznie właśnie użyłem Gimpa do stworzenia wersji „odwróconej pionowej” wszystkich moich zdjęć. Teraz nie muszę używać żadnych transformacji. Mamy nadzieję, że nie spowoduje to dalszych problemów na późniejszym etapie.
Quartz2d używa innego układu współrzędnych, którego pochodzenie znajduje się w lewym dolnym rogu. Kiedy więc Kwarc rysuje piksel x [5], y [10] obrazu 100 * 100, piksel ten jest rysowany w lewym dolnym rogu zamiast w lewym górnym rogu. Powodując w ten sposób „odwrócony” obraz.
Układ współrzędnych x pasuje, więc trzeba odwrócić współrzędne y.
Oznacza to, że przetłumaczyliśmy obraz o 0 jednostek na osi x i wysokość obrazów na osi y. Jednak to samo będzie oznaczać, że nasz obraz jest wciąż do góry nogami, po prostu zostanie narysowany „image.size.height” poniżej, gdzie chcemy go narysować.
Przewodnik po programowaniu Quartz2D zaleca stosowanie ScaleCTM i przekazywanie wartości ujemnych w celu odwrócenia obrazu. Aby to zrobić, możesz użyć następującego kodu -
Połącz dwa tuż przed
CGContextDrawImage
rozmową, a obraz powinien być narysowany poprawnie.Należy zachować ostrożność, jeśli współrzędne imageRect nie pasują do współrzędnych obrazu, ponieważ można uzyskać niezamierzone wyniki.
Aby przekonwertować współrzędne z powrotem:
źródło
CGContextSaveGState()
iCGContextRestoreGState()
nie zapisujesz i nie przywracasz macierzy transformacji?Najlepsze z obu światów, użyj UIImage
drawAtPoint:
lubdrawInRect:
wciąż określając swój niestandardowy kontekst:Ponadto unikasz modyfikowania swojego kontekstu
CGContextTranslateCTM
lub tego,CGContextScaleCTM
co robi druga odpowiedź.źródło
UIGraphicsBeginImageContextWithOptions
zamiast inicjować nowyCGContext
, wydawało się, że działa.Odpowiednie dokumenty Quartz2D: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP400S15W-CH14
źródło
Jeśli ktoś jest zainteresowany bezmyślnym rozwiązaniem do rysowania obrazu w niestandardowym odbiciu w kontekście:
Obraz zostanie przeskalowany, aby wypełnić prostokąt.
źródło
Nie jestem pewien
UIImage
, ale takie zachowanie zwykle występuje, gdy współrzędne są odwracane. Większość układów współrzędnych OS X ma swój początek w lewym dolnym rogu, jak w Postscript i PDF. AleCGImage
układ współrzędnych ma swój początek w lewym górnym rogu.Możliwe rozwiązania mogą obejmować
isFlipped
właściwość lubscaleYBy:-1
transformację afiniczną.źródło
UIImage
zawieraCGImage
jako główny element treści, a także czynniki skalowania i orientacji. PonieważCGImage
i jego różne funkcje pochodzą z OSX, oczekuje on układu współrzędnych, który jest do góry nogami w porównaniu do iPhone'a. Kiedy tworzyszUIImage
, domyślnie orientacja jest odwrócona, aby to zrekompensować (możesz to zmienić!). Użyj .CGImage
, aby uzyskać dostęp do bardzo zaawansowanychCGImage
funkcji, ale rysowanie na ekranie iPhone'a itp. najlepiej wykonywaćUIImage
metodami.źródło
Dodatkowa odpowiedź z kodem Swift
Kwarcowa grafika 2D używa układu współrzędnych z punktem początkowym w lewym dolnym rogu, podczas gdy UIKit w iOS używa układu współrzędnych z początkiem w lewym górnym rogu. Zazwyczaj wszystko działa dobrze, ale wykonując niektóre operacje graficzne, musisz samodzielnie zmodyfikować układ współrzędnych. W dokumentacji czytamy:
Zjawisko to można zaobserwować w następujących dwóch przykładach niestandardowych widoków, które rysują obraz w swoich
drawRect
metodach.Po lewej stronie obraz jest odwrócony, a po prawej stronie układ współrzędnych został przetłumaczony i przeskalowany, tak aby początek znajdował się w lewym górnym rogu.
Obraz do góry nogami
Zmodyfikowany układ współrzędnych
źródło
Swift 3.0 i 4.0
Żadna zmiana nie jest wymagana
źródło
Możemy rozwiązać ten problem za pomocą tej samej funkcji:
źródło
drawInRect
jest z pewnością właściwą drogą. Oto kolejna drobna rzecz, która będzie bardzo przydatna podczas tej czynności. Zwykle obraz i prostokąt, do którego ma się dostać, nie są zgodne. W takim przypadkudrawInRect
obraz zostanie rozciągnięty. Oto szybki i fajny sposób, aby upewnić się, że proporcje obrazu nie zostaną zmienione, poprzez odwrócenie transformacji (która będzie pasować do całości):źródło
Swift 3 CoreGraphics Solution
Jeśli chcesz używać CG z dowolnego powodu, zamiast UIImage, ta konstrukcja Swift 3 oparta na poprzednich odpowiedziach rozwiązała dla mnie problem:
źródło
Dzieje się tak, ponieważ QuartzCore ma układ współrzędnych „lewy dolny”, a UIKit - „lewy górny”.
W przypadku, gdy możesz rozszerzyć CGContext :
źródło
Używam tego Swift 5 , czystego rozszerzenia Core Graphics, które poprawnie obsługuje niezerowe początki w prostokątach obrazu:
Możesz użyć go dokładnie tak jak
CGContext
zwykłejdraw(: in:)
metody:źródło
W trakcie mojego projektu Skoczyłem z odpowiedzią Kendalla do odpowiedzi Cliffa aby rozwiązać ten problem w przypadku obrazów, które są ładowane z samego telefonu.
W końcu
CGImageCreateWithPNGDataProvider
zamiast tego użyłem :Nie ma to problemów z orientacją, które można uzyskać od
CGImage
a,UIImage
i może być użyte jako zawartośćCALayer
bez żadnych problemów .źródło
źródło
Szybka odpowiedź 5 oparta na doskonałej odpowiedzi @ ZpaceZombor
Jeśli masz UIImage, po prostu użyj
Jeśli masz CGImage, skorzystaj z mojej kategorii poniżej
Uwaga: W przeciwieństwie do niektórych innych odpowiedzi, ta bierze pod uwagę, że prostokąt, który chcesz narysować, może mieć y! = 0. Te odpowiedzi, które nie biorą tego pod uwagę, są niepoprawne i nie będą działać w ogólnym przypadku.
Użyj w ten sposób:
źródło
Możesz również rozwiązać ten problem, wykonując następujące czynności:
źródło