2012-10-26 17 views
8

Pracuję w aplikacji, w której muszę narysować histogram dowolnego wprowadzonego obrazu. Mogę narysować Histogram, ale nie jest tak ostry jak w PREVIEW w Mac OS.Histogram rysunkowy potrzebuje większej dokładności w iPhonie

Jako kod jest zbyt duży, mam wysłał go do GitHub Click here to Download

wartości RGB są odczytywane w

-(void)readImage:(UIImage*)image 
{ 
    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); 

    for (int yy=0;yy<height; yy++) 
    { 
     for (int xx=0; xx<width; xx++) 
     { 
      // Now your rawData contains the image data in the RGBA8888 pixel format. 
      int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel; 
      for (int ii = 0 ; ii < 1 ; ++ii) 
      { 
       CGFloat red = (rawData[byteIndex]  * 1.0) ; 
       CGFloat green = (rawData[byteIndex + 1] * 1.0) ; 
       CGFloat blue = (rawData[byteIndex + 2] * 1.0) ; 
       // CGFloat alpha = (rawData[byteIndex + 3] * 1.0)/255.0; 
       byteIndex += 4; 

       // TYPE CASTING ABOVE FLOAT VALUES TO THAT THEY CAN BE MATCHED WITH ARRAY'S INDEX. 

       int redValue = (int)red; 
       int greenValue = (int)green; 
       int blueValue = (int)blue; 


       // THESE COUNTERS COUNT " TOTAL NUMBER OF PIXELS " FOR THAT Red , Green or Blue Value IN ENTIRE IMAGE. 

       fltR[redValue]++; 
       fltG[greenValue]++; 
       fltB[blueValue]++;     
      } 
     } 
    } 
    [self makeArrays]; 
    free(rawData); 
} 

I przechowywanych wartości w zmiennych c tablicy FLTR, fltG, fltB.

mam klasy ClsDrawPoint ma elementy

@property CGFloat x; 
@property CGFloat y; 

Następnie wytwarza się układ zawierający przedmioty o [] jest wskaźnikiem FLTR ClsDrawPoint jako wartość X i wartość tego wskaźnika jako wartości y.

tablica jest przygotowany i wykres jest zasysane

-(void)makeArrays 

metodą

można zobaczyć wynik

enter image description here

Obecnie jego nie jest tak dokładna, jak to jest podgląd w mac dla tego samego obrazu. Możesz otworzyć obraz w aplikacji PREVIEW na Macu i w Narzędzia> AdjustColor, zobaczysz Histogram tego obrazu. Myślę, że jeśli mój wykres jest zgodny, to będzie ostrzejszy. Prosimy o sprawdzenie mojego kodu i zasugeruj, czy i tak znajdziesz go, aby był dokładniejszy.

Odpowiedz

4

Wyciągnąłem twoją próbkę z Githuba i odkryłem, że twoja metoda drawRect: w ClsDraw rysuje linie o szerokości jednego piksela. Skoki są wyśrodkowane na linii, a szerokość 1 dzieli się na półpiksele, co wprowadza wygładzanie.

Przesunąłem poziome przesunięcia o pół piksela, a rendering wygląda ostro. Nie bałam się pionowych przesunięć, ale żeby je ostrzyć, trzeba je zaokrąglić, a następnie przesunąć je również do przesunięcia o pół piksela. I tylko się następujące zmiany:

#define OFFSET_X 0.5 

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef ctx = UIGraphicsGetCurrentContext(); 
    if ([arrPoints count] > 0) 
    { 
    CGContextSetLineWidth(ctx, 1); 
    CGContextSetStrokeColorWithColor(ctx, graphColor.CGColor); 
    CGContextSetAlpha(ctx, 0.8); 
    ClsDrawPoint *objPoint; 
    CGContextBeginPath(ctx); 

    for (int i = 0 ; i < [arrPoints count] ; i++) 
    { 
     objPoint = [arrPoints objectAtIndex:i]; 
     CGPoint adjustedPoint = CGPointMake(objPoint.x+OFFSET_X, objPoint.y); 
     CGContextMoveToPoint(ctx, adjustedPoint.x, 0); 
     CGContextSetLineCap(ctx, kCGLineCapRound); 
     CGContextSetLineJoin(ctx, kCGLineJoinRound); 
     CGContextAddLineToPoint(ctx, adjustedPoint.x, adjustedPoint.y); 
     CGContextMoveToPoint(ctx, adjustedPoint.x, adjustedPoint.y); 
     CGContextStrokePath(ctx); 
    } 
    } 
} 

zauważy nowy OFFSET_X oraz wprowadzenie adjustedPoint.

Można także rozważyć użycie instancji w instancji NSValue dla punktów zamiast niestandardowej klasy ClsDrawPoint, chyba że użytkownik zamierza dodać dodatkowe zachowanie lub właściwości. Więcej szczegółów dostępnych here.

+1

dzięki za NSValue, naprawdę nie wiedziałem tego. Wykres jest dokładny, ale nadal nie jest tak dokładny, jak na podglądzie. Czy możesz mi zasugerować więcej ??? – HarshIT

+1

Próbowałem ciężko, ale nie mogłem uzyskać więcej ... dzięki. te głosy są do Twojej pracy ręcznej ... – HarshIT