2012-01-16 183 views
1

我正在iPhone應用程序中實施填充填充油漆桶工具,並且遇到了一些麻煩。用戶可以繪製,並且我希望油漆桶允許他們點擊一個點並填充所連接的顏色的所有內容。iPhone油漆桶

這裏是我的想法: 1)開始在該點的用戶選擇 2)保存點檢測到的NSMutableArray所以他們沒有得到重新檢查 3)如果在當前點的像素顏色是相同的作爲原始點擊點,保存到稍後要更改的數組中 4)如果當前點的像素顏色與原始點不同,則返回。 (邊界) 5)完成掃描後,通過像素陣列進行更改並將其設置爲新顏色。

但是到目前爲止還沒有解決問題。任何幫助或知識如何做到這一點將不勝感激!這是我的代碼。

-(void)flood:(int)x:(int)y 
{ 

    //NSLog(@"Flood %i %i", x, y); 

    CGPoint point = CGPointMake(x, y); 
    NSValue *value = [NSValue valueWithCGPoint:point]; 

    //Don't repeat checked pixels 
    if([self.checkedFloodPixels containsObject:value]) 
    { 
     return; 
    } 

    else 
    { 
     //If not checked, mark as checked 
     [self.checkedFloodPixels addObject:value]; 

     //Make sure in bounds 
     if([self isOutOfBounds:x:y] || [self reachedStopColor:x:y]) 
     { 
      return; 
     } 


     //Go to adjacent points 
     [self flood:x+1:y]; 
     [self flood:x-1:y]; 
     [self flood:x:y+1]; 
     [self flood:x:y-1]; 
    } 
} 

- (BOOL)isOutOfBounds:(int)x:(int)y 
{ 
    BOOL outOfBounds; 

    if(y > self.drawImage.frame.origin.y && y < (self.drawImage.frame.origin.y + self.drawImage.frame.size.height)) 
    { 
     if(x > self.drawImage.frame.origin.x && x < (self.drawImage.frame.origin.x + self.drawImage.frame.size.width)) 
     { 
      outOfBounds = NO; 
     } 

     else 
     { 
      outOfBounds = YES; 
     } 
    } 

    else 
    { 
     outOfBounds = YES; 
    } 

    if(outOfBounds) 
     NSLog(@"Out of bounds"); 

    return outOfBounds; 
} 

- (BOOL)reachedStopColor:(int)x:(int)y 
{ 
    CFDataRef theData = CGDataProviderCopyData(CGImageGetDataProvider(self.drawImage.image.CGImage)); 

    const UInt8 *pixelData = CFDataGetBytePtr(theData); 

    int red = 0; 
    int green = 1; 
    int blue = 2; 

    //RGB for point being checked 
    float newPointR; 
    float newPointG; 
    float newPointB; 

    //RGB for point initially clicked 
    float oldPointR; 
    float oldPointG; 
    float oldPointB; 

    int index; 
    BOOL reachedStopColor = NO; 


    //Format oldPoint RBG - pixels are every 4 bytes so round to 4 
    index = lastPoint.x * lastPoint.y; 

    if(index % 4 != 0) 
    { 
     index -= 2; 
     index /= 4; 
     index *= 4; 
    } 

    //Get into 0.0 - 1.0 value 
    oldPointR = pixelData[index + red]; 
    oldPointG = pixelData[index + green]; 
    oldPointB = pixelData[index + blue]; 

    oldPointR /= 255.0; 
    oldPointG /= 255.0; 
    oldPointB /= 255.0; 

    oldPointR *= 1000; 
    oldPointG *= 1000; 
    oldPointB *= 1000; 

    int oldR = oldPointR; 
    int oldG = oldPointG; 
    int oldB = oldPointB; 

    oldPointR = oldR/1000.0; 
    oldPointG = oldG/1000.0; 
    oldPointB = oldB/1000.0; 

    //Format newPoint RBG 
    index = x*y; 

    if(index % 4 != 0) 
    { 
     index -= 2; 
     index /= 4; 
     index *= 4; 
    } 

    newPointR = pixelData[index + red]; 
    newPointG = pixelData[index + green]; 
    newPointB = pixelData[index + blue]; 

    newPointR /= 255.0; 
    newPointG /= 255.0; 
    newPointB /= 255.0; 

    newPointR *= 1000; 
    newPointG *= 1000; 
    newPointB *= 1000; 

    int newR = newPointR; 
    int newG = newPointG; 
    int newB = newPointB; 

    newPointR = newR/1000.0; 
    newPointG = newG/1000.0; 
    newPointB = newB/1000.0; 

    //Check if different color 
    if(newPointR < (oldPointR - 0.02f) || newPointR > (oldPointR + 0.02f)) 
    { 
     if(newPointG < (oldPointG - 0.02f) || newPointG > (oldPointG + 0.02f)) 
     { 
      if(newPointB < (oldPointB - 0.02f) || newPointB > (oldPointB + 0.02f)) 
      { 
       reachedStopColor = YES; 
       NSLog(@"Different Color"); 
      } 

      else 
      { 
       NSLog(@"Same Color3"); 

       NSNumber *num = [NSNumber numberWithInt:index]; 
       [self.pixelsToChange addObject:num]; 
      } 
     } 

     else 
     { 
      NSLog(@"Same Color2"); 

      NSNumber *num = [NSNumber numberWithInt:index]; 
      [self.pixelsToChange addObject:num]; 
     } 
    } 

    else 
    { 
     NSLog(@"Same Color1"); 

     NSNumber *num = [NSNumber numberWithInt:index]; 
     [self.pixelsToChange addObject:num]; 
    } 

    CFRelease(theData); 

    if(reachedStopColor) 
     NSLog(@"Reached stop color"); 

    return reachedStopColor; 
} 

-(void)fillAll 
{ 
    CGContextRef ctx; 
    CGImageRef imageRef = self.drawImage.image.CGImage; 
    NSUInteger width = CGImageGetWidth(imageRef); 
    NSUInteger height = CGImageGetHeight(imageRef); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    unsigned char *rawData = malloc(height * width * 4); 
    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); 

    int red = 0; 
    int green = 1; 
    int blue = 2; 

    int index; 
    NSNumber *num; 

    for(int i = 0; i < [self.pixelsToChange count]; i++) 
    { 
     num = [self.pixelsToChange objectAtIndex:i]; 

     index = [num intValue]; 

     rawData[index + red] = (char)[[GameManager sharedManager] RValue]; 
     rawData[index + green] = (char)[[GameManager sharedManager] GValue]; 
     rawData[index + blue] = (char)[[GameManager sharedManager] BValue]; 
    } 

    ctx = CGBitmapContextCreate(rawData, 
          CGImageGetWidth(imageRef), 
          CGImageGetHeight(imageRef), 
          8, 
          CGImageGetBytesPerRow(imageRef), 
          CGImageGetColorSpace(imageRef), 
          kCGImageAlphaPremultipliedLast); 

    imageRef = CGBitmapContextCreateImage (ctx); 
    UIImage* rawImage = [UIImage imageWithCGImage:imageRef]; 

    CGContextRelease(ctx); 

    self.drawImage.image = rawImage; 

    free(rawData); 
} 
+1

那麼,什麼是不是現在的工作? – 2012-01-16 22:41:05

+0

運行fillAll後,它會將像素着色到完全錯誤的位置,而不是在我繪製的圓圈內。它就像是圖像頂部的散點圖,當我畫出底部的圓時 – 2012-01-16 22:59:18

+0

這不足以確定哪裏出錯。如果你在外部填充相同的顏色,可能你的'reachedStopColor'方法有問題。 – livingtech 2012-01-16 23:13:12

回答

1

,所以我發現這個(我知道現在的問題可能是無關緊要的,但人誰仍在尋找這樣的事情是不是):

在象素從上下文(從修改後的代碼獲取顏色here):

- (UIColor*) getPixelColorAtLocation:(CGPoint)point { 
UIColor* color; 
CGContextRef cgctx = UIGraphicsGetCurrentContext(); 

unsigned char* data = CGBitmapContextGetData (cgctx); 
if (data != NULL) { 
    int offset = 4*((ContextWidth*round(point.y))+round(point.x)); //i dont know how to get ContextWidth from current context so i have it as a instance variable in my code 
    int alpha = data[offset]; 
    int red = data[offset+1]; 
    int green = data[offset+2]; 
    int blue = data[offset+3]; 
    color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)]; 
} 

if (data) { free(data); } 

return color; 

}

和填充算法:是here

這就是我正在使用的,但填充本身與CGPath繪圖樣式相比非常慢。芹苴,如果你渲染屏幕外和/或你填寫動態像這樣它看起來有點酷:

here