Как сохранить изображение сетчатки, NSBitmapImageRep

Я пытаюсь создать что-то, что имитирует этот Mac OSX, встроенный в инструмент для создания снимков экрана, где, если вы сделаете снимок экрана на мониторе сетчатки (320x240), полученное изображение откроется в том же размере, что и был сделан, но это сетчатка в что dpi 144.

Однако, что бы я ни делал, я не могу делать то же самое. Я могу сохранить изображение с точно такими же метаданными, спецификациями (насколько я вижу), и оно просто открывается в двойном размере.

Вот данные из встроенного снимка экрана

Вот данные из изображения, которое я создаю

Единственное отличие, которое я вижу, заключается в том, что данные XMP exif отличаются. Но, с одной стороны, я не могу понять, как это изменить, и 2, я не понимаю, как это все равно имеет смысл, поэтому я думаю, что я все еще не вижу чего-то, что создает изображение сетчатки.

Я предполагаю, что есть какой-то скрытый флаг, который мне не хватает, который говорит Предпросмотру открыть встроенный скриншот с разрешением 320х240 вместо размера пикселя, 640х480

А вот и мой код. NSImageEXIFData, кажется, не залипает

   NSBitmapImageRep *bmpImageRep = [[NSBitmapImageRep alloc]
                                    initWithBitmapDataPlanes:NULL
                                    pixelsWide:640
                                    pixelsHigh:480
                                    bitsPerSample:8
                                    samplesPerPixel:4
                                    hasAlpha:YES
                                    isPlanar:NO
                                    colorSpaceName:NSCalibratedRGBColorSpace
                                    bitmapFormat:NSAlphaFirstBitmapFormat
                                    bytesPerRow:0
                                    bitsPerPixel:0
                                    ];


   bmpImageRep.size=NSMakeSize(320,240);

   id profile = [NSData dataWithContentsOfFile: @"/Library/ColorSync/Profiles/Displays/Color LCD-FD6E9053-53B7-5224-5892-F9F7EC52CEF3.icc"];
   [bmpImageRep setProperty:NSImageColorSyncProfileData withValue:profile];

   NSDictionary *exif = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithInt:640], kCGImagePropertyExifPixelXDimension, [NSNumber numberWithInt:480], kCGImagePropertyExifPixelYDimension, nil];
   [bmpImageRep setProperty:NSImageEXIFData withValue:exif];

   NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:bmpImageRep];
   [NSGraphicsContext saveGraphicsState];
   [NSGraphicsContext setCurrentContext: bitmapContext];

   NSRect bgRect = NSMakeRect(0,0,320,240);
   [myImage drawInRect:bgRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];

   [NSGraphicsContext restoreGraphicsState];


   NSData* pngData= [bmpImageRep representationUsingType:NSPNGFileType
                               properties:nil];
   return pngData;

2 ответа

Решение

Эта информация о снимке экрана, похоже, хранится в расширенных атрибутах файловой системы, а не в метаданных изображения определенного формата. Эти расширенные атрибуты будут продублированы вместе с копией файла или открытием / сохранением (если приложение явно не изменяет атрибуты), но не с копией только для содержимого (например, создайте новый файл и скопируйте содержимое исходного файла).

Вы можете использовать инструмент командной строки xattr для вывода списка расширенных атрибутов файла. Вот что вы ожидаете от скриншота:

com.apple.metadata: kMDItemIsScreenCapture com.apple.metadata: kMDItemScreenCaptureGlobalRect com.apple.metadata: kMDItemScreenCaptureType

И sys/xattr.h - заголовок, который содержит функции, необходимые для управления расширенными атрибутами файла.

Как оказалось, OSX записывает, какие изображения были захвачены с помощью инструмента "Снимок экрана", а затем говорит "Предварительному просмотру" открыть это изображение наполовину. Таким образом, на самом деле невозможно создать изображение, которое откроет половину размера в Preview, если вы не возитесь с файлами OS где-нибудь. Это на самом деле не имеет значения, потому что если вы откроете изображение, снятое с помощью инструмента "Снимок экрана", в Chrome или другом приложении, кроме предварительного просмотра, оно также откроется в двойном размере. Так что, похоже, это просто специальный корпус Apple, созданный для Preview + Встроенные скриншоты.

Это, конечно, все личные предположения, потому что я не смог найти документацию или дополнительную информацию по этому вопросу, однако могу вам сказать, что создал точную копию встроенного снимка экрана. Включая все метаданные и свойства, связанные с изображением, и оно по-прежнему открывалось по-другому в режиме предварительного просмотра.

Я попытался изменить любое подходящее свойство в NSBitmapImageRef, CGImage, CGContext, чтобы попытаться получить это. Попытался изменить свойства NSEXIF, но безрезультатно. (Связанный, независимо от того, что вы изменяете в метаданных, это не меняет фактическое изображение - оказывается, что это просто метки. Это имеет смысл, потому что я видел GIF-файлы с расширением.jpeg)

Вот статья того, кто масштабирует изображение, открытое в режиме предварительного просмотра, обратно, но это противоположно тому, что я хотел сделать

http://www.macissues.com/2014/03/29/adjust-retina-macbook-screenshots-to-be-actual-size/

В любом случае, после долгих раскопок, боюсь, мне придется пока пометить это дело как закрытое. Если кто-то сталкивается с этим и находит решение, пожалуйста, напишите мне:)

Другие вопросы по тегам