2011-07-15 4 views
1

カメラ画像(または写真集からの画像)へのアクセスにいくつかの問題があります。サイズ変更された画像の生のピクセルデータにアクセスする際のエラー

UIImageのサイズを変更した後(私はいくつかの異なるサイズ変更メソッドをテストしましたが、それらはすべて同じエラーに繋がります)複雑なアルゴリズムに渡すために個々のピクセルにアクセスしたいと思います。

問題は、CGImageGetDataProvider - > EXC_BAD_ACCESSエラーが発生する生のピクセルデータにアクセスするときに、画像サイズ(たとえば、幅* 4)に一致しないbytesPerRow値がしばしばあることです。

たぶん、私たちはここにiOSのバグを持っている...

それにもかかわらず、ここでのコードは次のとおりです。その後

// UIImage capturedImage from Camera 

CGImageRef capturedImageRef = capturedImage.CGImage; 

// getting bits per component from capturedImage 
size_t bitsPerComponentOfCapturedImage = CGImageGetBitsPerComponent(capturedImageRef); 
CGImageAlphaInfo alphaInfoOfCapturedImage = CGImageGetAlphaInfo(capturedImageRef); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

// calculate new size from interface data. 
// with respect to aspect ratio 

// ... 

// newWidth = XYZ; 
// newHeight = XYZ; 

CGContextRef context = CGBitmapContextCreate(NULL, newWidth, newHeight, bitsPerComponentOfCapturedImage,0 , colorSpace, alphaInfoOfCapturedImage); 

// I also tried to make use getBytesPerRow for CGBitmapContextCreate resulting in the same error 

// if image was rotated 
if(capturedImage.imageOrientation == UIImageOrientationRight) { 
    CGContextRotateCTM(context, -M_PI_2); 
    CGContextTranslateCTM(context, -newHeight, 0.0f); 
} 

// draw on new context with new size 
CGContextDrawImage(context, CGRectMake(0, 0, newWidth, newHeight), capturedImage.CGImage); 

CGImageRef scaledImage=CGBitmapContextCreateImage(context); 

// release 
CGColorSpaceRelease(colorSpace); 
CGContextRelease(context); 
theImage = [UIImage imageWithCGImage: scaledImage]; 

CGImageRelease(scaledImage); 

、私はのためだから

CGImageRef imageRef = theImage.CGImage; 
NSData *data  = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(imageRef)); 

unsigned char *pixels  = (unsigned char *)[data bytes]; 

// create a new image from the modified pixel data 
size_t width     = CGImageGetWidth(imageRef); 
size_t height     = CGImageGetHeight(imageRef); 
size_t bitsPerComponent   = CGImageGetBitsPerComponent(imageRef); 
size_t bitsPerPixel    = CGImageGetBitsPerPixel(imageRef); 
size_t bytesPerRow    = CGImageGetBytesPerRow(imageRef); 

CGDataProviderRef provider  = CGDataProviderCreateWithData(NULL, pixels, [data length], NULL); 

NSLog(@"bytesPerRow: %f ", (float)bytesPerRow); 
NSLog(@"Image width: %f ", (float)width); 
NSLog(@"Image height: %f ", (float)height); 

// manipulate the individual pixels 
for(int i = 0; i < [data length]; i += 4) { 

    // accessing (float) pixels[i]; 
    // accessing (float) pixels[i+1]; 
    // accessing (float) pixels[i+2]; 

} 

によってスケーリングされた画像にアクセスしたいですたとえば、511x768ピクセルの画像にアクセスし、290x436にスケールすると、次の出力が得られます。

画像の幅: 290.000000

画像の高さ: 436.000000

bitsPerComponent: 8.000000

bitsPerPixel: 32.000000

bytesPerRow: 1184.000000

となり、bytesPerRow(ココアによって自動的に選択されますが)はではなく、は画像の幅に一致します。

私はあなたがそれゆえ、無効な​​結果を受けて、可能なラインパディングを無視しているXcodeの4

+0

作業用としてpng表現に変換する使用 – faroit

答えて

1

上のiOS SDK 4.3を使用して任意のヘルプ


を見てみたいです。次のコードを追加し、ループを置き換えます。

size_t bytesPerPixel = bitsPerPixel/bitsPerComponent; 
//calculate the padding just to see what is happening 
size_t padding = bytesPerRow - (width * bytesPerPixel); 
size_t offset = 0; 
// manipulate the individual pixels 
while (offset < [data length]) 
{ 
    for (size_t x=0; x < width; x += bytesPerPixel) 
    { 
    // accessing (float) pixels[offset+x]; 
    // accessing (float) pixels[offset+x+1]; 
    // accessing (float) pixels[offset+x+2]; 
    } 
    offset += bytesPerRow; 
}; 

補遺:行パディングの基礎となる理由は、32ビット境界に、個々の行のメモリアクセスを最適化されています。これは実際には非常に一般的であり、最適化のために行われます。

+0

最初。はい、パディングがあります。ビューのアスペクト比とデバイスの回転に応じて、指定された幅にリサイズする場合、指定された高さにリサイズするとパディングはありません。 しかし、私はまだあなたが話していた「ラインパディング」がなぜ起こっているのか理解できません。根本的な理由は何ですか?上記以外の質問に答えるために補足が追加されました: – faroit

+0

私の解決策/回答があなたの問題を解決したら、私の答えの左側にある灰色のチェックマークをチェックし、上向きの矢印を使ってupvoteしてください。 – Till

+0

ご協力いただきありがとうございます! 私はUiimageのサイズを変更し、サイズ変更されたイメージのCGI​​mageRef表現にアクセスすると、このパディングを常にチェックする必要があります。これは、画像を新しいCALayerにレンダリングするか、画像自体に描画してから、後で元のピクセル値にアクセスするときにも適用されますか? これを回避する方法はありますか(例えば、ゆっくりとサイズを変更する)、きれいに「割り当てられた」イメージを持っていますか? – faroit

関連する問題