0

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 ("<>")
}
wivku
  • 2,457
  • 2
  • 33
  • 42
  • 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 Aug 07 '16 at 16:24
  • 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 Aug 07 '16 at 16:27
  • 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 Aug 07 '16 at 16:29
  • 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 Aug 07 '16 at 16:33
  • 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 Aug 07 '16 at 16:36
  • Thanks. In AppleScript it seems to work, I have added a working example. – wivku Aug 07 '16 at 18:15

2 Answers2

0

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)
Community
  • 1
  • 1
wivku
  • 2,457
  • 2
  • 33
  • 42
0

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)  
wivku
  • 2,457
  • 2
  • 33
  • 42