0
votes

I would like to write the profile picture of a contact to a file.

1) how to read TIFF image?

The dictionary describes the image property: image (*TIFFPicture* or missing value) : Image for person.

In the dictionary TIFFPicture is a link, but when I click it there's no additional information. When reading it the value seems to be <>. How do I read it as an image?

2) how to write TIFF image?

When writing it to a file, what format should be specified? The dictionary says: [as: type class] : how to write the data: as text, data, list, etc.

In case as: is needed for writing an image, what type should be specified? When I use e.g. as: 'data' the error is "Can't convert types".

Example:

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 ("<>")
}
2
What is the actual value of the data variable when you view it in SE? JXA's bridging of Apple event datatypes to/from JavaScript has various defects, so it's possible that 1. JXA doesn't know how handle the typeTIFF descriptor returned by Contacts when you call person.image(), or 2. it doesn't know how to pack that value back into an Apple event descriptor in the subsequent write command. Best thing to do is to write your script in AppleScript first: if it works there you know it's JXA being busted and crap; if it fails in AS too, the problem's probably elsewhere (e.g. Contacts).foo
actual value is the string "<>" (or null when there's no image). It's been a while since I used AppleScript, so I was hoping to solve it in JXA.wivku
BTW, image descriptor types have always been a bit janky to use IME, so if it fails in AS too then don't be overly surprised. (It's hard enough for app developers to implement standard Apple event features correctly given Apple's schlonky APIs and garbage docs, never mind half-baked afterthoughts.)foo
oh dear. :-) Related and/or different approach: are the profile pictures stored on the file system somewhere? It used to be ~/Library/Application Support/AddressBook/Images but it appears that is no longer the case.wivku
Unfortunately, JXA was written by Apple engineers who don't understand how Apple events are designed to work, never mind how they actually get spoken by real-world apps. The only supported solution that works correctly is AppleScript, so bite the bullet and try writing your script in that.foo

2 Answers

0
votes

Following foo's advice, here is a working AppleScript version:

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

and the equivalent JavaScript for Automation (not working):

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)
0
votes

Here is the JavaScript version, using the Objective C bridge and AddressBook framework. Bonus: conversion to 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)