문제

그 이유를 아는 사람이 있습니까? CGContextDrawImage 내 이미지를 거꾸로 그릴까요? 응용 프로그램에서 이미지를로드하고 있습니다.

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

그런 다음 핵심 그래픽을 내 컨텍스트로 그려달라고 요청합니다.

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

올바른 위치와 치수로 렌더링되지만 이미지는 거꾸로됩니다. 여기서 정말 명백한 것을 놓치고 있을까요?

도움이 되었습니까?

해결책

대신에

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

사용

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

시작/끝의 중간에 CGcontext 행동 양식.

이것은 현재 이미지 컨텍스트에 올바른 방향으로 이미지를 그릴 것입니다. UIImage 오리엔테이션에 대한 지식을 붙잡고 있습니다 CGContextDrawImage 방법은 방향을 이해하지 않고 기본 원시 이미지 데이터를 가져옵니다.

많은 영역 에서이 문제가 발생하지만 특정 예는 주소록 사용자 이미지를 다루는 것입니다.

다른 팁

내가 언급 한 모든 것을 적용한 후에도 여전히 이미지와 함께 드라마가있었습니다. 결국, 나는 방금 GIMP를 사용하여 모든 이미지의 '뒤집힌 수직'버전을 만들었습니다. 이제 변환을 사용할 필요가 없습니다. 바라건대 이것은 트랙에서 더 많은 문제를 일으키지 않을 것입니다.

CGContextDrawImage가 왜 내 이미지를 거꾸로 끌어 올리는지 아는 사람이 있습니까? 응용 프로그램에서 이미지를로드하고 있습니다.

Quartz2d는 원점이 왼쪽 하단에있는 다른 코디네이션 시스템을 사용합니다. 따라서 쿼츠가 100 * 100 이미지의 픽셀 X [5], Y [10]를 그릴 때, 그 픽셀은 왼쪽 상단 대신 왼쪽 하단 모서리에 그려지고 있습니다. 따라서 '뒤집는'이미지를 유발합니다.

X 코디네이트 시스템이 일치하므로 Y 코디네이션을 뒤집어 야합니다.

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

즉, X 축의 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);

두 세계 모두에서 Uiimage를 사용하십시오 drawAtPoint: 또는 drawInRect: 여전히 사용자 정의 컨텍스트를 지정하는 동안 :

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

또한 컨텍스트를 수정하지 마십시오 CGContextTranslateCTM 또는 CGContextScaleCTM 두 번째 대답이하는 일.

관련 쿼츠 2D 문서 : https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/graphicsDrawingOverView/GraphicsDrawingOverView.html#//apple_ref/doc/uid/tp40010156-ch14-sw4

기본 좌표계를 뒤집습니다

Uikit 드로잉에서 뒤집는 것은 백킹 칼레이가 수정하여 Uikit의 기본 좌표계와 LLO 좌표계를 갖는 드로잉 환경을 정렬합니다. Uikit 메소드와 드로잉 기능 만 사용하는 경우 CTM을 뒤집을 필요가 없습니다. 그러나 코어 그래픽 또는 이미지 I/O 기능 호출을 Uikit 호출과 혼합하면 CTM을 뒤집는 것이 필요할 수 있습니다.

구체적으로, Core 그래픽 기능을 직접 호출하여 이미지 또는 PDF 문서를 그려면 뷰의 컨텍스트에서 객체가 거꾸로 렌더링됩니다. 이미지와 페이지를 올바르게 표시하려면 CTM을 뒤집어야합니다.

Uikit보기에 표시 될 때 올바르게 나타나도록 핵심 그래픽 컨텍스트로 그려진 객체를 뒤집으려면 두 단계로 CTM을 수정해야합니다. 원점을 드로잉 영역의 왼쪽 상단 구석으로 번역 한 다음 y 좌표를 -1로 수정하여 스케일 번역을 적용합니다. 이를 수행하기위한 코드는 다음과 비슷해 보입니다.

CGContextSaveGState(graphicsContext);
CGContextTranslateCTM(graphicsContext, 0.0, imageHeight);
CGContextScaleCTM(graphicsContext, 1.0, -1.0);
CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight));
CGContextRestoreGState(graphicsContext);

확실하지 않습니다 UIImage, 그러나 이런 종류의 행동은 일반적으로 좌표가 뒤집을 때 발생합니다. OS X 좌표 시스템의 대부분은 PostScript 및 PDF에서와 같이 왼쪽 하단 모서리에 원점이 있습니다. 하지만 CGImage 좌표계는 왼쪽 상단에 원점이 있습니다.

가능한 솔루션에는 포함될 수 있습니다 isFlipped 재산 또는 a scaleYBy:-1 아핀 변환.

컨텍스트에서 사용자 정의 낙타로 이미지를 그리는 데 관심이없는 솔루션에 관심이있는 사람이 있다면 :

 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)

}

이미지는 낙타를 채우도록 조정됩니다.

동일한 기능을 사용 하여이 문제를 해결할 수 있습니다.

UIGraphicsBeginImageContext(image.size);

UIGraphicsPushContext(context);

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

UIGraphicsPopContext();

UIGraphicsEndImageContext();

UIImage a CGImage 스케일링 및 방향 요인뿐만 아니라 주요 컨텐츠 멤버로서. 부터 CGImage 그리고 다양한 기능은 OSX에서 파생되며 iPhone에 비해 거꾸로 된 좌표계를 기대합니다. 당신이 만들 때 UIImage, 기본값은 거꾸로 된 오리엔테이션으로 기본적으로 보상합니다 (이를 변경할 수 있습니다!). 사용 .CGImage 매우 강력한 자산에 액세스 할 수 있습니다 CGImage 함수이지만 iPhone 화면 등에 그리기가 가장 좋습니다. UIImage 행동 양식.

신속한 코드로 보충 답변

Quartz 2D 그래픽은 왼쪽 하단에 원점이있는 좌표계를 사용하고 iOS의 Uikit은 왼쪽 상단에 원점이있는 좌표계를 사용합니다. 모든 것이 일반적으로 잘 작동하지만 일부 그래픽 작업을 수행 할 때는 좌표계를 직접 수정해야합니다. 그만큼 선적 서류 비치 상태 :

일부 기술은 Quartz가 사용하는 것과는 다른 기본 좌표계를 사용하여 그래픽 컨텍스트를 설정합니다. 석영과 관련하여 이러한 좌표계는 수정 된 좌표계이며 일부 석영 드로잉 작업을 수행 할 때 보상해야합니다. 가장 일반적인 수정 된 좌표계는 컨텍스트의 왼쪽 상단 코너에 원점을 배치하고 y 축을 변경하여 페이지 하단을 향합니다.

이 현상은 다음과 같은 두 가지 인스턴스의 사용자 정의 뷰에서 볼 수 있습니다. drawRect 행동 양식.

enter image description here

왼쪽에서는 이미지가 거꾸로되어 오른쪽에서 좌표계가 번역되고 스케일되어 원점이 왼쪽 상단에 있습니다.

거꾸로 된 이미지

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

스위프트 3.0 & 4.0

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

변경이 필요하지 않습니다

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

Swift 3 Coregraphics 솔루션

Uiimage 대신에 CG를 사용하려면 이전 답변을 기반으로 한이 Swift 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()
}

내 프로젝트 과정에서 나는 뛰어 내렸다 켄달의 대답 에게 클리프의 대답 전화 자체에서로드 된 이미지에 대해이 문제를 해결합니다.

결국 나는 결국 사용했다 CGImageCreateWithPNGDataProvider 대신에:

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

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

이것은 당신이 얻는 것에서 얻을 수있는 오리엔테이션 문제로 어려움을 겪지 않습니다. CGImage a UIImage 그리고 그것은의 내용으로 사용될 수 있습니다. CALayer 장애없이.

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()
    }
}

이 작업을 수행 하여이 문제를 해결할 수도 있습니다.

//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.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top