2009-03-10 6 views
17

У меня есть небольшое приложение, которое позволяет пользователю рисовать на экране пальцем. У меня есть UIImageView, где пользователь рисует, создавая CGContextRef и различные функции CG draw. Я в основном рисую штрихи/линии с помощью функции CGContextAddLineToPointКак нарисовать прозрачный ход (или в любом случае прозрачную часть изображения) на iPhone

Теперь моя проблема такова: Пользователь может рисовать линии разных цветов. Я хочу дать ему возможность использовать инструмент "rubber", чтобы удалить часть изображения, нарисованного до сих пор пальцем. Я сначала сделал это, используя белый цвет для штриха (установлен с функцией CGContextSetRGBStrokeColor), но это не сработало ... потому что позже я обнаружил, что UIImage на UIImageView фактически имел прозрачный фон, а не белый ... поэтому я получаю прозрачное изображение с белыми линиями на нем!

Есть ли какой-либо способ установить цвет обводки "transparent" или есть ли другой способ очистить содержимое CGContextRef под пальцем пользователя, когда он перемещает его? Благодаря

ответ

57

Это будет делать трюк:

CGContextSetBlendMode(context, kCGBlendModeClear) 
+1

это не стереть ли изображение вместе с нарисованными линиями? Что делать, если я хочу, чтобы изображение не стиралось? и только стереть краску? – Shailesh

1

Я попытался с помощью:

CGContextSetStrokeColorWithColor (myContext, [[UIColor clearColor] CGColor]); 

, но это не работает, потому что, кажется, «рисунок» на верхней части контекста с невидимым цветом (и невидимым цветом + любой цвет, на который он рисует = цвет, на котором он нарисован).

Единственное решением, которое я нашел (что не является оптимальным) является:

CGContextClearRect (myContext, CGRectMake(x, y, width, height)); 

К сожалению, это означает, что вы должны проследить ряд прямоугольников и создать линию самостоятельно ...

6

Я закончил с использованием алгоритма брезенхэмы (harkening обратно в дни былое, когда я должен был писать свои собственные графические процедуры) ...

- (void) contextEraseLine:(CGContextRef) ctx from:(CGPoint)startPoint to:(CGPoint) endPoint withThickness:(int)thickness { 
    int x, cx, deltax, xstep, 
    y, cy, deltay, ystep, 
    error, st, dupe; 

    int x0, y0, x1, y1; 

    x0 = startPoint.x; 
    y0 = startPoint.y; 
    x1 = endPoint.x; 
    y1 = endPoint.y; 

    // find largest delta for pixel steps 
    st = (abs(y1 - y0) > abs(x1 - x0)); 

    // if deltay > deltax then swap x,y 
    if (st) { 
     (x0 ^= y0); (y0 ^= x0); (x0 ^= y0); // swap(x0, y0); 
     (x1 ^= y1); (y1 ^= x1); (x1 ^= y1); // swap(x1, y1); 
    } 

    deltax = abs(x1 - x0); 
    deltay = abs(y1 - y0); 
    error = (deltax/2); 
    y = y0; 

    if (x0 > x1) { xstep = -1; } 
    else   { xstep = 1; } 

    if (y0 > y1) { ystep = -1; } 
    else   { ystep = 1; } 

    for ((x = x0); (x != (x1 + xstep)); (x += xstep)) 
    { 
     (cx = x); (cy = y); // copy of x, copy of y 

     // if x,y swapped above, swap them back now 
     if (st) { (cx ^= cy); (cy ^= cx); (cx ^= cy); } 

     (dupe = 0); // initialize no dupe 

     if(!dupe) { // if not a dupe, write it out 
      //NSLog(@"(%2d, %2d)", cx, cy); 

      CGContextClearRect(ctx, CGRectMake(cx, cy, thickness, thickness)); 

    } 

     (error -= deltay); // converge toward end of line 

     if (error < 0) { // not done yet 
      (y += ystep); 
      (error += deltax); 
     } 
    } 
} 

Уф! Это долгий путь для создания (несколько) неуклюжей ластиковой линии.

Чтобы использовать его, сделать что-то вроде:

- (void)eraseStart { 
    // erase lines 
    UIGraphicsBeginImageContext(drawingBoard.size); 
    ctx = UIGraphicsGetCurrentContext(); 
    CGContextDrawImage(ctx,CGRectMake(0,0,drawingBoard.size.width, drawingBoard.size.height),[drawingBoard CGImage]); 
} 

- (void)eraseEnd { 
    drawingBoard = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    [drawingView removeFromSuperview]; 
    [drawingView release]; 

    drawingView = [[UIImageView alloc] initWithImage:drawingBoard]; 
    drawingView.frame = CGRectMake(intEtchX, intEtchY, intEtchWidth, intEtchHeight); 

    [self.view addSubview:drawingView]; 
} 

Это предполагает, что вы уже создали drawingView (UIImageView) и drawingBoard (UIImage).

Затем, чтобы стереть линию, просто сделать что-то вроде:

CGContextRef ctx = UIGraphicsGetCurrentContext(); 
[self eraseStart]; 
[self contextEraseLine:ctx from:CGPointMake (x1, y1) to:CGPointMake (x2, y2) withThickness:10]; 
[self eraseEnd]; 

(заменить x1, y1, x2, y2 и с соответствующими значениями) ...

-2
//erase part 
if(mouseSwiped) 
{ 

//**************Working Code*************// 


UIGraphicsBeginImageContext(frontImage.frame.size); 
[frontImage.image drawInRect:CGRectMake(0, 0, frontImage.frame.size.width, frontImage.frame.size.height)]; 
CGContextSetLineCap(UIGraphicsGetCurrentContext(),kCGImageAlphaNone); //kCGImageAlphaPremultipliedLast); 
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10); 
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1, 0, 0, 10); 
CGContextBeginPath(UIGraphicsGetCurrentContext()); 
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); 
CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(lastPoint.x, lastPoint.y, 10, 10)); 
CGContextStrokePath(UIGraphicsGetCurrentContext()); 
frontImage.image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 


lastPoint = currentPoint; 

mouseMoved++; 

if (mouseMoved == 10) 
{ 
    mouseMoved = 0; 
} 
} 
+0

Это не работает. В свою очередь, рисует коричневую линию над изображением. – Shailesh