Получение UIImage только для определенных границ области - PaintView

Я уже реализовал paint/draw используя:

- (void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event
-(void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event
- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event

Теперь проблема заключается в том, что для любой рисованной линии я хочу получить конкретное изображение линии/краски. Мне не нужен образ всего экрана, только область/граница рисованной линии/рисунка.

Причина заключается в том, что я хочу выполнять функции gothure/delete на основе этой линии/рисунка.

Пользователь может рисовать несколько строк, поэтому хочу UIImage для всех этих строк отдельно.

Любая логика или фрагмент кода будут действительно полезны

Заранее спасибо

Ответ 1

В зависимости от вашего приложения, в частности, сколько раз вы планируете делать это подряд, вы можете создать другое изображение/слой для каждой линии рисования. Ваше окончательное изображение будет по существу всеми отдельными линиями, нарисованными друг над другом.

Может быть более эффективным создание пользовательского представления для захвата событий касания. Вы можете сохранить список сенсорных координат для каждой линии рисования и отобразить их все сразу в пользовательском drawRect. Таким образом, вы сохраняете списки координат для каждой линии рисования и можете получать доступ к каждому из них, а не к списку изображений. Вы можете рассчитать площадь/границы из координат, используемых для визуализации линии.

Дополнительный контекст и код могут быть полезными, я не уверен, что полностью понимаю, чего вы пытаетесь выполнить!

Ответ 2

Я смотрю проект MVPaint. Кажется, у вас есть объект:

MVPaintDrawing _drawing;

который содержит массив MVPaintTransaction. Вы можете повторить эти MVPaintTransaction, чтобы нарисовать UIImage.

Итак, сначала вы можете добавить метод для получения изображения из MVPaintTransaction:

- (UIImage *) imageToDrawWithSize:(CGSize) size xScale:(CGFloat)xScale yScale:(CGFloat)yScale {

    UIGraphicsBeginImageContext(size);
    CGContextScaleCTM(UIGraphicsGetCurrentContext(), xScale, yScale);

    // call the existing draw method    
    [self draw];

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

Затем добавьте метод для получения массива изображения из массива MVPaintTransaction в классе MVPaintDrawing:

- (NSArray *) getImagesFromDrawingOnSurface: (UIImageView *) surface xScale: (CGFloat) xScale yScale: (CGFloat) yScale{

    NSMutableArray *imageArray = [NSMutableArray new];
    for (MVPaintTransaction * transaction in _drawing) {
        UIImage *image = [transaction imageToDrawWithSize:surface.frame.size xScale:xScale yScale:yScale];
        [imageArray addObject:image];
    }

    return imageArray;
}

Таким образом, у вас будет массив UIImage, соответствующий каждой линии, которую вы нарисовали. Если вы хотите, чтобы эти изображения имели минимальный возможный размер (я имею в виду без дополнительной альфа-части), вы можете применить этот метод (я добавил его в MVPaintTransaction класс):

- (UIImage *)trimmedImage:(UIImage *)img {

    CGImageRef inImage = img.CGImage;
    CFDataRef m_DataRef;
    m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));

    UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef);

    size_t width = CGImageGetWidth(inImage);
    size_t height = CGImageGetHeight(inImage);

    CGPoint top,left,right,bottom;

    BOOL breakOut = NO;
    for (int x = 0;breakOut==NO && x < width; x++) {
        for (int y = 0; y < height; y++) {
            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                left = CGPointMake(x, y);
                breakOut = YES;
                break;
            }
        }
    }

    breakOut = NO;
    for (int y = 0;breakOut==NO && y < height; y++) {

        for (int x = 0; x < width; x++) {

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                top = CGPointMake(x, y);
                breakOut = YES;
                break;
            }

        }
    }

    breakOut = NO;
    for (int y = height-1;breakOut==NO && y >= 0; y--) {

        for (int x = width-1; x >= 0; x--) {

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                bottom = CGPointMake(x, y);
                breakOut = YES;
                break;
            }

        }
    }

    breakOut = NO;
    for (int x = width-1;breakOut==NO && x >= 0; x--) {

        for (int y = height-1; y >= 0; y--) {

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) {
                right = CGPointMake(x, y);
                breakOut = YES;
                break;
            }

        }
    }


    CGFloat scale = img.scale;

    CGRect cropRect = CGRectMake(left.x / scale, top.y/scale, (right.x - left.x)/scale, (bottom.y - top.y) / scale);
    UIGraphicsBeginImageContextWithOptions( cropRect.size,
                                           NO,
                                           scale);
    [img drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y)
            blendMode:kCGBlendModeCopy
                alpha:1.];
    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CFRelease(m_DataRef);
    return croppedImage;
}

Затем просто замените в первом методе:

return result;

по

return [self trimmedImage:result];