From 417e8e2baff2d1e546fdf68c492fba88205d3fb5 Mon Sep 17 00:00:00 2001 From: Patrick Hulce Date: Thu, 4 Feb 2021 21:06:07 -0600 Subject: [PATCH 1/8] chore(ci): migrate to github actions (#86) --- .github/workflows/ci.yml | 19 +++++++++++++++++++ .travis.yml | 6 ------ 2 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0114b69 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,19 @@ +name: CI +on: + push: + branches: [master] + pull_request: # run on all PRs, not just PRs to a particular branch +jobs: + test: + strategy: + fail-fast: true + matrix: + nodeversion: [8.x, 10.x, 12.x, 14.x] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.nodeversion }} + - run: npm install + - run: npm test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c9045de..0000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js -node_js: - - '8' - - '10' - - '12' - - '14' From 13e1ffa04670d7c7a363d54eab92e31f01243cd7 Mon Sep 17 00:00:00 2001 From: Markus <53560412+brainbugfix@users.noreply.github.com> Date: Thu, 8 Apr 2021 00:26:09 +0200 Subject: [PATCH 2/8] feat: add comment tag encoding (#87) --- index.d.ts | 2 +- lib/encoder.js | 17 ++++++++++++++++- test/fixtures/redbox_comment.jpg | Bin 0 -> 2259 bytes test/index.js | 26 ++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/redbox_comment.jpg diff --git a/index.d.ts b/index.d.ts index 696cc7a..adbdd4b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -10,7 +10,7 @@ type UintArrRet = RawImageData; type ImageData = BufferRet | UintArrRet; type BufferLike = Buffer | Uint8Array | ArrayLike | Iterable | ArrayBuffer; -export declare function encode(imgData: RawImageData, quality?: number): BufferRet; +export declare function encode(imgData: RawImageData & {comments?: string[]}, quality?: number): BufferRet export declare function decode( jpegData: BufferLike, diff --git a/lib/encoder.js b/lib/encoder.js index bb17d3b..fdbc184 100644 --- a/lib/encoder.js +++ b/lib/encoder.js @@ -535,6 +535,20 @@ function JPEGEncoder(quality) { writeByte(std_ac_chrominance_values[p]); } } + + function writeCOM(comments) + { + if (typeof comments === "undefined" || comments.constructor !== Array) return; + comments.forEach(e => { + if (typeof e !== "string") return; + writeWord(0xFFFE); // marker + var l = e.length; + writeWord(l + 2); // length itself as well + var i; + for (i = 0; i < l; i++) + writeByte(e.charCodeAt(i)); + }); + } function writeSOS() { @@ -625,6 +639,7 @@ function JPEGEncoder(quality) { // Add JPEG headers writeWord(0xFFD8); // SOI writeAPP0(); + writeCOM(image.comments); writeAPP1(image.exifBuffer); writeDQT(); writeSOF0(image.width,image.height); @@ -782,7 +797,7 @@ function encode(imgData, qu) { return { data: data, width: imgData.width, - height: imgData.height + height: imgData.height, }; } diff --git a/test/fixtures/redbox_comment.jpg b/test/fixtures/redbox_comment.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0c4235df179f608851127b5637ff590bda64e0e GIT binary patch literal 2259 zcmex=X>4Kc;1T2J;1cd?ZV`|h7#^RL zo{?_nTUc3;QW2Ayp3EpHBqSj!p)Vz+pX_AeluR=Ce}F-dgJBD!12dx_1Ct;lvmoRD zBaDlH-e6?}0|qEyWMXDvWn<^yovIz$! zvMUve7&T5@$f4}C@t|nX#SbdRNkvVZTw>x9l2WQ_>Kd9_CZ=ZQ7M51dF0O9w9-dyo zA)#U65s^{JDXD4c8JStdC8cHM6_r)ZEv;?s9i3g1CQq3GGAU*RJ2VdF$b$$4{OPfBE|D`;VW$ z7#Wx$-T{&j4Gc)#w^HS&v10T&hG;Y hm>RekG#Eyy(I6O21)~{Zv@94c4#}z!{xkf)2>`3X8TSAH literal 0 HcmV?d00001 diff --git a/test/index.js b/test/index.js index 6944449..fd1339a 100644 --- a/test/index.js +++ b/test/index.js @@ -179,6 +179,32 @@ it('should be able to create a JPEG from an array', function () { expect(jpegImageData.data).toEqual(expected); }); +it('should be able to create a JPEG from an array with comment', function () { + var width = 320, + height = 180; + var comments = ["First comment", "Second comment"]; + var frameData = new Buffer(width * height * 4); + var i = 0; + while (i < frameData.length) { + frameData[i++] = 0xff; // red + frameData[i++] = 0x00; // green + frameData[i++] = 0x00; // blue + frameData[i++] = 0xff; // alpha - ignored in JPEGs + } + var rawImageData = { + data: frameData, + width: width, + height: height, + comments: comments, + }; + var jpegImageData = jpeg.encode(rawImageData, 50); + expect(jpegImageData.width).toEqual(width); + expect(jpegImageData.height).toEqual(height); + var expected = fixture('redbox_comment.jpg'); + expect(jpegImageData.data).toEqual(expected); + expect(jpeg.decode(jpegImageData.data).comments).toEqual(['First comment', 'Second comment']); +}); + it('should be able to decode a JPEG into a typed array', function () { var jpegData = fixture('grumpycat.jpg'); var rawImageData = jpeg.decode(jpegData, {useTArray: true}); From ffdc4a4d595e1e249a72b08d095363bff739aad7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jul 2021 14:21:19 -0500 Subject: [PATCH 3/8] chore(deps): bump lodash from 4.17.15 to 4.17.21 (#89) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8be955b..b0a97dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2251,9 +2251,9 @@ lodash.sortby@^4.7.0: integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= lodash@^4.17.13, lodash@^4.17.15: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== lolex@^5.0.0: version "5.1.2" From 9449a8bcda9340b9fd8ca475e2b699fefc2c2828 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jul 2021 14:21:27 -0500 Subject: [PATCH 4/8] chore(deps): bump hosted-git-info from 2.8.8 to 2.8.9 (#90) Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9. - [Release notes](https://github.com/npm/hosted-git-info/releases) - [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md) - [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b0a97dc..d081b0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1477,9 +1477,9 @@ has-values@^1.0.0: kind-of "^4.0.0" hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== html-encoding-sniffer@^1.0.2: version "1.0.2" From fd73289664cbdd3d18b5841c49874dfef7ea55fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jul 2021 14:21:39 -0500 Subject: [PATCH 5/8] chore(deps): bump ws from 7.2.3 to 7.4.6 (#91) Bumps [ws](https://github.com/websockets/ws) from 7.2.3 to 7.4.6. - [Release notes](https://github.com/websockets/ws/releases) - [Commits](https://github.com/websockets/ws/compare/7.2.3...7.4.6) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d081b0b..acca92d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3443,9 +3443,9 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.0.0: - version "7.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" - integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== xml-name-validator@^3.0.0: version "3.0.0" From 2c90858c95832e9fdf49170bcd09f3079567e417 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jul 2021 14:21:53 -0500 Subject: [PATCH 6/8] chore(deps): bump y18n from 4.0.0 to 4.0.3 (#98) Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.3. - [Release notes](https://github.com/yargs/y18n/releases) - [Changelog](https://github.com/yargs/y18n/blob/y18n-v4.0.3/CHANGELOG.md) - [Commits](https://github.com/yargs/y18n/compare/v4.0.0...y18n-v4.0.3) --- updated-dependencies: - dependency-name: y18n dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index acca92d..5ea1834 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3458,9 +3458,9 @@ xmlchars@^2.1.1: integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== yargs-parser@^18.1.1: version "18.1.3" From b58cc11b29a66f853b4195d31e9e2de6080fcd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Windel=20Emman=20Mascari=C3=B1as?= Date: Thu, 15 Jul 2021 12:23:07 -0700 Subject: [PATCH 7/8] fix(decoder): rethrow a more helpful error if Buffer is undefined (#93) --- lib/decoder.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/decoder.js b/lib/decoder.js index 4452834..d61a8b5 100644 --- a/lib/decoder.js +++ b/lib/decoder.js @@ -1123,13 +1123,19 @@ function decode(jpegData, userOpts = {}) { if(decoder.comments.length > 0) { image["comments"] = decoder.comments; } - } catch (err){ - if (err instanceof RangeError){ + } catch (err) { + if (err instanceof RangeError) { throw new Error("Could not allocate enough memory for the image. " + "Required: " + bytesNeeded); - } else { - throw err; + } + + if (err instanceof ReferenceError) { + if (err.message === "Buffer is not defined") { + throw new Error("Buffer is not globally defined in this environment. " + + "Consider setting useTArray to true"); + } } + throw err; } decoder.copyToImageData(image, opts.formatAsRGBA); From 9ccd35fb5f55a6c4f1902ac5b0f270f675750c27 Mon Sep 17 00:00:00 2001 From: Sohom Datta Date: Fri, 3 Jun 2022 20:10:52 +0530 Subject: [PATCH 8/8] fix: validate sampling factors (#106) --- lib/decoder.js | 9 ++++++++- test/index.js | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/decoder.js b/lib/decoder.js index d61a8b5..1982481 100644 --- a/lib/decoder.js +++ b/lib/decoder.js @@ -576,7 +576,9 @@ var JpegImage = (function jpegImage() { return array; } function prepareComponents(frame) { - var maxH = 0, maxV = 0; + // According to the JPEG standard, the sampling factor must be between 1 and 4 + // See https://github.com/libjpeg-turbo/libjpeg-turbo/blob/9abeff46d87bd201a952e276f3e4339556a403a3/libjpeg.txt#L1138-L1146 + var maxH = 1, maxV = 1; var component, componentId; for (componentId in frame.components) { if (frame.components.hasOwnProperty(componentId)) { @@ -745,6 +747,11 @@ var JpegImage = (function jpegImage() { var h = data[offset + 1] >> 4; var v = data[offset + 1] & 15; var qId = data[offset + 2]; + + if ( h <= 0 || v <= 0 ) { + throw new Error('Invalid sampling factor, expected values above 0'); + } + frame.componentsOrder.push(componentId); frame.components[componentId] = { h: h, diff --git a/test/index.js b/test/index.js index fd1339a..7f0edbb 100644 --- a/test/index.js +++ b/test/index.js @@ -7,10 +7,12 @@ function fixture(name) { return fs.readFileSync(path.join(__dirname, 'fixtures', name)); } -const SUPER_LARGE_JPEG_BASE64 = - '/9j/wJ39sP//DlKWvX+7xPlXkJa9f7v8DoDVAAD//zb6QAEAI2cBv3P/r4ADpX8Jf14AAAAAgCPE+VeQlr1/uwCAAAAVALNOjAGP2lIS'; +const SUPER_LARGE_JPEG_BASE64 = '/9j/wfFRBf//BdgC/9p/2P/E4d4='; + +const SUPER_LARGE_RESOLUTION_JPEG_BASE64 = '/9j/wfFR2PDh3g=='; const SUPER_LARGE_JPEG_BUFFER = Buffer.from(SUPER_LARGE_JPEG_BASE64, 'base64'); +const SUPER_LARGE_RESOLUTION_JPEG_BUFFER = Buffer.from(SUPER_LARGE_RESOLUTION_JPEG_BASE64, 'base64'); it('should be able read image with a bad e1 marker not preceeded by ff', function () { var jpegData = fixture('table-with-bad-e1.jpg'); @@ -274,8 +276,8 @@ it('should be able to decode large images within memory limits', () => { // See https://github.com/eugeneware/jpeg-js/issues/53 it('should limit resolution exposure', function () { - expect(() => jpeg.decode(SUPER_LARGE_JPEG_BUFFER)).toThrow( - 'maxResolutionInMP limit exceeded by 141MP', + expect(() => jpeg.decode(SUPER_LARGE_RESOLUTION_JPEG_BUFFER)).toThrow( + 'maxResolutionInMP limit exceeded by 3405MP', ); }); @@ -288,3 +290,9 @@ it('should limit memory exposure', function () { var jpegData = fixture('grumpycat.jpg'); expect(() => jpeg.decode(jpegData)).not.toThrow(); }, 30000); + +// See https://github.com/jpeg-js/jpeg-js/issues/105 +it('invalid sampling factor should error out', function () { + expect(() => jpeg.decode(Buffer.from('/9j/wfFR2AD/UdgA/9r/3g==', 'base64')).toThrow( + 'Invalid sampling factor, expected values above 0')) +});