【问题标题】:Creating an image out of the ios surface and saving it从 ios 表面创建图像并保存
【发布时间】:2012-12-14 04:36:47
【问题描述】:


我正在尝试获取与 ios 设备主屏幕关联的表面,从中创建图像并保存。这与这个问题有关 - Taking Screenshots from iOS app - emulating Display recorder (query on the internals)
代码如下:

    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);


但我得到的只是保存在我的照片文件夹中的空白图像。请帮忙看看我哪里出错了。 谢谢。

【问题讨论】:

    标签: ios ios5 ios4 iphone-privateapi


    【解决方案1】:

    我记得前段时间我看到了一些关于这个主题的东西(在后台截屏)。我无法找到我看到的确切位置和代码。我给自己留下的唯一笔记是 createScreenIOSurface 的用法

    我用谷歌搜索了一下,发现有几个提到:

    Get a screenshot while App is in background? (Private APIs allowed)

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

    http://pastie.org/pastes/3734430

    我记得代码比你展示的要紧凑。

    【讨论】:

    • 感谢您的链接。所以,我有指定的代码工作,它确实截取了最上面的表面。但是,我必须休眠 2 秒才能使其继续工作而不会暂停。您提到的代码很紧凑。但它会提高性能吗?
    【解决方案2】:

    如果您在后台运行指定的代码,它就会起作用。它确实在 iOS 设备的显示屏上截取了最上面的表面。
    面临的问题是由于在应用程序内部,它正在为应用程序创建的空白视图截屏。
    但是,您必须以至少 2 秒的间隔截取屏幕截图,否则操作系统会暂停您的应用程序。任何有关如何改进的建议都会有所帮助。

    【讨论】:

    • 嗨,Hrishikesh_Pardeshi,您是否找到了一种方法来改进代码以间隔截取屏幕截图
    猜你喜欢
    • 2015-01-27
    • 2020-10-24
    • 1970-01-01
    • 1970-01-01
    • 2019-02-02
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    相关资源
    最近更新 更多