{"id":13495775,"url":"https://github.com/axe312ger/sqip","last_synced_at":"2025-05-12T13:17:41.542Z","repository":{"id":25285231,"uuid":"103548171","full_name":"axe312ger/sqip","owner":"axe312ger","description":"\"SQIP\" (pronounced \\skwɪb\\ like the non-magical folk of magical descent) is a  SVG-based LQIP technique.","archived":false,"fork":false,"pushed_at":"2025-05-05T12:11:09.000Z","size":27457,"stargazers_count":3398,"open_issues_count":27,"forks_count":83,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-05-12T13:16:51.039Z","etag":null,"topics":["image","images","lqip","perceived-performance","performance","placeholder","svg","user-experience","webperf","webperformance"],"latest_commit_sha":null,"homepage":"http://axe312ger.github.io/sqip","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axe312ger.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-09-14T15:16:42.000Z","updated_at":"2025-05-10T09:12:55.000Z","dependencies_parsed_at":"2023-12-15T13:47:10.672Z","dependency_job_id":"ff00c756-0528-4d2d-9e4f-13d51d522634","html_url":"https://github.com/axe312ger/sqip","commit_stats":{"total_commits":549,"total_committers":32,"mean_commits":17.15625,"dds":0.7686703096539163,"last_synced_commit":"d445759aa761efb81932b9c06eddf05538855072"},"previous_names":["technopagan/sqip"],"tags_count":291,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axe312ger%2Fsqip","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axe312ger%2Fsqip/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axe312ger%2Fsqip/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axe312ger%2Fsqip/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axe312ger","download_url":"https://codeload.github.com/axe312ger/sqip/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253745196,"owners_count":21957319,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image","images","lqip","perceived-performance","performance","placeholder","svg","user-experience","webperf","webperformance"],"created_at":"2024-07-31T19:01:38.057Z","updated_at":"2025-05-12T13:17:41.508Z","avatar_url":"https://github.com/axe312ger.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Techniques","JavaScript","⚙️ Backend \u0026 APIs"],"sub_categories":["Information, news, etc."],"readme":"**This is the `v1 alpha` readme. [You can find the current docs here.](https://github.com/axe312ger/sqip/tree/legacy#readme)**\n\nSQIP - a pluggable image converter with vector support\n====================\n\n[![npm](https://img.shields.io/npm/v/sqip.svg?label=npm@latest)](https://www.npmjs.com/package/sqip)\n[![npm](https://img.shields.io/npm/v/sqip/canary.svg)](https://www.npmjs.com/package/sqip)\n[![npm](https://img.shields.io/npm/dm/sqip.svg)](https://www.npmjs.com/package/sqip)\n\n[![CircleCI](https://circleci.com/gh/axe312ger/sqip.svg?style=svg)](https://circleci.com/gh/axe312ger/sqip)\n[![codecov](https://codecov.io/gh/axe312ger/sqip/branch/master/graph/badge.svg)](https://codecov.io/gh/axe312ger/sqip)\n[![Maintainability](https://api.codeclimate.com/v1/badges/fc81fa5e535561c0a6ff/maintainability)](https://codeclimate.com/github/axe312ger/sqip/maintainability)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\n**SQIP** is a flexible, and a little bit different image processor. It is available as node API and CLI.\n\nBy combining plugins you can use it for several purposes:\n\n* Create super-tiny image previews to improve your websites lazy loading experience\n* Do art by converting images into abstract representations of themselfes\n* Quickly convert, resize or optimize a set of pixel or vector images\n* More? Ideas, contributions and community plugins are very welcome\n\n\n## Table of contents\n\n* [Examples](#Examples)\n* [Requirements](#Requirements)\n* [Node](#Node)\n* [CLI](#CLI)\n* [Config](#Config)\n* [Plugins](#plugins-1)\n* [Background \u0026 reseach](#background--reseach)\n* [Credits](#Credits)\n* [Contributing](#Contributing)\n* [License](#License)\n\n## Examples\n\nGet a more detailed look on [our demo website](https://axe312ger.github.io/sqip/).\n\n[![](demo/example.jpg)](https://axe312ger.github.io/sqip/)\n\n## Requirements\n\n* Node.js \u003e= v8 (https://nodejs.org/en/)\n* 64bit OS (Not all plugins, see below)\n\n\u003cdetails\u003e\n\u003csummary\u003e\n\u003cstrong\u003eNon-64bit operating systems requirements\u003c/strong\u003e\n\u003c/summary\u003e\n\nThe most common plugin `sqip-plugin-primitive` is packed with a 64bit executable for all 3 major operating systems. Users with non 32-bit operating system or those who simply want to use the latest and greatest verison of primitive need:\n\n* Golang (https://golang.org/doc/install)\n* Primitive (https://github.com/hashbite/primitive) (`go get -u github.com/hashbite/primitive`)\n\nAfter installing Primitive, you may also need to add the path to the ```Primitive``` binary file.\n\n#### For macOS\n\nIt would generally look something like\n\n```bash\n/Users/myMacbook/go/bin\n```\n\nTo do this on a Mac, type: ```sudo vim /etc/paths``` into your terminal, and add the path to your ```Primitive``` binary file, but be sure to add the full path, ```/Users/\u003cusername\u003e/go/bin``` and not ```~/go/bin```.\n\n#### For PC\n\nUsing the command line (https://www.windows-commandline.com/set-path-command-line)\nUsing a GUI (https://www.computerhope.com/issues/ch000549.htm)\n\n\u003c/details\u003e\n\n## Node\n\n[CLI see here](#cli)\n\n### Installation\n\nYou need the core plugin `sqip` plus all the plugins you want to use like `sqip-plugin-primtive`, `sqip-plugin-svgo` and more.\n\nFor example:\n\n```bash\nnpm install sqip@canary sqip-plugin-primitive@canary sqip-plugin-svgo@canary sqip-plugin-data-uri@canary\n```\n\n**This is the `v1 alpha` readme. [Click here for v0 \"stable\" instructions.](https://github.com/axe312ger/sqip/tree/legacy#readme)**\n\n**Hint:** SQIP is plugin based, you might want to install more plugins later on. See [Plugins](#plugins-1) section.\n\n### Usage\n\nSQIP is async.\n\n```js\ntry {\n  const result = await sqip({...options})\n  console.log(result)\n} catch (err) {\n  console.error(err)\n}\n\n// or\n\nsqip({...options})\n  .then(result =\u003e console.log(result))\n  .catch(error =\u003e console.error(error))\n```\n\nIf you passed a single image to process, SQIP will return the following result object:\n\n```js\n{\n  content: Buffer.from('\u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 300 188\"\u003e...\u003c/svg\u003e'),\n  metadata: {\n    originalWidth: 1024,\n    originalHeight: 640,\n    palette: {\n      Vibrant: Vibrant.Swatch,\n      DarkVibrant: Vibrant.Swatch,\n      LightVibrant: Vibrant.Swatch,\n      Muted: Vibrant.Swatch,\n      DarkMuted: Vibrant.Swatch,\n      LightMuted: Vibrant.Swatch\n    },\n    width: 300,\n    height: 188,\n    type: 'svg',\n    // These will be added by sqip-plugin-data-uri\n    dataURI: \"data:image/svg+xml,...\",\n    dataURIBase64: 'data:image/svg+xml;base64,...'\n  }\n}\n```\n\nDocumentation for all 6 colors from the palette: [Vibrant.Swatch](https://github.com/akfish/node-vibrant#vibrantswatch)\n\nPlugins might add their own meta data\n\nMultiple input images will result in an array of result objects.\n\n\n#### Process folder with default settings\n\n```js\nimport { sqip } from 'sqip'\nimport { resolve } from 'path'\n\n;(async () =\u003e {\n  try {\n    // Process whole folder with default settings\n    const folderResults = await sqip({\n      input: resolve(__dirname, 'images/originals'),\n      output: resolve(__dirname, 'images/previews')\n    })\n    console.log(folderResults)\n  } catch (err) {\n    console.log('Something went wrong generating the SQIP previews')\n    console.error(err)\n  }\n})()\n```\n\n#### Use custom plugin config\n\nThis will run:\n\n* Primitive with custom settings\n* SVGO with default settings\n\n```js\n;(async () =\u003e {\n  const pluginResults = await sqip({\n    input: resolve(__dirname, 'images/originals'),\n    output: resolve(__dirname, 'images/previews'),\n    plugins: [\n      {\n        name: 'sqip-plugin-primitive',\n        options: {\n          numberOfPrimitives: 8,\n          mode: 0,\n        },\n      },\n      'sqip-plugin-svgo',\n    ],\n  })\n  console.log(pluginResults)\n})()\n```\n\n[For further configuration options see here](#config)\n\n\n## CLI\n\n### Installation\n\n```sh\nnpm install -g sqip-cli@canary\n```\n\n**This is the `v1 alpha` readme. [You can find the current docs here.](https://github.com/axe312ger/sqip/tree/legacy#readme)**\n\n### Usage examples\n\n#### Using the help efficently\n\nMake sure to specify plugins when using `--help` to see the available plugin options.\n\n```sh\nsqip -h -p primitive -p blur -p svgo\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eResult:\u003c/summary\u003e\n\n```sh\nsqip CLI\n\n  Usage: sqip --input [path]\n\n  \"SQIP\" (pronounced skwɪb like the non-magical folk of magical descent) is a\n  SVG-based LQIP technique - https://github.com/technopagan/sqip\n\nOptions\n\n  -h, --help                                  Show help\n  --version                                   Show version number\n  -p, --plugins string[]                      One or more plugins. E.g. \"-p primitive blur\"\n  -i, --input string\n  -o, --output string                         Save the resulting SVG to a file. The svg result will be returned by default.\n  -n, --primitive-numberOfPrimitives number   The number of primitive shapes to use to build the SQIP SVG\n  -m, --primitive-mode number                 The style of primitives to use:\n                                              0=combo, 1=triangle, 2=rect, 3=ellipse, 4=circle, 5=rotatedrect, 6=beziers,\n                                              7=rotatedellipse, 8=polygon\n  -b, --blur-blur number                      Set the GaussianBlur SVG filter value. Disable it via 0.\n\nExamples\n\n  Output input.jpg image as SQIP\n  $ sqip --input /path/to/input.jpg\n\n  Save input.jpg as result.svg with 25 shapes and no blur\n  $ sqip -i input.jpg -n 25 -b 0 -o result.svg\n```\n\u003c/details\u003e\n\n#### Process single file\n\n```sh\n$ sqip -i __tests__/fixtures/beach.jpg\nProcessing: __tests__/fixtures/beach.jpg\n[Preview image (iTerm2 users only)]\n┌───────────────┬────────────────┬───────┬────────┬──────┐\n│ originalWidth │ originalHeight │ width │ height │ type │\n├───────────────┼────────────────┼───────┼────────┼──────┤\n│ 1024          │ 640            │ 300   │ 188    │ svg  │\n└───────────────┴────────────────┴───────┴────────┴──────┘\n┌─────────┬─────────────┬──────────────┬─────────┬───────────┬────────────┐\n│ Vibrant │ DarkVibrant │ LightVibrant │ Muted   │ DarkMuted │ LightMuted │\n├─────────┼─────────────┼──────────────┼─────────┼───────────┼────────────┤\n│ #dd852f │ #be4e0c     │ #f2b17a      │ #5c8fa4 │ #694e35   │ #cfc8b7    │\n└─────────┴─────────────┴──────────────┴─────────┴───────────┴────────────┘\n```\n\n##### Process multiple files via glob and use custom plugin config\n\n```sh\nsqip -p primitive -p blur -p svgo \\\n-i \"demo/*.jpg\" \\\n-b 6\n```\n\n[For further configuration options see here](#config)\n\n## Config\n\nThe configuration consists of three parts. A required input, an optional output path and a configuration of plugins to be applied on the images.\n\n### `input` - required\n\nInput file or directory. Supports feature rich globbing via [micromatch](https://github.com/micromatch/micromatch#why-use-micromatch).\n\n**CLI usage:** `-i/--input`\n\n### `output`\n\nIf set, the output will be written to the given file or directory.\n\nOtherwise, results will be output to CLI\n\n**CLI usage:** `-o/--output`\n\n### `width`\n\nSet the width of the resulting image. Negative values and 0 will fall back to the original image width.\n\n**CLI usage:** `-w/--width`\n\n### `plugins`\n\n**Default:** `['primitive', 'svgo']`\n\nArray of plugins. Either as a string (default config will be applied) or as a config object.\n\n**Example:**\n\n```js\nawait sqip({\n  ...\n  plugins: [\n    {\n      name: 'sqip-plugin-primitive',\n      options: {\n        numberOfPrimitives: 8,\n        mode: 0,\n      },\n    },\n    `sqip-plugin-svgo`,\n  ],\n})\n```\n\n**CLI usage:**\n\n`-p/--plugins`\n\n* Can be specified multiple times: `-p svgo -p blur`\n* If prefix was skipped, plugin names will be transformed to: `sqip-plugin-[name]`\n* To set plugin options, see [plugin specifc config](#plugin-specific-confic)\n\n### Plugin specific config\n\n* See the [Plugins](#plugins) section for a list of available plugins.\n* List all plugins subcommands by adding the plugin plus using the help parameter. For example: `-p blur -p svgo -h` will list you all options of the blur and the svgo plugins.\n* Follows the pattern `--[plugin-name]-[option]=[value]`\n\n**Example:**\n\nSet `blur` option of `blur` plugin to 3. You could use the `-b` shortcut as well.\n\n```sh\nsqip -i foo.jpg -p primitive -p blur -blur-blur 3\n```\n\n### `--parseable-output`\n\nnon-TTY consoles and when the `--parseable-output` input flag is set, the output will be the following:\n\n```sh\n$ sqip -i __tests__/fixtures/beach.jpg --parseable-output\nProcessing: __tests__/fixtures/beach.jpg\noriginalWidth originalHeight width height type\n1024          640            300   188    svg\nVibrant DarkVibrant LightVibrant Muted   DarkMuted LightMuted\n#dd852f #be4e0c     #f2b17a      #5c8fa4 #694e35   #cfc8b7\n```\n\n### `--silent`\n\nNo output at all on STDOUT. The process will still return an error code \u0026 message when something failed.\n\n\n### `--print`\n\nOutputs resulting SVG to STDOUT. Ignores `--silent` and works with `--parseable-output`.\n\n## Plugins\n\nSQIP comes with some core plugins, the community is very welcome to [contribute their own plugins](#contributing) to SQIP. The effort to implement a tool or script doing something with images into SQIP is very minimal.\n\n### Core plugins\n\nHere is a list of all current core plugins:\n\n* [sqip-plugin-primitive](https://github.com/axe312ger/sqip/tree/master/packages/sqip-plugin-primitive#readme)\n* [sqip-plugin-blur](https://github.com/axe312ger/sqip/tree/master/packages/sqip-plugin-blur#readme)\n* [sqip-plugin-svgo](https://github.com/axe312ger/sqip/tree/master/packages/sqip-plugin-svgo#readme)\n* [sqip-plugin-datauri](https://github.com/axe312ger/sqip/tree/master/packages/sqip-plugin-datauri#readme)\n* [sqip-plugin-pixels](https://github.com/axe312ger/sqip/tree/master/packages/sqip-plugin-pixels#readme)\n* [sqip-plugin-potrace](https://github.com/axe312ger/sqip/tree/master/packages/sqip-plugin-potrace#readme)\n\n## Debugging\n\nIf something is not going as expected, adding debug output might help a lot. You can achieve this by setting the `DEBUG` environment variable to `sqip*`.\n\nOn a *NIX environment, you might do the following:\n\n```sh\nDEBUG=sqip* node myscript.js\n\n# or for CLI:\n\nDEBUG=sqip* sqip --input...\n```\n\n## Background \u0026 reseach about image placeholder \u0026 previews\n\nImage placeholders are a thing: from grey boxes in skeleton screens over boxes\nthat show the predominant color of the image that will later occupy the space\nand CSS color gradients made from two dominant colors up to an actual low quality\nraster images downscaled to a few pixels, saved in low quality and then blurred\nto provide a preview of image contents.\n\nMany major players have adopted one of these image placeholder techniques:\n[Guypo](https://twitter.com/guypod) [incepted\nLQIP](https://www.guypo.com/introducing-lqip-low-quality-image-placeholders/) in\n2012 and Akamai adopted it as part of their image optimization tools, Google\nstarted using colored placeholders a long time ago,\n[Facebook](https://code.facebook.com/posts/991252547593574/the-technology-behind-preview-photos/),\n[Pinterest](https://blog.embed.ly/pinterests-colored-background-placeholders-4b4c9fb8bb77)\nand\n[Medium](https://jmperezperez.com/medium-image-progressive-loading-placeholder/)\nmade a significant impact on their LQIP implementations and the most popular\n[JS libraries for responsive\nimages](https://github.com/aFarkas/lazysizes#lqipblurry-image-placeholderblur-up-image-technique)\ninclude LQIP implementations.\n\n**Overview of Image Placeholder Techniques**\n[![Overview of Image Placeholders](demo/placeholder-overview.jpg)](https://raw.githubusercontent.com/technopagan/sqip/master/demo/placeholder-overview.jpg)\n\nOn the low end of the bytesize spectrum of image placeholder implementations, we\nhave skeleton screens and colored boxes, weighing only a few extra bytes each,\nbut providing no preview of image contents. On the high end of the bytesize\nspectrum, the LQIP technique ships an actual raster image, which gives a good\ninitial impression of image contents to come, but weighs more heavily in\nbytesize.\n\nIf we disregard Facebooks's native-app implementation of shipping a custom image\ndecoder that enables them to hardcode image headers, the current minimum\nbytesize for LQIP raster images is ~400-600 bytes. At this byterange, the\npreview image often looks distorted and coarse, especially on HiDPI screens.\nMany other LQIP implementations go for preview images of ~2kb in size, which\nprovides a much better initial visual impression but comes at the cost of\nsignificantly increased bytesize for the LQIP implementation.\n\nSQIP is an attempt to find a balance between these two extremes: it makes use\nof [Primitive](https://github.com/hashbite/primitive) to generate a SVG\nconsisting of several simple shapes that approximate the main features visible\ninside the image, optimizes the SVG using [SVGO](https://github.com/svg/svgo)\nand adds a Gaussian Blur filter to it. This produces a SVG placeholder which\nweighs in at only ~800-1000 bytes, looks smooth on all screens and provides an\nvisual cue of image contents to come.\n\n## Contributing\n\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\nBefore contribution, please make sure to read the [contribution guidelines](./CONTRIBUTING.md) guidelines and the [code of conduct](./CODE_OF_CONDUCT.md).\n\nPull requests, forks and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/axe312ger/sqip/issues/new).\n\n## Credits\n\n* trivago N.V. (https://github.com/trivago)\n* Efe Gürkan Yalaman (https://github.com/efegurkan)\n* Benedikt Rötsch (https://github.com/axe312ger)\n* Michael Fogleman (https://github.com/fogleman)\n\n## License\n\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to [\u003chttp://unlicense.org/\u003e](http://unlicense.org/)\n\n\n---\n\n## 🛠️ Sponsored by [hashbite.net](https://hashbite.net) | support \u0026 custom development available\n\nWe welcome everyone to post issues, fork the project, and contribute via pull requests. Together we can make this a better tool for all of us!\n\nIf the contribution process feels too slow or complex for your needs, [hashbite.net](https://hashbite.net) can quickly implement features, fix bugs, or develop custom variations of this plugin on a paid basis. Just reach out through their website for direct support.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxe312ger%2Fsqip","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxe312ger%2Fsqip","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxe312ger%2Fsqip/lists"}