{
 "kind": "feature",
 "id": "feature:images",
 "url": "https://headlesson.com/features/images",
 "title": "Resizing and cropping an image from the command line: ImageMagick, libvips or sips",
 "summary": "For assistants asked to resize, crop or convert an image, this feature compares the three recorded command-line tools on one small synthetic picture: a 16×12 PNG with four coloured quarters. On macOS in October 2026, cropping matched pixel for pixel across ImageMagick, libvips and sips, and halving the size matched between ImageMagick and libvips, but sips's half-size result differed in 24 of 48 pixels. Each tool ran under different install conditions; this is not a quality, speed or format comparison.",
 "published": "2026-10-14",
 "updated": "2026-10-14",
 "body": "# Three tools, three ways to get them\n\n- app:imagemagick provides the magick command; headlesson tested 7.1.2-33 installed with Homebrew on 2026-10-11, an install that also upgraded other shared libraries on the test Mac.\n- app:libvips provides the vips command; headlesson tested 8.18.7 as a minimal build in an isolated directory with the optional codecs beyond PNG and PPM turned off (its own native formats remain), which is not the same as the Homebrew package.\n- app:sips ships with macOS; headlesson tested sips-316 already at /usr/bin/sips, with nothing installed.\n- Editorial advice, not tested beyond this picture: on a Mac where nothing may be installed, app:sips can do basic crops and conversions; where exact pixel results matter, check the output of app:sips, app:libvips or app:imagemagick on the actual images rather than assuming they agree.\n\n# Observed in the tests\n\n- Cropping an 8×6 area from the same offset gave the same pixels with app:imagemagick, app:libvips and app:sips.\n- Halving the picture to 8×6 with nearest-neighbour sampling gave the same 48 pixels with app:imagemagick (point filter) and app:libvips. app:sips's default resize differed from that result in 24 of 48 pixels (largest channel difference 33); which method sips uses was not identified, and no tool is ranked for image quality.\n- app:sips kept every pixel on a round trip from PNG to LZW-compressed TIFF and back to PNG. app:libvips converted the PNG one way to PPM, and the PPM, read with a separate decoder, had the expected colours.\n- app:libvips's minimal build refused to write JPEG and exited 1, because that format was turned off in the build; app:sips was tested only with PNG and TIFF.\n- The libvips and sips results come from 2026-10-14 runs; app:imagemagick's crop and resize were run on 2026-10-14 as part of the libvips comparison, and its own lesson (a gradient image and JPEG output) passed on 2026-10-11.\n\n# Cautions from the records\n\n- app:sips: offsets for cropping and sizes for resampling are given height first, then width; without --out it may change the input file, so the test always wrote to a separate file.\n- app:imagemagick: in version 7 the magick command replaces convert; its default security policy allows everything unless denied, so restrict coders such as PDF and PS before handling untrusted files.\n- app:libvips: each command runs as a separate process, so chained operations go through intermediate files; output format is chosen from the file name suffix.\n\n# What was not tested\n\nThe comparison of app:imagemagick, app:libvips and app:sips used one synthetic RGB picture. Photographs, colour profiles, transparency, metadata, JPEG and other formats, large images, speed and memory were not tested. headlesson_get with sections [\"lesson\",\"gotchas\"] on each ID gives the exact commands, versions and failure conditions.\n",
 "refs": [
  {
   "id": "app:imagemagick",
   "name": "ImageMagick",
   "source": {
    "source": "https://imagemagick.org/",
    "checked": "2026-10-11",
    "certainty": "primary",
    "by": "official"
   }
  },
  {
   "id": "app:libvips",
   "name": "libvips",
   "source": {
    "source": "https://github.com/libvips/libvips/blob/v8.18.7/README.md",
    "checked": "2026-10-14",
    "certainty": "primary",
    "by": "editorial"
   }
  },
  {
   "id": "app:sips",
   "name": "sips",
   "source": {
    "source": "operator-provided; not publicly verifiable",
    "checked": "2026-10-14",
    "certainty": "primary",
    "by": "official"
   }
  }
 ],
 "article_source": {
  "source": "headlesson editorial judgement",
  "checked": "2026-10-14",
  "certainty": "inferred",
  "by": "editorial"
 },
 "note": "Editorial article by the headlesson operator, written from the catalog records it cites. Test results in it are the operator's own observations, not vendor claims. Each cited record keeps its own source; the article's editorial source does not stand in for them.",
 "mcp_get": "headlesson_get id=\"feature:images\"",
 "page_updated": "2026-10-14"
}
