Photoshop psd support

It would be handy to include more formats like psd. It seems it is not too difficult to convert it to jpg during import: command line - How to convert PSD to JPG or PNG on Linux with Gimp CLI/batch mode (or other server-side tool)? - Super User

ImageMagick has a pretty horrible security track record, but if someone doesn’t mind the security implications, installs it externally, I guess I could fork out a call to convert and if it returns something, I import it?

The referenced npm module is abandoned, but it’s just a wrapper around GitHub - meltingice/psd.js: A Photoshop PSD file parser for NodeJS and browsers

I haven’t tried it, but the library on your link says it has no native module dependencies. So your ImageMagick security concern could be avoided

ghostscript generates rastered images of .ai and .pdf:

gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=jpeg -SOutputFile=output.jpeg input.pdf

So facing this right now. There are two issues: 1. Storage 2. Display.

Storage:
I have PSDs that I would like stored along side the other files they correspond to. So that we have one … well… Structure for Photos… This feels necessary for me.

Display:
The solution above with imgmagick works. But in the interim - I can live with a placeholder image when I drill down into a view and the image not showing up in the summary/random seed based summary views.

This could work for any other filetypes or “related data” that you might want to store with the associated pictures.

Ideally there would be an way for advanced users to “teach” PhotoStructure how to handle file types that it currently can’t handle.

PhotoStructure needs a couple things to import files:

  1. A way to extract the “captured-at” time. This can revert to the mtime of the file, but that’s not great.

  2. A way to render the file as an image, so it can be presented in the tag galleries and asset views. This could be something as basic as a file icon with the extension, like this:

    , but a thumbnail would obviously be better.

  3. A way to extract tags from the file, so they can be added to more than just the date tag.

So… How to do this?

Option 1: I’d add a new PS_IMPORTERS_DIR. This would be a path to a directory containing files named either the file extension, or the mimetype (so psd.js or application/photoshop.js for PSD imports). This JavaScript file would have to export a set of well-defined functions to do the above 3 steps. I suspect this would be simplest to do with the PhotoStructure for Node edition, as that already requires the compiler toolchain to be set up on the box.

Here’s a sketch of the API I’m thinking you’d need to implement:

import { ExifDate, ExifDateTime } from "exiftool-vendored"

export interface PhotoStructureImporter {
  /**
   * Given a path to a file, try to pull out the "captured-at" time, or time
   * that the file was initially created.
   *
   * Ideally, a date and time, and possibly a time zone, can be returned,
   * encoded as an ExifDateTime object.
   *
   * If no time can be extracted with confidence, an ExifDate object can be
   * returned.
   *
   * If no "captured-at" time can be extracted, return `null`.
   *
   * @see https://photostructure.com/faq/captured-at
   * @see ExifDateTime
   * @throws Implementations should raise an error if the file is invalid.
   */
  extractCapturedAt(nativePath: string): Promise<ExifDateTime | ExifDate | null>

  /**
   * Given a path to a file, render as a JPEG.
   *
   * Rendering at a resolution higher than 5k (5120 × 2880) is probably
   * unnecessary.
   *
   * @throws Implementations should raise an error if they cannot render the
   * file.
   */
  renderAsJpeg(
    sourceNativePath: string,
    destinationJpegNativePath: string
  ): Promise<void>

  /**
   * Given a path to a file, extract tags suitable for your PhotoStructure
   * library, like `[["Who", "Rogers", "Fred"], ["Where", "France", "Paris"]]`
   *
   * @throws Implementations may raise an error if they cannot extract tags.
   */
  extractTags(nativePath: string): Promise<string[][]>
}

Option 2: something else y’all come up with that is easier to manage

1 Like

I like this approach!

Any option to just import the file with ‘generic’ values for all that and only show it in ‘folder’ view?

I could just take a list of file extensions, perhaps, and just show a generic file icon (with the basename?)

  • I just found out that Photoshop, if in “compatibility mode,” will embed a PhotoshopThumbnail that I can extract (which is all the psd.js library is doing)

  • I found that Alpine does indeed package up ghostscript, so I could add that to the docker image to add illustrator and PDF support, and ask users to install ghostscript if they wanted support.

  • Alpine also has a recent graphicsmagick build, and holy moly does it support a lot of formats.

  • There’s a python library that generates previews for a ton of different formats. It delegates to libreoffice to do word/excel conversions, inkscape for SVG, and poppler-utils to do PDF.

I’d basically use ghostscript, graphicsmagick, libreoffice, gimp, and inkscape as helper applications just like I currently use ffmpeg and vlc: if PhotoStructure can find them, and the version is recent(ish), I’ll automatically enable support for those file formats.

Does that sound like reasonable default behavior? I already have a copyToLibraryMimeTypes setting which defaults to “image/" and "video/”, but Photoshop’s MIME type, according to ExifTool, is application/vnd.adobe.photoshop, so I’d need to add that to the default list. Hilariously, depending on the file format version of the psd, it might also be image/vnd.adobe.photoshop, application/x-photoshop, application/photoshop, application/psd, or image/psd

I think this sounds like a good plan - both ghostscript and graphicsmagick have good reputations, have been around for years and a ton of work has gone into their ability to handle file types - seems like leveraging that would be a good plan with less “roll your own” aspect.