Hacker News new | past | comments | ask | show | jobs | submit login
Sips: Scriptable Image Processing System (simonwillison.net)
192 points by Amorymeltzer on Feb 18, 2023 | hide | past | favorite | 32 comments



I've found sips very helpful dealing with JPEG 2000 images in places where ImageMagick would not render them correctly.

Another very helpful Mac utility is textutil which will convert text documents between different formats. It uses the same underlying frameworks as TextEdit so it's not a replacement for {Microsoft,Libre}Office but it can spit out an OpenOffice document from an RTF or Word document in a pinch.


> convert text documents between different formats

see also pandoc, though obv not a built-in


Pandoc is far and away more powerful than textutil hands down. If you've got pandoc available you likely don't need textutil. However, as you point out, pandoc isn't built in.

Like sips it's nice to know it's available on a default macOS install.


Tangential, but one of the things I love about MacOS is stuff like this. It's hard to discover, but very cool when you do. Like the say command, which is still updated to work with the very latest AI voices.


But is it very different from ImageMagik in terms of functionality?


ImageMagick is vastly more powerful than sips. There's little reason not to use it when it's available. However if you're writing a script for macOS and sips suits your needs it's really nice to have. See also the avconvert tool, it's not as capable as ffmpeg but it'll ingest and convert any format/codec supported by AVFoundation and comes with the system.


ImageMagick has more features but SIPS covers almost all of the ones I’ve ever needed to use, and it’s much faster (sometimes an order of magnitude or more, see below) and tends to be better at correctness around colorspaces and formats.

I noticed this most noticeably working with JPEG-2000 files (I work at a library with large collections of scanned images). ImageMagick technically supported the format but it was by the Jasper library which was extremely slow and, worse, had a fair number of images which it couldn’t decode correctly so you’d get a black box from an allegedly error-free pass.

I never hit an issue with CoreImage like that, which was a point in favor of trustworthiness. The performance benefits varied but I never found a case where ImageMagick was faster or even less than a whole multiple slower.


Sips is way faster and produces better results in tens of quality (color management). It’s a tricky thing to do right with magick


Could you expand? I've used ImageMagick to do some fairly advanced color management, and I really don't see how that can be true. You have basic keyword arguments for common use-cases, and you can get down to matrix operations on the color space to have absolute control.

The only thing that I missed was that if you wanted to 'pipe' matrix transforms one into the other, you couldn't do it in different steps because of the precision loss (that is due to image encoding, not IM), so the best way to do that was to multiply the matrices to always do it on one step.


IM doesn't come with proper color profiles. You have to specify every single thing. It's apparent when converting between CMYK RGB and other color spaces. You probably know this, but you fail to acknowledge it.

The fact that you do advanced color management and like the complete control means you actually work with it and understand it. You'll have all the different profiles you need.

Most people don't, and for them it's a huge hassle, and for most it's like black magic(k).


>You probably know this, but you fail to acknowledge it.

I don't think my comment was really aggressive to justify assuming bad faith in such a way.

For all my normal usage (conversion, montage) I never have to specify anything. The advanced use-cases were explicitly about color management, so I spent some time reading the doc and managed to get done what I had to fairly painlessly.

There are things for which IM's CLI is uselessly tricky; for example calling `montage` you have to pass `-mode Concatenate` to have the command do what you expect it to do. I always use command history to remember how to call it properly.

So what I gather from your comment is that the commands' defaults are bad, but I'd have found interesting to have more precise examples of what can be done in a very trivial way in Sips that would require complex arguments in IM. Maybe that could be packaged as a simple helper script to close that gap, or added as a new interface.


> I don't think my comment was really aggressive to justify assuming bad faith in such a way.

Oh it definitely wasn't aggressive at all, and I'm not assuming bad faith. It's just that so many people in tech state things are simple, when in fact they are complex. The classic example on HN is the initial Dropbox post.

I've done quite some work with ImageMagick, GhostScript and poppler/xpdf, and most issues I came across were color management issues, and issues with CMYK jpegs. I don't remember exactly which issues, but one thing for example is that you can get a faded output when doing conversions without a profile, or with the wrong profile. Easily fixed, but with sips you don't have those issues, as it has some sane defaults.

With just ImageMagick + GhostScript it's nearly impossible to get a proper rendering of a PDF (let alone a complex PDF) without your machine blowing up in terms of resources. My solution was to use libpoppler/xpdf to convert to a bitmap image, and then process in IM.

Resizing larger files or vector formats require unnecessary planning about resource usage, and to improve quality they recommend you to first render at a higher resolution and then rescale it. This is partly because IM uses raw pixel information in memory, and if I recall correctly, each channel is 16-bit, unless you download the 8-bit version. And party because of the different methods of rendering a file to that buffer (sometimes it lacks antialiasing etc).

IM is a godsend because of all the features and support, but is also a big pain in the head and the butt at the same time in terms of usability, resources, security, and sometimes you stumble on bugs with some file parsers, but at least it's open source :) IM is just a huge toolkit which tries (and does) do it all. The CLI is def a pain to use, but some libraries make it easier to chain commands into an argument (and thereby keeping IM out of process).

Note that my experience with serious magick dates until around 2015, so I'm not sure what it is right now.


Not that I know of, but one has to install that.


Yep, these are my favorite kind of easter eggs. Commands that have been around for decades, but still work. Subliminal messages come to mind.


I've made use of sips(1) for years to un/bundle application icons for build processes and other things. Great tool, more or less unknown like so many other hidden userland gems in macOS.


Same. I use sips as part of my build process. The package target depends on the binary target and the icns target, which depends on the iconset target, which uses sips.


I've always used "iconutil" to do the same.


at first i thought this was some sort of wrapper around vips[1] which is extremely powerful, but whose CLI leaves a lot to be desired. even so, i make use of it quite a bit. here's how i'd convert the webps to png:

    parallel vips copy {} {.}.png ::: *.webp
[1] https://www.libvips.org/API/current/using-cli.html


How does this deal with throttling those operations? Like, if I’m converting 100 or 1000 PNGs to Webp, I probably only want 12-ish operations going on at a time so my CPU isn’t context-switching like crazy and the PNGs don’t all load into RAM at once.


They're using GNU parallel, which will default to the number of CPU threads available, but which can be tweaked to your liking.

https://www.gnu.org/software/parallel/sphinx.html


While I love GNU Parallel there's also the venerable (and installed by default) xargs.


Is there a place listing all these little known but useful macOS utilities?


`man -k .`


You can also do this with node

    npm install nbb canvas
create a draw.cljs file with the code below

    (ns draw.core
      (:require
       ["fs" :as fs]
       ["canvas" :refer (createCanvas)]))

    (def width 400)
    (def height 400)
    (def canvas (createCanvas width height))
    (def ctx (.getContext canvas "2d"))

    (set! (.-fillStyle ctx) "#764abc")
    (.fillRect ctx 0 0 width height)

    (set! (.-fillStyle ctx) "#fff")
    (set! (.-textAlign ctx) "center")
    (set! (.-font ctx) "bold 50pt 'PT Sans'")
    (.fillText ctx "Hello World" (/ width 2) (/ height 2))

    (set! (.-strokeStyle ctx) "#fff")
    (.beginPath ctx)
    (.arc ctx 75 75 50 0 (* 2 js/Math.PI) true)
    (.moveTo ctx 110, 75)
    (.arc ctx 75 75 35 0 js/Math.PI false)
    (.moveTo ctx 65 65)
    (.arc ctx 60 65 5 0 (* 2 js/Math.PI) true)
    (.moveTo ctx 95 65)
    (.arc ctx 90 65 5 0 (* 2 js/Math.PI) true)
    (.closePath ctx)
    (.stroke ctx)

    (.writeFileSync fs "./hello.png" (.toBuffer canvas "image/png"))
and run to make a PNG

    npx nbb draw.cljs
as a bonus you can start nREPL and connect your editor to it for interactive development

    nbb nrepl-server :port 1337


Um.

You can, but I'm not sure why you would, or how it's relevant?

sips is installed by default, that's the only reason you'd use it over any number of other drawing tools.

Using node and clojure seems like it's more effort, more obscure and less functionality than any number of other things. If you're going to install something, install imagemagick.

If you're looking for something else kind of like sips, try hand coding an svg like:

    <svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500">
    <rect x="3" y="3" width="200" height="200"></rect>
    </svg>
Then run the thumbnail generator on it:

    qlmanage -t -s 500 -o . junk.svg
Using clojure (nbb) for this seems... like a solution looking for a problem to solve.


Um.

This would not seem to be relevant only if you didn't bother reading the article in the submission. Once you do, you'll notice the following example there:

After some searching I found manicmaniac/sips-js-api which is the only place online I could see that documented how to use the sips --js option. Here's their example - save this in smile.js:

    const canvas = new Canvas(150, 150)
    canvas.beginPath()
    canvas.arc(75, 75, 50, 0, Math.PI * 2, true)
    canvas.moveTo(110, 75)
    canvas.arc(75, 75, 35, 0, Math.PI, false)
    canvas.moveTo(65, 65)
    canvas.arc(60, 65, 5, 0, Math.PI * 2, true)
    canvas.moveTo(95, 65)
    canvas.arc(90, 65, 5, 0, Math.PI * 2, true)
    canvas.stroke()
    const output = new Output(canvas, sips.outputPath)
    output.addToQueue()
Then run:

    sips -j smile.js -o smile.png
This produces an alpha-transparent PNG of a smiling face.

The obvious advantage of using node over sips is that it works on every platform. You'll also have to elaborate on what this additional effort you speak of is. If you have node installed, as practically everyone does nowadays, then the presumed effort is in having to run npm install?

Also, you obviously don't have to use Clojure, I chose it because that's the language I already use and like. You could just make a regular Js file as well.

Hope that helped clarify things for you.


Undermentioned macOS feature: right click an image in Finder, Quick Actions > Convert Image. Lets you change formats, resize, and strip metadata from images, and supports bulk operations too.


I've always used ImageMagick for this kind of stuff.


The problem with ImageMagick is that its scripting language sucks. I had tried using it a couple of times but it's too obscure and sparsely documented to get it to work for you. In the end I gave up because I realized that the result would be unmaintainable, so I'm better off with bash scripts.

Sips got it right with providing a Javascript API instead of inventing another obscure DSL.


What about making a bash script with ImageMagick commands? I didn't even know it had a scripting language.


If you need scripting just use IM as a lib from Python.


We need lossless content first and foremost, after that we can worry about yet another image compression pipeline.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: