2009年7月26日日曜日

ピクセルデータへのアクセス

ゲームを作るのに必須の手段。ピクセルデータへの直接アクセス方法です。

元画像としてUIImageへアクセスします。

UIImage *img;
int width = CGImageGetWidth (img.CGImage);
int height = CGImageGetHeight (img.CGImage);
CFDataRef inputData = CGDataProviderCopyData (CGImageGetDataProvider (img.CGImage)); UInt8 *pData = (UInt8 *)CFDataGetBytePtr (inputData);

pDataに先頭アドレスが入っているのでここからRGBと明るさの順でアクセスできます。
変更後は新しいUIImageへ変換してあげます。

CFDataRef data = CFDataCreate (NULL, m_pData, CFDataGetLength (inputData));
CGDataProviderRef dataProv = CGDataProviderCreateWithCFData (data);
CGImageRef img = CGImageCreate (width, height, 8, 32, width * 4,
CGColorSpaceCreateDeviceRGB (),
kCGImageAlphaLast,
dataProv, NULL, 0, kCGRenderingIntentDefault);
UIImage *pImage = [[UIImage alloc] initWithCGImage:img];
[pImage autorelease];

pImageに新しいUIImageが出来上がります。後はこれを画面に表示させるもよし、保存するもよし。
UIImageを作り直さずに更新できればいいのですが、どうもよくわからないです。

最後に、使い終わったリソースを解放します。
どれを解放すればいいのかわからずに、UIImageViewのimageを更新し続けるとメモリリークして実機で落ちる現象が出てかなり悩みました。

CGImageRelease (img);
CGDataProviderRelease (dataProv);
CFRelease (data);
CFRelease (inputData);

矩形のコピーは以下のようにできます。

for (int y = 0; y < height; y ++) {
int posSrc = ((srcY + y) * widthSrcSize) + (srcX * 4);
int posDst = ((dstY + y) * widthDstSize) + (dstX * 4);
for (int x = 0; x < width; x ++, posSrc += 4, posDst += 4) {
UInt8 *pDataSrcTmp = &pDataSrc[posSrc];
UInt8 *pDataDstTmp = &m_pData[posDst];
pDataDstTmp[0] = pDataSrcTmp[0];
pDataDstTmp[1] = pDataSrcTmp[1];
pDataDstTmp[2] = pDataSrcTmp[2];
pDataDstTmp[3] = 255;
}
}

初めは UInt8 ではなく unsigned char でやっていたのですが、UInt8 にするとかなりスピードアップしました。何か変換が内部で走るのでしょうかね。

0 件のコメント:

コメントを投稿