сохранить изображение профиля контакта с помощью JavaScript для автоматизации

Я хотел бы записать изображение профиля контакта в файл.

1) как читать изображение в формате TIFF?

Словарь описывает свойство изображения: image (*TIFFPicture* or missing value) : Image for person.

В словаре TIFFPicture есть ссылка, но когда я нажимаю на нее, никакой дополнительной информации нет. При чтении значение кажется <>. Как я могу прочитать это как изображение?

2) как записать изображение в формате TIFF?

При записи в файл какой формат указывать? В словаре сказано: [as: type class] : how to write the data: as text, data, list, etc.

В случае, если для записи изображения требуется as:, какой тип указать? Когда я использую, например. as: 'data' ошибка "Не удается преобразовать типы".

Пример:

var app = Application.currentApplication();
app.includeStandardAdditions = true;

myPeople = Application("Contacts").people.whose({ _and: [{lastName: "Doe" },{firstName: "John"}] });

for (i in myPeople) {
    person = myPeople[i];

    if (person.image() == null) continue;

    var data = person.image();

    var file = Path("/var/tmp/test.tiff");

    app.openForAccess(file, { writePermission: true });
    app.setEof(file, {to:0} ); // reset length
    app.write(data, {
        to: file,
        //as: 'data',
    });

    app.closeAccess(file);

    // result: file with 2 bytes ("<>")
}

person wivku    schedule 07.08.2016    source источник
comment
Каково фактическое значение переменной data, когда вы просматриваете ее в SE? Соединение JXA типов данных событий Apple в/из JavaScript имеет различные дефекты, поэтому возможно, что 1. JXA не знает, как обрабатывать дескриптор typeTIFF, возвращаемый Contacts при вызове person.image(), или 2. он не знает, как его упаковать. значение обратно в дескриптор события Apple в последующей команде write. Лучше всего сначала написать свой сценарий на AppleScript: если он работает там, вы знаете, что JXA разоряется и дерьмо; если он не работает и в AS, проблема, вероятно, в другом месте (например, в контактах).   -  person foo    schedule 07.08.2016
comment
фактическое значение — строка "<>" (или null, если изображения нет). Прошло некоторое время с тех пор, как я использовал AppleScript, поэтому я надеялся решить эту проблему в JXA.   -  person wivku    schedule 07.08.2016
comment
Кстати, типы дескрипторов изображений всегда были немного неудобны для использования IME, поэтому, если он не работает и в AS, не удивляйтесь слишком сильно. (Разработчикам приложений достаточно сложно правильно реализовать стандартные функции событий Apple, учитывая неуклюжие API-интерфейсы Apple и мусорную документацию, не говоря уже о полусырых запоздалых размышлениях.)   -  person foo    schedule 07.08.2016
comment
о, Боже. :-) Связанный и/или другой подход: изображения профиля хранятся где-то в файловой системе? Раньше это было ~/Library/Application Support/AddressBook/Images, но, похоже, это уже не так.   -  person wivku    schedule 07.08.2016
comment
К сожалению, JXA был написан инженерами Apple, которые не понимают, как устроены события Apple, не говоря уже о том, как они на самом деле озвучиваются реальными приложениями. Единственным поддерживаемым решением, которое работает корректно, является AppleScript, так что не останавливайтесь на достигнутом и попробуйте написать свой сценарий на нем.   -  person foo    schedule 07.08.2016
comment
Спасибо. В AppleScript это работает, я добавил рабочий пример.   -  person wivku    schedule 07.08.2016


Ответы (2)


Следуя совету foo, вот рабочая версия AppleScript:

tell application "Contacts"
    set {name:personName, image:personImage} to (get my card)
    set filePath to (((path to desktop folder) as text) & personName & ".tif")
    set theFile to open for access file filePath with write permission

    set eof of theFile to 0
    write personImage to theFile
    close access theFile
end tell

и эквивалентный JavaScript для автоматизации (не работает):

var app = Application.currentApplication()
app.includeStandardAdditions = true

var person = Application("Contacts").myCard()
var filePath = Path(app.pathTo("desktop") +"/"+ person.name() +".tif")
var theFile = app.openForAccess(filePath, { writePermission: true })

app.setEof(theFile, { to:0} )
app.write(person.image(), { to: theFile })
app.closeAccess(theFile)
person wivku    schedule 07.08.2016

Вот версия JavaScript, использующая мост Objective C и структуру AddressBook. Бонус: конвертация в PNG.

ObjC.import("AddressBook")
ObjC.import("AppKit")

person = $.ABAddressBook.addressBook.me
filename = $("~/Desktop/"+ person.displayName.js +".png").stringByExpandingTildeInPath.js

image = $.NSImage.alloc.initWithData(person.imageData)
imageData = $.NSBitmapImageRep.imageRepWithData(image.TIFFRepresentation)
png = imageData.representationUsingTypeProperties($.NSPNGFileType, $())
png.writeToFileAtomically(filename, false)  
person wivku    schedule 15.08.2016