{"id":42235437,"url":"https://github.com/dotherightthing/focalpoint-multi-cropper","last_synced_at":"2026-01-27T03:17:37.413Z","repository":{"id":179806471,"uuid":"622034379","full_name":"dotherightthing/focalpoint-multi-cropper","owner":"dotherightthing","description":"Add a focalpoint to an image and generate project-specific crops.","archived":false,"fork":false,"pushed_at":"2025-12-06T10:27:34.000Z","size":109138,"stargazers_count":0,"open_issues_count":50,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-10T04:23:35.462Z","etag":null,"topics":["cropperjs","electron","imagemagick"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dotherightthing.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-04-01T00:06:30.000Z","updated_at":"2025-11-18T10:30:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"509a2bee-0b89-4886-a20f-1faca05a161a","html_url":"https://github.com/dotherightthing/focalpoint-multi-cropper","commit_stats":null,"previous_names":["dotherightthing/focalpoint-multi-cropper"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dotherightthing/focalpoint-multi-cropper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotherightthing%2Ffocalpoint-multi-cropper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotherightthing%2Ffocalpoint-multi-cropper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotherightthing%2Ffocalpoint-multi-cropper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotherightthing%2Ffocalpoint-multi-cropper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dotherightthing","download_url":"https://codeload.github.com/dotherightthing/focalpoint-multi-cropper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dotherightthing%2Ffocalpoint-multi-cropper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28798794,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T01:07:07.743Z","status":"online","status_checked_at":"2026-01-27T02:00:07.755Z","response_time":168,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cropperjs","electron","imagemagick"],"created_at":"2026-01-27T03:17:35.423Z","updated_at":"2026-01-27T03:17:37.406Z","avatar_url":"https://github.com/dotherightthing.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# focalpoint-multi-cropper\n\n\u003cimg src=\"screenshot-1.png\"\u003e\n\n\u003cimg src=\"screenshot-2.png\"\u003e\n\n\u003cimg src=\"screenshot-3.png\"\u003e\n\n\u003cimg src=\"screenshot-4.png\"\u003e\n\n## Features\n\n* **Preview** - Single window containing multiple instances of [cropperjs](https://github.com/fengyuanchen/cropperjs) - one master cropper and one or more slave croppers with user-defined `exportWidth` and `exportHeight` proportions\n* **Load** - Leverage [Electron](https://www.electronjs.org/) to allow for loading of folders of images\n* **Filter** - Filter thumbnails by partial filename, and whether they have been cropped\n* **Set focalpoint** - Click the master cropper image or use the number inputs to set a focalpoint, slave croppers' crop boxes will automatically follow\n* **Rounding** - Round focalpoint XY to integers for easier storage\n* **Storage** - Toggle on auto-save to write a non-default focalpoint to the image filename as a resolution-independent percentage of its width and height (integers), e.g. `foo__[40%,37%].jpg` (regular) or `bar__[40%,37%,P].jpg` (panorama)\n* **Reset** - Remove user changes and reapply the focalpoint stored in the image filename, or the defaults\n* **Delete** - Delete the focalpoint and remove non-default focalpoint from the image filename\n* **Resize \u0026 Crop** - Use [gm](https://github.com/aheckmann/gm) to `resizeAndCrop` from the slave croppers' crop boxes, and `resize` from the hidden non-cropper inclusions\n* **Locate** - Easily open the source and target image folders to keep track of where files are\n* **Embed** - Copy paths including a relative link suitable for pasting into a Markdown document or webpage, optionally output a target cross on the image\n* **Geotag** - Copy latitude/longitude information if available\n* **Restore** - Settings are restored when reopening the Electron app\n* **Presets** - Store a batch of settings in userData (macOS: `/Users/NAME/Library/Application Support/focalpoint-multi-cropper/user-preferences.json`)\n\n## Usage\n\n### Install\n\n```js\nnpm install\n```\n\n### Run (Electron App)\n\n```js\n# run with devtools closed\nnpm run start\n\n# run with devtools open\nnpm run start:debug\n```\n\n### Run (Web App)\n\n```js\nnpm run serve\nopen http://127.0.0.1:8000\n```\n\n### Lint\n\n```js\nnpm run lint\n```\n\n### Test\n\nCypress does not have full support for Electron, so tests are run in-browser and test only non-Electron functionality.\n\n```js\nnpm run test\n```\n\n### Debug\n\n```js\n// inspect the current state of fmcCroppersUi\ndocument.getElementById('croppers').fmcCroppersUi\n```\n\n## Research\n\n### Background\n\nI needed a tool to art-direct thousands of images for my bicycle touring blog.\n\nPreviously I've used WordPress with Imgix. I'm now moving away from subscription-based systems.\n\nI will use this app to generate image URLs for the next version of my blog which runs on Vuepress.\n\nMy Vuepress app uses the following image sizes:\n\n```js\nimagesSizes: {\n   type: Object,\n   default: () =\u003e ({\n      collapsed: {\n         width: 865,\n         height: 368\n      },\n      expanded: {\n         width: 865,\n      },\n      panorama: {\n         height: 368\n      },\n      thumbnail: {\n         width: 320,\n         height: 320\n      },\n   })\n},\n```\n\n### Alternatives\n\nExcluding anything that requires a subscription fee or complex serverside setup.\n\n* \u003chttps://markerjs.com/docs/cropro/getting-started\u003e - doesn't appear to offer preset size crops (only ratios)\n* \u003chttps://github.com/fengyuanchen/cropperjs\u003e - `cropBoxResizable` option\n* \u003chttps://github.com/danfickle/bulk-image-cropper\u003e - no overview of crop position for multiple images (one at a time)\n* \u003chttps://w3codegenerator.com/code-snippets/javascript/how-to-crop-multiple-images-with-cropper-js\u003e\n* \u003chttps://pqina.nl/blog/rename-a-file-with-javascript/\u003e\n* \u003chttps://codepen.io/saleemnaufa/pen/gVewZw\u003e\n* \u003chttps://stackoverflow.com/questions/60995032/crop-and-resize-image-around-a-custom-focus-point\u003e - crop around a crop point\n\n### Electron\n\nImages need to be loaded into the cropping tool. As this is best done locally to remove dependency on web-based subscription services, the app needs to be able to interact with the local file system.\n\nThe combination of `input[type=\"file\"]` and JavaScript's [FileReader object](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) only provides access to a single file.\n\nTo provide a visual overview, the cropper needs access to a folder of files.\n\nA web browser is sandboxed for security reasons. Electron can run a web browser whilst also providing access to the operating system.\n\n* [What is the difference between IPC send / on and invoke / handle in electron?](https://stackoverflow.com/questions/59889729/what-is-the-difference-between-ipc-send-on-and-invoke-handle-in-electron) - invoke vs send/on\n* [Inter-Process Communication](https://www.electronjs.org/docs/latest/tutorial/ipc) - send/on\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotherightthing%2Ffocalpoint-multi-cropper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdotherightthing%2Ffocalpoint-multi-cropper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdotherightthing%2Ffocalpoint-multi-cropper/lists"}