これUIImage
を黒線で2分割する方法。の上部輪郭セットUIBezierPath
。
結果の 2 つの s を取得する必要がありますUIImage
。それで、それは可能ですか?
これUIImage
を黒線で2分割する方法。の上部輪郭セットUIBezierPath
。
結果の 2 つの s を取得する必要がありますUIImage
。それで、それは可能ですか?
次の一連のルーチンは、パス内のコンテンツのみ、またはそのパス外のコンテンツのみを持つ UIImage のバージョンを作成します。
どちらもcompositeImage
CGBlendMode を使用するメソッドを使用します。CGBlendMode は、描画できる他のものに対して描画できるものをマスクするのに非常に強力です。他のブレンド モードで compositeImage: を呼び出すと、(常に役立つとは限りませんが) 興味深い効果が得られます。すべてのモードについては、CGContext リファレンスを参照してください。
OPへのコメントで説明したクリッピング方法は機能し、おそらくより高速ですが、クリッピングするすべての領域を定義する UIBezierPaths がある場合に限ります。
- (UIImage*) compositeImage:(UIImage*) sourceImage onPath:(UIBezierPath*) path usingBlendMode:(CGBlendMode) blend;
{
// Create a new image of the same size as the source.
UIGraphicsBeginImageContext([sourceImage size]);
// First draw an opaque path...
[path fill];
// ...then composite with the image.
[sourceImage drawAtPoint:CGPointZero blendMode:blend alpha:1.0];
// With drawing complete, store the composited image for later use.
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
// Graphics contexts must be ended manually.
UIGraphicsEndImageContext();
return maskedImage;
}
- (UIImage*) maskImage:(UIImage*) sourceImage toAreaInsidePath:(UIBezierPath*) maskPath;
{
return [self compositeImage:sourceImage onPath:maskPath usingBlendMode:kCGBlendModeSourceIn];
}
- (UIImage*) maskImage:(UIImage*) sourceImage toAreaOutsidePath:(UIBezierPath*) maskPath;
{
return [self compositeImage:sourceImage onPath:maskPath usingBlendMode:kCGBlendModeSourceOut];
}
クリッピングをテストしましたが、いくつかの異なるテストでは、マスキングよりも25% 遅く[maskImage: toAreaInsidePath:]
、他の回答の方法と同じ結果が得られました。完全を期すためにここに含めますが、正当な理由なしに使用しないでください。
- (UIImage*) clipImage:(UIImage*) sourceImage toPath:(UIBezierPath*) path;
{
// Create a new image of the same size as the source.
UIGraphicsBeginImageContext([sourceImage size]);
// Clipping means drawing only happens within the path.
[path addClip];
// Draw the image to the context.
[sourceImage drawAtPoint:CGPointZero];
// With drawing complete, store the composited image for later use.
UIImage *clippedImage = UIGraphicsGetImageFromCurrentImageContext();
// Graphics contexts must be ended manually.
UIGraphicsEndImageContext();
return clippedImage;
}
これは実行できますが、三角法が必要です。上の画像の場合を考えてみましょう。最初に、 の最下部の終点を決定し、UIBezierPath
を使用UIGraphicsBeginImageContext
して線より上のイメージの上部を取得します。これは次のようになります。
ここで、線が直線であると仮定して、垂直線を描く線に沿ってピクセルごとに移動します(上部のループ。下部の同様の線に進みます) stroke
。clearColor
for(int currentPixel_x=0;currentPixel_x<your_ui_image_top.size.width)
UIGraphicsBeginImageContext(your_ui_image_top.size);
[your_ui_image_top drawInRect:CGRectMake(0, 0, your_ui_image_top.size.width, your_ui_image_top.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeClear);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(),[UIColor clearColor].CGColor);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), currentPixel_x, m*currentPixel_x + c);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPixel_x, your_ui_image_top.size.height);
CGContextStrokePath(UIGraphicsGetCurrentContext());
your_ui_image_top = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
フォームUIBezierPath
の直線に変換する必要がありますy = m*x + c
。このx
式の はcurrentPixel_x
上記になります。イメージの幅をcurrentPixel_x
1 ずつ増やしながら繰り返します。next_y_point_on_your_line
次のように計算されます。
next_y_point_on_your_line = m*currentPixel_x + c
各垂直線stroke
は 1 ピクセル幅で、高さは縦線をどのように通過するかによって異なります。何度か繰り返した後、画像は大まかに次のようになります (写真編集のスキルが低いことをお許しください!)。
明確なストロークを描く方法は複数ありますが、これは 1 つの方法にすぎません。より良い結果が得られる場合は、指定されたパスに平行な明確なストロークを作成することもできます。
もう 1 つの方法は、線の下のピクセルのアルファを 0 に設定することです。