我在一个应用程序中工作,我需要绘制任何输入图像的直方图。我可以成功绘制直方图,但它不像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
方法
您可能会看到结果
目前它不像在同一图像的预览中那样精确。您可以在Mac中的PREVIEW应用程序中打开图像,然后在工具&gt; AdjustColor中,您将能够看到该图像的直方图。 我认为如果我的图表是有效的,它会更清晰。请检查我的代码,如果您发现无论如何都要建议我更准确。
答案 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_X
和adjustedPoint
的介绍。
除非您计划添加一些其他行为或属性,否则您可能还会考虑将CGPoint
填充到NSValue
实例中,而不是自定义类ClsDrawPoint
。更多详细信息here。