CGContextDrawImage felhívja a képet fejjel lefelé, amikor telt UIImage.CGImage

szavazat
169

Tudja valaki, hogy miért CGContextDrawImagelenne felhívta a képet fejjel lefelé? Én betöltése egy képet az én alkalmazás:

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

És akkor egyszerűen megkérdezi core grafika felhívni, hogy az én összefüggésben:

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

Ez teszi a megfelelő helyen, és a méretek, de a kép fejjel lefelé van. Azt kell, hogy hiányzik valami igazán nyilvánvaló itt?

A kérdést 03/02/2009 11:23
a forrás felhasználó
Más nyelveken...                            


18 válasz

szavazat
218

Ahelyett

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

Használat

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

A közepén a kezdet / vég CGcontextmódszerekkel.

Ez felhívja a képet a megfelelő orientációban az aktuális kép összefüggésben - Biztos vagyok benne, ennek valami köze a UIImagekapaszkodott ismerete orientáció, miközben a CGContextDrawImagemódszer kapja a mögöttes nyers képadatok nem értette a tájolást.

Jó tudni, hogy befut ez a probléma sok területen, de egy konkrét példát foglalkozik címjegyzékben felhasználói képek.

Válaszolt 06/02/2009 21:46
a forrás felhasználó

szavazat
211

Még alkalmazása után mindaz, amit említettem, én már mindig volt drámák a képeket. A végén, én már csak használt Gimp hogy hozzon létre egy „tükrözött vertikális” változata az összes képeim. Most már nem kell használni minden átváltozik. Remélhetőleg ez nem okoz további problémákat le a pályán.

Tudja valaki, hogy miért CGContextDrawImage lenne felhívta a képet fejjel lefelé? Én betöltése egy képet az én alkalmazás:

Quartz2d használ egy másik koordináta-rendszerben, ahol az eredet, a bal alsó sarokban. Tehát amikor Kvarc felhívja pixel x [5], Y [10] egy 100 * 100 kép, hogy a pixel van húzva a bal alsó sarokban helyett a bal felső. Így okozva a „tükrözött” képet.

Az x koordináta-rendszere illeszkedik, így szükség lesz a flip y koordinátáit.

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

Ez azt jelenti, hogy lefordította a képet 0 egység az x tengelyen, valamint a képek magassága az y tengelyen. Azonban ez önmagában azt jelenti, mi kép még mindig fejjel lefelé, éppen most húzott „image.size.height” alul, ahol szeretnénk, hogy kell elkészíteni.

A Quartz2D programozási útmutató javasolja ScaleCTM és halad a negatív értékek tükrözik a képet. Használhatja az alábbi kódot, hogy ezt -

CGContextScaleCTM(context, 1.0, -1.0);

Keverjük össze a két, mielőtt a CGContextDrawImagehívást, és akkor a kép készült helyesen.

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

Csak vigyázz, ha a imageRect koordinátáit nem egyeznek meg a kép, ahogy tud kívánt eredményeket.

Átalakítani vissza a koordinátákat:

CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0, -imageRect.size.height);
Válaszolt 04/02/2009 13:49
a forrás felhasználó

szavazat
19

Mindkét világból a legjobbat, használja UIImage féle drawAtPoint:vagy drawInRect:, miközben továbbra is meghatározza az egyéni háttér:

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

Szintén kerülni a módosításával az kontextus CGContextTranslateCTMvagy CGContextScaleCTMamely a második válasz nem.

Válaszolt 07/08/2013 06:47
a forrás felhasználó

szavazat
8

Releváns Quartz2D docs: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4

Essek Az alapértelmezett koordináta-rendszer

Essek a UIKit rajz módosítja a hátlap CALayer összehangolni a rajzkörnyezetet amelynek LLO koordinátarendszer az alapértelmezett koordináta-rendszerében UIKit. Ha csak UIKit módszereket és funkció rajz, akkor nem kell, hogy fordítsa meg a CTM. Azonban, ha összekeverjük Core Graphics vagy fényképek I / O művelet hívja a UIKit hívásokat, essek a CTM lehet szükség.

Pontosabban, ha készít egy képet vagy PDF dokumentum hívja Core Graphics funkció közvetlenül a tárgy teszi fejjel lefelé a nézet összefüggésben. Meg kell fordítanod a CTM a kép megjelenítéséhez és oldalak helyesen.

A flip egy tárgyat húzott egy Core Graphics összefüggésben, hogy helyesen jelenjen meg, amikor megjelenik egy UIKit nézetben, módosítani kell a CTM két lépésben. Lefordítani eredetét a bal felső sarokban a rajz területen, majd alkalmazza skálán fordítás, módosítja az y-koordináta által -1. A kód ezt hasonlít a következő:

CGContextSaveGState(graphicsContext);
CGContextTranslateCTM(graphicsContext, 0.0, imageHeight);
CGContextScaleCTM(graphicsContext, 1.0, -1.0);
CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight));
CGContextRestoreGState(graphicsContext);
Válaszolt 08/04/2016 06:11
a forrás felhasználó

szavazat
7

Nem vagyok benne biztos számára UIImage, de ez a fajta viselkedés általában akkor fordul elő, ha a koordinátákat tükrözött. A legtöbb OS X koordináta rendszerek eredete a bal alsó sarokban, mint a Postscript és PDF. De CGImagekoordináta-rendszer eredete a bal felső sarokban.

Lehetséges megoldások járhat egy isFlippedtulajdonság vagy egy scaleYBy:-1affin transzformáció.

Válaszolt 03/02/2009 11:34
a forrás felhasználó

szavazat
6

Ha valaki érdeklődik egy nem-agy megoldás rajz egy képet egy egyéni len olyan összefüggésben:

 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)

}

A képet méretezni, hogy töltse ki a len.

Válaszolt 18/02/2016 14:20
a forrás felhasználó

szavazat
3

Swift 3.0 & 4.0

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

Nem szükséges módosítása

Válaszolt 04/08/2017 10:41
a forrás felhasználó

szavazat
3

Mi lehet megoldani ezt a problémát ugyanaz a funkciója:

UIGraphicsBeginImageContext(image.size);

UIGraphicsPushContext(context);

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

UIGraphicsPopContext();

UIGraphicsEndImageContext();
Válaszolt 25/08/2011 07:27
a forrás felhasználó

szavazat
3

UIImagetartalmaz CGImage, mint a fő tartalmi elem, valamint a méretezés és orientáció tényezők. Mivel CGImageés különféle funkciók származó OSX elvárja, hogy egy koordináta-rendszert, amely fejjel lefelé, mint az iPhone. Amikor létrehoz egy UIImage, az alapértelmezett a fejjel lefelé helyzetben, hogy kompenzálja (meg lehet változtatni ezt!). Használja a . CGImagetulajdonság eléréséhez nagyon erős CGImagefunkciókat, de a rajz rá az iPhone képernyőjén, stb lehet a legjobban elvégezni a UIImagemódszereket.

Válaszolt 01/08/2010 00:26
a forrás felhasználó

szavazat
2

Kiegészítő választ Swift kód

Quartz 2D grafikus egy koordinátarendszert az origó a bal alsó sarokban, miközben UIKit iOS használ koordinátarendszer eredetére a bal felső sarokban. Minden általában jól működik, de amikor egy bizonyos grafikai műveleteket, akkor módosítania kell a koordináta-rendszer magad. A dokumentáció kimondja:

Egyes technológiák létre a grafikus környezetben egy másik alapértelmezett koordináta-rendszerben, mint az egyik által használt Quartz. Relatív, hogy Quartz, mint egy koordináta-rendszer egy módosított koordinátarendszer és kompenzálni kell, ha végrehajt bizonyos Quartz húzási művelet során. A leggyakoribb módosított koordinátarendszerben helyezi a származási bal felső sarokban a kontextus, és megváltoztatja az y tengely irányába mutatnak az az oldal alján.

Ez a jelenség látható az alábbi két esetben egyéni nézetek, hogy dolgozzon egy képet a saját drawRectmódszereit.

írja kép leírása itt

A bal oldalon, a kép fejjel lefelé és a jobb oldalon a koordináta-rendszer lett fordítva, és méretezhető, hogy az eredet a bal felső sarokban.

Fejjel lefelé képet

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)

}

Módosított koordinátarendszer

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)
}
Válaszolt 22/12/2015 03:25
a forrás felhasználó

szavazat
1

drawInRectminden bizonnyal az út. Itt van egy másik kis dolog, hogy jön a módja hasznos, ha ezt. Általában a képet, és a téglalap, amelynek azt fog menni nem felelnek. Ebben az esetben drawInRectmegnyúlik a kép. Íme egy gyors és jó módja annak, hogy megbizonyosodjon arról, hogy a kép oldalarányban nem változik, megfordítva a transzformáció (amely az lesz, hogy illeszkedjen az egészet):

//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];
Válaszolt 22/02/2010 06:57
a forrás felhasználó

szavazat
0

Ez azért történik, mert QuartzCore van a koordináta-rendszer „bal alsó”, míg UIKit - „bal felső”.

Abban az esetben, ha kiterjeszti 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)
Válaszolt 30/09/2019 11:28
a forrás felhasználó

szavazat
0

Swift 5 válasz alapján @ ZpaceZombor ez remek válasz

Ha van egy UIImage, csak használja

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

Ha van egy CGImage használni a kategória az alábbi

Megjegyzés: Ellentétben néhány más választ, ezt figyelembe vesszük, hogy a len szeretné felhívni a meglehet van y! = 0. Ezek a választ, hogy nem vette figyelembe a helytelen, és nem fog működni az általános esetben.

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)

    }
} 

Használd, mint ez:

let imageFrame: CGRect = ...
let context: CGContext = ....
let img: CGImage = ..... 
context.drawImage(image: img, inRect: imageFrame)
Válaszolt 20/09/2019 10:24
a forrás felhasználó

szavazat
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()
    }
}
Válaszolt 03/05/2018 12:06
a forrás felhasználó

szavazat
0

Swift 3 CoreGraphics megoldás

Ha a használni kívánt CG Bármi lehet, ahelyett, UIImage ez Swift 3 építési alapuló korábbi válaszokat nem oldaná meg a problémát számomra:

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()
}
Válaszolt 31/08/2017 20:05
a forrás felhasználó

szavazat
0

Során a projektem átugrottam Kendall válasza , hogy Cliff válasza , hogy megoldja ezt a problémát a képek betöltött a telefon is.

A végén én végül a CGImageCreateWithPNGDataProviderhelyett:

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

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

Ez nem szenvednek az orientációs problémák, amit kapnánk a szerzés az CGImageegy UIImageés akkor lehet használni, mint a tartalmát egy CALayerzökkenőmentesen.

Válaszolt 15/03/2014 17:13
a forrás felhasználó

Válaszolt 26/11/2009 13:24
a forrás felhasználó

szavazat
-5

Azt is megoldani ezt a problémát azáltal, hogy ezt:

//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.
Válaszolt 04/04/2012 02:55
a forrás felhasználó

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