2012-10-26 10 views
8

Ich arbeite in einer App, in der ich Histogramm von jedem eingefügten Bild zeichnen muss. Ich kann Histogramm erfolgreich zeichnen, aber es ist nicht so scharf wie in PREVIEW in Mac OS.Zeichnung Histogramm benötigt mehr Genauigkeit in iPhone

als Code zu groß ist, ich es GitHub hochgeladen Click here to Download

Die RGB-Werte werden in

lesen
-(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 gespeicherten Werte in c Feldvariablen, FLTR, fltG, fltB.

Ich habe eine Klasse ClsDrawPoint es Mitglieder

@property CGFloat x; 
@property CGFloat y; 

Dann zubereitet ein Array mit Objekten der ClsDrawPoint mit FLTR [] 's Index als X-Wert und den Wert für diesen Index als Y Wert hat.

Array hergestellt und Graph in

-(void)makeArrays 

Methode

Sie das Ergebnis

enter image description here

gezogen wird Derzeit sehen kann seine nicht so genau, wie es in PREVIEW ist in Mac für das gleiche Bild. Sie können ein Bild in der PREVIEW-App auf Mac öffnen und unter Extras> Farbe anpassen können Sie das Histogramm dieses Bildes sehen. Ich denke, wenn mein Graph akkraten wird, wird es schärfer sein. Überprüfen Sie bitte meinen Code und schlagen Sie mir vor, wenn Sie es dennoch finden, um es genauer zu machen.

Antwort

4

Ich zog Ihre Probe von Github und fand, dass Ihre drawRect: Methode in ClsDraw Linien zeichnet, die ein Pixel breit sind. Striche sind auf der Linie zentriert und mit einer Breite von 1 wird der Strich in Halbpixel aufgeteilt, wodurch Anti-Aliasing eingeführt wird.

Ich bewegte Ihre horizontalen Offsets um einen halben Pixel und Rendering sieht scharf aus. Ich habe mich nicht mit vertikalen Offsets herumgeschlagen, aber um sie scharf zu machen, müsste man sie runden und sie dann auf einen Halb-Pixel-Offset verschieben. Ich habe nur die folgende Änderung:

#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); 
    } 
    } 
} 

Beachten Sie die neue OFFSET_X und die Einführung von adjustedPoint.

Sie auch ein CGPoint gestopft mit in eine NSValue Instanz für Ihre Punkte statt Ihrer benutzerdefinierten Klasse ClsDrawPoint betrachten könnte, es sei denn, Sie einige zusätzliche Verhalten oder Eigenschaften hinzufügen möchten. Mehr Details verfügbar here.

+1

danke für NSValue, das wusste ich wirklich nicht. Graph ist genau, aber immer noch nicht so genau wie in der Vorschau .. Können Sie mir mehr vorschlagen ??? – HarshIT

+1

ich habe versucht, aber konnte nicht mehr weg .... danke. Diese Stimmen sind für deine Handarbeit ... – HarshIT

Verwandte Themen