8

入力した画像のヒストグラムを描画する必要があるアプリで作業しています。ヒストグラムは正常に描画できますが、MacOSのPREVIEWほど鮮明ではありません。

コードが大きすぎるため、GitHubにアップロードしました。ダウンロードするにはここをクリックしてください

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;

次に、fltR []のインデックスをX値として、そのインデックスの値をY値として持つClsDrawPointのオブジェクトを含む配列を準備しました。

配列を作成し、グラフを描画します

-(void)makeArrays

方法

あなたは結果を見るかもしれません

ここに画像の説明を入力してください

現在、同じ画像のMacのプレビューにあるほど正確ではありません。Macのプレビューアプリと[ツール]>[色の調整]で画像を開くと、その画像のヒストグラムを確認できます。私のグラフが正確であれば、より鮮明になると思います。親切に私のコードをチェックして、それをより正確にするためにとにかく見つけたら私に提案してください。

4

1 に答える 1

4

あなたのサンプルを Github から取り出したところ、あなたのdrawRect:方法ClsDrawが 1 ピクセル幅の線を描いていることがわかりました。ストロークは線の中央に配置され、幅が 1 の場合、ストロークは半ピクセルに分割され、アンチエイリアシングが導入されます。

水平方向のオフセットを 0.5 ピクセル移動したところ、レンダリングがシャープに見えます。私は垂直方向のオフセットを台無しにしませんでしたが、それらをシャープにするには、それらを丸めてからハーフピクセルのオフセットにも移動する必要があります. 次の変更のみを行いました。

#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のインスタンスに詰め込まれたを使用することを検討することもできます。詳細については、こちらをご覧くださいNSValueClsDrawPoint

于 2012-10-27T14:40:12.390 に答える