CGContextDrawImage başaşağı UIImage.CGImage geçtiğinde görüntü çizen

oy
169

Neden bilen var mı CGContextDrawImagebaş aşağı Resmimi çizim olurdu? Benim uygulamadan bir görüntü yüklenirken ediyorum:

UIImage *image = [UIImage imageNamed:@testImage.png];

Sonra sadece benim içeriğe çizmek çekirdek grafikleri soran:

CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);

Doğru yerde kılar, ve boyutlar, ancak görüntü tersine döndü. Burada çok belirgin bir şey eksik olmalı?

Oluştur 03/02/2009 saat 11:23
kaynak kullanıcı
Diğer dillerde...                            


18 cevaplar

oy
218

Yerine

CGContextDrawImage(context, CGRectMake(0, 0, 145, 15), image.CGImage);

kullanım

[image drawInRect:CGRectMake(0, 0, 145, 15)];

Senin başlamak / bitiş ortasında CGcontextyöntemlerle.

Bu, geçerli görüntü bağlamında içine doğru yönlendirme ile görüntü çekecek - Bununla ilgili bir şey var eminim UIImageise oryantasyon bilgisi üzerine tutma CGContextDrawImageyöntemi yöneliminin anlamadan ilişkili ham görüntü verilerini alır.

Eğer birçok alanda bu soruna içine edeceğiz, ama bir spesifik bir örnek adres defteri kullanıcı görüntüleri ile uğraşan unutmayın.

Cevap 06/02/2009 saat 21:46
kaynak kullanıcı

oy
211

Hatta bahsettiğim her şeyi uygulandıktan sonra, hala görüntülerle dramalar yaşadım. Sonunda, ben sadece tüm görüntülerin bir 'çevrilmiş dikey' versiyonunu yaratmak için Gimp kullandım. Şimdi herhangi dönüşümleri kullanmaya gerek yoktur. Umarım bu parça altındaki sorunlara neden olmaz.

CGContextDrawImage baş aşağı Resmimi çizim nedenlerine bilen var mı? Benim uygulamadan bir görüntü yüklenirken ediyorum:

Quartz2d kökenli sol alt köşesinde Farklı koordinat sistemini kullanır. Böylece Kuvars 100 x 100 görüntünün piksel x [5] y [10], o piksel sol alt köşesinde yerine sol üst çizilmiş olan çektiğinde. Bu nedenle, 'ters çevrilmiş imajını neden olur.

Eğer y koordinatlarını çevirmek gerekir böylece x-koordinatı sistemi, eşleşir.

CGContextTranslateCTM(context, 0, image.size.height);

Bu, X ekseni üzerinde 0 birimleri ve y ekseni üzerinde görüntüler yüksekliği ile görüntü tercüme anlamına gelir. Ancak bu tek başına çekilecek hala baş aşağı, sadece onu diliyorum yerin altındaki "image.size.height" çizilmiş olan imajımızı anlamına gelecektir.

Quartz2D programlama kılavuzu ScaleCTM kullanarak ve Resimleri çevirmek negatif değerler geçirmeden önerir. Bunu yapmak için aşağıdaki kodu kullanabilirsiniz -

CGContextScaleCTM(context, 1.0, -1.0);

Sadece daha önce iki birleştirin CGContextDrawImageçağrı ve görüntü doğru çizilmiş olmalıdır.

UIImage *image = [UIImage imageNamed:@"testImage.png"];    
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);       

CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextDrawImage(context, imageRect, image.CGImage);

Eğer istenmeyen sonuçlar alabilirsiniz olarak imageRect koordinatlar, görüntünüzün eşleşmiyor eğer Sadece dikkatli olun.

Koordinatları geri dönüştürmek için:

CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0, -imageRect.size.height);
Cevap 04/02/2009 saat 13:49
kaynak kullanıcı

oy
19

Her iki dünyanın en iyi, UIImage en kullanabilir drawAtPoint:veya drawInRect:yine özel bağlamını belirtilse de:

UIGraphicsPushContext(context);
[image drawAtPoint:CGPointZero]; // UIImage will handle all especial cases!
UIGraphicsPopContext();

Ayrıca birlikte bağlamını değiştirerek önlemek CGContextTranslateCTMveya CGContextScaleCTMhangi ikinci cevap yok.

Cevap 07/08/2013 saat 06:47
kaynak kullanıcı

oy
8

İlgili Quartz2D dokümanlar: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4

Koordinat Sistemi Varsayılan Lanetleme

UIKit çizimde çevirme bir LLO UIKit koordinat sistemi varsayılan koordinat sistemi olan bir çekme ortamı hizalamak için destek CALayer değiştirir. Yalnızca çizim UIKit yöntem ve işlevini kullanırsanız, CTM'yi çevirmek gerekmez. Ancak, Çekirdek Grafik veya Resmi G / Ç fonksiyonu gerekli olabilir CTM'yi saygısız, UIKit çağrıları ile karıştırın eğer.

doğrudan Çekirdek Grafik fonksiyonlarını çağırarak bir resim veya PDF dokümanı çizmek Özellikle, nesne görünümün bağlamda içinde başaşağı oluşturulur. Doğru görüntü ve sayfaları görüntülemek için CTM'yi çevirmek gerekir.

Bir UIKit görünümünde görüntülenen zaman düzgün görünmesine, iki adımda CTM'yi değiştirmelisiniz böylece Çekirdek Grafik bağlamına çizilen bir nesneyi çevirmek için. Sen çizim alanının sol üst köşesine kökeni çevirmek ve sonra -1 ile y-koordinatı değiştirerek, bir ölçek çevirisini geçerlidir. Bunu yapmak için kod aşağıdaki benzer:

CGContextSaveGState(graphicsContext);
CGContextTranslateCTM(graphicsContext, 0.0, imageHeight);
CGContextScaleCTM(graphicsContext, 1.0, -1.0);
CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight));
CGContextRestoreGState(graphicsContext);
Cevap 08/04/2016 saat 06:11
kaynak kullanıcı

oy
7

Ben emin değilim UIImageama koordinatlar çevirdi zaman bu tür bir davranış genellikle oluşur. Koordinat OS X sistemlerin çoğu Postscript ve PDF gibi sol alt köşesinde kökenlerine sahip. Ama CGImagesistem sol üst köşesinde aslına vardır koordinat.

Olası çözeltiler içerebilir isFlippedözellik veya bir scaleYBy:-1afin dönüşümü.

Cevap 03/02/2009 saat 11:34
kaynak kullanıcı

oy
6

Herkes bir bağlamda özel bir rect bir görüntü çizmek için no-beyin çözümü ile ilgilenen ise:

 func drawImage(image: UIImage, inRect rect: CGRect, context: CGContext!) {

    //flip coords
    let ty: CGFloat = (rect.origin.y + rect.size.height)
    CGContextTranslateCTM(context, 0, ty)
    CGContextScaleCTM(context, 1.0, -1.0)

    //draw image
    let rect__y_zero = CGRect(origin: CGPoint(x: rect.origin.x, y:0), size: rect.size)
    CGContextDrawImage(context, rect__y_zero, image.CGImage)

    //flip back
    CGContextScaleCTM(context, 1.0, -1.0)
    CGContextTranslateCTM(context, 0, -ty)

}

görüntü rect doldurmak için ölçeklenir.

Cevap 18/02/2016 saat 14:20
kaynak kullanıcı

oy
3

Swift 3.0 & 4.0

yourImage.draw(in: CGRect, blendMode: CGBlendMode, alpha: ImageOpacity)

gerekmez Değişim

Cevap 04/08/2017 saat 10:41
kaynak kullanıcı

oy
3

Aynı işlevi kullanarak bu sorunu çözebilir:

UIGraphicsBeginImageContext(image.size);

UIGraphicsPushContext(context);

[image drawInRect:CGRectMake(gestureEndPoint.x,gestureEndPoint.y,350,92)];

UIGraphicsPopContext();

UIGraphicsEndImageContext();
Cevap 25/08/2011 saat 07:27
kaynak kullanıcı

oy
3

UIImageihtiva eden bir CGImageana içerik üyesi olarak ölçekleme ve yönlendirme faktörler gibi. Bu yana CGImageçeşitli fonksiyonları OS X elde edilir ve bu bir ters iPhone karşılaştırılır koordinat sistemi bekler. Bir oluştururken UIImagetelafi etmek ters bir yönde, varsayılan (sizin! Bu değiştirebilirsiniz). Kullan . CGImagemülkiyet çok güçlü erişmek için CGImagefonksiyonlar, ancak iPhone ekranı vb üzerine çizim ile en iyi şekilde yapılır UIImageyöntemlerle.

Cevap 01/08/2010 saat 00:26
kaynak kullanıcı

oy
2

Swift kodu ile Ek cevap

Kuvars 2D grafik iOS'deki UIKit sol üst kısmında kökene sahip bir koordinat sistemi kullanır iken sol alt kısmında kökene sahip bir koordinat sistemi kullanın. Her şey genellikle iyi çalışır ancak bazı grafik işlemlerini yaparken, sen sistemi kendini koordine değiştirmek zorundayız. Dokümantasyon durumları:

Bazı teknolojiler farklı bir varsayılan Kuvars kullandığı olandan koordinat sistemi kullanarak grafik bağlamları kurdu. Kuvars ile karşılaştırıldığında, bu tür bir koordinat sistemi, bir koordinat modifiye edilmiş bir sistem olup, bir kuvars çizim işlemleri gerçekleştirirken telafi edilmelidir. koordinat sistemi modifiye en yaygın bağlamda sol üst köşesinde kökeni yerleri ve sayfanın alt tarafına doğru y-ekseni değiştirir.

Bu olgu onların bir görüntü çizmek Özel görünümlerin aşağıdaki iki durumda görülebilir drawRectyöntemlerle.

Burada görüntü açıklama girin

Sol tarafta, görüntü baş aşağıdır ve kökeni sol üst olacak şekilde sağ tarafta koordinat sistemi tercüme ve ölçekli edilmiştir.

Baş aşağı görüntü

override func drawRect(rect: CGRect) {

    // image
    let image = UIImage(named: "rocket")!
    let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)

    // context
    let context = UIGraphicsGetCurrentContext()

    // draw image in context
    CGContextDrawImage(context, imageRect, image.CGImage)

}

koordinat sistemi Modifiye

override func drawRect(rect: CGRect) {

    // image
    let image = UIImage(named: "rocket")!
    let imageRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)

    // context
    let context = UIGraphicsGetCurrentContext()

    // save the context so that it can be undone later
    CGContextSaveGState(context)

    // put the origin of the coordinate system at the top left
    CGContextTranslateCTM(context, 0, image.size.height)
    CGContextScaleCTM(context, 1.0, -1.0)

    // draw the image in the context
    CGContextDrawImage(context, imageRect, image.CGImage)

    // undo changes to the context
    CGContextRestoreGState(context)
}
Cevap 22/12/2015 saat 03:25
kaynak kullanıcı

oy
1

drawInRectkesinlikle gitmek yoludur. İşte Bunu yaparken de yolu kullanışlı gelecektir başka küçük bir şey. Genellikle resim ve uymayan gidecek içine dikdörtgen. Bu durumda drawInRectresmi uzatmak olacaktır. Resmin görüntü oranı dönüşümü (içinde her şeyi sığdırmak için olacak) tersine çevirerek, değişmez olduğunu Burada emin olmak için hızlı ve serin yolu şudur:

//Picture and irect don't conform, so there'll be stretching, compensate
    float xf = Picture.size.width/irect.size.width;
    float yf = Picture.size.height/irect.size.height;
    float m = MIN(xf, yf);
    xf /= m;
    yf /= m;
    CGContextScaleCTM(ctx, xf, yf);

    [Picture drawInRect: irect];
Cevap 22/02/2010 saat 06:57
kaynak kullanıcı

oy
0

"Sol üst" - UIKit ederken QuartzCore, koordinat sistemi "alt-sol" vardır diye bir şey yok.

Eğer uzatabilirsiniz CGContext :

extension CGContext {
  func changeToTopLeftCoordinateSystem() {
    translateBy(x: 0, y: boundingBoxOfClipPath.size.height)
    scaleBy(x: 1, y: -1)
  }
}

// somewhere in render 
ctx.saveGState()
ctx.changeToTopLeftCoordinateSystem()
ctx.draw(cgImage!, in: frame)
Cevap 30/09/2019 saat 11:28
kaynak kullanıcı

oy
0

Swift 5 cevap @ ZpaceZombor dayalı mükemmel bir cevap

Eğer bir UIImage varsa, sadece kullanmak

var image: UIImage = .... 
image.draw(in: CGRect)

Eğer bir CGImage varsa aşağıda benim kategorisini kullanmak

Not: Bazı diğer cevaplar aksine, bu istediğiniz rect y olabilir çekmek için bu hesaba katar = 0. hesaba o yanlıştır yapmayız ve genel durumda işe yaramaz olanlar cevapları!.

extension CGContext {
    final func drawImage(image: CGImage, inRect rect: CGRect) {

        //flip coords
        let ty: CGFloat = (rect.origin.y + rect.size.height)
        translateBy(x: 0, y: ty)
        scaleBy(x: 1.0, y: -1.0)

        //draw image
        let rect__y_zero = CGRect(x: rect.origin.x, y: 0, width: rect.width, height: rect.height)
        draw(image, in: rect__y_zero)

        //flip back
        scaleBy(x: 1.0, y: -1.0)
        translateBy(x: 0, y: -ty)

    }
} 

Böyle kullanın:

let imageFrame: CGRect = ...
let context: CGContext = ....
let img: CGImage = ..... 
context.drawImage(image: img, inRect: imageFrame)
Cevap 20/09/2019 saat 10:24
kaynak kullanıcı

oy
0
func renderImage(size: CGSize) -> UIImage {
    return UIGraphicsImageRenderer(size: size).image { rendererContext in
        // flip y axis
        rendererContext.cgContext.translateBy(x: 0, y: size.height)
        rendererContext.cgContext.scaleBy(x: 1, y: -1)

        // draw image rotated/offsetted
        rendererContext.cgContext.saveGState()
        rendererContext.cgContext.translateBy(x: translate.x, y: translate.y)
        rendererContext.cgContext.rotate(by: rotateRadians)
        rendererContext.cgContext.draw(cgImage, in: drawRect)
        rendererContext.cgContext.restoreGState()
    }
}
Cevap 03/05/2018 saat 12:06
kaynak kullanıcı

oy
0

Swift 3 CoreGraphics Çözüm

Eğer sebebi ne olursa olsun için CG, yerine UIImage kullanmak istiyorsanız, önceki cevaplara bağlı bu Swift 3 inşaat için beni sorunu çözmek yaptı:

if let cgImage = uiImage.cgImage {
    cgContext.saveGState()
    cgContext.translateBy(x: 0.0, y: cgRect.size.height)
    cgContext.scaleBy(x: 1.0, y: -1.0)
    cgContext.draw(cgImage, in: cgRect)
    cgContext.restoreGState()
}
Cevap 31/08/2017 saat 20:05
kaynak kullanıcı

oy
0

Projemin boyunca buradaki atlayan Kendall cevap için Cliff'in cevap telefondan kendisinden yüklenen görüntüler için bu sorunu çözmek için.

Sonunda kullanarak sona erdi CGImageCreateWithPNGDataProvideryerine:

NSString* imageFileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"clockdial.png"];

return CGImageCreateWithPNGDataProvider(CGDataProviderCreateWithFilename([imageFileName UTF8String]), NULL, YES, kCGRenderingIntentDefault);

Bu girmesini alacağı oryantasyon sorunları muzdarip değil CGImagebir den UIImageve bir içeriklerinden olarak kullanılabilecek CALayerbir aksamadan.

Cevap 15/03/2014 saat 17:13
kaynak kullanıcı

Cevap 26/11/2009 saat 13:24
kaynak kullanıcı

oy
-5

Ayrıca böyle yaparak bu sorunu çözebilir:

//Using an Image as a mask by directly inserting UIImageObject.CGImage causes
//the same inverted display problem. This is solved by saving it to a CGImageRef first.

//CGImageRef image = [UImageObject CGImage];

//CGContextDrawImage(context, boundsRect, image);

Nevermind... Stupid caching.
Cevap 04/04/2012 saat 02:55
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more