Как сохранить изображение сетчатки, 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/
В любом случае, после долгих раскопок, боюсь, мне придется пока пометить это дело как закрытое. Если кто-то сталкивается с этим и находит решение, пожалуйста, напишите мне:)