├── .gitignore ├── .travis.yml ├── webp.js ├── fixture ├── test_pattern.bmp ├── test_pattern.gif ├── test_pattern.jpg ├── test_pattern.png ├── test_pattern.tif ├── test_pattern.webp └── index.js ├── .npmignore ├── tiff.js ├── png.js ├── jpg.js ├── bmp.js ├── package.json ├── gif.js ├── index.js ├── .eslintrc.json ├── readme.md └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | *.sock 4 | out.png 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "node" 5 | -------------------------------------------------------------------------------- /webp.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function decode (data, o) { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /fixture/test_pattern.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dy/image-decode/HEAD/fixture/test_pattern.bmp -------------------------------------------------------------------------------- /fixture/test_pattern.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dy/image-decode/HEAD/fixture/test_pattern.gif -------------------------------------------------------------------------------- /fixture/test_pattern.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dy/image-decode/HEAD/fixture/test_pattern.jpg -------------------------------------------------------------------------------- /fixture/test_pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dy/image-decode/HEAD/fixture/test_pattern.png -------------------------------------------------------------------------------- /fixture/test_pattern.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dy/image-decode/HEAD/fixture/test_pattern.tif -------------------------------------------------------------------------------- /fixture/test_pattern.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dy/image-decode/HEAD/fixture/test_pattern.webp -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules/* 16 | test/* 17 | 18 | fixture 19 | -------------------------------------------------------------------------------- /tiff.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var UTIF = require('utif') 4 | 5 | module.exports = function decode(data, o) { 6 | var ifds = UTIF.decode(data) 7 | UTIF.decodeImages(data, ifds) 8 | 9 | var rgba = UTIF.toRGBA8(ifds[0]) 10 | 11 | return { 12 | data: rgba, 13 | height: ifds[0].height, 14 | width: ifds[0].width 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /png.js: -------------------------------------------------------------------------------- 1 | // decode png buffer 2 | 'use strict' 3 | 4 | 5 | var PNG = require('pngjs').PNG 6 | var toab = require('to-array-buffer') 7 | 8 | module.exports = function read (data, o) { 9 | var imgData = PNG.sync.read(Buffer.from(data)) 10 | 11 | var pixels = new Uint8Array(toab(imgData.data)) 12 | 13 | return { 14 | data: pixels, 15 | width: imgData.width | 0, 16 | height: imgData.height | 0 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /jpg.js: -------------------------------------------------------------------------------- 1 | // decode jpeg buffer 2 | 'use strict' 3 | 4 | var jpeg = require('jpeg-js') 5 | var b2u8 = require('buffer-to-uint8array') 6 | 7 | module.exports = read 8 | 9 | function read (data, o) { 10 | var jpegData = jpeg.decode(data) 11 | 12 | if(!jpegData) { 13 | throw new Error("Error decoding jpeg") 14 | } 15 | 16 | return { 17 | data: b2u8(jpegData.data), 18 | height: jpegData.height, 19 | width: jpegData.width 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /bmp.js: -------------------------------------------------------------------------------- 1 | // decode bmp buffer 2 | 'use strict' 3 | 4 | var bmp = require('bmp-js') 5 | 6 | module.exports = function read (data, o) { 7 | var bmpData = bmp.decode(Buffer.from(data)) 8 | var width = bmpData.width 9 | var height = bmpData.height 10 | 11 | var pixels = new Uint8Array(width * height * 4) 12 | 13 | // bmp stores stuff as ABGR seq 14 | for (var i = 0; i < pixels.length; i+=4) { 15 | var alpha = bmpData.data[i + 0]; 16 | var blue = bmpData.data[i + 1]; 17 | var green = bmpData.data[i + 2]; 18 | var red = bmpData.data[i + 3]; 19 | 20 | pixels[i + 0] = red; 21 | pixels[i + 1] = green; 22 | pixels[i + 2] = blue; 23 | pixels[i + 3] = bmpData.is_with_alpha ? alpha : 0xff; 24 | } 25 | 26 | return { 27 | data: pixels, 28 | width: bmpData.width, 29 | height: bmpData.height 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "image-decode", 3 | "version": "1.2.3", 4 | "description": "Decode image data from gif, jpeg, png, tiff or bmp", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/dy/image-decode.git" 12 | }, 13 | "keywords": [ 14 | "image", 15 | "image-decode", 16 | "get-pixels", 17 | "image-pixels", 18 | "pixels" 19 | ], 20 | "author": "dy", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/dy/image-decode/issues" 24 | }, 25 | "homepage": "https://github.com/dy/image-decode#readme", 26 | "devDependencies": { 27 | "brfs": "^2.0.1", 28 | "image-equal": "^3.1.0", 29 | "tape": "^4.9.1" 30 | }, 31 | "dependencies": { 32 | "bmp-js": "^0.1.0", 33 | "buffer-to-uint8array": "^1.1.0", 34 | "image-type": "^3.0.0", 35 | "jpeg-js": "^0.4.3", 36 | "omggif": "^1.0.9", 37 | "pngjs": "^3.3.3", 38 | "to-array-buffer": "^3.0.0", 39 | "utif": "^2.0.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /gif.js: -------------------------------------------------------------------------------- 1 | // decode gif buffer 2 | 'use strict' 3 | 4 | var GifReader = require('omggif').GifReader 5 | 6 | module.exports = function read (data, o) { 7 | var reader = new GifReader(Buffer.from(data)) 8 | 9 | // TODO: handle multiframe gif 10 | // if(reader.numFrames() > 0) { 11 | // var nshape = [reader.numFrames(), reader.height, reader.width, 4] 12 | // try { 13 | // var ndata = new Uint8Array(nshape[0] * nshape[1] * nshape[2] * nshape[3]) 14 | // } catch(err) { 15 | // cb(err) 16 | // return 17 | // } 18 | 19 | // var result = ndarray(ndata, nshape) 20 | // try { 21 | // for(var i=0; i < reader.numFrames(); ++i) { 22 | // reader.decodeAndBlitFrameRGBA(i, ndata.subarray( 23 | // result.index(i, 0, 0, 0), 24 | // result.index(i+1, 0, 0, 0))) 25 | // } 26 | // } catch(err) { 27 | // cb(err) 28 | // return 29 | // } 30 | 31 | // cb(null, result.transpose(0,2,1)) 32 | // } 33 | 34 | // single frame gif 35 | var pixels = new Uint8Array(reader.width * reader.height * 4) 36 | 37 | reader.decodeAndBlitFrameRGBA(0, pixels) 38 | 39 | return { 40 | data: pixels, 41 | width: reader.width, 42 | height: reader.height 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var detectType = require('image-type') 4 | var toab = require('to-array-buffer') 5 | 6 | module.exports = decode 7 | 8 | 9 | function decode (data, o) { 10 | data = toab(data) 11 | 12 | if (!data) return null 13 | 14 | if (!o) o = {} 15 | else if (typeof o === 'string') o = {type: o} 16 | 17 | var type = o.type 18 | 19 | if (!type) { 20 | type = detectType(new Uint8Array(data)) 21 | 22 | // we do not throw an error since argument can be decoded data already 23 | if (!type) return null 24 | 25 | type = type.mime 26 | 27 | if (!decode[type]) throw Error('Type `' + type + '` does not seem to be supported') 28 | } 29 | 30 | return decode[type](data, o) 31 | } 32 | 33 | 34 | decode['png'] = 35 | decode['image/png'] = require('./png') 36 | decode['gif'] = 37 | decode['image/gif'] = require('./gif'), 38 | decode['image/jpeg'] = 39 | decode['image/jpg'] = 40 | decode['jpg'] = 41 | decode['jpeg'] = require('./jpg') 42 | decode['bmp'] = 43 | decode['image/bmp'] = 44 | decode['image/bitmap'] = require('./bmp') 45 | decode['tiff'] = 46 | decode['image/tiff'] = require('./tiff') 47 | decode['webp'] = 48 | decode['image/webp'] = require('./webp') 49 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "commonjs": true, 6 | "es6": true 7 | }, 8 | "extends": "eslint:recommended", 9 | "rules": { 10 | "strict": 2, 11 | "indent": 0, 12 | "linebreak-style": 0, 13 | "quotes": 0, 14 | "semi": 0, 15 | "no-cond-assign": 1, 16 | "no-constant-condition": 1, 17 | "no-duplicate-case": 1, 18 | "no-empty": 1, 19 | "no-ex-assign": 1, 20 | "no-extra-boolean-cast": 1, 21 | "no-extra-semi": 1, 22 | "no-fallthrough": 1, 23 | "no-func-assign": 1, 24 | "no-global-assign": 1, 25 | "no-implicit-globals": 2, 26 | "no-inner-declarations": ["error", "functions"], 27 | "no-irregular-whitespace": 2, 28 | "no-loop-func": 1, 29 | "no-magic-numbers": ["warn", { "ignore": [1, 0, -1], "ignoreArrayIndexes": true}], 30 | "no-multi-str": 1, 31 | "no-mixed-spaces-and-tabs": 1, 32 | "no-proto": 1, 33 | "no-sequences": 1, 34 | "no-throw-literal": 1, 35 | "no-unmodified-loop-condition": 1, 36 | "no-useless-call": 1, 37 | "no-void": 1, 38 | "no-with": 2, 39 | "wrap-iife": 1, 40 | "no-redeclare": 1, 41 | "no-unused-vars": ["error", { "vars": "all", "args": "none" }], 42 | "no-sparse-arrays": 1 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # image-decode [![unstable](https://img.shields.io/badge/stability-unstable-green.svg)](http://github.com/badges/stability-badges) [![Build Status](https://img.shields.io/travis/dy/image-decode.svg)](https://travis-ci.org/dy/image-decode) 2 | 3 | Decode image data from raw encoded binary data in any image format: PNG, GIF, BMP, JPEG, TIFF. 4 | 5 | ## Usage 6 | 7 | [![npm install image-decode](https://nodei.co/npm/image-decode.png?mini=true)](https://npmjs.org/package/image-decode/) 8 | 9 | ```js 10 | let decode = require('image-decode') 11 | 12 | let {data, width, height} = decode(fs.readFileSync('./data.png')) 13 | ``` 14 | 15 | ## API 16 | 17 | ### `let {data, width, height} = decode(buffer, mimeType?)` 18 | 19 | Takes input `buffer` with encoded image data and decodes its contents, returns pixels `data` array with layout `[r, g, b, a, r, g, b, a, ...]`. `mimeType` can be passed to skip image type detection. 20 | 21 | `buffer` can be any binary data container: 22 | 23 | * ArrayBuffer 24 | * Buffer 25 | * Uint8Array 26 | * base64 string 27 | 28 | 29 | ## See also 30 | 31 | * [image-encode](https://ghub.io/image-encode) − encode pixels data to target format. 32 | * [image-equal](https://ghub.io/image-equal) − image data comparing tool. 33 | * [image-pixels](https://ghub.io/image-pixels) − load or save pixel data from/to any source. 34 | * [image-save](https://ghub.io/image-save) − save image pixels data to a target. 35 | * [image-type](https://ghub.io/image-type) − detect input image data type. 36 | 37 | 38 | ## Credits 39 | 40 | © 2018 Dmitry Yv. MIT License. 41 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | let decode = require('./') 4 | let t = require('tape') 5 | let fix = require('./fixture') 6 | let fs = require('fs') 7 | let eq = require('image-equal') 8 | 9 | 10 | t('png', async t => { 11 | let data = decode(fs.readFileSync('./fixture/test_pattern.png')) 12 | 13 | t.ok(await eq(data, fix)) 14 | 15 | t.equal(data.width, fix.width) 16 | t.equal(data.height, fix.height) 17 | 18 | t.end() 19 | }) 20 | 21 | t('jpg', async t => { 22 | let data = decode(fs.readFileSync('./fixture/test_pattern.jpg')) 23 | 24 | t.ok(await eq(data, fix, {tol: 0.04})) 25 | 26 | t.equal(data.width, fix.width) 27 | t.equal(data.height, fix.height) 28 | t.end() 29 | }) 30 | 31 | t('bmp', async t => { 32 | let data = decode(fs.readFileSync('./fixture/test_pattern.jpg')) 33 | 34 | t.ok(await eq(data, fix, {tol: 0.04})) 35 | 36 | t.equal(data.width, fix.width) 37 | t.equal(data.height, fix.height) 38 | t.end() 39 | }) 40 | 41 | t('gif', async t => { 42 | let data = decode(fs.readFileSync('./fixture/test_pattern.gif')) 43 | 44 | t.ok(await eq(data, fix)) 45 | 46 | t.equal(data.width, fix.width) 47 | t.equal(data.height, fix.height) 48 | t.end() 49 | }) 50 | 51 | t.skip('webp', async t => { 52 | let data = decode(fs.readFileSync('./fixture/test_pattern.webp')) 53 | 54 | t.ok(await eq(data, fix)) 55 | 56 | t.equal(data.width, fix.width) 57 | t.equal(data.height, fix.height) 58 | t.end() 59 | }) 60 | 61 | t('tiff', async t => { 62 | let data = decode(fs.readFileSync('./fixture/test_pattern.tif')) 63 | 64 | t.ok(await eq(data, fix)) 65 | 66 | t.equal(data.width, fix.width) 67 | t.equal(data.height, fix.height) 68 | t.end() 69 | }) 70 | 71 | t('undefined type', async t => { 72 | let data = decode([0,0,0,0,0,0,0,0,0]) 73 | t.notOk(data) 74 | 75 | t.end() 76 | }) 77 | 78 | // TODO 79 | t('base64') 80 | t('arraybuffer') 81 | t('buffer') 82 | t('uint8') 83 | t('file') 84 | t('blob') 85 | t('datauri') 86 | -------------------------------------------------------------------------------- /fixture/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var fixture = { 4 | data: new Uint8Array([0,0,0,255,255,0,0,255,255,255,0,255,255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,255,0,255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255]), 5 | width: 16, 6 | height: 8, 7 | } 8 | 9 | fixture.pngDataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAICAYAAADwdn+XAAAAM0lEQVQoU92PsREAMAgCn/2HJodOEO38AioEBdhEAbn9A+FESkYoA3rCDO3i+XrVf+LAA/NHIOnNxlR4AAAAAElFTkSuQmCC' 10 | fixture.jpgDataURL = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAAIABADAREAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAABwr/xAAcEAEBAAIDAQEAAAAAAAAAAAAGBQQHAQMIAgD/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAHxEAAwEAAgIDAQAAAAAAAAAABAUGAwIHAAESExQX/9oADAMBAAIRAxEAPwC3nzZ5k095R1QF1Fp4lFgwwwY2C67OKaHH0CSYZyLdLGy0fAg0SO8d+UiUrlH1JPHj5GPbXI/oqaPTaPM7rcRkoHJoPNTymQRtKAym5ziHm21W5uTU8/OatCz37R5S0tBrNSUmgZ2lm/pbulAmUutbUP2Ifo/mXEOwpeejzrHsCsSyuWmKL+hdg2nYzMHPQNWs+Gbu5e0Dj6sE6JAgAH9nflVTU7NzCrAKenEaxe//AJ48/9k=' 11 | 12 | fixture.pngURL = 'https://raw.githubusercontent.com/dy/get-pixel-data/master/test/test_pattern.png' 13 | fixture.jpgURL = 'https://raw.githubusercontent.com/dy/get-pixel-data/master/test/test_pattern.jpg' 14 | 15 | 16 | module.exports = fixture 17 | --------------------------------------------------------------------------------