Как создать UIImage с UIBezierPath

Я написал некоторый код для создания UIImage с UIBezierPath но это не сработало.

Может ли кто-нибудь помочь мне выяснить, что не так с моим кодом?

-(UIImage*) drawTriangle{
    CGRect rect = CGRectMake(0.0, 0.0, 30.0, 30.0);
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    UIBezierPath *bezier = [UIBezierPath bezierPathWithRect:rect];
    [bezier moveToPoint:CGPointMake(25, 5)];
    [bezier addLineToPoint:CGPointMake(5, 15)];
    [bezier addLineToPoint:CGPointMake(25, 25)];
    [bezier setLineWidth:3.0];
    [bezier setLineJoinStyle:kCGLineJoinBevel];
    [bezier stroke];
    CGContextAddPath(context, bezier.CGPath);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsPopContext();
    UIGraphicsEndImageContext();
    return image;
}

Ответ 1

попробуйте эту категорию для UIBezierPath

@interface UIBezierPath (Image)

/** Returns an image of the path drawn using a stroke */
-(UIImage*) strokeImageWithColor:(UIColor*)color;

@end

@implementation UIBezierPath (Image)

-(UIImage*) strokeImageWithColor:(UIColor*)color {
    // adjust bounds to account for extra space needed for lineWidth
    CGFloat width = self.bounds.size.width + self.lineWidth * 2;
    CGFloat height = self.bounds.size.height + self.lineWidth * 2;
    CGRect bounds = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, width, height);

    // create a view to draw the path in
    UIView *view = [[UIView alloc] initWithFrame:bounds];

    // begin graphics context for drawing
    UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);

    // configure the view to render in the graphics context
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    // get reference to the graphics context
    CGContextRef context = UIGraphicsGetCurrentContext();

    // translate matrix so that path will be centered in bounds
    CGContextTranslateCTM(context, -(bounds.origin.x - self.lineWidth), -(bounds.origin.y - self.lineWidth));

    // set color
    [color set];

    // draw the stroke
    [self stroke];

    // get an image of the graphics context
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();

    // end the context
    UIGraphicsEndImageContext();

    return viewImage;
}

@end

Ответ 2

Ваше использование будет:

UIBezierPath *path = [UIBezierPath trianglePathWithSize: CGSizeMake(50, 50)];
              path.lineWidth = 2;

UIImage *image = [path imageWithStrokeColor: [UIColor blueColor] 
                                  fillColor: [UIColor redColor]];

Категория для создания форм безье:

@implementation UIBezierPath (Shapes)

+ (UIBezierPath *) trianglePathWithSize: (CGSize) size;
{
    UIBezierPath *result = [UIBezierPath bezierPath];
    result.lineJoinStyle = kCGLineJoinMiter;

    [result moveToPoint: CGPointMake(0, 0)];
    [result addLineToPoint: CGPointMake(size.width, size.height / 2)];
    [result addLineToPoint: CGPointMake(0, size.height)];
    [result closePath];

    return result;
}

@end

Категория, чтобы взять любой путь и сделать в UIImage из него:

@implementation UIBezierPath (UIImage)

- (UIImage *) imageWithStrokeColor: (UIColor *) strokeColor fillColor: (UIColor *) 

fillColor;
{
    CGRect bounds = self.bounds;

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(bounds.size.width + self.lineWidth * 2, bounds.size.width + self.lineWidth * 2),
                                           false, [UIScreen mainScreen].scale);

    CGContextRef context = UIGraphicsGetCurrentContext();

    // offset the draw to allow the line thickness to not get clipped
    CGContextTranslateCTM(context, self.lineWidth, self.lineWidth);

    if (!strokeColor)
    {
        strokeColor = fillColor;
    }
    else
    if (!fillColor)
    {
        fillColor = strokeColor;
    }

    [strokeColor setStroke];
    [fillColor setFill];

    [self fill];
    [self stroke];

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return result;
}

@end

Ответ 3

Вы можете создать изображение с BeizerPath Swift-3: -

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var imageOutlet: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()
        let path3 = createBeizePath()
        let image:UIImage = UIImage.shapeImageWithBezierPath(bezierPath: path3, fillColor: .red, strokeColor: .black)
        imageOutlet.image = image
}

func createBeizePath() -> UIBezierPath
{
    let path = UIBezierPath()
    //Rectangle path Trace
    path.move(to: CGPoint(x: 20, y: 100) )
    path.addLine(to: CGPoint(x: 50 , y: 100))
    path.addLine(to: CGPoint(x: 50, y: 150))
    path.addLine(to: CGPoint(x: 20, y: 150))
    return path
  }

}

extension UIImage {

    class func shapeImageWithBezierPath(bezierPath: UIBezierPath, fillColor: UIColor?, strokeColor: UIColor?, strokeWidth: CGFloat = 0.0) -> UIImage! {
        bezierPath.apply(CGAffineTransform(translationX: -bezierPath.bounds.origin.x, y: -bezierPath.bounds.origin.y ) )
        let size = CGSize(width: 100    , height: 100)
        UIGraphicsBeginImageContext(size)
        let context = UIGraphicsGetCurrentContext()
        var image = UIImage()
        if let context  = context {
            context.saveGState()
            context.addPath(bezierPath.cgPath)
            if strokeColor != nil {
                strokeColor!.setStroke()
                context.setLineWidth(strokeWidth)
            } else { UIColor.clear.setStroke() }
            fillColor?.setFill()
            context.drawPath(using: .fillStroke)
             image = UIGraphicsGetImageFromCurrentImageContext()!
            context.restoreGState()
            UIGraphicsEndImageContext()
        }
        return image
    }

}

enter image description here

Демо-приложение

Ссылка

Ответ 4

Попробуйте это

CAShapeLayer *maskLayer = [CAShapeLayer layer];

maskLayer.frame = imageview.frame;

maskLayer.path = [path CGPath];

imageview.layer.mask = maskLayer;

Ответ 5

Я нашел, что не так с моим кодом.

Я сделал ошибку в коде заказа. Просто переместите UIGraphicsBeginImageContext(rect.size) в соответствующую позицию.

-(UIImage*) drawTriangle{
    CGRect rect = CGRectMake(0.0, 0.0, 30.0, 30.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsPushContext(context);
    UIGraphicsBeginImageContext(rect.size); //now it here.
    UIBezierPath *bezier = [UIBezierPath bezierPathWithRect:rect];
    [bezier moveToPoint:CGPointMake(25, 5)];
    [bezier addLineToPoint:CGPointMake(5, 15)];
    [bezier addLineToPoint:CGPointMake(25, 25)];
    [bezier setLineWidth:3.0];
    [bezier setLineJoinStyle:kCGLineJoinBevel];
    [bezier stroke];
    CGContextAddPath(context, bezier.CGPath);
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsPopContext();
    UIGraphicsEndImageContext();
    return image;
}

Ответ 6

fooobar.com/questions/540728/... Переведено в Swift

import UIKit

extension UIBezierPath {

    /** Returns an image of the path drawn using a stroke */
    func strokeImageWithColor(var strokeColor: UIColor?,var fillColor: UIColor?) -> UIImage {

        // get your bounds
        let bounds: CGRect = self.bounds

        UIGraphicsBeginImageContextWithOptions(CGSizeMake(bounds.size.width + self.lineWidth * 2, bounds.size.width + self.lineWidth * 2), false, UIScreen.mainScreen().scale)

        // get reference to the graphics context
        let reference: CGContextRef = UIGraphicsGetCurrentContext()!

        // translate matrix so that path will be centered in bounds
        CGContextTranslateCTM(reference, self.lineWidth, self.lineWidth)

        if strokeColor == nil {
            strokeColor = fillColor!;
        }
        else if fillColor == nil {
            fillColor = strokeColor!;
        }

        // set the color
        fillColor?.setFill()
        strokeColor?.setStroke()

        // draw the path
        fill()
        stroke()


        // grab an image of the context
        let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

        UIGraphicsEndImageContext()

        return image
    }

}

Ответ 7

extension UIBezierPath {
    func shapeImage(view: UIView) -> UIImage! {

    // begin graphics context for drawing
    UIGraphicsBeginImageContextWithOptions(view.frame.size, false, UIScreen.main.scale)

    // configure the view to render in the graphics context
    //view.layer.render(in: UIGraphicsGetCurrentContext()!)

    // get reference to the graphics context
    let context = UIGraphicsGetCurrentContext()

    // translate matrix so that path will be centered in bounds
    context?.translateBy(x: -(bounds.origin.x - self.lineWidth), y: -(bounds.origin.y - self.lineWidth))
    // set color
    UIColor.black.setStroke()

    // draw the stroke
    stroke()

    // get an image of the graphics context
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!

    // end the context
    UIGraphicsEndImageContext()

    return image
    }
}

первый взгляд с Безье

second - Безье преобразуется в изображение

введите описание изображения здесь