web-dev-qa-db-ja.com

iOSで正方形の画像を角の丸い画像にマスクする方法は?

正方形の画像を角の丸い画像にマスクするにはどうすればよいですか?

34
erotsppa

CoreGraphicsを使用して、次のコードスニペットで丸い長方形のパスを作成できます。

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
    float fw, fh;
    if (ovalWidth == 0 || ovalHeight == 0) {
        CGContextAddRect(context, rect);
        return;
    }
    CGContextSaveGState(context);
    CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
    CGContextScaleCTM (context, ovalWidth, ovalHeight);
    fw = CGRectGetWidth (rect) / ovalWidth;
    fh = CGRectGetHeight (rect) / ovalHeight;
    CGContextMoveToPoint(context, fw, fh/2);
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
    CGContextClosePath(context);
    CGContextRestoreGState(context);
}

次に、CGContextClip(context);を呼び出します。長方形のパスにクリップします。これで、画像の描画を含む、行われた描画はすべて、丸い長方形の形にクリップされます。

例として、「image」がUIImageであり、これがdrawRect:メソッド内にあると想定します。

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
addRoundedRectToPath(context, self.frame, 10, 10);
CGContextClip(context);
[image drawInRect:self.frame];
CGContextRestoreGState(context);
67
NilObject

IPhone 3.0以降で利用できるさらに簡単な方法を次に示します。すべてのビューベースのオブジェクトには、関連するレイヤーがあります。各レイヤーにはコーナー半径を設定できます。これにより、必要なものが得られます。

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * layer = [roundedView layer];
[layer setMasksToBounds:YES];
[layer setCornerRadius:10.0];

// You can even add a border
[layer setBorderWidth:4.0];
[layer setBorderColor:[[UIColor blueColor] CGColor]];

これらのメソッドを使用するには、追加が必要になる場合があります。

#import <QuartzCore/QuartzCore.h>
35
MagicSeth

私はこれが古いニュースであることに気づきますが、少し煮詰めます:

ここでは2可能な質問があります:(1)画面に表示されるUIView(UIImageViewなど)に丸みを帯びた角を適用する方法、および(2)正方形をマスクする方法画像(つまり、UIImage)は、角が丸い新しい画像を生成します。

(1)の場合、CoreAnimationを使用して、view.layer.cornerRadiusプロパティを設定するのが最も簡単なコースです。

 // Because we're using CoreAnimation, we must include QuartzCore.h
 // and link QuartzCore.framework in a build phases 
 #import <QuartzCore/QuartzCore.h> 

 // start with an image 
 UIImage * fooImage = [UIImage imageNamed:@"foo.png"];
 // put it in a UIImageView
 UIView * view = [UIImageView alloc] initWithImage:fooImage];
 // round its corners. This mask now applies to the view's layer's *background*
 view.layer.cornerRadius = 10.f
 // enable masksToBounds, so the mask applies to its foreground, the image
 view.layer.masksToBounds = YES;

(2)の場合、最良の方法はUIKitグラフィック操作を使用することです。

// start with an image 
UIImage * fooImage = [UIImage imageNamed:@"foo.png"];
CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height);
// set the implicit graphics context ("canvas") to a bitmap context for images
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0);
// create a bezier path defining rounded corners
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f];
// use this path for clipping in the implicit context
[path addClip];
// draw the image into the implicit context
[fooImage drawInRect:imageRect];
// save the clipped image from the implicit context into an image 
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
// cleanup
UIGraphicsEndImageContext();

問題(2)についてトリッキーなのは、CoreAnimationのview.layer.maskプロパティを使用して操作全体を実行できると思うかもしれないということです。しかし、CALayer renderInContext:メソッドは、マスクされたレイヤーからUIImageを生成するために使用しますが、マスクを無視しているようです。さらに悪いことに、renderInContext:はこれについて言及しておらず、OSX 10.5の動作をほのめかしています。

さらにいくつかのコンテキスト:(2)への上記のアプローチは、より基本的なCoreGraphics機能の周りにUIKitのラッパーを使用しています。 CoreGraphicsの呼び出しを直接使用して同じことを行うことができます。つまり、選択した答えがそうです。ただし、曲線と直線から手動で丸められた四角形のベジェパスを構築する必要があり、CoreGraphicsが使用するという事実を補正する必要もあります。 UIKitに対して反転される描画座標系。

15
algal

この投稿を見る-非常に簡単な答え

iPhoneのUI画像に丸い角を設定する方法

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];
2
GAL

とても簡単です。 self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width/2; self.profileImageView.clipsToBounds = YES;

すべてのビューに、バンドルされたレイヤープロパティがあります。上記の最初の行は、レイヤーオブジェクト(つまり、CALayerクラスのインスタンス)のコーナー半径を設定することです。正方形の画像から円形の画像を作成するには、半径をUIImageViewの幅の半分に設定します。たとえば、正方形の画像の幅が100ピクセルの場合です。半径は50ピクセルに設定されています。次に、レイヤーを機能させるために、clipsToBoundsプロパティをYESに設定する必要があります。

1
Shahab Qureshi

この方法を使用します。

+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size;
    {
      UIImage *img = nil;


        CGRect rect = CGRectMake(0, 0, size.width, size.height);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context,
                                     color.CGColor);
        CGContextFillRect(context, rect);
        img = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();


      return img;
    }
0
Voda Ion

algal を基にして、UIImageカテゴリに配置すると便利ないくつかのメソッドを次に示します。


- (UIImage *) roundedCornerImageWithRadius:(CGFloat)radius
{
    CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height);
    UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); //scale 0 yields better results

    //create a bezier path defining rounded corners and use it for clippping
    UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius];
    [path addClip];

    // draw the image into the implicit context
    [self drawInRect:imageRect];

    // get image and cleanup
    UIImage *roundedCornerImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return roundedCornerImage;
}

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andCornerRadius:(CGFloat)radius
{
    UIImage *image = nil;
    if (size.width == 0 || size.height == 0) {
        size = CGSizeMake(1.0, 1.0);
    }
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
    UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0); //yields sharper results than UIGraphicsBeginImageContext(rect.size)
    CGContextRef context = UIGraphicsGetCurrentContext();
    if (context)
    {
        CGContextSetFillColorWithColor(context, [color CGColor]);
        if (radius > 0.0) {
            //create a bezier path defining rounded corners and use it for clippping
            UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
            [path addClip];
            CGContextAddPath(context, path.CGPath);
        }
        CGContextFillRect(context, rect);
        image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
    return image;
}
0
n8tr

どちらの方法でも機能しますが、使用する場所によって違いが現れます。

例:テーブルビューにセルが他のラベルなどと共に画像を表示している場合、レイヤを使用してcornerRadiusを設定すると、スクロールが大きな影響を与えます。ぎくしゃくする。

テーブルビューセルの画像にレイヤーを使用しているときにこの問題に直面し、ジャーキーの原因を解明しようとして、CALayerが原因であることがわかりました。

NilObjectで説明されているdrawRectでの処理を行う最初のソリューションを使用しました。それはシルクのように滑らかなスクロールで魅力のように機能します。

一方、これをポップオーバービューなどの静的ビューで使用する場合は、レイヤーが最も簡単な方法です。

先に述べたように、どちらの方法も、使用する場所に基づいて決定する必要があるだけでうまく機能します。

0
Deepak G M