绘制直方图在iPhone中需要更高的精度

时间:2012-10-26 11:31:55

标签: iphone ios uiimage histogram

我在一个应用程序中工作,我需要绘制任何输入图像的直方图。我可以成功绘制直方图,但它不像Mac OS中的PREVIEW那样清晰。

由于代码太大,我已将其上传到GitHub Click here to Download

RGB值读入

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

我将值存储在c数组变量fltR,fltG,fltB。

我有一个ClsDrawPoint类,它有成员

@property CGFloat x;
@property CGFloat y;

然后准备一个包含ClsDrawPoint对象的数组,其中fltR []的索引为X值,该索引的值为Y值。

准备

数组并在

中绘制图表
-(void)makeArrays

方法

您可能会看到结果

enter image description here

目前它不像在同一图像的预览中那样精确。您可以在Mac中的PREVIEW应用程序中打开图像,然后在工具&gt; AdjustColor中,您将能够看到该图像的直方图。 我认为如果我的图表是有效的,它会更清晰。请检查我的代码,如果您发现无论如何都要建议我更准确。

1 个答案:

答案 0 :(得分:4)

我从Github上取下你的样本,发现drawRect:中的ClsDraw方法是绘制一个像素宽的线条。笔划以线为中心,宽度为1时,笔划被分成半像素,这会引入抗锯齿。

我将水平偏移移动了半个像素,渲染看起来很清晰。我没有弄乱垂直偏移,但要使它们锐利,你需要将它们四舍五入,然后将它们移动到半像素偏移。我只做了以下改变:

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

请注意新的OFFSET_XadjustedPoint的介绍。

除非您计划添加一些其他行为或属性,否则您可能还会考虑将CGPoint填充到NSValue实例中,而不是自定义类ClsDrawPoint。更多详细信息here