首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何从MAC上的所有显示中获得屏幕截图?

如何从MAC上的所有显示中获得屏幕截图?
EN

Stack Overflow用户
提问于 2018-07-24 06:49:51
回答 1查看 0关注 0票数 0

我试图从所有与我的MAC连接的显示器截图到一张图片。我知道,如果每个监视器的屏幕截图都会保存到不同的图片中,我怎么能做到这一点,但这不是我想要的。我找到了CGGetDisplaysWithRect,但是我的解决方案不起作用,因为输出图片是空的。我想,CGDisplayCreateImageForect函数的问题(*因为第一个参数必须是CGDirectDisplayID类型,而不是CGDirectDisplayID*。但是我找不到函数,它可以用一些CGDirectDisplayID对象创建一个图片。

帮帮我!

代码语言:txt
复制
#include <stdio.h>
#include <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    CGDisplayCount displayCount;
    CGDirectDisplayID displays[32];
    memset(&displays, 0, 32);
    CGImageRef image[32];
    CGRect rect = CGRectNull;

    //grab the active displays
    if (CGGetActiveDisplayList(32, displays, &displayCount) != kCGErrorSuccess)
    {
        printf("Error occured: %s\n", strerror(errno));
    }

    //go through the list
    for (int i = 0; i < displayCount; i++)
    {
        if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay)
        {
            continue;
        }
        //return the smallest rectangle wich contain the two source rectangles
        rect = CGRectUnion(rect, CGDisplayBounds(displays[i]));
        if (CGRectIsNull(rect))
        {
            printf("Error: %s", strerror(errno));
        }
    }

    CGFloat whitePoint[3];
    CGFloat blackPoint[3];
    CGFloat gamma[3];
    CGFloat matrix[9];

    CGColorSpaceRef colorSpace = CGColorSpaceCreateCalibratedRGB (&whitePoint[3], &blackPoint[3], &gamma[3], &matrix[9] );
    if(colorSpace == NULL)
    {
        printf("Error: %s", strerror(errno));
    }

    //CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);

    //Create bmp context for image
    CGContextRef context = CGBitmapContextCreate(NULL,                      //data
                                          CGRectGetWidth(rect),         //width
                                          CGRectGetHeight(rect),        //height
                                          8,                            //bitPerComponent, for RGB must be 8
                                          0,                            //if data == NULL, it must be 0
                                          colorSpace,                   //colorspace device independent
                                          kCGBitmapByteOrderDefault );  //bitmap info
    if(context == NULL)
    {
        printf("Error: %s", strerror(errno));
    }

    //Create a snapshot image
    for (int i = 0; i < displayCount; i++)
    {
        image[i] = CGBitmapContextCreateImage(context);
        if(image == NULL)
        {
            //printf("Error: %s", strerror(errno));
        }
    }

    //Create destination to image
    CFURLRef url = CFURLCreateWithString ( kCFAllocatorDefault, CFSTR("out.bmp"), NULL);
    if(url == NULL)
    {
        printf("Error: %s", strerror(errno));
    }
    CFErrorRef *error = NULL;
    CFURLRef urlToFile = CFURLCreateFilePathURL ( kCFAllocatorDefault, url, error );
    if(urlToFile == NULL)
    {
        //printf("Error: %s", error);
    }

    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL(urlToFile, kUTTypeBMP, displayCount, NULL);
    if(imageDestination == NULL)
    {
        printf("Error: %s", strerror(errno));
    }

    //CGImageDestinationAddImage(imageDestination, image, NULL);
    CGImageDestinationFinalize(imageDestination);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    CFRelease(imageDestination);
    return 0;
} 

APDATE:我尝试了下面告诉我的smth,但是现在我遇到了错误:

错误:CGBitmapContextCreate:不支持参数组合:8整数位/组件;24位/像素;3分量颜色空间;kCGCGImageAlphaNone;3456字节/行。

EN

回答 1

Stack Overflow用户

发布于 2018-07-24 15:52:42

这里有一些代码应该可以做到这一点。一方面,我还无法在多监视器系统上进行测试,但另一方面,代码是在没有任何假设的情况下编写的。所以这应该管用。

代码语言:txt
复制
    CGDirectDisplayID displays[32];
    uint32_t count;
    if (CGGetActiveDisplayList(sizeof(displays)/sizeof(displays[0]), displays, &count) != kCGErrorSuccess)
    {
        NSLog(@"failed to get display list");
        exit(EXIT_FAILURE);
    }

    CGRect rect = CGRectNull;
    CGRect primaryDisplayRect = CGRectZero;
    for (uint32_t i = 0; i < count; i++)
    {
        // if display is secondary mirror of another display, skip it
        if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay)
            continue;

        CGRect displayRect = CGDisplayBounds(displays[i]);
        if (i == 0)
            primaryDisplayRect = displayRect;
        displayRect.origin.y = CGRectGetMaxY(primaryDisplayRect) - CGRectGetMaxY(displayRect);
        rect = CGRectUnion(rect, displayRect);
    }

    NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                         pixelsWide:CGRectGetWidth(rect)
                                                                         pixelsHigh:CGRectGetHeight(rect)
                                                                      bitsPerSample:8
                                                                    samplesPerPixel:4
                                                                           hasAlpha:YES
                                                                           isPlanar:NO
                                                                     colorSpaceName:NSCalibratedRGBColorSpace
                                                                       bitmapFormat:0
                                                                        bytesPerRow:0
                                                                       bitsPerPixel:32];
    if (!imageRep)
    {
        NSLog(@"failed to create bitmap image rep");
        exit(EXIT_FAILURE);
    }

    NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithBitmapImageRep:imageRep];
    if (!context)
    {
        NSLog(@"failed to create graphics context");
        exit(EXIT_FAILURE);
    }

    [NSGraphicsContext saveGraphicsState];
    {
        [NSGraphicsContext setCurrentContext:context];
        CGContextRef cgcontext = [context graphicsPort];

        CGContextClearRect(cgcontext, CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)));

        for (uint32_t i = 0; i < count; i++)
        {
            // if display is secondary mirror of another display, skip it
            if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay)
                continue;

            CGRect displayRect = CGDisplayBounds(displays[i]);
            displayRect.origin.y = CGRectGetMaxY(primaryDisplayRect) - CGRectGetMaxY(displayRect);
            CGImageRef image = CGDisplayCreateImage(displays[i]);
            if (!image)
                continue;

            CGRect dest = CGRectMake(displayRect.origin.x - rect.origin.x,
                                     displayRect.origin.y - rect.origin.y,
                                     displayRect.size.width,
                                     displayRect.size.height);
            CGContextDrawImage(cgcontext, dest, image);
            CGImageRelease(image);
        }

        [[NSGraphicsContext currentContext] flushGraphics];
    }
    [NSGraphicsContext restoreGraphicsState];


    NSData* data = [imageRep representationUsingType:NSPNGFileType properties:@{ }];
    [data writeToFile:@"/tmp/screenshot.png" atomically:YES];

主要的失败点是为一个足够大到包含所有显示的矩形分配位图图像上下文。请注意,所有显示器的总RECT可能比任何显示器的RECT大得多。例如,如果设置了两个显示器,使它们在一个角落几乎不接触,那么包含它们的矩形将几乎与2x2排列中的四个监视器一样大。对于三个显示器,它可以大到9个显示器在一个3x3的安排。等


这里有一个不使用Cocoa的实现,只使用核心图形:

代码语言:txt
复制
    CGDirectDisplayID displays[32];
    uint32_t count;
    if (CGGetActiveDisplayList(sizeof(displays)/sizeof(displays[0]), displays, &count) != kCGErrorSuccess)
    {
        NSLog(@"failed to get display list");
        exit(EXIT_FAILURE);
    }

    CGRect rect = CGRectNull;
    for (uint32_t i = 0; i < count; i++)
    {
        // if display is secondary mirror of another display, skip it
        if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay)
            continue;

        rect = CGRectUnion(rect, CGDisplayBounds(displays[i]));
    }

    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    if (!colorspace)
    {
        NSLog(@"failed to create colorspace");
        exit(EXIT_FAILURE);
    }

    CGContextRef cgcontext = CGBitmapContextCreate(NULL, CGRectGetWidth(rect), CGRectGetHeight(rect), 8, 0, colorspace, (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorspace);
    if (!cgcontext)
    {
        NSLog(@"failed to create bitmap context");
        exit(EXIT_FAILURE);
    }

    CGContextClearRect(cgcontext, CGRectMake(0, 0, CGRectGetWidth(rect), CGRectGetHeight(rect)));

    for (uint32_t i = 0; i < count; i++)
    {
        // if display is secondary mirror of another display, skip it
        if (CGDisplayMirrorsDisplay(displays[i]) != kCGNullDirectDisplay)
            continue;

        CGRect displayRect = CGDisplayBounds(displays[i]);
        CGImageRef image = CGDisplayCreateImage(displays[i]);
        if (!image)
            continue;

        CGRect dest = CGRectMake(displayRect.origin.x - rect.origin.x,
                                 displayRect.origin.y - rect.origin.y,
                                 displayRect.size.width,
                                 displayRect.size.height);
        CGContextDrawImage(cgcontext, dest, image);
        CGImageRelease(image);
    }

    CGImageRef image = CGBitmapContextCreateImage(cgcontext);
    CGContextRelease(cgcontext);
    if (!image)
    {
        NSLog(@"failed to create image from bitmap context");
        exit(EXIT_FAILURE);
    }

    CFURLRef url = CFURLCreateWithFileSystemPath(NULL, CFSTR("/tmp/screenshot.png"), kCFURLPOSIXPathStyle, NO);
    if (!url)
    {
        NSLog(@"failed to create URL");
        exit(EXIT_FAILURE);
    }

    CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
    CFRelease(url);
    if (!dest)
    {
        NSLog(@"failed to create image destination");
        exit(EXIT_FAILURE);
    }

    CGImageDestinationAddImage(dest, image, NULL);
    CGImageRelease(image);
    if (!CGImageDestinationFinalize(dest))
    {
        NSLog(@"failed to finalize image destination");
        exit(EXIT_FAILURE);
    }
    CFRelease(dest);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100005685

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档