CGContextDrawImage छवि खींचता है उल्टा जब UIImage.CGImage पारित कर दिया

वोट
169

क्या किसी को पता है कि क्यों CGContextDrawImageमेरी छवि उल्टा ड्राइंग किया जाएगा? मैं अपने आवेदन से में एक छवि लोड हो रहा है कर रहा हूँ:

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

और फिर बस कोर ग्राफिक्स पूछ मेरे संदर्भ के लिए यह आकर्षित करने के लिए:

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

यह सही जगह में प्रस्तुत हुई है, और आयाम है, लेकिन छवि उल्टा है। मैं यहाँ वास्तव में कुछ स्पष्ट याद आ रही किया जाना चाहिए?

03/02/2009 को 11:23
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


18 जवाब

वोट
218

के बजाय

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

उपयोग

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

अपने शुरू / अंत के बीच में CGcontextतरीकों।

यह आपके वर्तमान छवि संदर्भ में सही ओरिएंटेशन के साथ छवि आकर्षित करेगा - मैं बहुत यकीन है कि यह साथ क्या करने के लिए कुछ है कर रहा हूँ UIImage, जबकि उन्मुखीकरण के ज्ञान पर पकड़े CGContextDrawImageविधि उन्मुखीकरण का कोई समझ के साथ उपलब्ध अपरिष्कृत छवि डेटा हो जाता है।

ध्यान दें कि आप कई क्षेत्रों में इस समस्या में पड़ जाएगा, लेकिन एक विशिष्ट उदाहरण पता पुस्तिका उपयोगकर्ता छवियों के साथ काम कर रहा है।

06/02/2009 को 21:46
का स्रोत उपयोगकर्ता

वोट
211

यहां तक ​​कि सब कुछ मैं उल्लेख किया है लागू करने के बाद, मैं अभी भी छवियों के साथ नाटक किया है। अंत में, मैं सिर्फ एक 'फ़्लिप ऊर्ध्वाधर' मेरे सभी छवियों के संस्करण बनाने के लिए Gimp का उपयोग किया है। अब मैं किसी भी Transforms उपयोग करने की आवश्यकता नहीं है। उम्मीद है कि इस ट्रैक नीचे आगे समस्याओं का कारण नहीं होगा।

क्या किसी को पता है कि क्यों CGContextDrawImage उल्टा मेरी छवि ड्राइंग किया जाएगा? मैं अपने आवेदन से में एक छवि लोड हो रहा है कर रहा हूँ:

Quartz2d एक अलग समन्वय प्रणाली है, जहां मूल निचले बाएँ कोने में है का उपयोग करता है। तो जब क्वार्ट्ज ड्रॉ पिक्सेल एक्स [5], वाई [10] एक 100 * 100 छवि के, कि पिक्सेल निचले बाएँ बजाय कोने ऊपरी बाएँ में तैयार की जा रही है। इस प्रकार 'फ़्लिप' छवि के कारण।

एक्स समन्वय प्रणाली, से मेल खाता है तो आप y समन्वय फ्लिप करने की आवश्यकता होगी।

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

इसका मतलब यह है कि हम एक्स अक्ष पर 0 इकाइयों द्वारा और y अक्ष पर छवियों ऊंचाई से छवि का अनुवाद किया है। बहरहाल, यह अकेले अभी भी उल्टा, बस तैयार की जा रही है नीचे जहाँ हम यह चाहते हैं "image.size.height" हमारी छवि का मतलब होगा तैयार हो।

Quartz2D प्रोग्रामिंग गाइड ScaleCTM का उपयोग कर और नकारात्मक मान पास छवि फ्लिप करने की सिफारिश की गई। ऐसा करने के लिए निम्नलिखित कोड का उपयोग कर सकते हैं -

CGContextScaleCTM(context, 1.0, -1.0);

बस अपने पहले दो कम्बाइन CGContextDrawImageकॉल और आप छवि को सही ढंग से तैयार होना चाहिए।

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

बस सावधान यदि आपका imageRect समन्वय, अपनी छवि के विवरणों से मेल नहीं के रूप में आप अनायास ही परिणाम प्राप्त कर सकते हो।

वापस निर्देशांक बदलने के लिए:

CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0, -imageRect.size.height);
04/02/2009 को 13:49
का स्रोत उपयोगकर्ता

वोट
19

दोनों दुनिया के सर्वश्रेष्ठ, UIImage का उपयोग करें drawAtPoint:या drawInRect:, जबकि अभी भी अपने कस्टम संदर्भ को निर्दिष्ट:

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

इसके अलावा, आप के साथ अपने संदर्भ को संशोधित करने से बचने CGContextTranslateCTMया CGContextScaleCTMजो दूसरी जवाब नहीं करता है।

07/08/2013 को 06:47
का स्रोत उपयोगकर्ता

वोट
8

प्रासंगिक Quartz2D डॉक्स: https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html#//apple_ref/doc/uid/TP40010156-CH14-SW4

डिफ़ॉल्ट flipping निर्देशांक प्रणाली

UIKit ड्राइंग में flipping एक Llo समन्वय डिफ़ॉल्ट के साथ प्रणाली UIKit की समन्वय प्रणाली होने एक ड्राइंग पर्यावरण संरेखित करने के लिए समर्थन CALayer संशोधित करता है। आप केवल ड्राइंग के लिए UIKit तरीकों और फ़ंक्शन का उपयोग करें, तो आप CTM फ्लिप करने की जरूरत नहीं होनी चाहिए। हालांकि, अगर आप कोर ग्राफिक्स या छवि आई / ओ समारोह CTM flipping आवश्यक हो सकता है, UIKit कॉल के साथ कॉल मिश्रण है।

विशेष रूप से, अगर आप कोर ग्राफिक्स कार्यों सीधे फोन करके एक छवि या पीडीएफ दस्तावेज़ आकर्षित, वस्तु को देखने के संदर्भ में उलटा प्रदान की गई है। आप CTM सही ढंग से छवि और पृष्ठों को प्रदर्शित करने फ्लिप चाहिए।

एक वस्तु एक कोर ग्राफिक्स संदर्भ के लिए तैयार है, तो यह सही ढंग से प्रतीत होता है कि जब एक UIKit दृश्य में प्रदर्शित है, तो आप दो चरणों में CTM संशोधित करना होगा से घुमाने के लिए। आप ड्राइंग क्षेत्र के ऊपरी-बाएं कोने करने के लिए मूल का अनुवाद, और फिर आप पैमाने अनुवाद लागू होते हैं, को संशोधित -1 से y- निर्देशांक। ऐसा करने के लिए कोड निम्नलिखित जैसा दिखता है:

CGContextSaveGState(graphicsContext);
CGContextTranslateCTM(graphicsContext, 0.0, imageHeight);
CGContextScaleCTM(graphicsContext, 1.0, -1.0);
CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight));
CGContextRestoreGState(graphicsContext);
08/04/2016 को 06:11
का स्रोत उपयोगकर्ता

वोट
7

मैं के लिए यकीन नहीं है UIImage, लेकिन इस तरह का व्यवहार आम तौर पर जब निर्देशांक फ़्लिप कर रहे हैं होता है। ओएस एक्स के अधिकांश समन्वय प्रणाली पोस्टस्क्रिप्ट और पीडीएफ के रूप में, निचले बाएँ कोने में अपने मूल है। लेकिन CGImageसमन्वय प्रणाली ऊपरी बाएँ कोने में अपने मूल है।

संभावित समाधान एक शामिल हो सकता है isFlippedसंपत्ति या एक scaleYBy:-1affine बदलना।

03/02/2009 को 11:34
का स्रोत उपयोगकर्ता

वोट
6

अगर कोई एक संदर्भ में एक कस्टम रेक्ट में एक छवि ड्राइंग के लिए एक नहीं brainer समाधान में रुचि रखता है:

 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)

}

छवि रेक्ट को भरने के लिए बदल दिया जाएगा।

18/02/2016 को 14:20
का स्रोत उपयोगकर्ता

वोट
3

स्विफ्ट 3.0 और 4.0

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

कोई बदलाव की जरूरत

04/08/2017 को 10:41
का स्रोत उपयोगकर्ता

वोट
3

हम एक ही समारोह का उपयोग कर इस समस्या को हल कर सकते हैं:

UIGraphicsBeginImageContext(image.size);

UIGraphicsPushContext(context);

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

UIGraphicsPopContext();

UIGraphicsEndImageContext();
25/08/2011 को 07:27
का स्रोत उपयोगकर्ता

वोट
3

UIImageशामिल एक CGImageअपने मुख्य सामग्री सदस्य के साथ ही स्केलिंग और अभिविन्यास कारक के रूप में। के बाद से CGImageऔर इसके विभिन्न कार्यों OSX से प्राप्त कर रहे हैं, यह एक समन्वय प्रणाली है कि उल्टा iPhone की तुलना में उम्मीद है। जब आप एक बनाने UIImageकी भरपाई के लिए, यह एक उलटा उन्मुखीकरण के लिए डिफ़ॉल्ट (आप इसे बदल सकते हैं!)। उपयोग । CGImageसंपत्ति बहुत शक्तिशाली उपयोग करने के लिए CGImageकाम करता है, लेकिन iPhone स्क्रीन आदि पर ड्राइंग सबसे अच्छा के साथ किया है UIImageतरीकों।

01/08/2010 को 00:26
का स्रोत उपयोगकर्ता

वोट
2

स्विफ्ट कोड के साथ पूरक जवाब

क्वार्ट्ज 2 डी ग्राफिक्स तल में मूल के साथ एक समन्वय प्रणाली का उपयोग छोड़ दिया, जबकि आईओएस में UIKit ऊपरी बाईं ओर स्थित मूल के साथ एक समन्वय प्रणाली का उपयोग करता है। सब कुछ आम तौर पर ठीक काम करता है, लेकिन जब कुछ ग्राफिक्स संचालन कर रही है, आप अपने आप को समन्वय प्रणाली को संशोधित करने के लिए है। प्रलेखन कहता है:

कुछ प्रौद्योगिकियों भिन्न डिफ़ॉल्ट समन्वय क्वार्ट्ज द्वारा इस्तेमाल किया एक से प्रणाली का उपयोग कर अपने ग्राफिक्स संदर्भों की स्थापना की। क्वार्ट्ज के सापेक्ष, इस तरह के एक समन्वय प्रणाली एक संशोधित समन्वय प्रणाली है और जब कुछ क्वार्ट्ज ड्राइंग ऑपरेशनों को करने के लिए मुआवजा दिया जाना चाहिए। सबसे आम समन्वय प्रणाली संशोधित संदर्भ के ऊपरी-बाएं कोने में मूल स्थानों और y- अक्ष में परिवर्तन पृष्ठ के नीचे की ओर इंगित करने के लिए।

यह घटना है कि उनके में एक छवि आकर्षित कस्टम दृश्य के निम्नलिखित दो मामलों में देखा जा सकता है drawRectतरीकों।

यहाँ छवि विवरण दर्ज

बाईं ओर, छवि उलझा रहा है और सही पक्ष पर समन्वय प्रणाली अनुवाद किया गया है और उनके आकलन के लिए इतना है कि मूल ऊपर बाईं ओर में है।

उलटा छवि

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)

}

संशोधन समन्वय प्रणाली

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)
}
22/12/2015 को 03:25
का स्रोत उपयोगकर्ता

वोट
1

drawInRectनिश्चित रूप से जाने के लिए रास्ता है। यहाँ एक और छोटी सी बात यह है कि जिस तरह से में उपयोगी आ जाएगा जब यह कर रहा है। आमतौर पर चित्र और आयत जिसमें यह अनुरूप नहीं है जाने के लिए जा रहा है। उस मामले में drawInRectचित्र खिंचाव जाएगा। यहाँ सुनिश्चित करने के लिए एक त्वरित और अच्छा तरीका है कि तस्वीर के पहलू राशन परिवर्तन (जिसमें पूरी बात फिट करने के लिए किया जाएगा) उलट कर, नहीं बदला गया है:

//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];
22/02/2010 को 06:57
का स्रोत उपयोगकर्ता

वोट
0

यह इसलिए होता है क्योंकि QuartzCore, समन्वय प्रणाली "निचले बाएं" है, जबकि UIKit - "ऊपर से छोड़ दिया"।

मामले में आप विस्तार कर सकते हैं 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)
30/09/2019 को 11:28
का स्रोत उपयोगकर्ता

वोट
0

स्विफ्ट 5 जवाब @ ZpaceZombor के आधार पर उत्कृष्ट जवाब

यदि आप एक UIImage है, तो बस का उपयोग

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

यदि आप एक CGImage है, तो नीचे मेरी श्रेणी का उपयोग करें

नोट: कुछ अन्य उत्तर विपरीत यह ध्यान में रखा जाता है कि रेक्ट आप चाहते हैं में आकर्षित करने के लिए y हो सकता है = 0. उन जवाब है कि नहीं लेते कि खाते में सही नहीं हैं और सामान्य स्थिति में काम नहीं करेगा!।

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)

    }
} 

इस तरह का उपयोग करें:

let imageFrame: CGRect = ...
let context: CGContext = ....
let img: CGImage = ..... 
context.drawImage(image: img, inRect: imageFrame)
20/09/2019 को 10:24
का स्रोत उपयोगकर्ता

वोट
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()
    }
}
03/05/2018 को 12:06
का स्रोत उपयोगकर्ता

वोट
0

स्विफ्ट 3 CoreGraphics समाधान

आप जो कुछ भी तटरक्षक के लिए अपने कारण हो सकता है, बजाय UIImage का उपयोग करना चाहते हैं, तो यह स्विफ्ट 3 निर्माण पिछले उत्तरों के आधार मेरे लिए इस मुद्दे को हल किया:

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()
}
31/08/2017 को 20:05
का स्रोत उपयोगकर्ता

वोट
0

अपने प्रोजेक्ट के दौरान मैं से कूद केंडल के जवाब के लिए क्लिफ के जवाब छवियों है कि फोन से ही लोड किए गए हैं के लिए इस समस्या को हल करने के लिए।

अंत में मैं का उपयोग कर समाप्त हो गया CGImageCreateWithPNGDataProviderके बजाय:

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

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

इस उन्मुखीकरण के मुद्दों है कि आप को प्राप्त करने से मिलेगा से ग्रस्त नहीं है CGImageएक से UIImageहै और यह एक की सामग्री के रूप में इस्तेमाल किया जा सकता CALayerबिना किसी अवरोध के।

15/03/2014 को 17:13
का स्रोत उपयोगकर्ता

26/11/2009 को 13:24
का स्रोत उपयोगकर्ता

वोट
-5

तुम भी ऐसा करने से इस समस्या का समाधान कर सकते हैं:

//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.
04/04/2012 को 02:55
का स्रोत उपयोगकर्ता

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