【问题标题】:How to take screenshot of entire screen on a Jailbroken iOS Device?如何在越狱的 iOS 设备上截取整个屏幕?
【发布时间】:2016-01-26 22:12:59
【问题描述】:

我需要对包括状态栏在内的整个屏幕进行截图,我使用CARenderServerRenderDisplay 来实现这一点,它在 iPad 上可以正常工作,但在 iPhone 6 Plus 上就出错了。作为代码中的*标记部分,如果我设置width=screenSize.width*scaleheight=screenSize.height*scale,它会导致崩溃,如果我只是将它们更改为:width=screenSize.height*scaleheight=screenSize.width*scale,它会起作用,但会产生这样的图像: ,我尝试了很多,但没有找到原因,有人知道吗?我希望我已经描述得够清楚了。

- (void)snapshot
{
    CGFloat scale = [UIScreen mainScreen].scale;
    CGSize screenSize = [UIScreen mainScreen].bounds.size;

    //*********** the place where problem appears        
    size_t width = screenSize.height * scale;
    size_t height = screenSize.width * scale;
    //***********

    size_t bytesPerElement = 4;
    OSType pixelFormat = 'ARGB';
    size_t bytesPerRow = bytesPerElement * width;
    size_t surfaceAllocSize = bytesPerRow * height;

    NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithBool:YES], kIOSurfaceIsGlobal,
                                [NSNumber numberWithUnsignedLong:bytesPerElement], kIOSurfaceBytesPerElement,
                                [NSNumber numberWithUnsignedLong:bytesPerRow], kIOSurfaceBytesPerRow,
                                [NSNumber numberWithUnsignedLong:width], kIOSurfaceWidth,
                                [NSNumber numberWithUnsignedLong:height], kIOSurfaceHeight,
                                [NSNumber numberWithUnsignedInt:pixelFormat], kIOSurfacePixelFormat,
                                [NSNumber numberWithUnsignedLong:surfaceAllocSize], kIOSurfaceAllocSize,
                                nil];

    IOSurfaceRef destSurf = IOSurfaceCreate((__bridge CFDictionaryRef)(properties));

    IOSurfaceLock(destSurf, 0, NULL);
    CARenderServerRenderDisplay(0, CFSTR("LCD"), destSurf, 0, 0);
    IOSurfaceUnlock(destSurf, 0, NULL);

    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];
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}

【问题讨论】:

  • 我的环境是 iOS 9.0.2 的 iPhone 6 Plus 越狱。
  • 您的提供者只能提供width * height * 4 字节,但CGImageCreate 会要求它提供IOSurfaceGetBytesPerRow(destSurf) * height * 4 字节。也许这就是它崩溃的原因?
  • @robmayoff,我刚才测试了一下,在CARenderServerRenderDisplay 崩溃了。

标签: ios objective-c screenshot jailbreak iphone-privateapi


【解决方案1】:

如果你在越狱环境中,可以使用私有UIImage方法_UICreateScreenUIImage

OBJC_EXTERN UIImage *_UICreateScreenUIImage(void);

// ...

- (void)takeScreenshot {
    UIImage *screenImage = _UICreateScreenUIImage();
    // do something with your screenshot
}

此方法使用CARenderServerRenderDisplay 更快地渲染整个设备屏幕。它取代了在 iOS 7 SDK 的 arm64 版本中删除的 UICreateScreenImageUIGetScreenImage 方法。

【讨论】:

  • 你知道如何在 Xamarin (C#) 中声明/调用这个方法吗?
  • @Benj 嘿,我不确定这在 Xamarin 中如何工作。有没有办法加载或运行 C 函数?就是这样。
  • @JAL thx,我让它在这里工作stackoverflow.com/questions/40099954/… 只是挣扎了一段时间在哪个库中寻找方法
猜你喜欢
  • 2014-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 2020-05-15
  • 2016-07-15
  • 2016-09-19
  • 2014-06-05
相关资源
最近更新 更多