web-dev-qa-db-ja.com

コアグラフィックスの反転した座標系を補正して簡単に描画するにはどうすればよいですか?

本当に面倒ですが、-drawRect:でUIImageを描画すると、常に逆さまになります。

座標を反転すると、画像は正しく描画されますが、他のすべてのCG関数が「間違った」(反転)描画するという犠牲が伴います。

画像などを描くときの戦略は?この問題に何度も立ち往生しないようにするための経験則はありますか?

また、y軸を反転するときの厄介なことの1つは、UIImageViewフレームからのCGRectが間違っていることです。予想どおり、原点が左上の10,10に表示される代わりに、下部に表示されます。

しかし同時に、CGContextのこれらの通常の線画関数はすべて正しい座標を取ります。 -drawRectでOrigin10,10を左上にした線の描画は、実際には左上から始まります。しかし同時に、それは奇妙なことです。コアグラフィックスには、実際には下部にy0が付いた反転座標系があるためです。

ですから、そこには何かが本当に矛盾しているようです。 CGContext関数を使用した描画では、座標が「期待される」と見なされます(cmon、左下から始まる座標では誰も考えません、それはばかげています)が、どのような種類の画像でも描画は「間違った」方法で機能します。

ヘルパーメソッドを使用して画像を描画していますか?それとも、画像の描画をお尻の痛みではなくするのに役立つものはありますか?

31

問題:原点は左下隅にあります。正のyは上向きになります(負のyは下向きになります)。
目標:左上隅の原点。正のyは下向きになります(負のyは上向きになります)。

解決:

  1. ビューの高さだけ原点を上に移動します。
  2. Y軸を否定(-1を掛ける)します。

コードでこれを行う方法は、 translate をビュー境界の高さと scale (1、-1)の順で。

Quartz 2Dプログラミングガイド には、 「Drawingto」など、このトピックに関連する部分がいくつかあります。 iPhone OSのグラフィックスコンテキスト」 および変換の章全体。もちろん、あなたは本当に全部を読むべきです。

29
Peter Hosey

UIKit関連の座標で変換したいポイントにaffinetransformを適用することでそれを行うことができます。以下は例です。

// Create a affine transform object
CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
// First translate your image View according to transform
transform = CGAffineTransformTranslate(transform, 0, - imageView.bounds.size.height);
// Then whenever you want any point according to UIKit related coordinates apply this transformation on the point or rect.
// To get tranformed point
CGPoint newPointForUIKit = CGPointApplyAffineTransform(oldPointInCGKit, transform);
// To get transformed rect
CGRect newRectForUIKit = CGRectApplyAffineTransform(oldPointInCGKit, transform);
9
shahid610169

この問題に対するより良い答えは、UIImageメソッドdrawInRect:を使用して画像を描画することです。画像をビューの境界全体に広げる必要があると想定しています。これは、drawRect:メソッドに入力するものです。

の代わりに:

CGContextRef ctx = UIGraphicsGetCurrentContext();  
UIImage *myImage = [UIImage imageNamed:@"theImage.png"];  
CGImageRef img = [myImage CGImage];
CGRect bounds = [self bounds];
CGContextDrawImage(ctx, bounds, img);

これを書いてください:

UIImage *myImage = [UIImage imageNamed:@"theImage.png"];
CGRect bounds = [self bounds];
[myImage drawInRect:bounds];
4
kevmalek

本当に面倒ですが、-drawRect:でUIImageを描画すると、常に逆さまになります。

UIImageに描画するように指示していますか、それともCGImageを取得して描画していますか?

「iPhoneOSでのグラフィックスコンテキストへの描画」 に記載されているように、UIImagesは座標空間の違いを認識しており、座標空間を自分で反転しなくても正しく描画する必要があります。

3
Peter Hosey
CGImageRef flip (CGImageRef im) {
    CGSize sz = CGSizeMake(CGImageGetWidth(im), CGImageGetHeight(im));
    UIGraphicsBeginImageContextWithOptions(sz, NO, 0);
    CGContextDrawImage(UIGraphicsGetCurrentContext(),
                       CGRectMake(0, 0, sz.width, sz.height), im);
    CGImageRef result = [UIGraphicsGetImageFromCurrentImageContext() CGImage];
    UIGraphicsEndImageContext();
    return result;
}

以下のコードを使用して上記のメソッドを呼び出します。このコードは、既存のUIImageviewから画像の左半分を取得し、生成された画像を新しいimageviewに設定することを処理します-imgViewleft

CGContextRef con = UIGraphicsGetCurrentContext();
CGContextDrawImage(con,  
                   CGRectMake(0,0,sz.width/2.0,sz.height),
                   flip(leftReference));
imgViewLeft = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
0
Abhishek Bedi