0

この機能を使用して、IPAD アプリのスクリーンショットを作成しています。プロジェクトで Sparrow Framework を使用しています。SPDisplayObject は、OpenGl-ES ベースのレンダリングを使用します。

@implementation SPDisplayObject (ScreenshotFromSPDisplayObject)

- (UIImage *)getImageScreenshot{

int WIDTH = 1024;
int HEIGHT = 768;

CGSize size = CGSizeMake(WIDTH,HEIGHT);
//Create un buffer for pixels
GLuint bufferLenght=size.width*size.height*4;
GLubyte *buffer = (GLubyte *) malloc(bufferLenght);

//Read Pixels from OpenGL
glReadPixels(0,0,size.width,size.height,GL_RGBA,GL_UNSIGNED_BYTE,buffer);
//Make data provider with data.
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, bufferLenght, NULL);

//Configure image
int bitsPerComponent = 8;
int bitsPerPixel = 32;
int bytesPerRow = 4 * size.width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
CGImageRef iref = CGImageCreate(size.width,size.height,bitsPerComponent,bitsPerPixel,bytesPerRow,colorSpaceRef,bitmapInfo,provider,NULL,NO,renderingIntent);

uint32_t *pixels = (uint32_t *)malloc(bufferLenght);
CGContextRef context = CGBitmapContextCreate(pixels, WIDTH, HEIGHT, 8, WIDTH*4, CGImageGetColorSpace(iref), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGContextTranslateCTM(context,0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextDrawImage(context, CGRectMake(0.0, 0.0, size.width, size.height), iref);
UIImage* screenshot = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];

UIGraphicsEndImageContext();

//free memory
CGColorSpaceRelease(colorSpaceRef);
CGDataProviderRelease(provider);
CGImageRelease(iref);
CGContextRelease(context);
free(buffer);
free(pixels);

return screenshot;
}

@end

UIViewController から次のように使用します。

@interface
    UIImageView *screenShot;
    UIImage *tempImage;

-(void) deactivePage
{
// attach screenshot
tempImage = [self.stage getImageScreenshot];
screenShot = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,1024,768)];
screenShot.image = tempImage;  
[self.view addSubview:screenShot];
}

- (void)dealloc 
{
screenShot.image = nil;
[screenShot removeFromSuperview];
[screenShot release];
[super dealloc];
}

UIViewController が解放され、割り当てが解除されます。「deactivePage」関数が呼び出されてから 5 秒後。スクリーンショットはビュー遷移に使用されます。

スクリーンショットを撮るのは魅力的ですが、スクリーンショットごとにアプリが約 10 MB 大きくなるため、アプリがクラッシュするまで約 15 回実行できます。

では、漏れはどこにあるのでしょうか?ハマった.. :-(

4

2 に答える 2

1

getImageScreenshot 関数では、次のようにします。

UIImage* screenshot = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];

CGImageRef を作成し、そこから UIImage を作成 (自動解放) します。ここで何が起こるかというと、この CGImageRef は生きたまま解放されないため、リークしています。

代わりに、次のことを行う必要があります。


CGImageRef myCGImage = CGBitmapContextCreateImage(context);
UIImage* screenshot = [UIImage imageWithCGImage:myCGImage];
CGImageRelease(myCGImage);

Instruments (Leaks または Heapshots) を使用して表示しようとしましたか? これらの CGImareRef 要素がまだ生きていることがわかるはずです。

于 2011-02-26T16:56:08.843 に答える
0

UIViewController がダウンしているときに tempImage の割り当てを解除する場所がわかりません。

于 2011-02-26T16:47:48.527 に答える