├── test.png ├── .gitignore ├── .npmignore ├── test.js ├── package.json ├── LICENSE.md ├── README.md └── index.js /test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hughsk/png-chunks-encode/HEAD/test.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | *.log 4 | .DS_Store 5 | bundle.js 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | bower_components 2 | node_modules 3 | *.log 4 | .DS_Store 5 | bundle.js 6 | test 7 | test.js 8 | demo/ 9 | .npmignore 10 | LICENSE.md -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const extract = require('png-chunks-extract') 2 | const encode = require('./') 3 | const test = require('tape') 4 | const path = require('path') 5 | const fs = require('fs') 6 | 7 | test('png-chunks-encode', function (t) { 8 | const buffer = fs.readFileSync( 9 | path.join(__dirname, 'test.png') 10 | ) 11 | 12 | t.deepEqual( 13 | buffer, 14 | new Buffer(encode(extract(buffer))), 15 | 'input and output are exactly the same when not modified' 16 | ) 17 | 18 | t.end() 19 | }) 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "png-chunks-encode", 3 | "version": "1.0.0", 4 | "description": "Return a fresh PNG buffer given a set of PNG chunks", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "author": { 8 | "name": "Hugh Kennedy", 9 | "email": "hughskennedy@gmail.com", 10 | "url": "https://github.com/hughsk" 11 | }, 12 | "dependencies": { 13 | "crc-32": "^0.3.0", 14 | "sliced": "^1.0.1" 15 | }, 16 | "devDependencies": { 17 | "png-chunks-extract": "^1.0.0", 18 | "tap-spec": "^4.1.0", 19 | "tape": "^4.2.0" 20 | }, 21 | "scripts": { 22 | "test": "node test | tap-spec" 23 | }, 24 | "keywords": [ 25 | "png,", 26 | "buffer,", 27 | "encode,", 28 | "recode,", 29 | "modify,", 30 | "crc,", 31 | "buffer,", 32 | "uint8array" 33 | ], 34 | "repository": { 35 | "type": "git", 36 | "url": "git://github.com/hughsk/png-chunks-encode.git" 37 | }, 38 | "homepage": "https://github.com/hughsk/png-chunks-encode", 39 | "bugs": { 40 | "url": "https://github.com/hughsk/png-chunks-encode/issues" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2015 Hugh Kennedy 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # png-chunks-encode 2 | 3 | [![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges) 4 | 5 | Return a fresh PNG buffer given a set of PNG chunks. Useful in combination with [png-chunks-encode](https://github.com/hughsk/png-chunks-extract) to easily modify or add to the data of a PNG file. 6 | 7 | By adding your own `tEXt` or `zEXt` chunks you have a useful alternative to LSB steganography for making "magical" images with "secret" data available for your applications: the data is hardly hidden this way, but you can store as much as you like. If you really wanted to, you could probably get away with sneaking a 300MB 3D model in there without too much trouble 👻 8 | 9 | ## Usage 10 | 11 | [![NPM](https://nodei.co/npm/png-chunks-encode.png)](https://www.npmjs.com/package/png-chunks-encode) 12 | 13 | ### `buffer = encode(chunks)` 14 | 15 | Takes an array of `chunks`, each with a `name` and `data`: 16 | 17 | ``` javascript 18 | [ 19 | { name: 'IHDR', data: Uint8Array([...]) }, 20 | { name: 'IDAT', data: Uint8Array([...]) }, 21 | { name: 'IDAT', data: Uint8Array([...]) }, 22 | { name: 'IDAT', data: Uint8Array([...]) }, 23 | { name: 'IDAT', data: Uint8Array([...]) }, 24 | { name: 'IEND', data: Uint8Array([]) } 25 | ] 26 | ``` 27 | 28 | And returns a `Uint8Array` containing the raw PNG buffer. 29 | 30 | ## See Also 31 | 32 | * [png-chunks-extract](https://github.com/hughsk/png-chunks-extract) 33 | 34 | ## License 35 | 36 | MIT, see [LICENSE.md](http://github.com/hughsk/png-chunks-encode/blob/master/LICENSE.md) for details. 37 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var sliced = require('sliced') 2 | var crc32 = require('crc-32') 3 | 4 | module.exports = encodeChunks 5 | 6 | // Used for fast-ish conversion between uint8s and uint32s/int32s. 7 | // Also required in order to remain agnostic for both Node Buffers and 8 | // Uint8Arrays. 9 | var uint8 = new Uint8Array(4) 10 | var int32 = new Int32Array(uint8.buffer) 11 | var uint32 = new Uint32Array(uint8.buffer) 12 | 13 | function encodeChunks (chunks) { 14 | var totalSize = 8 15 | var idx = totalSize 16 | var i 17 | 18 | for (i = 0; i < chunks.length; i++) { 19 | totalSize += chunks[i].data.length 20 | totalSize += 12 21 | } 22 | 23 | var output = new Uint8Array(totalSize) 24 | 25 | output[0] = 0x89 26 | output[1] = 0x50 27 | output[2] = 0x4E 28 | output[3] = 0x47 29 | output[4] = 0x0D 30 | output[5] = 0x0A 31 | output[6] = 0x1A 32 | output[7] = 0x0A 33 | 34 | for (i = 0; i < chunks.length; i++) { 35 | var chunk = chunks[i] 36 | var name = chunk.name 37 | var data = chunk.data 38 | var size = data.length 39 | var nameChars = [ 40 | name.charCodeAt(0), 41 | name.charCodeAt(1), 42 | name.charCodeAt(2), 43 | name.charCodeAt(3) 44 | ] 45 | 46 | uint32[0] = size 47 | output[idx++] = uint8[3] 48 | output[idx++] = uint8[2] 49 | output[idx++] = uint8[1] 50 | output[idx++] = uint8[0] 51 | 52 | output[idx++] = nameChars[0] 53 | output[idx++] = nameChars[1] 54 | output[idx++] = nameChars[2] 55 | output[idx++] = nameChars[3] 56 | 57 | for (var j = 0; j < size;) { 58 | output[idx++] = data[j++] 59 | } 60 | 61 | var crcCheck = nameChars.concat(sliced(data)) 62 | var crc = crc32.buf(crcCheck) 63 | 64 | int32[0] = crc 65 | output[idx++] = uint8[3] 66 | output[idx++] = uint8[2] 67 | output[idx++] = uint8[1] 68 | output[idx++] = uint8[0] 69 | } 70 | 71 | return output 72 | } 73 | --------------------------------------------------------------------------------