0


iOSデバイスのメイン画面に関連付けられているサーフェスを取得し、そこから画像を作成して保存しようとしています。これは、この質問に関連しています-iOSアプリからスクリーンショットを撮る-ディスプレイレコーダーをエミュレートします(内部のクエリ)
コードは次のとおりです。

    IOMobileFramebufferConnection connect;
    kern_return_t result;

    io_service_t framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleH1CLCD"));
    if(!framebufferService)
        framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleM2CLCD"));
    if(!framebufferService)
        framebufferService = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleCLCD"));

    result = IOMobileFramebufferOpen(framebufferService, mach_task_self(), 0, &connect);

    result = IOMobileFramebufferGetLayerDefaultSurface(connect, 0, &screenSurface);

    uint32_t aseed;
    IOSurfaceLock(screenSurface, kIOSurfaceLockReadOnly, &aseed);
    uint32_t width = IOSurfaceGetWidth(screenSurface);
    uint32_t height = IOSurfaceGetHeight(screenSurface);

    CFMutableDictionaryRef dict;
    int pitch = width*4, size = 4*width*height;
    int bPE=4;
    char pixelFormat[4] = {'A','R','G','B'};
    dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    CFDictionarySetValue(dict, kIOSurfaceIsGlobal, kCFBooleanTrue);
    CFDictionarySetValue(dict, kIOSurfaceBytesPerRow, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch));
    CFDictionarySetValue(dict, kIOSurfaceBytesPerElement, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bPE));
    CFDictionarySetValue(dict, kIOSurfaceWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width));
    CFDictionarySetValue(dict, kIOSurfaceHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height));
    CFDictionarySetValue(dict, kIOSurfacePixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat));
    CFDictionarySetValue(dict, kIOSurfaceAllocSize, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &size));

    IOSurfaceRef destSurf = IOSurfaceCreate(dict);
    IOSurfaceAcceleratorRef outAcc;
    IOSurfaceAcceleratorCreate(NULL, 0, &outAcc);

    CFDictionaryRef ed = (__bridge CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys: nil];
    IOSurfaceAcceleratorTransferSurface(outAcc, screenSurface, destSurf, ed, NULL);

    IOSurfaceUnlock(screenSurface, kIOSurfaceLockReadOnly, &aseed);

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, IOSurfaceGetBaseAddress(destSurf), (width*height*4), NULL);
    CGImageRef cgImage=CGImageCreate(width, height, 8, 8*4, IOSurfaceGetBytesPerRow(destSurf), CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little, provider, NULL, YES, kCGRenderingIntentDefault);
    UIImage *image = [UIImage imageWithCGImage: cgImage];
    CGImageRelease(cgImage);
    UIImageWriteToSavedPhotosAlbum(image, self, nil, nil);


しかし、私が得るのは私の写真フォルダに保存された空白の画像だけです。私がどこで間違っているのか助けてください。ありがとう。

4

2 に答える 2

2

しばらく前に、このテーマについて何かを見たのを覚えています(バックグラウンドでスクリーンショットを撮っています)。私が見た正確な場所とコードを見つけることができませんでした。私が自分に残した唯一のメモは、createScreenIOSurfaceの使用法でした

私は少しグーグルして、いくつかの言及を見つけました:

アプリがバックグラウンドにあるときにスクリーンショットを取得しますか?(プライベートAPIが許可されています)

https://github.com/rpetrich/FastBlurredNotificationCenter/blob/master/Tweak.x

http://pastie.org/pastes/3734430

私が覚えているように、コードはあなたが示したものよりもはるかにコンパクトでした。

于 2012-12-14T20:21:28.350 に答える
1

指定されたコードは、バックグラウンドで実行すると機能します。iOSデバイスのディスプレイの最上面のスクリーンショットを撮ります。
直面した問題は、アプリ内で、アプリ用に作成された空白のビューのスクリーンショットを撮っていたという事実が原因でした。
ただし、最低2秒間隔でスクリーンショットを撮る必要があります。そうしないと、OSがアプリを一時停止します。それを改善する方法についての提案は役に立ちます。

于 2012-12-17T04:08:57.847 に答える