{"id":27222227,"url":"https://github.com/paazmaya/shigehachi","last_synced_at":"2025-04-10T08:57:39.805Z","repository":{"id":26093699,"uuid":"29537755","full_name":"paazmaya/shigehachi","owner":"paazmaya","description":"Compare two sets of images","archived":false,"fork":false,"pushed_at":"2024-04-30T07:33:37.000Z","size":1748,"stargazers_count":2,"open_issues_count":5,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-05-01T22:47:45.711Z","etag":null,"topics":["comparison","diff","graphicsmagick","hacktoberfest","nodejs","testing","visual-regression-testing"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paazmaya.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2015-01-20T15:53:29.000Z","updated_at":"2024-05-03T23:35:49.371Z","dependencies_parsed_at":"2023-01-17T01:00:12.810Z","dependency_job_id":"c7609665-79eb-4301-8e37-258747ecc9c2","html_url":"https://github.com/paazmaya/shigehachi","commit_stats":{"total_commits":307,"total_committers":6,"mean_commits":"51.166666666666664","dds":0.3420195439739414,"last_synced_commit":"707907ce181251e15e4ccc47a866916f6a5b7e2c"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paazmaya%2Fshigehachi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paazmaya%2Fshigehachi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paazmaya%2Fshigehachi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paazmaya%2Fshigehachi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paazmaya","download_url":"https://codeload.github.com/paazmaya/shigehachi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248190439,"owners_count":21062278,"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":["comparison","diff","graphicsmagick","hacktoberfest","nodejs","testing","visual-regression-testing"],"created_at":"2025-04-10T08:57:39.129Z","updated_at":"2025-04-10T08:57:39.793Z","avatar_url":"https://github.com/paazmaya.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# shigehachi (繁八)\n\n\u003e Compare two sets of images and generate difference images\n\n![Mr Shigehachi Sonobe](./logo.png)\n\n[![Ubuntu Build Status](https://paazmaya.semaphoreci.com/badges/shigehachi/branches/master.svg)](https://paazmaya.semaphoreci.com/projects/shigehachi)\n[![Windows build status](https://ci.appveyor.com/api/projects/status/0tj1ycxk27j5ff58/branch/master?svg=true)](https://ci.appveyor.com/project/paazmaya/shigehachi/branch/master)\n[![codecov](https://codecov.io/gh/paazmaya/shigehachi/branch/master/graph/badge.svg)](https://codecov.io/gh/paazmaya/shigehachi)\n[![Inline docs](http://inch-ci.org/github/paazmaya/shigehachi.svg?branch=master)](http://inch-ci.org/github/paazmaya/shigehachi)\n\nThis tool reads a folder, searching for images and then tries to find matching ones\nfrom another folder. These pairs are compared and an image is created to a third folder,\nwhich visualises the differences of the first two.\n\n## Background for the name\n\nThe name of the project is for honouring the legacy of Mr Sonobe Shigehachi (園部 繁八),\nwho was the 16th head master of\n[Jikishinkageryu Naginatajutsu (直心影流薙刀術)](http://naginata.fi/en/koryu),\nwhich is an ancient Japanese martial art, focusing the handling of a long pole like weapon\ncalled naginata.\n\n## Getting started\n\nMake sure you have [GraphicMagick](http://www.graphicsmagick.org/) installed and available\nin the `PATH`, before trying to use `shigehachi`. This can be tested by running for example\nthe following command which should provide plenty of information when successful:\n\n```sh\ngm version\n```\n\nThe version tested of GraphicMagick is `1.3.40`.\n\nInstall the `shigehachi` command line utility globally with [npm](https://www.npmjs.com/).\nElevated privileges might be needed via `sudo`, depending on the platform. In most cases just:\n\n```sh\nnpm install --global shigehachi\n```\n\nPlease note that the minimum supported version of [Node.js](https://nodejs.org/en/) is `22.11.0`,\nwhich is [the active Long Term Support (LTS) version](https://github.com/nodejs/Release#release-schedule).\n\nRun from the command line, for example getting the help output:\n\n```sh\nshigehachi -h\n```\n\nCompare two directories with the default comparison algorithm and store\ndifferentiation images to a folder called `images-diff`:\n\n```sh\nshigehachi -P images-previous -C images-current -O images-diff\n```\n\nAlong with the \"compare\" image, there will also be a \"negate\" and \"composite\" images,\nwhich should help to determine which metric algorithm is the most suitable for the given\ncomparison.\n\n## Comparison example\n\nBy running the following command on two screen captures of\n[naginata.fi](https://naginata.fi/en/koryu) that were taken while adjusting paddings:\n\n```sh\nshigehachi --current-dir tests/fixtures/curr/website \\\n --previous-dir tests/fixtures/prev/website \\\n --output-dir tests/expected/website \\\n --match '\\.(png)$' \\\n --metric rmse\n```\n\n...would result these three images, in the order of \"difference\", \"negate\", and \"composite\":\n\n[![naginata.fi koryu page difference](./naginata-koryu_thumb.png)](./tests/expected/website/naginata-koryu.png)\n[![naginata.fi koryu page negate](./naginata-koryu-negate_thumb.png)](./tests/expected/website/naginata-koryu-negate.png)\n[![naginata.fi koryu page composite](./naginata-koryu-composite_thumb.png)](./tests/expected/website/naginata-koryu-composite.png)\n\nThe [previous](./tests/fixtures/prev/website/naginata-koryu.png) and\n[current](./tests/fixtures/curr/website/naginata-koryu.png) images are available at\nthe `tests/fixtures` directory.\n\nThe file `shigehachi.json` generated to the output directory, looks something similar to this:\n\n```json\n{\n  \"a0db9e2b1dec76cd4964bbac45daa719\": {\n    \"metric\": \"MeanAbsoluteError\",\n    \"normalized\": {\n      \"red\": \"0.0135227820\",\n      \"green\": \"0.0771904810\",\n      \"blue\": \"0.0779529725\",\n      \"opacity\": \"0.0982667803\",\n      \"total\": \"0.0667332540\"\n    },\n    \"absolute\": {\n      \"red\": \"886.2\",\n      \"green\": \"5058.7\",\n      \"blue\": \"5108.6\",\n      \"opacity\": \"6439.9\",\n      \"total\": \"4373.4\"\n    },\n    \"A\": \"tests/fixtures/prev/website/naginata-koryu.png\",\n    \"B\": \"tests/fixtures/curr/website/naginata-koryu.png\",\n    \"D\": \"tests/expected/website/naginata-koryu.png\",\n    \"N\": \"tests/expected/website/naginata-koryu-negate.png\"\n  }\n}\n```\n\nThe index hash is made with `md5` algorithm, from the file path string of image A.\n\n## Command line options\n\nThe output of `shigehachi --help` pretty much covers all the options:\n\n```sh\nshigehachi [options]\n\n  -h, --help                 Help and usage instructions\n  -V, --version              Version number, with verbosity also application name\n  -v, --verbose              Verbose output, will print which file is currently being processed\n  -P, --previous-dir String  Directory in which the previous images are stored - default: previous\n  -C, --current-dir String   Directory in which the current images are stored - default: current\n  -O, --output-dir String    Directory in which the resulting differentiation images are stored - default: diff-2019-05-15T15-22\n  -c, --color String         Color used in the output images, such as #b10dc9 or purple - default: pink\n  -m, --metric String        Difference calculation metric - either: mae, mse, pae, psnr, or rmse - default: pae\n  -s, --style String         Style in which the differentiation image is created - either: assign, threshold, tint, or xor - default: tint\n  -p, --compose String       Composition type used for creating a composite image - either: over, in, out, atop, xor, plus, minus, add, subtract, difference, divide, multiply,\n                             bumpmap, copy, copyred, copygreen, copyblue, copyopacity, copycyan, copymagenta, copyyellow, or copyblack - default: difference\n  -A, --all-variations       Generate diff image variations for all alternatives of metric and compose options\n  -M, --match String         Regular expression for matching and filtering image files - default: \\.png$\n  -l, --long-diff-name       Include used metric, style and composition options in difference image file names\n  -r, --recursive            Recursive search of images in the previous and current directories\n\nVersion 8.0.0\n```\n\nBe aware of using the `--all-variations` option, since it will execute about 1320 commands per single image comparison pair.\n\nCombining `--version` and `--verbose` (or using `-Vv`) the output will also contain the name\nof the application in addition to the version number.\n\n## Using in a Node.js script\n\nBest example of the usage inside another application is inside the script that is used\nfor the command line interface, `bin/shigehachi.js`.\n\nInstallation with [npm](https://www.npmjs.com/):\n\n```sh\nnpm install --save shigehachi\n```\n\nFirst include this module in your script:\n\n```js\nconst Shigehachi = require('shigehachi');\n```\n\nOr as EcmaScript Modules style:\n\n```js\nimport Shigehachi from 'shigehachi';\n```\n\nDefine the options, which follow the same convention as the command line options, with the\nexception of being camelCased from the long versions. Below is an example of all configuration\noptions by using their default values:\n\n```js\nconst options = {\n  color: 'pink',\n  compose: 'difference',\n  currentDir: 'current',\n  longDiffName: false,\n  match: '\\.png$',\n  metric: 'pae',\n  outputDir: 'diffence',\n  previousDir: 'previous',\n  recursive: false,\n  allVariations: false,\n  style: 'tint',\n  verbose: false,\n  whenDone: null\n};\n```\n\nInitialise an instance with the above `options` object and call `exec()` method\nto generate the images:\n\n```js\nconst hachi = new Shigehachi(options);\nhachi.exec();\n```\n\nIn addition to the options used for command line, there is also a callback which gets\ncalled when the execution has been done. It gets passed one argument, which is the\ncollection object of metrics, indexed by the current image file path.\n\n```js\nconst options = {\n  whenDone: function (metrics) {\n    console.log(JSON.stringify(metrics, null, '  '));\n  }\n};\n\nconst hachi = new Shigehachi(options);\nhachi.exec();\n```\n\nThe metrics output looks something similar to:\n\n```json\n{\n  \"a0db9e2b1dec76cd4964bbac45daa719\": {\n    \"metric\": \"MeanAbsoluteError\",\n    \"normalized\": {\n      \"red\": \"0.0135227820\",\n      \"green\": \"0.0771904810\",\n      \"blue\": \"0.0779529725\",\n      \"opacity\": \"0.0982667803\",\n      \"total\": \"0.0667332540\"\n    },\n    \"absolute\": {\n      \"red\": \"886.2\",\n      \"green\": \"5058.7\",\n      \"blue\": \"5108.6\",\n      \"opacity\": \"6439.9\",\n      \"total\": \"4373.4\"\n    },\n    \"A\": \"tests/fixtures/prev/postcss.png\",\n    \"B\": \"tests/fixtures/curr/postcss.png\",\n    \"D\": \"tests/fixtures/output/postcss-mae-tint.png\",\n    \"N\": \"tests/fixtures/output/postcss-mae-tint-negate.png\"\n  }\n}\n```\n\n## File matching\n\nPlease note that the command line option and the module configuration expects the `match`\nto be a string which is passed to [`new RegExp()` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/RegExp).\n\nBy default all PNG files are taken in use, with `/\\.png$/`, but the reason for having\nthe option as a regular expression, is to have much more flexibility in which file names\nare filtered. Please note that while escaping characters in a string, the backward slash\nneeds to be escaped as well.\n\nThe current implementation does not allow to set any flags for the regular expression,\nbut the functionality can be added with a suitable pull request.\n\n[More about JavaScript regular expressions.](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions)\n\n## Output image files and their naming\n\nIt is possible to alter the naming scheme of the images that are produced by the comparison,\nnegation and composition steps inside the single comparison of two image files.\n\nBy default the comparison image will have the same basename as the two which are being compared.\nFor example `prev/image.jpg` and `curr/image.jpg` will produce `diff/image.png`.\nPlease note that the generated images are always in [png](http://www.w3.org/TR/PNG/)\nformat, due to quality requirements.\n\nThe negated image, which is generated from the comparison image, will have `-negate` appended\nto the basename, before the suffix. For example in the above case it would\nbe `diff/image-negate.png`.\n\nThe third image is a composition of the two images that are being compared. In many cases\nthis is visually the most useful image, depending of the colours and composition method used.\nThe basename is appended with `-composite`, thus in the example above `diff/image-composite.png`.\n\nThese filenames can be altered via `longDiffName` boolean option. By default it is set to `false`\nand the filenames are created as explained above. In case it is set to `true`, the filenames\nwill also be appended with the used `metric`, `style`, or `color`, depending of the relevance\nto the given method.\n\nFor example, while following the above example and setting the `longDiffName` to `true`, the\ngenerated three images would become with the default options:\n\n* `diff/image-pae-tint.png`\n* `diff/image-pae-tint-negate.png`\n* `diff/image-pae-tint-composite-difference.png`\n\n## GraphicMagick is used underneath\n\nThe amount of supported metric algorithms, comparison styles and composition types depends\nof the GraphicsMagick version. Available options are listed in [the source file](./index.js) and\nin the [relevant GraphicsMagick documentation](http://www.graphicsmagick.org/compare.html).\n\nUnderneath, the image comparison boils down to a command similar to this:\n\n```sh\ngm compare \\\n -metric mae \\\n -highlight-color purple \\\n -highlight-style xor \\\n -file tests/fixtures/diff/square-mae-xor.png \\\n tests/fixtures/prev/square.png \\\n tests/fixtures/curr/square.png\n```\n\nOutput from the above command with GraphicMagick, would output something like:\n\n```txt\nImage Difference (MeanAbsoluteError):\n           Normalized    Absolute\n          ============  ==========\n     Red: 1.0000000000    65535.0\n   Green: 0.5019607843    32896.0\n    Blue: 0.4980392157    32639.0\n   Total: 0.6666666667    43690.0\n```\n\nIn similar manner, with the different metric types the results vary, namely `mse`, `pae`, `psnr`, and `rmse`:\n\n```txt\nImage Difference (MeanSquaredError):\n           Normalized    Absolute\n          ============  ==========\n     Red: 1.0000000000    65535.0\n   Green: 0.2519646290    16512.5\n    Blue: 0.2480430604    16255.5\n   Total: 0.5000025631    32767.7\n```\n\n```txt\nImage Difference (PeakAbsoluteError):\n           Normalized    Absolute\n          ============  ==========\n     Red: 1.0000000000    65535.0\n   Green: 0.5019607843    32896.0\n    Blue: 0.4980392157    32639.0\n   Total: 1.0000000000    65535.0\n```\n\n```txt\nImage Difference (PeakSignalToNoiseRatio):\n           PSNR\n          ======\n     Red: 0.00\n   Green: 5.99\n    Blue: 6.05\n   Total: 3.01\n```\n\n```txt\nImage Difference (RootMeanSquaredError):\n           Normalized    Absolute\n          ============  ==========\n     Red: 1.0000000000    65535.0\n   Green: 0.5019607843    32896.0\n    Blue: 0.4980392157    32639.0\n   Total: 0.7071085936    46340.4\n```\n\n## Contributing\n\n[\"A Beginner's Guide to Open Source: The Best Advice for Making your First Contribution\"](http://www.erikaheidi.com/blog/a-beginners-guide-to-open-source-the-best-advice-for-making-your-first-contribution/).\n\n[Also there is a blog post about \"45 Github Issues Dos and Don’ts\"](https://davidwalsh.name/45-github-issues-dos-donts).\n\nLinting is done with [ESLint](http://eslint.org) and can be executed with `npm run lint`.\nThere should be no errors appearing after any JavaScript file changes.\n\nUnit tests are written with [`tape`](https://github.com/substack/tape) and can be executed with `npm test`.\nCode coverage is inspected with [`c8`](https://github.com/bcoe/c8) and\ncan be executed with `npm run coverage` after running `npm test`.\nPlease make sure it is over 90% at all times.\n\n## Version history\n\n[Changes happening across different versions and upcoming changes are tracked in the `CHANGELOG.md` file.](CHANGELOG.md)\n\n## License\n\nCopyright (c) [Juga Paazmaya](https://paazmaya.fi) \u003cpaazmaya@yahoo.com\u003e\n\nLicensed under [the MIT license](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaazmaya%2Fshigehachi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaazmaya%2Fshigehachi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaazmaya%2Fshigehachi/lists"}