{"id":27876302,"url":"https://github.com/rustamli/tasvir","last_synced_at":"2026-04-29T00:32:00.729Z","repository":{"id":65514791,"uuid":"44168557","full_name":"rustamli/tasvir","owner":"rustamli","description":"Bulk image manipulation tool implemented in pure JS","archived":false,"fork":false,"pushed_at":"2015-10-15T07:59:29.000Z","size":164,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-21T13:19:23.345Z","etag":null,"topics":[],"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/rustamli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-10-13T10:21:04.000Z","updated_at":"2025-02-05T23:57:50.000Z","dependencies_parsed_at":"2023-01-26T21:05:10.580Z","dependency_job_id":null,"html_url":"https://github.com/rustamli/tasvir","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustamli%2Ftasvir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustamli%2Ftasvir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustamli%2Ftasvir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustamli%2Ftasvir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustamli","download_url":"https://codeload.github.com/rustamli/tasvir/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251149089,"owners_count":21543548,"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":[],"created_at":"2025-05-05T02:46:44.694Z","updated_at":"2026-04-29T00:31:55.709Z","avatar_url":"https://github.com/rustamli.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tasvir\n\nTasvir is a tool for bulk image manipulations (resize, crop, optimize and more). It might be useful in context of static website generation to produce thumbnails and optimized versions of the content images. Also tasvir could be used to produce images of different sizes for responsive websites.\n\n## Installation\n\n```\nnpm install tasvir -g\n```\n\n## Configuration\n\nCreate a file named **tasvir.config.js** in root folder of your project:\n\n\n```javascript\n\nmodule.exports = {\n  prefixSeparator: '--',\n  \n  paths: [\n    'static/images/*',\n    'static/users/photos/*'\n  ],\n\n  rules: [\n    {\n      chain: [\n        { apply: 'resize', params: [ 600, 'AUTO' ] },\n        { apply: 'write', prefix: 'w600' }\n      ]\n    },\n    {\n      chain: [\n        { apply: 'cover', params: [ 300, 300 ] },\n        { apply: 'write', prefix: 'sq' }\n      ]\n    }\n  ]\n};\n\n```\n\n- **prefixSeparator** - All processed images are saved in same folder as original image with additional prefixes. *prefixSeparator* specifies separator between original file name and prefix. For example `123.png` would be saved as `123--small.png` with *prefixSeparator: '--'* and *prefix: small*. Please note that tasvir ignores all files containing *prefixSeparator* in their names on consecutive runs. So in our example rules are not applied to `123--small.png` on second run. \n- **paths** - List of path patterns which specify files that should be processed inside the root folder (folder which contains tasvir.config.js). Matching is dong using [**glob**](https://github.com/isaacs/node-glob) library. \n- **rules** - List of rules to be applied for each file that is matched using the patterns in `paths`:\n\n### Rules \n\nEach rule represents an object with single parameter `chain`. \nEach `chain` contains number `actions` to be applied to each image:\n\n```javascript\n{\n  chain: [\n    { apply: 'resize', params: [ 600, 'AUTO' ] },\n    { apply: 'write', prefix: 'w600' }\n  ]\n}\n```\n\n#### Actions\n\nTasvir uses [**jimp**](https://github.com/oliver-moran/jimp) for image manipulations. \nEvery action in a `chain` is a call translated to a **jimp** method:\n\n```javascript\n{ apply: 'resize', params: [ 600, 'AUTO' ] },\n{ apply: 'greyscale', params: [] },\n{ apply: 'mirror', params: [] },\n{ apply: 'write', prefix: 'small' }\n```\n\nRunning this for `sample.png` will result in: \n\n```javascript\nimage.resize(600, Jimp.AUTO).greyscale().mirror().write('sample--small.png');\n```\n\nHere are some of the actions supported: `crop`, `invert`, `flip`, `gaussian`, `blur`, `greyscale`, `sepia`, `opacity`, `resize`, `scale`, `rotate`, `blit`, `composite`, `brightness`, `contrast`, `posterize`, `mask`, `dither565`, `cover`, `contain`, `background`, `color`, `mirror`, `fade`. For their description and params, please refer to [**jimp**](https://github.com/oliver-moran/jimp) documentation.\n\n#### Multiple writes per rule \n\nPlease note that you can call `{ apply: 'write' }` multiple times per each rule:\n\n```javascript\n{ apply: 'resize', params: [ 600, 'AUTO' ] },\n{ apply: 'write', prefix: 'sm' }\n{ apply: 'greyscale', params: [] },\n{ apply: 'mirror', params: [] },\n{ apply: 'write', prefix: 'sm-gs-mr' }\n```\nThis will produce two files `sample--sm.png` (resized to 600px in width) and `sample--sm-gs-mr.png` (resized to 600px in width, greyscaled and mirrored).\n\n## Usage\n\n### Normal mode\n\nExecute in your project root folder (folder containing `tasvir.config.js`):\n\n```\ntasvir\n```\n\nAll files containing `prefixSeparator` (for example `--`) will be ignored.\nIn normal mode tasvir will be applied only for files that were not previously processed. \nBefore applying each rule to a file, tasvir checks whether files with resulting prefixes already exists in that case rule is ignored for that file.\n\nSo a rule for file `sample.png`: \n\n```\n{ apply: 'resize', params: [ 600, 'AUTO' ] }, { apply: 'write', prefix: 'sm' }\n```\n\nwill be ignored in case if a file named `sample--sm.png` exists\n\n### Overwrite mode\n\nExecute in your project root folder: \n\n```\ntasvir overwrite\n```\n\nAll files containing `prefixSeparator` (for example `--`) will still be ignored.\n\nUnlike normal mode. All rules will be executed even, if resulting files already exist.\n\n## Tinify integration\n\nTasvir also optionally uses [Tinify](https://tinypng.com/developers) to optimize your images. \n\nHere's a sample **tasvir.config.js** file with enabled tinify integration: \n\n```javascript\nmodule.exports = {\n  prefixSeparator: '--',\n\n  tinify: {\n    enabled: true,\n    apiKey: '\u003cYOUR-KEY\u003e',\n    originalPrefix: 'orig',\n  },\n\n  paths: [\n    'static/images/*'\n  ],\n\n  rules: [ ... ]\n};\n```\n\nIf tinify integration is enabled, before applying rules Tasvir will save a copy of original image file with a prefix specified in `tinify.originalPrefix` configuration, run tinify optimization and replace file with the result. After that rules are executed normally. \n\nIn normal mode, tinify even if it is enabled won't be executed if a file with a `tinify.originalPrefix` in its name exists.\nHowever in overwrite mode tinify will still be executed despite existing file with a `tinify.originalPrefix`.\n\n### Example\n\n- `sample.png` - Original unoptimized image \n\nafter tinify execution:\n\n(given `orig` as a value for `tinify.originalPrefix` in **tasvir.config.js**)\n\n- `sample.png` - Tinified (optimized) image \n- `sample--orig.png` - Original unoptimized image \n\nafter applying rules:\n\n- `sample.png` - Tinified (optimized) image \n- `sample--sm.png` - Tinified (optimized) and resized image\n- `sample--sm-gs-mr.png` - Tinified (optimized), resized, greyscaled and mirrored image \n- `sample--orig.png` - Original unoptimized image \n\n\n## License\n\nReleased under MIT license\n\nSee LICENSE file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustamli%2Ftasvir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustamli%2Ftasvir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustamli%2Ftasvir/lists"}