Как нарисовать линию на изображении не целым UIImageView?

Перед раскрашиванием изображения:

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

После раскрашивания изображения:

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

Это мой код:

-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [[event allTouches] anyObject];
    touchPoint = [touch locationInView:self.imgColor];
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
    [path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)];
    startingPoint=touchPoint;
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [path CGPath];
    shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
    shapeLayer.lineWidth = 3.0;
    shapeLayer.fillColor = [[UIColor redColor] CGColor];
    [self.imgColor.layer addSublayer:shapeLayer];
    [arrLayer addObject:shapeLayer];
    NSLog(@"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);  
}

В зависимости от касания пользователя, он рисует линию внутри UIImageView.

Что мне нужно:

Если размер изображения слишком мал, я не хочу позволять рисовать за пределами изображения.

Внутри изображения пользователь должен рисовать, есть ли способ? Пожалуйста, предложите мне.


person Kishore Kumar    schedule 11.01.2016    source источник
comment
Самый простой способ - остановить линию, когда if (!CGRectContainsPoint(doggyImage.frame, touchPoint))   -  person zcui93    schedule 11.01.2016
comment
хорошо @zcui93, я попробую твою точку зрения ...   -  person Kishore Kumar    schedule 11.01.2016
comment
нет @zcui93 мой кадр UIImageView большой, но изображение собаки маленькое, мне нравится раскрашивать только внутри изображения собаки.   -  person Kishore Kumar    schedule 11.01.2016
comment
Предлагаемый код только предотвращает рисование линии изнутри наружу. Идея состоит в том, чтобы проверить, находится ли точка касания внутри изображения вашей собаки или нет. Вам нужно сделать аналогичную проверку, чтобы не начать рисовать, когда touchStart.   -  person zcui93    schedule 11.01.2016
comment
можете ли вы предложить более глубокий код об этом @zcui93   -  person Kishore Kumar    schedule 11.01.2016
comment
это то, что я пробовал @zcui93 if (!CGRectContainsPoint(_imgColor.frame, touchPoint)) { [self.imgColor.layer addSublayer:shapeLayer]; [arrLayer addObject: shapeLayer]; } еще { }   -  person Kishore Kumar    schedule 11.01.2016


Ответы (4)


Добавьте этот код в свой сенсорный вид.

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    return CGRectContainsPoint(doggyImage.frame, point)
}
person Arun Ammannaya    schedule 11.01.2016

Код, представленный в первом комментарии if (!CGRectContainsPoint(doggyImage.frame, touchPoint)), является некоторым условием, которое вы можете использовать, чтобы проверить, находится ли точка касания в одном конкретном представлении, где, я думаю, вы должны использовать для сравнения с изображением вашей собаки (я не знаю, что это за переменная, поэтому Я использовал doggyImage. Может быть, self.imgColor правильный или нет).

И для самого простого решения вам нужно сделать как минимум две вещи

  • Если touchesBegan за пределами doggyImage, ничего не делайте, только return.
  • Предотвратите рисование линий изнутри наружу, поэтому используйте то же условие и примените тот же код, который вы использовали в touchesEnd, для обработки чего-то вроде stopDrawLine.

Более продвинутый метод будет включать в себя вычисление ближайшей точки от прикосновения к изображению, если оно снаружи, и отрисовку ее на краю.

Кстати, в настоящее время в вашем touchesMoved вы создали одну новую UIBezierPath для каждой точки касания, что привело к сотням отдельных небольших фрагментов линии. Вы можете попробовать создать новый path, когда touchesBegan и addLineToPoint в touchesMoved. Чтобы вся строка была в один путь, и поэтому можно было предлагать фритуры вроде "отменить".

person zcui93    schedule 11.01.2016

взять один объект CGRect. Глобально присвоить его значение следующим образом.

 CGRect imagerect = CGRectMake(imgColor.center.x - (imgColor.image.size.width/2 + imgColor.frame.origin.x), imgColor.center.y - (imgColor.image.size.height/2+ imgColor.frame.origin.y), imgColor.image.size.width, imgColor.image.size.height);

теперь в методе touchesMoved ставим одно условие перед рисованием if( CGRectContainsPoint(imagerect, touchPoint))

так что метод будет такой

-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [[event allTouches] anyObject];
      touchPoint = [touch locationInView:self.imgColor];


    if( CGRectContainsPoint(imagerect, touchPoint))
    {

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
    [path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)];
    startingPoint=touchPoint;
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [path CGPath];
    shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
    shapeLayer.lineWidth = 3.0;
    shapeLayer.fillColor = [[UIColor redColor] CGColor];
    [self.imgColor.layer addSublayer:shapeLayer];
    [arrLayer addObject:shapeLayer];
    NSLog(@"Touch moving point =x : %f Touch moving point =y : %f", touchPoint.x, touchPoint.y);
    }

}
person Jaydeep Patel    schedule 11.01.2016
comment
Джей, спасибо за ответ, но ваш код работает только для прямоугольного изображения, а не для всего изображения, в моем случае изображение должно отличаться, например, круг, прямоугольник, затмение. - person Kishore Kumar; 11.01.2016
comment
Я добавил новый ответ, пожалуйста, проверьте. я не редактировал его, потому что если кто-то захочет нарисовать прямоугольное изображение, он будет использовать этот код - person Jaydeep Patel; 19.01.2016
comment
@jey после добавления слоя, как я могу создать из него новое отредактированное изображение и сохранить или отправить его. - person Hardik Vyas; 29.06.2020
comment
@HardikVyas слишком старая надежда, что приведенный ниже код работает для вас ``` - (UIImage *) imageWithView:(UIView *)view {UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [[UIScreen mainScreen] scale]); if (_videoURL) { [view.layer renderInContext:UIGraphicsGetCurrentContext()]; } else { [представление drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO]; } // UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); вернуть изображение; }``` вам нужно создать изображение из вашего представления - person Jaydeep Patel; 30.06.2020

Возможно, это не идеальное решение, но я стараюсь соответствовать вашим требованиям. Пожалуйста, попробуйте с этим

#import "ViewController.h"

@interface ViewController ()
{
    CGPoint touchPoint,startingPoint;

    CALayer *layer;
    float x1;
    float y1;
    IBOutlet UIImageView *imgColor;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    layer = [CALayer layer];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
-(void)viewDidAppear:(BOOL)animated
{

    CGSize scaledImageSize = imgColor.image.size;
    CGRect imageFrame = CGRectMake(roundf(0.5f*(CGRectGetWidth(imgColor.bounds)-scaledImageSize.width)), roundf(0.5f*(CGRectGetHeight(imgColor.bounds)-scaledImageSize.height)), roundf(scaledImageSize.width), roundf(scaledImageSize.height));
    x1 = imageFrame.origin.x ;
    y1 =  imageFrame.origin.y ;


}



- (UIColor*)getRGBAsFromImage:(UIImage*)image atX:(int)x andY:(int)y
{
    if (x < 0 || y<0  || x> image.size.width || y > image.size.height) {
        return nil;
    }
    // First get the image into your data buffer
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.
    NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;

        CGFloat alpha = ((CGFloat) rawData[byteIndex + 3] ) / 255.0f;
        CGFloat red   = ((CGFloat) rawData[byteIndex]     ) / alpha;
        CGFloat green = ((CGFloat) rawData[byteIndex + 1] ) / alpha;
        CGFloat blue  = ((CGFloat) rawData[byteIndex + 2] ) / alpha;
        byteIndex += bytesPerPixel;
    if (red >= 0 || green >= 0 || blue >= 0) {
        return  [UIColor colorWithRed:red green:green blue:blue alpha:alpha];

    }
    return nil;
}

-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [[event allTouches] anyObject];

    touchPoint = [touch locationInView:imgColor];

    ;
    if ([self getRGBAsFromImage:imgColor.image atX:touchPoint.x - x1 andY:touchPoint.y - y1] && !(touchPoint.x == 0 && touchPoint.y == 0)) {

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(touchPoint.x,touchPoint.y)];
    [path addLineToPoint:CGPointMake(startingPoint.x,startingPoint.y)];
    startingPoint=touchPoint;
    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [path CGPath];
    shapeLayer.strokeColor = [[UIColor blueColor] CGColor];
    shapeLayer.lineWidth = 1.0;
    shapeLayer.fillColor = [[UIColor redColor] CGColor];


        [imgColor.layer addSublayer:shapeLayer];
    }

}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
{
    touchPoint = CGPointMake(0, 0);
}
@end
person Jaydeep Patel    schedule 19.01.2016