{"id":15399500,"url":"https://github.com/chai2010/guetzli-js","last_synced_at":"2025-04-15T22:30:49.760Z","repository":{"id":57256596,"uuid":"85924689","full_name":"chai2010/guetzli-js","owner":"chai2010","description":"Guetzli for NodeJS/Browser","archived":false,"fork":false,"pushed_at":"2020-03-31T14:47:26.000Z","size":1074,"stargazers_count":29,"open_issues_count":3,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-06T07:37:26.657Z","etag":null,"topics":["china","guetzli","guetzli-js","javascript","jpeg","jpeg-encoder","js","node","nodejs","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/guetzli-js","language":"C++","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/chai2010.png","metadata":{"files":{"readme":"README.md","changelog":"changes.md","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":"2017-03-23T08:25:04.000Z","updated_at":"2023-10-27T06:44:53.000Z","dependencies_parsed_at":"2022-08-25T02:30:53.902Z","dependency_job_id":null,"html_url":"https://github.com/chai2010/guetzli-js","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fguetzli-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fguetzli-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fguetzli-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chai2010%2Fguetzli-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chai2010","download_url":"https://codeload.github.com/chai2010/guetzli-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248560401,"owners_count":21124646,"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":["china","guetzli","guetzli-js","javascript","jpeg","jpeg-encoder","js","node","nodejs","typescript"],"created_at":"2024-10-01T15:49:10.148Z","updated_at":"2025-04-15T22:30:48.123Z","avatar_url":"https://github.com/chai2010.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003cimg src=\"https://raw.githubusercontent.com/chai2010/guetzli-js/master/guetzli.png\" alt=\"Guetzli\" width=\"64\"\u003e\u003c/p\u003e\n\n----\n\n- *赞助 BTC: 1Cbd6oGAUUyBi7X7MaR4np4nTmQZXVgkCW*\n- *赞助 ETH: 0x623A3C3a72186A6336C79b18Ac1eD36e1c71A8a6*\n- *Go语言付费QQ群: 1055927514*\n\n----\n\n# guetzli-js\n\n[![Build Status](https://travis-ci.org/chai2010/guetzli-js.svg)](https://travis-ci.org/chai2010/guetzli-js) [![NPM](https://img.shields.io/npm/dt/guetzli-js.svg)](https://www.npmjs.com/package/guetzli-js) [![NPM Version](https://img.shields.io/npm/v/guetzli-js.svg)](https://www.npmjs.com/package/guetzli-js) ![License](https://img.shields.io/npm/l/guetzli-js.svg)\n\n[![NPM](https://nodei.co/npm/guetzli-js.png?downloads=true\u0026downloadRank=true\u0026stars=true)](https://npmjs.org/guetzli-js)\n[![NPM](https://nodei.co/npm-dl/guetzli-js.png?height=3\u0026months=9)](https://npmjs.org/guetzli-js)\n\n\n\u003e [Guetzli](https://github.com/google/guetzli) is a JPEG encoder that aims for excellent compression density at high visual quality. Guetzli-generated images are typically 20-30% smaller than images of equivalent quality generated by libjpeg.\n\n[Guetzli](https://github.com/google/guetzli) for NodeJS/Browser\n\n## Demo\n\nThis demo show guetzli-js in browser, encode a canvas and save as a jpeg file.\n\n- https://chai2010.github.io/guetzli-js/example/hello-01\n\n\n**Browser suggest: Chrome, Firefox, Edge. Chrome is the best choice!**\n\n\n## Install\n\n### Windows\n\n```\n$ npm install -g windows-build-tool\n$ npm install -g node-gyp\n\n$ node-gyp install\n$ npm install -g guetzli-js\n```\n\n### macOS and Linux\n\n```\n$ npm install -g node-gyp\n\n$ node-gyp install\n$ npm install -g guetzli-js\n```\n\n\n## Command: `guetzli-cli`\n\n```\n$ guetzli-cli bees.png bees.jpg\nDone\n\n$ guetzli-cli -h\nUsage: guetzli input_filename output_filename\n\n$ guetzli-cli -v\nguetzli-1.0.1\n```\n\n\n## Guetzli API\n\n### Image Type:\n\n```ts\n// const image = require('guetzli-js/dist/lib/image')\n\ninterface image.Image {\n\twidth:    number;\n\theight:   number;\n\tchannels: number; // Gray=1, RGB=3, RGBA=4\n\tstride?:  number; // 0 or \u003e= width*channels\n\tpix:      Uint8Array;\n}\n```\n\n### Guetzli API:\n\n```ts\n// const guetzli = require('guetzli-js')\n// const guetzli_asmjs = require('guetzli-js/dist/lib/cxx-emscripten/guetzli.out')\n\nconst version: string;        // google/guetzli version\nconst minQuality: number;     // 84\nconst maxQuality: number;     // 110\nconst defaultQuality: number; // 95\n\nfunction encodeImage(\n\tm: image.Image, quality?: number = defaultQuality\n): Uint8Array;\n\nfunction encodeGray(\n\tpix: Uint8Array, width: number, height: number,\n\tstride?: number = 0, quality?: number = defaultQuality\n): Uint8Array;\n\nfunction encodeRGB(\n\tpix: Uint8Array, width: number, height: number,\n\tstride?: number = 0, quality?: number = defaultQuality\n): Uint8Array;\n\nfunction encodeRGBA(\n\tpix: Uint8Array, width: number, height: number,\n\tstride?: number = 0, quality?: number = defaultQuality\n): Uint8Array;\n```\n\n### Helpers (NodeJS Only):\n\n\n```ts\n// const helper = require('guetzli-js/dist/lib/helper')\n\nfunction decodePng(data: Uint8Array, expect_channels?: number = 4): image.Image;\nfunction decodeJpg(data: Uint8Array, expect_channels?: number = 3): image.Image;\n\nfunction encodePng(\n\tpix: Uint8Array, width: number, height: number,\n\tchannels: number, stride?: number = 0\n): Uint8Array;\n\nfunction encodeJpg(\n\tpix: Uint8Array, width: number, height: number,\n\tchannels: number, stride?: number = 0,\n\tquality?: number = 95\n): Uint8Array;\n\n// only for jpg/png format\nfunction loadImage(filename: string): image.Image;\n```\n\n## Examples\n\n### NodeJS\n\n```js\nconst fs = require('fs')\nconst guetzli = require('guetzli-js')\nconst helper = require('guetzli-js/dist/lib/helper')\n\n// load png\nlet data = fs.readFileSync('bees.png')\n\n// decode png image\nlet m = helper.decodePng(data, 4)\n\n// encode jpg image\nlet jpegData = guetzli.encodeRGBA(m.pix, m.width, m.height, 0, guetzli.defaultQuality)\n\n// save jpg\nfs.writeFileSync('bees.jpg', jpegData)\n```\n\n### Borwser\n\n```html\n\u003c!DOCTYPE html\u003e\n\n\u003chead\u003e\n\u003ctitle\u003eHello\u003c/title\u003e\n\n\u003cscript src=\"./jquery.min.js\"\u003e\u003c/script\u003e\n\u003cscript src='./dist/lib/cxx-emscripten/guetzli.out.js'\u003e\u003c/script\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n\u003ccanvas id=\"myCanvas\" width=\"120\" height=\"80\"\u003eshow image\u003c/canvas\u003e\n\u003cdiv\u003e\u003cbutton id=\"saveAsBtnRun\"\u003eSave As...\u003c/button\u003e\u003c/div\u003e\n\n\u003cscript\u003e\nconst guetzli = Module\n\n$(document).ready(function() {\n\tlet canvas = document.getElementById('myCanvas')\n\tlet ctx = canvas.getContext('2d')\n\n\tlet m = new Image()\n\tm.src = './testdata/bees.png'\n\tm.onload = function() {\n\t\tctx.drawImage(m, 0, 0, canvas.width, canvas.height)\n\t}\n})\n$(\"#saveAsBtnRun\").click(function() {\n\tlet canvas = document.getElementById('myCanvas')\n\tlet ctx = canvas.getContext('2d')\n\tlet imgd = ctx.getImageData(0, 0, canvas.width, canvas.height)\n\n\tlet jpegData = guetzli.encodeImage({\n\t\twidth:    canvas.width,\n\t\theight:   canvas.height,\n\t\tchannels: 4,\n\t\tstride:   canvas.width*4,\n\t\tpix:      imgd.data,\n\t})\n})\n\u003c/script\u003e\n\u003c/body\u003e\n```\n\nSee https://chai2010.github.io/guetzli-js/example/hello-01/\n\n### Borwser: Settings\n\n```html\n\u003cscript\u003e\nvar Module = {}\nModule.TOTAL_STACK = 5*1024*1024;   // 5 MB\nModule.TOTAL_MEMORY = 64*1024*1024; // 64 MB\nModule.ALLOW_MEMORY_GROWTH = true;\nModule.SIMD = false;\n\u003c/script\u003e\n\n\u003cscript src='./dist/lib/cxx-emscripten/guetzli.out.js'\u003e\u003c/script\u003e\n```\n\n### RGB \u003c==\u003e Gray\n\n```js\nfunction gray2rgb(gray, width, height, stride) {\n\tif(stride == 0) { stride = width }\n\n\tlet rgb = new Uint8Array(width*height*3)\n\tlet off = 0\n\n\tfor(let y = 0; y \u003c height; y++) {\n\t\tfor(let x = 0; x \u003c width; x++) {\n\t\t\tlet V = gray[y*stride + x]\n\n\t\t\trgb[off++] = V // R\n\t\t\trgb[off++] = V // G\n\t\t\trgb[off++] = V // B\n\t\t}\n\t}\n\treturn rgb\n}\n\nfunction rgb2gray(rgb, width, height, stride) {\n\tif(stride == 0) { stride = width*3 }\n\n\tlet gray = new Uint8Array(width*height)\n\tlet off = 0\n\n\tfor(let y = 0; y \u003c height; y++) {\n\t\tfor(let x = 0; x \u003c width; x++) {\n\t\t\tlet idx = y*stride + x*3\n\t\t\tlet R = rgb[idx+0]\n\t\t\tlet G = rgb[idx+1]\n\t\t\tlet B = rgb[idx+2]\n\n\t\t\tgray[off++] = ((R+G+B)/3)|0\n\t\t}\n\t}\n\treturn gray\n}\n```\n\n## Other\n\n### Benchmark\n\n```\n$ gulp bench\n[09:12:33] Running suite Guetzli [D:\\work\\guetzli-js\\dist\\lib\\bench.js]...\n[09:12:52]    encodeImage.bees-small.rgb x 0.63 ops/sec ±0.81% (6 runs sampled)\n[09:13:22]    encodeImage.asm.bees-small.rgb x 0.35 ops/sec ±2.18% (5 runs sampled)\n[09:13:27]    helper.encodeJpg.bees-small.rgb x 1,464 ops/sec ±0.79% (94 runs sampled)\n[09:13:33]    helper.encodePng.bees-small.rgb x 173 ops/sec ±1.32% (82 runs sampled)\n[09:13:33] Fastest test is helper.encodeJpg.bees-small.rgb at 8.5x faster than helper.encodePng.bees-small.rgb\n```\n\n### Unit Test\n\n```\n$ npm test\n\u003e guetzli-js@1.0.8 test D:\\work\\guetzli-js\n\u003e nodeunit dist/lib/test.js\n\ntest.js\n√ testVersion\n√ testIsPngFilename\n√ testIsJpegFilename\n√ testLoadImage_png\n√ testLoadImage_jpeg\n√ testGuetzliEncode\n\nOK: 21 assertions (12483ms)\n```\n\n\n### Build `guetzli.node` with CMake\n\n**Windows x64**\n\n- Install CMake 3.5+\n- Install VS2015\n- run `build-win64.bat` in command line\n\n**Windows x86**\n\n- Install CMake 3.5+\n- Install VS2015\n- run `build-win32.bat` in command line\n\n**Darwin or Linux**\n\n- Install CMake 3.5+\n- Install GCC\n- `mkdir build`\n- `cd build \u0026\u0026 cmake .. \u0026\u0026 make install`\n\n### Build `lib/cxx-emscripten/guetzli.out.js` with Emscripten\n\n- Install Emscripten\n- `make`\n\n\n### NPM mirror for China\n\n- https://npm.taobao.org/\n- `npm install -g cnpm --registry=https://registry.npm.taobao.org`\n- `cnpm install -g windows-build-tool` (Windows)\n- `cnpm install -g node-gyp`\n- `cnpm install -g guetzli-js`\n\n\n## License\n\nMIT © [chai2010](https://github.com/chai2010)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchai2010%2Fguetzli-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchai2010%2Fguetzli-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchai2010%2Fguetzli-js/lists"}