├── .github └── workflows │ └── node.js.yml ├── .gitignore ├── .npmignore ├── History.md ├── README.md ├── examples ├── append.js ├── background.js ├── bitdepth.js ├── blur.js ├── changeFormat.js ├── charcoal.js ├── chop.js ├── colorize.js ├── colors.js ├── comment.js ├── compare.js ├── contrast.js ├── crop.js ├── cycle.js ├── despeckle.js ├── dither.js ├── drawing.js ├── edge.js ├── emboss.js ├── enhance.js ├── equalize.js ├── extent.js ├── flatten.js ├── flip.js ├── flop.js ├── gamma.js ├── getters.js ├── gravity.js ├── imgs │ ├── blue.gif │ ├── identifyParseErr.jpg │ ├── layers.psd │ ├── lost.png │ ├── morpher.jpg │ ├── orientation │ │ ├── Landscape_1.jpg │ │ ├── Landscape_1.jpg.correct.jpg │ │ ├── Landscape_2.jpg │ │ ├── Landscape_2.jpg.correct.jpg │ │ ├── Landscape_3.jpg │ │ ├── Landscape_3.jpg.correct.jpg │ │ ├── Landscape_4.jpg │ │ ├── Landscape_4.jpg.correct.jpg │ │ ├── Landscape_5.jpg │ │ ├── Landscape_5.jpg.correct.jpg │ │ ├── Landscape_6.jpg │ │ ├── Landscape_6.jpg.correct.jpg │ │ ├── Landscape_7.jpg │ │ ├── Landscape_7.jpg.correct.jpg │ │ ├── Landscape_8.jpg │ │ ├── Landscape_8.jpg.correct.jpg │ │ ├── Portrait_1.jpg │ │ ├── Portrait_1.jpg.correct.jpg │ │ ├── Portrait_2.jpg │ │ ├── Portrait_2.jpg.correct.jpg │ │ ├── Portrait_3.jpg │ │ ├── Portrait_3.jpg.correct.jpg │ │ ├── Portrait_4.jpg │ │ ├── Portrait_4.jpg.correct.jpg │ │ ├── Portrait_5.jpg │ │ ├── Portrait_5.jpg.correct.jpg │ │ ├── Portrait_6.jpg │ │ ├── Portrait_6.jpg.correct.jpg │ │ ├── Portrait_7.jpg │ │ ├── Portrait_7.jpg.correct.jpg │ │ ├── Portrait_8.jpg │ │ └── Portrait_8.jpg.correct.jpg │ ├── original.gif │ ├── original.jpg │ ├── original.png │ ├── originalSideways.jpg │ └── photo.JPG ├── implode.js ├── label.js ├── limit.js ├── lower.js ├── magnify.js ├── median.js ├── minify.js ├── modulate.js ├── monochrome.js ├── morph.js ├── negative.js ├── new.js ├── noise1.js ├── noise2.js ├── paint.js ├── quality.js ├── raise.js ├── region.js ├── resample.js ├── resize.js ├── roll.js ├── rotate.js ├── scale.js ├── sepia.js ├── sharpen.js ├── size.js ├── solarize.js ├── source_buffer.js ├── spread.js ├── swirl.js ├── thumb.js ├── thumbExact.js └── thumbnail.js ├── index.js ├── lib ├── args.js ├── command.js ├── compare.js ├── composite.js ├── convenience.js ├── convenience │ ├── autoOrient.js │ ├── morph.js │ ├── sepia.js │ └── thumb.js ├── drawing.js ├── getters.js ├── montage.js ├── options.js └── utils.js ├── package.json └── test ├── 109.js ├── 118.js ├── 393.js ├── 417.js ├── 422.js ├── 429.js ├── 68.js ├── 70.js ├── 78.js ├── alpha.js ├── append.js ├── arc.js ├── autoOrient.js ├── autoOrientAll.js ├── autoOrientAndThumb.js ├── autoOrientStream.js ├── background.js ├── bezier.js ├── bitdepth.js ├── blur.js ├── changeFormat.js ├── charcoal.js ├── chop.js ├── circle.js ├── colorize.js ├── colors.js ├── comment.js ├── compare.js ├── composite.js ├── contrast.js ├── crop.js ├── cycle.js ├── densityGm.js ├── despeckle.js ├── dispose.js ├── dither.js ├── edge.js ├── ellipse.js ├── emboss.js ├── enhance.js ├── equalize.js ├── extent.js ├── fixtures ├── compare_1.png ├── compare_2.png ├── favicon.png ├── iptc-multiple.jpg ├── iptc.jpg ├── loading.gif ├── nyancat.gif └── test.ico ├── flatten.js ├── flip.js ├── flop.js ├── fromBuffer.js ├── gamma.js ├── geometry.js ├── getterColor.js ├── getterDepth.js ├── getterFilesize.js ├── getterFormat.js ├── getterFormatGIF.js ├── getterIdentify.js ├── getterIptc.js ├── getterMultipleIptc.js ├── getterRes.js ├── getterSize.js ├── gh-17.js ├── gifFrame.js ├── gifFrameIdentify.js ├── gifFrameStream.js ├── gravity.js ├── implode.js ├── index.js ├── inputIs.js ├── interlace.js ├── label.js ├── limit.js ├── line.js ├── lower.js ├── magnify.js ├── median.js ├── minify.js ├── minifyIM.js ├── modulate.js ├── monochrome.js ├── montage.js ├── morph-more.js ├── morph.js ├── negative.js ├── new.js ├── newImage.js ├── noise1.js ├── noise2.js ├── options.js ├── paint.js ├── polygon.js ├── polyline.js ├── quality.js ├── raise.js ├── rectangle.js ├── region.js ├── repagePlus.js ├── resample.js ├── resize.js ├── resizeAndAutoOrientFromBuffer.js ├── resizeBuffer.js ├── resizeWrong.js ├── roll.js ├── rotate.js ├── scale.js ├── selectFrame.js ├── sepia.js ├── setFormat.js ├── sharpen.js ├── solarize.js ├── spread.js ├── streamIn.js ├── streamInGetter.js ├── streamInOut.js ├── streamOut.js ├── streamOutFormat.js ├── strip.js ├── subclass.js ├── swirl.js ├── text.js ├── thumb.js ├── thumbnail.js ├── timeout.js ├── toBuffer.js ├── toBufferFormat.js ├── utils.js └── webp.js /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ${{ matrix.os }} 15 | 16 | env: 17 | DEBUG: "gm*" 18 | 19 | strategy: 20 | matrix: 21 | os: [windows-latest, ubuntu-latest] 22 | node-version: [14.x, 16.x, 18.x] 23 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 24 | 25 | steps: 26 | - name: Install GraphicsMagic and Imagemagick on Ubuntu 27 | if: contains(matrix.os, 'ubuntu') 28 | run: sudo apt-get install -y imagemagick graphicsmagick 29 | - name: Install GraphicsMagic and Imagemagick on Windows 30 | if: contains(matrix.os, 'windows') 31 | run: choco install -y imagemagick graphicsmagick 32 | - uses: actions/checkout@v3 33 | - name: Use Node.js ${{ matrix.node-version }} 34 | uses: actions/setup-node@v3 35 | with: 36 | node-version: ${{ matrix.node-version }} 37 | - run: npm i 38 | - name: Run tests on Windows 39 | if: contains(matrix.os, 'windows') 40 | shell: cmd 41 | run: | 42 | call refreshenv 43 | npm test 44 | - name: Run tests on Ubuntu 45 | if: contains(matrix.os, 'ubuntu') 46 | run: npm test -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | package-lock.json 4 | examples/imgs/* 5 | !examples/imgs/original.jpg 6 | !examples/imgs/original.png 7 | !examples/imgs/original.gif 8 | !examples/imgs/originalSideways.jpg 9 | !examples/imgs/morpher.jpg 10 | !examples/imgs/photo.JPG 11 | !examples/imgs/orientation/*\d.jpg 12 | !examples/imgs/orientation/*.correct.jpg 13 | *.sw* 14 | .idea 15 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | examples/ 3 | -------------------------------------------------------------------------------- /examples/append.js: -------------------------------------------------------------------------------- 1 | var gm = require('../') 2 | , dir = __dirname + '/imgs' 3 | , imgs = 'lost.png original.jpg'.split(' ').map(function (img) { 4 | return dir + '/' + img 5 | }) 6 | , out = dir + '/append.jpg' 7 | 8 | gm(imgs[0]) 9 | .append(imgs[1]) 10 | .append() 11 | .background('#222') 12 | .write(out, function (err) { 13 | if (err) return console.dir(arguments) 14 | console.log(this.outname + " created :: " + arguments[3]) 15 | require('child_process').exec('open ' + out) 16 | }); 17 | 18 | -------------------------------------------------------------------------------- /examples/background.js: -------------------------------------------------------------------------------- 1 | var gm = require('../') 2 | , dir = __dirname + '/imgs' 3 | 4 | gm(dir + "/original.jpg") 5 | .crop(140,100) 6 | .background("#FF0000") 7 | .extent(340,300) 8 | .write(dir + '/background.jpg', function (err) { 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + " created :: " + arguments[3]) 11 | }); 12 | 13 | -------------------------------------------------------------------------------- /examples/bitdepth.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .bitdepth(2) 9 | .write(dir + '/bitdepth.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/blur.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .blur(19, 10) 9 | .write(dir + '/blur.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/changeFormat.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .write(dir + '/original.jpg', function(err){ 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + " created :: " + arguments[3]) 11 | } 12 | ) 13 | -------------------------------------------------------------------------------- /examples/charcoal.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .charcoal(1) 9 | .write(dir + '/charcoal.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/chop.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .chop(54, 1, 307, 1) 9 | .write(dir + "/chop.jpg", function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/colorize.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .colorize(80, 0, 30) 9 | .write(dir + '/colorize.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/colors.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .colors(16) 9 | .write(dir + '/colors.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/comment.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .comment("%m:%f %wx%h") 9 | .write(dir + '/comment.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/compare.js: -------------------------------------------------------------------------------- 1 | var gm = require('../') 2 | , dir = __dirname + '/imgs' 3 | , imgs = 'bitdepth.png original.jpg'.split(' ').map(function (img) { 4 | return dir + '/' + img 5 | }) 6 | , out = dir + '/compare.jpg' 7 | 8 | gm.compare(imgs[0], imgs[1], { highlightColor: "#fff", file: out }, function (err) { 9 | if (err) return console.dir(arguments) 10 | console.log('The images are equal: %s', arguments[1]); 11 | console.log('Actual equality: %d', arguments[2]); 12 | console.log(this.outname + " created :: " + arguments[3]); 13 | require('child_process').exec('open ' + out); 14 | }); 15 | 16 | -------------------------------------------------------------------------------- /examples/contrast.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .contrast(2) 9 | .write(dir + '/contrast.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/crop.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .crop(200, 155, 300, 0) 9 | .write(dir + "/crop.jpg", function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/cycle.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .cycle(4) 9 | .write(dir + '/cycle.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/despeckle.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .despeckle() 9 | .write(dir + '/despeckle.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/dither.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .monochrome() 9 | .dither() 10 | .write(dir + '/dither.jpg', function(err){ 11 | if (err) return console.dir(arguments) 12 | console.log(this.outname + ' created :: ' + arguments[3]) 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /examples/drawing.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .blur(8, 4) 9 | .stroke("red", 7) 10 | .fill("#ffffffbb") 11 | .drawLine(20, 10, 50, 40) 12 | .fill("#2c2") 13 | .stroke("blue", 1) 14 | .drawRectangle(40, 10, 50, 20) 15 | .drawRectangle(60, 10, 70, 20, 3) 16 | .drawArc(80, 10, 90, 20, 0, 180) 17 | .drawEllipse(105, 15, 3, 5) 18 | .drawCircle(125, 15, 120, 15) 19 | .drawPolyline([140, 10], [143, 13], [145, 13], [147, 15], [145, 17], [143, 19]) 20 | .drawPolygon([160, 10], [163, 13], [165, 13], [167, 15], [165, 17], [163, 19]) 21 | .drawBezier([180, 10], [183, 13], [185, 13], [187, 15], [185, 17], [183, 19]) 22 | .fontSize(68) 23 | .stroke("#efe", 2) 24 | .fill("#888") 25 | .drawText(-20, 98, "graphics magick") 26 | .write(dir + '/drawing.png', function(err){ 27 | if (err) return console.dir(arguments) 28 | console.log(this.outname + ' created :: ' + arguments[3]) 29 | } 30 | ) 31 | -------------------------------------------------------------------------------- /examples/edge.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .edge(2) 9 | .write(dir + '/edge.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/emboss.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .emboss(2) 9 | .write(dir + '/emboss.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/enhance.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .enhance() 9 | .write(dir + '/enhance.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/equalize.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .equalize() 9 | .write(dir + '/equalize.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/extent.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .resize(200,100) 9 | .extent(300, 300) 10 | .write(dir + '/extent.jpg', function(err){ 11 | if (err) return console.dir(arguments) 12 | console.log(this.outname + " created :: " + arguments[3]) 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /examples/flatten.js: -------------------------------------------------------------------------------- 1 | // gm - Copyright Aaron Heckmann (MIT Licensed) 2 | 3 | var gm = require('../') 4 | , dir = __dirname + '/imgs' 5 | 6 | gm(dir + '/layers.psd') 7 | .flatten() 8 | .write(dir + "/unlayered.jpg", function(err){ 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + " created :: " + arguments[3]) 11 | } 12 | ) 13 | -------------------------------------------------------------------------------- /examples/flip.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .flip() 9 | .write(dir + '/flip.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/flop.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .flop() 9 | .write(dir + '/flop.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/gamma.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .gamma(1.7, 2.3, 1.3) 9 | .write(dir + '/gamma.png', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/getters.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | var methods = 8 | [ "size" 9 | , "identify" 10 | , "format" 11 | , "depth" 12 | , "color" 13 | , "res" 14 | , "filesize" 15 | ] 16 | 17 | var image = gm(dir + '/original.png') 18 | methods.forEach(function(method){ 19 | image[method](function(err, result){ 20 | console.log(method + " result:") 21 | console.dir(result) 22 | }) 23 | }) 24 | 25 | -------------------------------------------------------------------------------- /examples/gravity.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .resize(200,100) 9 | .gravity("South") // Be sure to use gravity BEFORE extent 10 | .extent(300, 300) 11 | .write(dir + '/gravity.jpg', function(err){ 12 | if (err) return console.dir(arguments) 13 | console.log(this.outname + " created :: " + arguments[3]) 14 | } 15 | ) 16 | -------------------------------------------------------------------------------- /examples/imgs/blue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/blue.gif -------------------------------------------------------------------------------- /examples/imgs/identifyParseErr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/identifyParseErr.jpg -------------------------------------------------------------------------------- /examples/imgs/layers.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/layers.psd -------------------------------------------------------------------------------- /examples/imgs/lost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/lost.png -------------------------------------------------------------------------------- /examples/imgs/morpher.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/morpher.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_1.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_1.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_1.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_2.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_2.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_2.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_3.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_3.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_3.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_4.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_4.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_4.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_5.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_5.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_5.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_6.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_6.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_6.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_7.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_7.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_7.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_8.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Landscape_8.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Landscape_8.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_1.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_1.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_1.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_2.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_2.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_2.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_3.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_3.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_3.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_4.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_4.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_4.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_5.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_5.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_5.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_6.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_6.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_6.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_7.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_7.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_7.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_8.jpg -------------------------------------------------------------------------------- /examples/imgs/orientation/Portrait_8.jpg.correct.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/orientation/Portrait_8.jpg.correct.jpg -------------------------------------------------------------------------------- /examples/imgs/original.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/original.gif -------------------------------------------------------------------------------- /examples/imgs/original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/original.jpg -------------------------------------------------------------------------------- /examples/imgs/original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/original.png -------------------------------------------------------------------------------- /examples/imgs/originalSideways.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/originalSideways.jpg -------------------------------------------------------------------------------- /examples/imgs/photo.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/examples/imgs/photo.JPG -------------------------------------------------------------------------------- /examples/implode.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .implode(0.8) 9 | .write(dir + '/implode.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/label.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .label("%m:%f %wx%h") 9 | .write(dir + '/label.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/limit.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .limit("memory", "32MB") 9 | .limit("map", "64MB") 10 | .write(dir + '/limit.jpg', function(err){ 11 | if (err) return console.dir(arguments) 12 | console.log(this.outname + ' created :: ' + arguments[3]) 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /examples/lower.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .lower(10, 14) 9 | .write(dir + '/lower.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/magnify.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .magnify() 9 | .write(dir + '/magnify.png', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/median.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .median(4) 9 | .write(dir + '/median.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/minify.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | gm(dir + '/original.png') 7 | .minify() 8 | .write(dir + '/minify.png', function(err){ 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + " created :: " + arguments[3]) 11 | } 12 | ) -------------------------------------------------------------------------------- /examples/modulate.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .modulate(120, 100, 80) 9 | .write(dir + '/modulate.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/monochrome.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .monochrome() 9 | .write(dir + '/monochrome.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/morph.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .morph(dir + '/morpher.jpg', dir + '/morph.jpg', function(err){ 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + ' created :: ' + arguments[3]) 11 | } 12 | ) 13 | -------------------------------------------------------------------------------- /examples/negative.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .negative() 9 | .write(dir + '/negative.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/new.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(525, 110, "#00ff55aa") 8 | .fontSize(68) 9 | .stroke("#efe", 2) 10 | .fill("#555") 11 | .drawText(20, 72, "graphics") 12 | .fill("#fa0") 13 | .drawText(274, 72, " magick") 14 | .write(dir + '/new.png', function(err){ 15 | if (err) return console.dir(arguments) 16 | console.log(this.outname + ' created :: ' + arguments[3]) 17 | } 18 | ) 19 | -------------------------------------------------------------------------------- /examples/noise1.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .noise(0.3) 9 | .write(dir + '/noise1.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/noise2.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .noise("laplacian") 9 | .write(dir + '/noise2.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/paint.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .paint(2) 9 | .write(dir + '/paint.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/quality.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .quality(5) 9 | .write(dir + '/quality.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/raise.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .raise(10, 14) 9 | .write(dir + '/raise.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/region.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | // region must come before other affected arguments 9 | .region(130, 170, 307, 00).charcoal(1) 10 | .write(dir + '/region.jpg', function(err){ 11 | if (err) return console.dir(arguments) 12 | console.log(this.outname + ' created :: ' + arguments[3]) 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /examples/resample.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .resample(420, 120) 9 | .write(dir + '/resample.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/resize.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .resize(58, 50, '%') 9 | .write(dir + '/resize.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/roll.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .roll(40,-100) 9 | .quality(100) 10 | .write(dir + '/roll.png', function(err){ 11 | if (err) return console.dir(arguments) 12 | console.log(this.outname + " created :: " + arguments[3]) 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /examples/rotate.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .rotate('red', -30) 9 | .write(dir + '/rotate.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/scale.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .resize(58, 20) 9 | .write(dir + '/scale.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/sepia.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .sepia() 9 | .write(dir + '/sepia.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + " created :: " + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/sharpen.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .sharpen(19, 10) 9 | .write(dir + '/sharpen.jpg', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/size.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | var methods = 8 | [ "size" 9 | ] 10 | 11 | var image = gm(dir + '/original.png') 12 | methods.forEach(function(method){ 13 | image[method](function(err, result){ 14 | console.log(method + " result:") 15 | console.dir(result) 16 | }) 17 | }) 18 | 19 | -------------------------------------------------------------------------------- /examples/solarize.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .solarize(68.9) 9 | .write(dir + '/solarize.png', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/source_buffer.js: -------------------------------------------------------------------------------- 1 | var gm = require('../') 2 | , fs = require('fs') 3 | , dir = __dirname + '/../examples/imgs' 4 | 5 | var buf = fs.readFileSync(dir + '/original.jpg'); 6 | 7 | gm(buf) 8 | .noise('laplacian') 9 | .write(dir + '/fromBuffer.png', function (err) { 10 | if (err) return console.dir(arguments); 11 | 12 | console.log(this.outname + ' created :: ' + arguments[3]); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/spread.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .spread(10) 9 | .write(dir + '/spread.png', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/swirl.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.png') 8 | .swirl(90) // degrees 9 | .write(dir + '/swirl.png', function(err){ 10 | if (err) return console.dir(arguments) 11 | console.log(this.outname + ' created :: ' + arguments[3]) 12 | } 13 | ) 14 | -------------------------------------------------------------------------------- /examples/thumb.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .thumb(150, 50, dir + '/thumb.jpg', function(err){ 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + " created :: " + arguments[3]) 11 | }); 12 | -------------------------------------------------------------------------------- /examples/thumbExact.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | 4 | var gm = require('../') 5 | , dir = __dirname + '/imgs' 6 | 7 | gm(dir + '/original.jpg') 8 | .thumbExact(150, 50, dir + '/thumb.jpg', function(err){ 9 | if (err) return console.dir(arguments) 10 | console.log(this.outname + " created :: " + arguments[3]) 11 | }); 12 | -------------------------------------------------------------------------------- /examples/thumbnail.js: -------------------------------------------------------------------------------- 1 | var gm = require('../') 2 | , dir = __dirname + '/imgs' 3 | 4 | gm(dir + '/original.jpg') 5 | .thumbnail(150, 150) 6 | .write(dir + '/thumbnail.jpg', function(err){ 7 | if (err) return console.dir(arguments) 8 | console.log(this.outname + " created :: " + arguments[3]) 9 | } 10 | ) 11 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var Stream = require('stream').Stream; 7 | var EventEmitter = require('events').EventEmitter; 8 | var util = require('util'); 9 | 10 | util.inherits(gm, EventEmitter); 11 | 12 | /** 13 | * Constructor. 14 | * 15 | * @param {String|Number} path - path to img source or ReadableStream or width of img to create 16 | * @param {Number} [height] - optional filename of ReadableStream or height of img to create 17 | * @param {String} [color] - optional hex background color of created img 18 | */ 19 | 20 | function gm (source, height, color) { 21 | var width; 22 | 23 | if (!(this instanceof gm)) { 24 | return new gm(source, height, color); 25 | } 26 | 27 | EventEmitter.call(this); 28 | 29 | this._options = {}; 30 | this.options(this.__proto__._options); 31 | 32 | this.data = {}; 33 | this._in = []; 34 | this._out = []; 35 | this._outputFormat = null; 36 | this._subCommand = 'convert'; 37 | 38 | if (source instanceof Stream) { 39 | this.sourceStream = source; 40 | source = height || 'unknown.jpg'; 41 | } else if (Buffer.isBuffer(source)) { 42 | this.sourceBuffer = source; 43 | source = height || 'unknown.jpg'; 44 | } else if (height) { 45 | // new images 46 | width = source; 47 | source = ""; 48 | 49 | this.in("-size", width + "x" + height); 50 | 51 | if (color) { 52 | this.in("xc:"+ color); 53 | } 54 | } 55 | 56 | if (typeof source === "string") { 57 | // then source is a path 58 | 59 | // parse out gif frame brackets from filename 60 | // since stream doesn't use source path 61 | // eg. "filename.gif[0]" 62 | var frames = source.match(/(\[.+\])$/); 63 | if (frames) { 64 | this.sourceFrames = source.substr(frames.index, frames[0].length); 65 | source = source.substr(0, frames.index); 66 | } 67 | } 68 | 69 | this.source = source; 70 | 71 | this.addSrcFormatter(function (src) { 72 | // must be first source formatter 73 | 74 | var inputFromStdin = this.sourceStream || this.sourceBuffer; 75 | var ret = inputFromStdin ? '-' : this.source; 76 | 77 | const fileNameProvied = typeof height === 'string'; 78 | if (inputFromStdin && fileNameProvied && /\.ico$/i.test(this.source)) { 79 | ret = `ico:-`; 80 | } 81 | 82 | if (ret && this.sourceFrames) ret += this.sourceFrames; 83 | 84 | src.length = 0; 85 | src[0] = ret; 86 | }); 87 | } 88 | 89 | /** 90 | * Subclasses the gm constructor with custom options. 91 | * 92 | * @param {options} options 93 | * @return {gm} the subclasses gm constructor 94 | */ 95 | 96 | var parent = gm; 97 | gm.subClass = function subClass (options) { 98 | function gm (source, height, color) { 99 | if (!(this instanceof parent)) { 100 | return new gm(source, height, color); 101 | } 102 | 103 | parent.call(this, source, height, color); 104 | } 105 | 106 | gm.prototype.__proto__ = parent.prototype; 107 | gm.prototype._options = {}; 108 | gm.prototype.options(options); 109 | 110 | return gm; 111 | } 112 | 113 | /** 114 | * Augment the prototype. 115 | */ 116 | 117 | require("./lib/options")(gm.prototype); 118 | require("./lib/getters")(gm); 119 | require("./lib/args")(gm.prototype); 120 | require("./lib/drawing")(gm.prototype); 121 | require("./lib/convenience")(gm.prototype); 122 | require("./lib/command")(gm.prototype); 123 | require("./lib/compare")(gm.prototype); 124 | require("./lib/composite")(gm.prototype); 125 | require("./lib/montage")(gm.prototype); 126 | 127 | /** 128 | * Expose. 129 | */ 130 | 131 | module.exports = exports = gm; 132 | module.exports.utils = require('./lib/utils'); 133 | module.exports.compare = require('./lib/compare')(); 134 | module.exports.version = require('./package.json').version; 135 | -------------------------------------------------------------------------------- /lib/command.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var spawn = require('cross-spawn'); 7 | var utils = require('./utils'); 8 | var debug = require('debug')('gm'); 9 | var series = require('array-series'); 10 | var PassThrough = require('stream').PassThrough; 11 | 12 | /** 13 | * Error messaging. 14 | */ 15 | 16 | var noBufferConcat = 'gm v1.9.0+ required node v0.8+. Please update your version of node, downgrade gm < 1.9, or do not use `bufferStream`.'; 17 | 18 | /** 19 | * Extend proto 20 | */ 21 | 22 | module.exports = function (proto) { 23 | 24 | function args (prop) { 25 | return function args () { 26 | var len = arguments.length; 27 | var a = []; 28 | var i = 0; 29 | 30 | for (; i < len; ++i) { 31 | a.push(arguments[i]); 32 | } 33 | 34 | this[prop] = this[prop].concat(a); 35 | return this; 36 | } 37 | } 38 | 39 | function streamToUnemptyBuffer(stream, callback) { 40 | var done = false 41 | var buffers = [] 42 | 43 | stream.on('data', function (data) { 44 | buffers.push(data) 45 | }) 46 | 47 | stream.on('end', function () { 48 | if (done) 49 | return 50 | 51 | done = true 52 | let result = Buffer.concat(buffers) 53 | buffers = null 54 | 55 | if (result.length === 0) { 56 | const err = new Error("Stream yields empty buffer"); 57 | callback(err, null); 58 | } else { 59 | callback(null, result); 60 | } 61 | }) 62 | 63 | stream.on('error', function (err) { 64 | done = true 65 | buffers = null 66 | callback(err) 67 | }) 68 | } 69 | 70 | proto.in = args('_in'); 71 | proto.out = args('_out'); 72 | 73 | proto._preprocessor = []; 74 | proto.preprocessor = args('_preprocessor'); 75 | 76 | /** 77 | * Execute the command and write the image to the specified file name. 78 | * 79 | * @param {String} name 80 | * @param {Function} callback 81 | * @return {Object} gm 82 | */ 83 | 84 | proto.write = function write (name, callback) { 85 | if (!callback) callback = name, name = null; 86 | 87 | if ("function" !== typeof callback) { 88 | throw new TypeError("gm().write() expects a callback function") 89 | } 90 | 91 | if (!name) { 92 | return callback(TypeError("gm().write() expects a filename when writing new files")); 93 | } 94 | 95 | this.outname = name; 96 | 97 | var self = this; 98 | this._preprocess(function (err) { 99 | if (err) return callback(err); 100 | self._spawn(self.args(), true, callback); 101 | }); 102 | } 103 | 104 | /** 105 | * Execute the command and return stdin and stderr 106 | * ReadableStreams providing the image data. 107 | * If no callback is passed, a "through" stream will be returned, 108 | * and stdout will be piped through, otherwise the error will be passed. 109 | * 110 | * @param {String} format (optional) 111 | * @param {Function} callback (optional) 112 | * @return {Stream} 113 | */ 114 | 115 | proto.stream = function stream (format, callback) { 116 | if (!callback && typeof format === 'function') { 117 | callback = format; 118 | format = null; 119 | } 120 | 121 | var throughStream; 122 | 123 | if ("function" !== typeof callback) { 124 | throughStream = new PassThrough(); 125 | callback = function (err, stdout, stderr) { 126 | if (err) throughStream.emit('error', err); 127 | else stdout.pipe(throughStream); 128 | } 129 | } 130 | 131 | if (format) { 132 | format = format.split('.').pop(); 133 | this.outname = format + ":-"; 134 | } 135 | 136 | var self = this; 137 | this._preprocess(function (err) { 138 | if (err) return callback(err); 139 | return self._spawn(self.args(), false, callback); 140 | }); 141 | 142 | return throughStream || this; 143 | } 144 | 145 | /** 146 | * Convenience function for `proto.stream`. 147 | * Simply returns the buffer instead of the stream. 148 | * 149 | * @param {String} format (optional) 150 | * @param {Function} callback 151 | * @return {null} 152 | */ 153 | 154 | proto.toBuffer = function toBuffer (format, callback) { 155 | if (!callback) callback = format, format = null; 156 | 157 | if ("function" !== typeof callback) { 158 | throw new Error('gm().toBuffer() expects a callback.'); 159 | } 160 | 161 | return this.stream(format, function (err, stdout) { 162 | if (err) return callback(err); 163 | 164 | streamToUnemptyBuffer(stdout, callback); 165 | }) 166 | } 167 | 168 | /** 169 | * Run any preProcessor functions in series. Used by autoOrient. 170 | * 171 | * @param {Function} callback 172 | * @return {Object} gm 173 | */ 174 | 175 | proto._preprocess = function _preprocess (callback) { 176 | series(this._preprocessor, this, callback); 177 | } 178 | 179 | /** 180 | * Execute the command, buffer input and output, return stdout and stderr buffers. 181 | * 182 | * @param {String} bin 183 | * @param {Array} args 184 | * @param {Function} callback 185 | * @return {Object} gm 186 | */ 187 | 188 | proto._exec = function _exec (args, callback) { 189 | return this._spawn(args, true, callback); 190 | } 191 | 192 | /** 193 | * Execute the command with stdin, returning stdout and stderr streams or buffers. 194 | * @param {String} bin 195 | * @param {Array} args 196 | * @param {ReadableStream} stream 197 | * @param {Boolean} shouldBuffer 198 | * @param {Function} callback, signature (err, stdout, stderr) -> * 199 | * @return {Object} gm 200 | * @TODO refactor this mess 201 | */ 202 | 203 | proto._spawn = function _spawn (args, bufferOutput, callback) { 204 | var appPath = this._options.appPath || ''; 205 | var bin 206 | 207 | // Resolve executable 208 | switch (this._options.imageMagick) { 209 | // legacy behavior 210 | case true: 211 | bin = args.shift(); 212 | break; 213 | 214 | // ImgeMagick >= 7 215 | case '7+': 216 | bin = 'magick' 217 | break; 218 | 219 | // GraphicsMagick 220 | default: 221 | bin = 'gm'; 222 | break; 223 | } 224 | 225 | // Prepend app path 226 | bin = appPath + bin 227 | 228 | var cmd = bin + ' ' + args.map(utils.escape).join(' ') 229 | , self = this 230 | , proc, err 231 | , timeout = parseInt(this._options.timeout) 232 | , disposers = this._options.disposers 233 | , timeoutId; 234 | 235 | debug(cmd); 236 | //imageMagick does not support minify (https://github.com/aheckmann/gm/issues/385) 237 | if(args.indexOf("-minify") > -1 && this._options.imageMagick){ 238 | return cb(new Error("imageMagick does not support minify, use -scale or -sample. Alternatively, use graphicsMagick")); 239 | } 240 | try { 241 | proc = spawn(bin, args); 242 | } catch (e) { 243 | return cb(e); 244 | } 245 | proc.stdin.once('error', cb); 246 | 247 | proc.on('error', function(err){ 248 | if (err.code === 'ENOENT') { 249 | cb(new Error('Could not execute GraphicsMagick/ImageMagick: '+cmd+" this most likely means the gm/convert binaries can't be found")); 250 | } else { 251 | cb(err); 252 | } 253 | }); 254 | 255 | if (timeout) { 256 | timeoutId = setTimeout(function(){ 257 | dispose('gm() resulted in a timeout.'); 258 | }, timeout); 259 | } 260 | 261 | if (disposers) { 262 | disposers.forEach(function(disposer) { 263 | disposer.events.forEach(function(event) { 264 | disposer.emitter.on(event, dispose); 265 | }); 266 | }); 267 | } 268 | 269 | if (self.sourceBuffer) { 270 | proc.stdin.write(this.sourceBuffer); 271 | proc.stdin.end(); 272 | } else if (self.sourceStream) { 273 | 274 | if (!self.sourceStream.readable) { 275 | return cb(new Error("gm().stream() or gm().write() with a non-readable stream.")); 276 | } 277 | 278 | self.sourceStream.pipe(proc.stdin); 279 | 280 | // bufferStream 281 | // We convert the input source from a stream to a buffer. 282 | if (self.bufferStream && !this._buffering) { 283 | if (!Buffer.concat) { 284 | throw new Error(noBufferConcat); 285 | } 286 | 287 | // Incase there are multiple processes in parallel, 288 | // we only need one 289 | self._buffering = true; 290 | 291 | streamToUnemptyBuffer(self.sourceStream, function (err, buffer) { 292 | self.sourceBuffer = buffer; 293 | self.sourceStream = null; // The stream is now dead 294 | }) 295 | } 296 | } 297 | 298 | // for _exec operations (identify() mostly), we also 299 | // need to buffer the output stream before returning 300 | if (bufferOutput) { 301 | var stdout = '' 302 | , stderr = '' 303 | , onOut 304 | , onErr 305 | , onExit 306 | 307 | proc.stdout.on('data', onOut = function (data) { 308 | stdout += data; 309 | }); 310 | 311 | proc.stderr.on('data', onErr = function (data) { 312 | stderr += data; 313 | }); 314 | 315 | proc.on('close', onExit = function (code, signal) { 316 | let err; 317 | if (code !== 0 || signal !== null) { 318 | err = new Error('Command failed: ' + stderr); 319 | err.code = code; 320 | err.signal = signal; 321 | }; 322 | cb(err, stdout, stderr, cmd); 323 | stdout = stderr = onOut = onErr = onExit = null; 324 | }); 325 | } else { 326 | cb(null, proc.stdout, proc.stderr, cmd); 327 | } 328 | 329 | return self; 330 | 331 | function cb (err, stdout, stderr, cmd) { 332 | if (cb.called) return; 333 | if (timeoutId) clearTimeout(timeoutId); 334 | cb.called = 1; 335 | if (args[0] !== 'identify' && bin !== 'identify') { 336 | self._in = []; 337 | self._out = []; 338 | } 339 | callback.call(self, err, stdout, stderr, cmd); 340 | } 341 | 342 | function dispose (msg) { 343 | const message = msg ? msg : 'gm() was disposed'; 344 | const err = new Error(message); 345 | cb(err); 346 | if (proc.exitCode === null) { 347 | proc.stdin.pause(); 348 | proc.kill(); 349 | } 350 | } 351 | } 352 | 353 | /** 354 | * Returns arguments to be used in the command. 355 | * 356 | * @return {Array} 357 | */ 358 | 359 | proto.args = function args () { 360 | var outname = this.outname || "-"; 361 | if (this._outputFormat) outname = this._outputFormat + ':' + outname; 362 | 363 | return [].concat( 364 | this._subCommand 365 | , this._in 366 | , this.src() 367 | , this._out 368 | , outname 369 | ).filter(Boolean); // remove falsey 370 | } 371 | 372 | /** 373 | * Adds an img source formatter. 374 | * 375 | * `formatters` are passed an array of images which will be 376 | * used as 'input' images for the command. Useful for methods 377 | * like `.append()` where multiple source images may be used. 378 | * 379 | * @param {Function} formatter 380 | * @return {gm} this 381 | */ 382 | 383 | proto.addSrcFormatter = function addSrcFormatter (formatter) { 384 | if ('function' != typeof formatter) 385 | throw new TypeError('sourceFormatter must be a function'); 386 | this._sourceFormatters || (this._sourceFormatters = []); 387 | this._sourceFormatters.push(formatter); 388 | return this; 389 | } 390 | 391 | /** 392 | * Applies all _sourceFormatters 393 | * 394 | * @return {Array} 395 | */ 396 | 397 | proto.src = function src () { 398 | var arr = []; 399 | for (var i = 0; i < this._sourceFormatters.length; ++i) { 400 | this._sourceFormatters[i].call(this, arr); 401 | } 402 | return arr; 403 | } 404 | 405 | /** 406 | * Image types. 407 | */ 408 | 409 | var types = { 410 | 'jpg': /\.jpe?g$/i 411 | , 'png' : /\.png$/i 412 | , 'gif' : /\.gif$/i 413 | , 'tiff': /\.tif?f$/i 414 | , 'bmp' : /(?:\.bmp|\.dib)$/i 415 | , 'webp': /\.webp$/i 416 | }; 417 | 418 | types.jpeg = types.jpg; 419 | types.tif = types.tiff; 420 | types.dib = types.bmp; 421 | 422 | /** 423 | * Determine the type of source image. 424 | * 425 | * @param {String} type 426 | * @return {Boolean} 427 | * @example 428 | * if (this.inputIs('png')) ... 429 | */ 430 | 431 | proto.inputIs = function inputIs (type) { 432 | if (!type) return false; 433 | 434 | var rgx = types[type]; 435 | if (!rgx) { 436 | if ('.' !== type[0]) type = '.' + type; 437 | rgx = new RegExp('\\' + type + '$', 'i'); 438 | } 439 | 440 | return rgx.test(this.source); 441 | } 442 | 443 | /** 444 | * add disposer (like 'close' of http.IncomingMessage) in order to dispose gm() with any event 445 | * 446 | * @param {EventEmitter} emitter 447 | * @param {Array} events 448 | * @return {Object} gm 449 | * @example 450 | * command.addDisposer(req, ['close', 'end', 'finish']); 451 | */ 452 | 453 | proto.addDisposer = function addDisposer (emitter, events) { 454 | if (!this._options.disposers) { 455 | this._options.disposers = []; 456 | } 457 | this._options.disposers.push({ 458 | emitter: emitter, 459 | events: events 460 | }); 461 | return this; 462 | }; 463 | } 464 | -------------------------------------------------------------------------------- /lib/compare.js: -------------------------------------------------------------------------------- 1 | // compare 2 | 3 | var spawn = require('cross-spawn'); 4 | var debug = require('debug')('gm'); 5 | var utils = require('./utils'); 6 | 7 | /** 8 | * Compare two images uses graphicsmagicks `compare` command. 9 | * 10 | * gm.compare(img1, img2, 0.4, function (err, equal, equality) { 11 | * if (err) return handle(err); 12 | * console.log('The images are equal: %s', equal); 13 | * console.log('There equality was %d', equality); 14 | * }); 15 | * 16 | * @param {String} orig Path to an image. 17 | * @param {String} compareTo Path to another image to compare to `orig`. 18 | * @param {Number|Object} [options] Options object or the amount of difference to tolerate before failing - defaults to 0.4 19 | * @param {Function} cb(err, Boolean, equality, rawOutput) 20 | */ 21 | 22 | module.exports = exports = function (proto) { 23 | function compare(orig, compareTo, options, cb) { 24 | 25 | var isImageMagick = this._options && this._options.imageMagick; 26 | var appPath = this._options && this._options.appPath || ''; 27 | var args = ['-metric', 'mse', orig, compareTo]; 28 | 29 | // Resove executable 30 | let bin; 31 | 32 | switch (isImageMagick) { 33 | case true: 34 | bin = 'compare'; 35 | break; 36 | case '7+': 37 | bin = 'magick' 38 | args.unshift('compare'); 39 | break; 40 | default: 41 | bin = 'gm' 42 | args.unshift('compare'); 43 | break 44 | } 45 | 46 | // Prepend app path 47 | bin = appPath + bin 48 | 49 | var tolerance = 0.4; 50 | // outputting the diff image 51 | if (typeof options === 'object') { 52 | 53 | if (options.highlightColor && options.highlightColor.indexOf('"') < 0) { 54 | options.highlightColor = '"' + options.highlightColor + '"'; 55 | } 56 | 57 | if (options.file) { 58 | if (typeof options.file !== 'string') { 59 | throw new TypeError('The path for the diff output is invalid'); 60 | } 61 | // graphicsmagick defaults to red 62 | if (options.highlightColor) { 63 | args.push('-highlight-color'); 64 | args.push(options.highlightColor); 65 | } 66 | if (options.highlightStyle) { 67 | args.push('-highlight-style') 68 | args.push(options.highlightStyle) 69 | } 70 | // For IM, filename is the last argument. For GM it's `-file ` 71 | if (!isImageMagick) { 72 | args.push('-file'); 73 | } 74 | args.push(options.file); 75 | } 76 | 77 | if (typeof options.tolerance != 'undefined') { 78 | if (typeof options.tolerance !== 'number') { 79 | throw new TypeError('The tolerance value should be a number'); 80 | } 81 | tolerance = options.tolerance; 82 | } 83 | } else { 84 | // For ImageMagick diff file is required but we don't care about it, so null it out 85 | if (isImageMagick) { 86 | args.push('null:'); 87 | } 88 | 89 | if (typeof options == 'function') { 90 | cb = options; // tolerance value not provided, flip the cb place 91 | } else { 92 | tolerance = options 93 | } 94 | } 95 | 96 | var cmd = bin + ' ' + args.map(utils.escape).join(' ') 97 | debug(cmd); 98 | 99 | var proc = spawn(bin, args); 100 | var stdout = ''; 101 | var stderr = ''; 102 | proc.stdout.on('data',function(data) { stdout+=data }); 103 | proc.stderr.on('data',function(data) { stderr+=data }); 104 | proc.on('close', function (code) { 105 | // ImageMagick returns err code 2 if err, 0 if similar, 1 if dissimilar 106 | if (isImageMagick) { 107 | if (code === 0) { 108 | return cb(null, 0 <= tolerance, 0, stdout); 109 | } 110 | else if (code === 1) { 111 | stdout = stderr; 112 | } else { 113 | return cb(stderr); 114 | } 115 | } else { 116 | if(code !== 0) { 117 | return cb(stderr); 118 | } 119 | } 120 | // Since ImageMagick similar gives err code 0 and no stdout, there's really no matching 121 | // Otherwise, output format for IM is `12.00 (0.123)` and for GM it's `Total: 0.123` 122 | var regex = isImageMagick ? /\((\d+\.?[\d\-\+e]*)\)/m : /Total: (\d+\.?\d*)/m; 123 | var match = regex.exec(stdout); 124 | if (!match) { 125 | return cb(new Error('Unable to parse output.\nGot ' + stdout)); 126 | } 127 | 128 | var equality = parseFloat(match[1]); 129 | cb(null, equality <= tolerance, equality, stdout, orig, compareTo); 130 | }); 131 | } 132 | 133 | if (proto) { 134 | proto.compare = compare; 135 | } 136 | return compare; 137 | }; 138 | 139 | -------------------------------------------------------------------------------- /lib/composite.js: -------------------------------------------------------------------------------- 1 | // composite 2 | 3 | /** 4 | * Composite images together using the `composite` command in graphicsmagick. 5 | * 6 | * gm('/path/to/image.jpg') 7 | * .composite('/path/to/second_image.jpg') 8 | * .geometry('+100+150') 9 | * .write('/path/to/composite.png', function(err) { 10 | * if(!err) console.log("Written composite image."); 11 | * }); 12 | * 13 | * @param {String} other Path to the image that contains the changes. 14 | * @param {String} [mask] Path to the image with opacity informtion. Grayscale. 15 | */ 16 | 17 | module.exports = exports = function(proto) { 18 | proto.composite = function(other, mask) { 19 | this.in(other); 20 | 21 | // If the mask is defined, add it to the output. 22 | if(typeof mask !== "undefined") 23 | this.out(mask); 24 | 25 | this.subCommand("composite"); 26 | 27 | return this; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/convenience.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Extend proto 4 | */ 5 | 6 | module.exports = function (proto) { 7 | require("./convenience/thumb")(proto); 8 | require("./convenience/morph")(proto); 9 | require("./convenience/sepia")(proto); 10 | require("./convenience/autoOrient")(proto); 11 | } 12 | -------------------------------------------------------------------------------- /lib/convenience/autoOrient.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Extend proto. 4 | */ 5 | 6 | module.exports = function (proto) { 7 | 8 | var exifTransforms = { 9 | topleft: '' 10 | , topright: ['-flop'] 11 | , bottomright: ['-rotate', 180] 12 | , bottomleft: ['-flip'] 13 | , lefttop: ['-flip', '-rotate', 90] 14 | , righttop: ['-rotate', 90] 15 | , rightbottom: ['-flop', '-rotate', 90] 16 | , leftbottom: ['-rotate', 270] 17 | } 18 | 19 | proto.autoOrient = function autoOrient () { 20 | // Always strip EXIF data since we can't 21 | // change/edit it. 22 | 23 | // imagemagick has a native -auto-orient option 24 | // so does graphicsmagick, but in 1.3.18. 25 | // nativeAutoOrient option enables this if you know you have >= 1.3.18 26 | if (this._options.nativeAutoOrient || this._options.imageMagick) { 27 | this.out('-auto-orient'); 28 | return this; 29 | } 30 | 31 | this.preprocessor(function (callback) { 32 | this.orientation({bufferStream: true}, function (err, orientation) { 33 | if (err) return callback(err); 34 | 35 | var transforms = exifTransforms[orientation.toLowerCase()]; 36 | if (transforms) { 37 | 38 | // remove any existing transforms that might conflict 39 | var index = this._out.indexOf(transforms[0]); 40 | if (~index) { 41 | this._out.splice(index, transforms.length); 42 | } 43 | 44 | // repage to fix coordinates 45 | this._out.unshift.apply(this._out, transforms.concat('-page', '+0+0')); 46 | } 47 | 48 | callback(); 49 | }); 50 | }); 51 | 52 | return this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/convenience/morph.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var fs = require('fs'); 7 | var parallel = require('array-parallel'); 8 | 9 | /** 10 | * Extend proto. 11 | */ 12 | 13 | module.exports = function (proto) { 14 | 15 | /** 16 | * Do nothing. 17 | */ 18 | 19 | function noop () {} 20 | 21 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-morph 22 | proto.morph = function morph (other, outname, callback) { 23 | if (!outname) { 24 | throw new Error("an output filename is required"); 25 | } 26 | 27 | callback = (callback || noop).bind(this) 28 | 29 | var self = this; 30 | 31 | if (Array.isArray(other)) { 32 | other.forEach(function (img) { 33 | self.out(img); 34 | }); 35 | self.out("-morph", other.length); 36 | } else { 37 | self.out(other, "-morph", 1); 38 | } 39 | 40 | self.write(outname, function (err, stdout, stderr, cmd) { 41 | if (err) return callback(err, stdout, stderr, cmd); 42 | 43 | // Apparently some platforms create the following temporary files. 44 | // Check if the output file exists, if it doesn't, then 45 | // work with temporary files. 46 | fs.exists(outname, function (exists) { 47 | if (exists) return callback(null, stdout, stderr, cmd); 48 | 49 | parallel([ 50 | fs.unlink.bind(fs, outname + '.0'), 51 | fs.unlink.bind(fs, outname + '.2'), 52 | fs.rename.bind(fs, outname + '.1', outname) 53 | ], function (err) { 54 | callback(err, stdout, stderr, cmd); 55 | }) 56 | }) 57 | }); 58 | 59 | return self; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/convenience/sepia.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Extend proto. 4 | */ 5 | 6 | module.exports = function (proto) { 7 | proto.sepia = function sepia () { 8 | return this.modulate(115, 0, 100).colorize(7, 21, 50); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /lib/convenience/thumb.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Extend proto. 4 | */ 5 | 6 | module.exports = function (proto) { 7 | 8 | proto.thumb = function thumb (w, h, name, quality, align, progressive, callback, opts) { 9 | var self = this, 10 | args = Array.prototype.slice.call(arguments); 11 | 12 | opts = args.pop(); 13 | 14 | if (typeof opts === 'function') { 15 | callback = opts; 16 | opts = ''; 17 | } else { 18 | callback = args.pop(); 19 | } 20 | 21 | w = args.shift(); 22 | h = args.shift(); 23 | name = args.shift(); 24 | quality = args.shift() || 63; 25 | align = args.shift() || 'topleft'; 26 | var interlace = args.shift() ? 'Line' : 'None'; 27 | 28 | self.size(function (err, size) { 29 | if (err) { 30 | return callback.apply(self, arguments); 31 | } 32 | 33 | w = parseInt(w, 10); 34 | h = parseInt(h, 10); 35 | 36 | var w1, h1; 37 | var xoffset = 0; 38 | var yoffset = 0; 39 | 40 | if (size.width < size.height) { 41 | w1 = w; 42 | h1 = Math.floor(size.height * (w/size.width)); 43 | if (h1 < h) { 44 | w1 = Math.floor(w1 * (((h-h1)/h) + 1)); 45 | h1 = h; 46 | } 47 | } else if (size.width > size.height) { 48 | h1 = h; 49 | w1 = Math.floor(size.width * (h/size.height)); 50 | if (w1 < w) { 51 | h1 = Math.floor(h1 * (((w-w1)/w) + 1)); 52 | w1 = w; 53 | } 54 | } else if (size.width == size.height) { 55 | var bigger = (w>h?w:h); 56 | w1 = bigger; 57 | h1 = bigger; 58 | } 59 | 60 | if (align == 'center') { 61 | if (w < w1) { 62 | xoffset = (w1-w)/2; 63 | } 64 | if (h < h1) { 65 | yoffset = (h1-h)/2; 66 | } 67 | } 68 | 69 | self 70 | .quality(quality) 71 | .in("-size", w1+"x"+h1) 72 | .scale(w1, h1, opts) 73 | .crop(w, h, xoffset, yoffset) 74 | .interlace(interlace) 75 | .noProfile() 76 | .write(name, function () { 77 | callback.apply(self, arguments); 78 | }); 79 | }); 80 | 81 | return self; 82 | }; 83 | 84 | proto.thumbExact = function () { 85 | var self = this, 86 | args = Array.prototype.slice.call(arguments); 87 | 88 | args.push('!'); 89 | 90 | self.thumb.apply(self, args); 91 | }; 92 | }; 93 | -------------------------------------------------------------------------------- /lib/drawing.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var escape = require('./utils').escape; 7 | 8 | /** 9 | * Extend proto. 10 | */ 11 | 12 | module.exports = function (proto) { 13 | 14 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-fill 15 | proto.fill = function fill (color) { 16 | return this.out("-fill", color || "none"); 17 | } 18 | 19 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-stroke 20 | proto.stroke = function stroke (color, width) { 21 | if (width) { 22 | this.strokeWidth(width); 23 | } 24 | 25 | return this.out("-stroke", color || "none"); 26 | } 27 | 28 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-strokewidth 29 | proto.strokeWidth = function strokeWidth (width) { 30 | return this.out("-strokewidth", width); 31 | } 32 | 33 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-font 34 | proto.font = function font (font, size) { 35 | if (size) { 36 | this.fontSize(size); 37 | } 38 | 39 | return this.out("-font", font); 40 | } 41 | 42 | // http://www.graphicsmagick.org/GraphicsMagick.html 43 | proto.fontSize = function fontSize (size) { 44 | return this.out("-pointsize", size); 45 | } 46 | 47 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 48 | proto.draw = function draw (args) { 49 | return this.out("-draw", [].slice.call(arguments).join(" ")); 50 | } 51 | 52 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 53 | proto.drawPoint = function drawPoint (x, y) { 54 | return this.draw("point", x +","+ y); 55 | } 56 | 57 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 58 | proto.drawLine = function drawLine (x0, y0, x1, y1) { 59 | return this.draw("line", x0+","+y0, x1+","+y1); 60 | } 61 | 62 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 63 | proto.drawRectangle = function drawRectangle (x0, y0, x1, y1, wc, hc) { 64 | var shape = "rectangle" 65 | , lastarg; 66 | 67 | if ("undefined" !== typeof wc) { 68 | shape = "roundRectangle"; 69 | 70 | if ("undefined" === typeof hc) { 71 | hc = wc; 72 | } 73 | 74 | lastarg = wc+","+hc; 75 | } 76 | 77 | return this.draw(shape, x0+","+y0, x1+","+y1, lastarg); 78 | } 79 | 80 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 81 | proto.drawArc = function drawArc (x0, y0, x1, y1, a0, a1) { 82 | return this.draw("arc", x0+","+y0, x1+","+y1, a0+","+a1); 83 | } 84 | 85 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 86 | proto.drawEllipse = function drawEllipse (x0, y0, rx, ry, a0, a1) { 87 | if (a0 == undefined) a0 = 0; 88 | if (a1 == undefined) a1 = 360; 89 | return this.draw("ellipse", x0+","+y0, rx+","+ry, a0+","+a1); 90 | } 91 | 92 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 93 | proto.drawCircle = function drawCircle (x0, y0, x1, y1) { 94 | return this.draw("circle", x0+","+y0, x1+","+y1); 95 | } 96 | 97 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 98 | proto.drawPolyline = function drawPolyline () { 99 | return this.draw("polyline", formatPoints(arguments)); 100 | } 101 | 102 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 103 | proto.drawPolygon = function drawPolygon () { 104 | return this.draw("polygon", formatPoints(arguments)); 105 | } 106 | 107 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 108 | proto.drawBezier = function drawBezier () { 109 | return this.draw("bezier", formatPoints(arguments)); 110 | } 111 | 112 | proto._gravities = [ 113 | "northwest" 114 | , "north" 115 | , "northeast" 116 | , "west" 117 | , "center" 118 | , "east" 119 | , "southwest" 120 | , "south" 121 | , "southeast"]; 122 | 123 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 124 | proto.drawText = function drawText (x0, y0, text, gravity) { 125 | var gravity = String(gravity || "").toLowerCase() 126 | , arg = ["text " + x0 + "," + y0 + " " + escape(text)]; 127 | 128 | if (~this._gravities.indexOf(gravity)) { 129 | arg.unshift("gravity", gravity); 130 | } 131 | 132 | return this.draw.apply(this, arg); 133 | } 134 | 135 | proto._drawProps = ["color", "matte"]; 136 | 137 | // http://www.graphicsmagick.org/GraphicsMagick.html#details-draw 138 | proto.setDraw = function setDraw (prop, x, y, method) { 139 | prop = String(prop || "").toLowerCase(); 140 | 141 | if (!~this._drawProps.indexOf(prop)) { 142 | return this; 143 | } 144 | 145 | return this.draw(prop, x+","+y, method); 146 | } 147 | 148 | } 149 | 150 | function formatPoints (points) { 151 | var len = points.length 152 | , result = [] 153 | , i = 0; 154 | 155 | for (; i < len; ++i) { 156 | result.push(points[i].join(",")); 157 | } 158 | 159 | return result; 160 | } 161 | -------------------------------------------------------------------------------- /lib/getters.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Extend proto. 3 | */ 4 | 5 | module.exports = function (gm) { 6 | 7 | var proto = gm.prototype; 8 | 9 | /** 10 | * `identify` states 11 | */ 12 | 13 | const IDENTIFYING = 1; 14 | const IDENTIFIED = 2; 15 | 16 | /** 17 | * Map getter functions to output names. 18 | * 19 | * - format: specifying the -format argument (see man gm) 20 | * - verbose: use -verbose instead of -format (only if necessary b/c its slow) 21 | * - helper: use the conversion helper 22 | */ 23 | 24 | var map = { 25 | 'format': { key: 'format', format: '%m ', helper: 'Format' } 26 | , 'depth': { key: 'depth', format: '%q' } 27 | , 'filesize': { key: 'Filesize', format: '%b' } 28 | , 'size': { key: 'size', format: '%wx%h ', helper: 'Geometry' } 29 | , 'color': { key: 'color', format: '%k', helper: 'Colors' } 30 | , 'orientation': { key: 'Orientation', format: '%[EXIF:Orientation]', helper: 'Orientation' } 31 | , 'res': { key: 'Resolution', verbose: true } 32 | } 33 | 34 | /** 35 | * Getter functions 36 | */ 37 | 38 | Object.keys(map).forEach(function (getter) { 39 | proto[getter] = function (opts, callback) { 40 | if (!callback) callback = opts, opts = {}; 41 | if (!callback) return this; 42 | 43 | var val = map[getter] 44 | , key = val.key 45 | , self = this; 46 | 47 | if (self.data[key]) { 48 | callback.call(self, null, self.data[key]); 49 | return self; 50 | } 51 | 52 | self.on(getter, callback); 53 | 54 | self.bufferStream = !!opts.bufferStream; 55 | 56 | if (val.verbose) { 57 | self.identify(opts, function (err, stdout, stderr, cmd) { 58 | if (err) { 59 | self.emit(getter, err, self.data[key], stdout, stderr, cmd); 60 | } else { 61 | self.emit(getter, err, self.data[key]); 62 | } 63 | }); 64 | return self; 65 | } 66 | 67 | var args = makeArgs(self, val); 68 | self._exec(args, function (err, stdout, stderr, cmd) { 69 | if (err) { 70 | self.emit(getter, err, self.data[key], stdout, stderr, cmd); 71 | return; 72 | } 73 | 74 | var result = (stdout||'').trim(); 75 | 76 | if (val.helper in helper) { 77 | helper[val.helper](self.data, result); 78 | } else { 79 | self.data[key] = result; 80 | } 81 | 82 | self.emit(getter, err, self.data[key]); 83 | }); 84 | 85 | return self; 86 | } 87 | }); 88 | 89 | /** 90 | * identify command 91 | * 92 | * Overwrites all internal data with the parsed output 93 | * which is more accurate than the fast shortcut 94 | * getters. 95 | */ 96 | 97 | proto.identify = function identify (opts, callback) { 98 | // identify with pattern 99 | if (typeof(opts) === 'string') { 100 | opts = { 101 | format: opts 102 | } 103 | } 104 | if (!callback) callback = opts, opts = {}; 105 | if (!callback) return this; 106 | if (opts && opts.format) return identifyPattern.call(this, opts, callback); 107 | 108 | var self = this; 109 | 110 | if (IDENTIFIED === self._identifyState) { 111 | callback.call(self, null, self.data); 112 | return self; 113 | } 114 | 115 | self.on('identify', callback); 116 | 117 | if (IDENTIFYING === self._identifyState) { 118 | return self; 119 | } 120 | 121 | self._identifyState = IDENTIFYING; 122 | 123 | self.bufferStream = !!opts.bufferStream; 124 | 125 | var args = makeArgs(self, { verbose: true }); 126 | 127 | self._exec(args, function (err, stdout, stderr, cmd) { 128 | if (err) { 129 | self.emit('identify', err, self.data, stdout, stderr, cmd); 130 | return; 131 | } 132 | 133 | err = parse(stdout, self); 134 | 135 | if (err) { 136 | self.emit('identify', err, self.data, stdout, stderr, cmd); 137 | return; 138 | } 139 | 140 | self.data.path = self.source; 141 | 142 | self.emit('identify', null, self.data); 143 | self._identifyState = IDENTIFIED; 144 | }); 145 | 146 | return self; 147 | } 148 | 149 | 150 | /** 151 | * identify with pattern 152 | * 153 | * Execute `identify -format` with custom pattern 154 | */ 155 | 156 | function identifyPattern (opts, callback) { 157 | var self = this; 158 | 159 | self.bufferStream = !!opts.bufferStream; 160 | 161 | var args = makeArgs(self, opts); 162 | self._exec(args, function (err, stdout, stderr, cmd) { 163 | if (err) { 164 | return callback.call(self, err, undefined, stdout, stderr, cmd); 165 | } 166 | 167 | callback.call(self, err, (stdout||'').trim()); 168 | }); 169 | 170 | return self; 171 | } 172 | 173 | 174 | /** 175 | * Parses `identify` responses. 176 | * 177 | * @param {String} stdout 178 | * @param {Gm} self 179 | * @return {Error} [optionally] 180 | */ 181 | 182 | function parse (stdout, self) { 183 | // normalize 184 | var parts = (stdout||"").trim().replace(/\r\n|\r/g, "\n").split("\n"); 185 | 186 | // skip the first line (its just the filename) 187 | parts.shift(); 188 | 189 | try { 190 | var len = parts.length 191 | , rgx1 = /^( *)(.+?): (.*)$/ // key: val 192 | , rgx2 = /^( *)(.+?):$/ // key: begin nested object 193 | , out = { indent: {} } 194 | , level = null 195 | , lastkey 196 | , i = 0 197 | , res 198 | , o 199 | 200 | for (; i < len; ++i) { 201 | res = rgx1.exec(parts[i]) || rgx2.exec(parts[i]); 202 | if (!res) continue; 203 | 204 | var indent = res[1].length 205 | , key = res[2] ? res[2].trim() : ''; 206 | 207 | if ('Image' == key || 'Warning' == key) continue; 208 | 209 | var val = res[3] ? res[3].trim() : null; 210 | 211 | // first iteration? 212 | if (null === level) { 213 | level = indent; 214 | o = out.root = out.indent[level] = self.data; 215 | } else if (indent < level) { 216 | // outdent 217 | if (!(indent in out.indent)) { 218 | continue; 219 | } 220 | o = out.indent[indent]; 221 | } else if (indent > level) { 222 | // dropping into a nested object 223 | out.indent[level] = o; 224 | // weird format, key/val pair with nested children. discard the val 225 | o = o[lastkey] = {}; 226 | } 227 | 228 | level = indent; 229 | 230 | if (val) { 231 | // if previous key was exist and we got the same key 232 | // cast it to an array. 233 | if(o.hasOwnProperty(key)){ 234 | // cast it to an array and dont forget the previous value 235 | if(!Array.isArray(o[key])){ 236 | var tmp = o[key]; 237 | o[key] = [tmp]; 238 | } 239 | 240 | // set value 241 | o[key].push(val); 242 | } else { 243 | o[key] = val; 244 | } 245 | 246 | if (key in helper) { 247 | helper[key](o, val); 248 | } 249 | } 250 | 251 | lastkey = key; 252 | } 253 | 254 | } catch (err) { 255 | err.message = err.message + "\n\n Identify stdout:\n " + stdout; 256 | return err; 257 | } 258 | } 259 | 260 | /** 261 | * Create an argument array for the identify command. 262 | * 263 | * @param {gm} self 264 | * @param {Object} val 265 | * @return {Array} 266 | */ 267 | 268 | function makeArgs (self, val) { 269 | var args = [ 270 | 'identify' 271 | , '-ping' 272 | ]; 273 | 274 | if (val.format) { 275 | args.push('-format', val.format); 276 | } 277 | 278 | if (val.verbose) { 279 | args.push('-verbose'); 280 | } 281 | 282 | args = args.concat(self.src()); 283 | return args; 284 | } 285 | 286 | /** 287 | * Map exif orientation codes to orientation names. 288 | */ 289 | 290 | var orientations = { 291 | '1': 'TopLeft' 292 | , '2': 'TopRight' 293 | , '3': 'BottomRight' 294 | , '4': 'BottomLeft' 295 | , '5': 'LeftTop' 296 | , '6': 'RightTop' 297 | , '7': 'RightBottom' 298 | , '8': 'LeftBottom' 299 | } 300 | 301 | /** 302 | * identify -verbose helpers 303 | */ 304 | 305 | var helper = gm.identifyHelpers = {}; 306 | 307 | helper.Geometry = function Geometry (o, val) { 308 | // We only want the size of the first frame. 309 | // Each frame is separated by a space. 310 | var split = val.split(" ").shift().split("x"); 311 | var width = parseInt(split[0], 10); 312 | var height = parseInt(split[1], 10); 313 | if (o.size && o.size.width && o.size.height) { 314 | if (width > o.size.width) o.size.width = width; 315 | if (height > o.size.height) o.size.height = height; 316 | } else { 317 | o.size = { 318 | width: width, 319 | height: height 320 | } 321 | } 322 | }; 323 | 324 | helper.Format = function Format (o, val) { 325 | o.format = val.split(" ")[0]; 326 | }; 327 | 328 | helper.Depth = function Depth (o, val) { 329 | o.depth = parseInt(val, 10); 330 | }; 331 | 332 | helper.Colors = function Colors (o, val) { 333 | o.color = parseInt(val, 10); 334 | }; 335 | 336 | helper.Orientation = function Orientation (o, val) { 337 | if (val in orientations) { 338 | o['Profile-EXIF'] || (o['Profile-EXIF'] = {}); 339 | o['Profile-EXIF'].Orientation = val; 340 | o.Orientation = orientations[val]; 341 | } else { 342 | o.Orientation = val || 'Unknown'; 343 | } 344 | }; 345 | } 346 | 347 | -------------------------------------------------------------------------------- /lib/montage.js: -------------------------------------------------------------------------------- 1 | // montage 2 | 3 | /** 4 | * Montage images next to each other using the `montage` command in graphicsmagick. 5 | * 6 | * gm('/path/to/image.jpg') 7 | * .montage('/path/to/second_image.jpg') 8 | * .geometry('+100+150') 9 | * .write('/path/to/montage.png', function(err) { 10 | * if(!err) console.log("Written montage image."); 11 | * }); 12 | * 13 | * @param {String} other Path to the image that contains the changes. 14 | */ 15 | 16 | module.exports = exports = function(proto) { 17 | proto.montage = function(other) { 18 | this.in(other); 19 | 20 | this.subCommand("montage"); 21 | 22 | return this; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/options.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = exports = function (proto) { 3 | proto._options = {}; 4 | 5 | proto.options = function setOptions (options) { 6 | var keys = Object.keys(options) 7 | , i = keys.length 8 | , key 9 | 10 | while (i--) { 11 | key = keys[i]; 12 | this._options[key] = options[key]; 13 | } 14 | 15 | return this; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Escape the given shell `arg`. 4 | * 5 | * @param {String} arg 6 | * @return {String} 7 | * @api public 8 | */ 9 | 10 | exports.escape = function escape (arg) { 11 | return '"' + String(arg).trim().replace(/"/g, '\\"') + '"'; 12 | }; 13 | 14 | exports.unescape = function escape (arg) { 15 | return String(arg).trim().replace(/"/g, ""); 16 | }; 17 | 18 | exports.argsToArray = function (args) { 19 | var arr = []; 20 | 21 | for (var i = 0; i <= arguments.length; i++) { 22 | if ('undefined' != typeof arguments[i]) 23 | arr.push(arguments[i]); 24 | } 25 | 26 | return arr; 27 | }; 28 | 29 | exports.isUtil = function (v) { 30 | var ty = 'object'; 31 | switch (Object.prototype.toString.call(v)) { 32 | case '[object String]': 33 | ty = 'String'; 34 | break; 35 | case '[object Array]': 36 | ty = 'Array'; 37 | break; 38 | case '[object Boolean]': 39 | ty = 'Boolean'; 40 | break; 41 | } 42 | return ty; 43 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gm", 3 | "description": "GraphicsMagick and ImageMagick for node.js", 4 | "version": "1.25.1", 5 | "author": "Aaron Heckmann ", 6 | "keywords": [ 7 | "graphics", 8 | "magick", 9 | "image", 10 | "graphicsmagick", 11 | "imagemagick", 12 | "gm", 13 | "convert", 14 | "identify", 15 | "compare" 16 | ], 17 | "engines": { 18 | "node": ">=14" 19 | }, 20 | "bugs": { 21 | "url": "http://github.com/aheckmann/gm/issues" 22 | }, 23 | "licenses": [ 24 | { 25 | "type": "MIT", 26 | "url": "http://www.opensource.org/licenses/mit-license.php" 27 | } 28 | ], 29 | "main": "./index", 30 | "scripts": { 31 | "security": "npm audit", 32 | "test": "npm run security && npm run test-integration", 33 | "test-integration": "node test/ --integration", 34 | "test-unit": "node test/" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/aheckmann/gm.git" 39 | }, 40 | "license": "MIT", 41 | "devDependencies": { 42 | "async": "~0.9.0" 43 | }, 44 | "dependencies": { 45 | "array-parallel": "~0.1.3", 46 | "array-series": "~0.1.5", 47 | "cross-spawn": "^7.0.5", 48 | "debug": "^3.1.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/109.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) return finish(); 6 | 7 | const original = path.join(dir, 'original.jpg'); 8 | const buf = fs.readFileSync(original); 9 | const m = gm(buf, 'original.jpg').options({ imageMagick }); 10 | 11 | m.identify(function (err, _) { 12 | finish(err); 13 | }); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /test/118.js: -------------------------------------------------------------------------------- 1 | /* 2 | * If only the width is specified for a resize operation, 3 | * GraphicsMagick requires the format 4 | * -resize 10x 5 | * while ImageMagick requires the format 6 | * -resize 10 7 | * 8 | */ 9 | const assert = require('assert') 10 | const path = require('path'); 11 | 12 | module.exports = function (_, dir, finish, gm, imageMagick) { 13 | if (!gm.integration) return finish(); 14 | 15 | var src = path.join(dir, 'originalSideways.jpg'); 16 | var dst = path.join(dir, 'originalSideways10x.jpg'); 17 | 18 | gm(src).options({ imageMagick }).resize(10).write(dst, function(err) { 19 | gm(dst).options({ imageMagick }).size(function(err, size) { 20 | if (err) return finish(err); 21 | assert.equal(10, size.width); 22 | finish(); 23 | }); 24 | }); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /test/393.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | if (!gm.integration) return finish(); 7 | 8 | var imagePath = path.join(__dirname, 'fixtures', 'nyancat.gif'); 9 | var inputStream = fs.createReadStream(imagePath); 10 | gm(inputStream).options({ imageMagick }).identify({ bufferStream: true }, function(err, value) { 11 | if (err) return finish(err); 12 | var size = value.size; 13 | assert.equal(400, size.width); 14 | assert.equal(400, size.height); 15 | finish(); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /test/417.js: -------------------------------------------------------------------------------- 1 | 2 | const assert = require('assert') 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | 6 | module.exports = function (_, dir, finish, gm, imageMagick) { 7 | if (!gm.integration) 8 | return finish(); 9 | 10 | const originalPathName = path.join(dir, 'original.jpg'); 11 | const thumbPathName = path.join(dir, 'thumb.png'); 12 | 13 | gm(originalPathName).options({ imageMagick }).thumb(150, 40, thumbPathName, function thumb (err) { 14 | gm(thumbPathName).options({ imageMagick }).size(function (err, size) { 15 | if (err) return finish(err); 16 | 17 | assert.equal(142, size.width); 18 | assert.equal(40, size.height); 19 | 20 | gm(originalPathName).options({ imageMagick }).thumbExact(150, 40, thumbPathName, function thumb (err) { 21 | gm(thumbPathName).options({ imageMagick }).size(function (err, size) { 22 | assert.equal(150, size.width); 23 | assert.equal(40, size.height); 24 | finish(err); 25 | }); 26 | }); 27 | }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /test/422.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM, imageMagick) { 5 | // Same image 6 | const originalPathName = path.join(dir, 'original.jpg'); 7 | 8 | gm.compare(originalPathName, originalPathName, function(err, same, diff) { 9 | if (err) return finish(err); 10 | if (!same) { 11 | const msg = `Compare should be the same! "${same}" "${diff}"`; 12 | return finish(new Error(msg)); 13 | } 14 | 15 | // Compare almost similar images for which ImageMagick 16 | // returns an exponent-style floating point number 17 | const compare1PathName = path.join(__dirname, 'fixtures', 'compare_1.png'); 18 | const compare2PathName = path.join(__dirname, 'fixtures', 'compare_2.png'); 19 | 20 | gm.compare(compare1PathName, compare2PathName, function(err, same, diff) { 21 | if (err) return finish(err); 22 | if (!same) { 23 | const msg = `Compare should be the same! "${same}" "${diff}"`; 24 | return finish(new Error(msg)); 25 | } 26 | 27 | const noisePathName = path.join(dir, 'noise3.png'); 28 | 29 | // Create a new noisy image 30 | gm.noise(0.3).write(noisePathName, function (err) { 31 | if (err) return finish(err); 32 | 33 | var options = { 34 | highlightColor: '#fff', 35 | file: path.join(dir, 'diff.png'), 36 | tolerance: 0.001 37 | }; 38 | 39 | const originalPathName = path.join(dir, 'original.jpg'); 40 | 41 | // Compare these images and write to a file. 42 | gm.compare(originalPathName, noisePathName, options, function(err) { 43 | if (err) return finish(err); 44 | 45 | fs.access(options.file, fs.constants.F_OK, function(err) { 46 | if (err) { 47 | finish(new Error('Diff file does not exist.')); 48 | } else { 49 | fs.unlink(options.file, finish); 50 | } 51 | }); 52 | }); 53 | }); 54 | }); 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /test/429.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM, imageMagick) { 5 | if (!GM.integration) return finish(); 6 | 7 | const ico = path.join(__dirname, 'fixtures', 'test.ico'); 8 | const buffer = fs.readFileSync(ico); 9 | const stream = fs.createReadStream(ico); 10 | 11 | GM(ico).options({ imageMagick }).size(function (err) { 12 | if (err) { 13 | err.message = 'Failed using ico filename. ' + err.message; 14 | return finish(err); 15 | } 16 | 17 | GM(buffer, 'img.ico').options({ imageMagick }).size(function (err) { 18 | if (err) { 19 | err.message = 'Failed using ico buffer. ' + err.message; 20 | return finish(err); 21 | } 22 | 23 | GM(stream, 'img.ico').options({ imageMagick }).size({bufferStream: true}, function (err) { 24 | if (err) { 25 | err.message = 'Failed using ico stream. ' + err.message; 26 | return finish(err); 27 | } 28 | finish(); 29 | }); 30 | }); 31 | }); 32 | } -------------------------------------------------------------------------------- /test/68.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | var assert = require('assert') 4 | var url = require('url') 5 | var http = require('http') 6 | 7 | module.exports = function (_, dir, finish, gm) { 8 | return finish(); 9 | 10 | // use this test when gm is not installed. 11 | // it demonstrates that err is often passed as null (timing) 12 | // to detect the stream error that the gm command is not installed, 13 | // you must test the stderr output manually for "execvp(): No such file or directory" 14 | 15 | function done (err){ 16 | if (err) return finish(done.ran = err); 17 | if (done.ran) return; 18 | finish(); 19 | } 20 | 21 | http.get(url.parse('http://www.google.com/images/srpr/logo3w.png'), function (resp) { 22 | gm(resp, 'logo3w.png').stream(function (err, stdout, stderr) { 23 | return finish(); 24 | 25 | if (err) { 26 | console.error('Error processing image', err) 27 | } else { 28 | stdout.on('data', function (chunk) { 29 | console.log('Chunk recieved', chunk.toString()) 30 | }) 31 | stdout.on('end', function () { 32 | console.log('Stream ended') 33 | }) 34 | stderr.on('data', function (chunk) { 35 | console.log('err Chunk recieved', chunk.toString()) 36 | }) 37 | stderr.on('end', function () { 38 | console.log('err Stream ended') 39 | }) 40 | } 41 | }) 42 | }) 43 | .on('error', function (err) { 44 | console.error('Error fetching image', err) 45 | }) 46 | 47 | } 48 | -------------------------------------------------------------------------------- /test/70.js: -------------------------------------------------------------------------------- 1 | 2 | const assert = require('assert') 3 | const path = require('path'); 4 | 5 | var times = 16; 6 | var loading = path.join(__dirname, 'fixtures', 'loading.gif'); 7 | var favicon = path.join(__dirname, 'fixtures', 'favicon.png'); 8 | 9 | module.exports = function (_, dir, finish, gm, imageMagick) { 10 | if (!gm.integration) return finish(); 11 | 12 | var pending = times/2; 13 | 14 | var res = {}; 15 | res[loading] = {}; 16 | res[favicon] = {}; 17 | 18 | function done (err){ 19 | if (err) return finish(done.ran = err); 20 | if (done.ran) return; 21 | if (--pending) return; 22 | finish(); 23 | } 24 | 25 | new Array(times).join('x').split('x').forEach(function (_, i) { 26 | ;[loading, favicon].forEach(function (img) { 27 | gm(img).options({imageMagick}).size(function (err, size) { 28 | if (err) return done(err); 29 | 30 | 'width height'.split(' ').forEach(function (prop) { 31 | if (!(prop in res[img])) { 32 | res[img][prop] = size[prop]; 33 | } else { 34 | assert.equal(res[img][prop], size[prop]); 35 | } 36 | }); 37 | 38 | done(err); 39 | }); 40 | }); 41 | }); 42 | 43 | } 44 | -------------------------------------------------------------------------------- /test/78.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) return finish(); 6 | 7 | var name = imageMagick ? '78-IM' : '78'; 8 | var out = path.join(dir, name); 9 | 10 | _.resize(600, 450, '!').write(out + '.png', function (err) { 11 | if (err) return finish(err); 12 | 13 | var img = gm(out + '.png').options({ imageMagick }); 14 | 15 | img 16 | .crop(70, 70, 100, 100) 17 | .resize(50, 50) 18 | .write(out + '-2.jpg', function (err) { 19 | if (err) return finish(err); 20 | finish(); 21 | }) 22 | }); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /test/alpha.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const Async = require('async'); 3 | const path = require('path'); 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | if (!gm.integration) return finish(); 7 | 8 | var alphaTypes = [ 9 | "Activate", 10 | "On", 11 | "Deactivate", 12 | "Off", 13 | "Set", 14 | "Opaque", 15 | "Transparent", 16 | "Extract", 17 | "Copy", 18 | "Shape", 19 | "Background" 20 | ]; 21 | 22 | const edgePath = path.join(dir, 'original.png'); 23 | const failPath = path.join(dir, 'alpha_fail.png'); 24 | 25 | // alpha not supported by GM so only test IM 26 | if (!imageMagick) { 27 | assert.throws(function() { 28 | gm(edgePath) 29 | .alpha(alphaTypes.pop()) 30 | .write(failPath); 31 | }); 32 | finish(); 33 | } else { 34 | 35 | Async.eachSeries(alphaTypes, function(alphaType, cb) { 36 | var m = gm(edgePath).options({imageMagick}).alpha( alphaType ); 37 | var args = m.args(); 38 | assert.equal('convert', args[0]); 39 | assert.equal('-alpha', args[2]); 40 | assert.equal(alphaType, args[3]); 41 | 42 | const writePath = path.join(dir, `alpha_${alphaType}.png`); 43 | m.write(writePath, cb); 44 | }, finish); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/append.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | const out = path.resolve(dir, 'append.jpg'); 6 | const lostPath = path.join(dir, 'lost.png'); 7 | const originalPath = path.join(dir, 'original.jpg'); 8 | 9 | try { 10 | require('fs').unlinkSync(out); 11 | } catch (_) {} 12 | 13 | var m = gm(lostPath) 14 | .options({imageMagick}) 15 | .append(originalPath, originalPath) 16 | .append() 17 | .background('#222') 18 | 19 | var args = m.args(); 20 | assert.equal('convert', args[0]); 21 | assert.equal('-background',args[1]); 22 | assert.equal('#222',args[2]); 23 | assert.ok(/lost\.png$/.test(args[3])); 24 | assert.ok(/original\.jpg$/,args[4]); 25 | assert.ok(/original\.jpg$/,args[5]); 26 | assert.equal('-append',args[6]); 27 | assert.equal('-',args[7]); 28 | 29 | if (!gm.integration) { 30 | return horizontal({ dir, finish, gm, originalPath, lostPath, imageMagick }); 31 | } 32 | 33 | m.write(out, function (err) { 34 | if (err) return finish(err); 35 | gm(out) 36 | .options({imageMagick}) 37 | .size(function (err, size) { 38 | if (err) return finish(err); 39 | assert.equal(460, size.width); 40 | assert.equal(435, size.height); 41 | 42 | horizontal({ dir, finish, gm, originalPath, lostPath, imageMagick }); 43 | }) 44 | }); 45 | } 46 | 47 | function horizontal ({ dir, finish, gm, originalPath, lostPath, imageMagick }) { 48 | var out = path.resolve(dir, 'appendHorizontal.jpg'); 49 | 50 | var m = gm(originalPath).append(lostPath, true).options({imageMagick}); 51 | 52 | var args = m.args(); 53 | assert.equal('convert', args[0]); 54 | assert.ok(/original\.jpg$/.test(args[1])); 55 | assert.ok(/lost\.png$/.test(args[2])); 56 | assert.equal('+append',args[3]); 57 | assert.equal('-',args[4]); 58 | 59 | if (!gm.integration) { 60 | return finish(); 61 | } 62 | 63 | m.write(out, function (err) { 64 | if (err) return finish(err); 65 | gm(out).options({imageMagick}).size(function (err, size) { 66 | if (err) return finish(err); 67 | assert.equal(697, size.width); 68 | assert.equal(155, size.height); 69 | 70 | finish(); 71 | }) 72 | }); 73 | 74 | } 75 | -------------------------------------------------------------------------------- /test/arc.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("red", 3) 9 | .fill("#ffffffbb") 10 | .drawArc(80, 10, 90, 20, 0, 180) 11 | 12 | var args = m.args(); 13 | assert.equal('convert', args[0]); 14 | assert.equal('-blur', args[2]); 15 | assert.equal('8x4', args[3]); 16 | assert.equal('-strokewidth', args[4]); 17 | assert.equal(3, args[5]); 18 | assert.equal('-stroke', args[6]); 19 | assert.equal('red', args[7]); 20 | assert.equal('-fill', args[8]); 21 | assert.equal('#ffffffbb', args[9]); 22 | assert.equal('-draw', args[10]); 23 | assert.equal('arc 80,10 90,20 0,180', args[11]); 24 | 25 | if (!GM.integration) return finish(); 26 | 27 | const arcPath = path.join(dir, 'arc.png'); 28 | 29 | m.write(arcPath, function arc (err) { 30 | finish(err); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/autoOrient.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | const sidewaysPath = path.join(dir, 'originalSideways.jpg'); 9 | 10 | gm(sidewaysPath) 11 | .options({imageMagick}) 12 | .identify(function (err, o) { 13 | if (err) return finish(err); 14 | 15 | const geo = imageMagick ? '155x460+0+0' : '155x460'; 16 | assert.equal(geo, o.Geometry); 17 | 18 | // this image is sideways, but may be auto-oriented by modern OS's 19 | // try opening it in a browser to see its true orientation 20 | gm(sidewaysPath) 21 | .options({imageMagick}) 22 | .autoOrient() 23 | .stream(function (err, stream) { 24 | if (err) return finish(err); 25 | 26 | gm(stream) 27 | .options({imageMagick}) 28 | .identify(function (err, data) { 29 | if (err) return finish(err); 30 | 31 | const geo2 = imageMagick ? '460x155+0+0' : '460x155'; 32 | assert.equal(geo2, data.Geometry); 33 | finish(err); 34 | }) 35 | }) 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/autoOrientAll.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | if (!gm.integration) return finish(); 7 | 8 | var beforeValues = { 9 | 'Landscape_1.jpg': ['TopLeft', 1, '600x450'], 10 | 'Landscape_2.jpg': ['TopRight', 2, '600x450'], 11 | 'Landscape_3.jpg': ['BottomRight', 3, '600x450'], 12 | 'Landscape_4.jpg': ['BottomLeft', 4, '600x450'], 13 | 'Landscape_5.jpg': ['LeftTop', 5, '450x600'], 14 | 'Landscape_6.jpg': ['RightTop', 6, '450x600'], 15 | 'Landscape_7.jpg': ['RightBottom', 7, '450x600'], 16 | 'Landscape_8.jpg': ['LeftBottom', 8, '450x600'], 17 | 'Portrait_1.jpg': ['TopLeft', 1, '450x600'], 18 | 'Portrait_2.jpg': ['TopRight', 2, '450x600'], 19 | 'Portrait_3.jpg': ['BottomRight', 3, '450x600'], 20 | 'Portrait_4.jpg': ['BottomLeft', 4, '450x600'], 21 | 'Portrait_5.jpg': ['LeftTop', 5, '600x450'], 22 | 'Portrait_6.jpg': ['RightTop', 6, '600x450'], 23 | 'Portrait_7.jpg': ['RightBottom', 7, '600x450'], 24 | 'Portrait_8.jpg': ['LeftBottom', 8, '600x450'] 25 | }; 26 | 27 | var afterValues = { 28 | 'Landscape_1.jpg': '600x450', 29 | 'Landscape_2.jpg': '600x450', 30 | 'Landscape_3.jpg': '600x450', 31 | 'Landscape_4.jpg': '600x450', 32 | 'Landscape_5.jpg': '600x450', 33 | 'Landscape_6.jpg': '600x450', 34 | 'Landscape_7.jpg': '600x450', 35 | 'Landscape_8.jpg': '600x450', 36 | 'Portrait_1.jpg': '450x600', 37 | 'Portrait_2.jpg': '450x600', 38 | 'Portrait_3.jpg': '450x600', 39 | 'Portrait_4.jpg': '450x600', 40 | 'Portrait_5.jpg': '450x600', 41 | 'Portrait_6.jpg': '450x600', 42 | 'Portrait_7.jpg': '450x600', 43 | 'Portrait_8.jpg': '450x600' 44 | }; 45 | 46 | const orientationDir = path.join(dir, 'orientation'); 47 | 48 | fs.readdir(orientationDir, function(err, files) { 49 | if (err) return finish(err); 50 | 51 | var originalFiles = files.filter(function(file) { 52 | return beforeValues[file] && afterValues[file]; 53 | }); 54 | 55 | function next () { 56 | test(originalFiles.pop()); 57 | } 58 | 59 | return next(); 60 | 61 | function test (filename) { 62 | if (!filename) return finish(); 63 | 64 | const fileToAutoOrient = path.join(orientationDir, filename); 65 | const newFilename = fileToAutoOrient + '.oriented.jpg'; 66 | const constant = fileToAutoOrient + '.correct.jpg'; 67 | 68 | gm(fileToAutoOrient).options({imageMagick}).orientation(function (err, o) { 69 | if (err) return finish(err); 70 | 71 | assert.equal(beforeValues[filename][0], o); 72 | assert.equal(beforeValues[filename][1], this.data['Profile-EXIF'].Orientation, 'No Profile-EXIF data found'); 73 | 74 | // this image is sideways, but may be auto-oriented by modern OS's 75 | // try opening it in a browser to see its true orientation 76 | gm(fileToAutoOrient) 77 | .options({ imageMagick }) 78 | .autoOrient() 79 | .write(newFilename, function autoOrient (err) { 80 | if (err) return finish(err); 81 | 82 | // fs race condition 83 | setTimeout(function () { 84 | gm(newFilename).options({ imageMagick }).identify(function (err) { 85 | if (err) return finish(err); 86 | 87 | const afterValue = imageMagick ? `${afterValues[filename]}+0+0` : afterValues[filename]; 88 | assert.equal(afterValue, this.data.Geometry, `Bad-Geometry for ${filename}. Got "${this.data.Geometry}"`); 89 | 90 | gm().options({imageMagick}).compare(newFilename, constant, 0.1, function (err, equal) { 91 | if (err) return finish(err); 92 | assert.ok(equal); 93 | next(); 94 | }) 95 | }); 96 | }, 200); 97 | }); 98 | }); 99 | } 100 | }); 101 | 102 | }; 103 | -------------------------------------------------------------------------------- /test/autoOrientAndThumb.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | var original = path.join(dir, 'orientation', 'Portrait_7.jpg'); 9 | var result = path.join(dir, 'autoOrientAndThumb.png'); 10 | 11 | size(original, imageMagick, function (err, origSize) { 12 | if (err) return finish(err); 13 | 14 | assert.ok(origSize.width < 610); 15 | assert.ok(origSize.height < 460); 16 | 17 | gm(original) 18 | .options({imageMagick}) 19 | .autoOrient() 20 | .thumb(100, 100, result, function (err) { 21 | if (err) return finish(err); 22 | 23 | size(result, imageMagick, function (err, newSize) { 24 | if (err) return finish(err); 25 | assert.ok(newSize.width < 80); 26 | assert.ok(newSize.height < 110); 27 | finish(); 28 | }); 29 | 30 | }); 31 | }); 32 | 33 | function size (file, imageMagick, cb) { 34 | gm(file).options({imageMagick}).identify(function (err, data) { 35 | if (err) return cb(err); 36 | cb(err, data.size); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/autoOrientStream.js: -------------------------------------------------------------------------------- 1 | 2 | // gm - Copyright Aaron Heckmann (MIT Licensed) 3 | // This is a copy of `autoOrient.js` using streams 4 | 5 | const assert = require('assert') 6 | const fs = require('fs') 7 | const path = require('path'); 8 | 9 | module.exports = function (_, dir, finish, gm, imageMagick) { 10 | if (!gm.integration) 11 | return finish(); 12 | 13 | const filename = path.join(dir, 'autoOrientStream.jpg'); 14 | const sidewaysPathName = path.join(dir, 'originalSideways.jpg'); 15 | 16 | gm(fs.createReadStream(sidewaysPathName)).options({imageMagick}).identify(function (err) { 17 | if (err) return finish(err); 18 | 19 | const geo = imageMagick ? '155x460+0+0' : '155x460'; 20 | assert.equal(geo, this.data.Geometry); 21 | 22 | // this image is sideways, but may be auto-oriented by modern OS's 23 | // try opening it in a browser to see its true orientation 24 | gm(fs.createReadStream(sidewaysPathName)) 25 | .options({imageMagick}) 26 | .autoOrient() 27 | .write(filename, function autoOrient (err) { 28 | if (err) return finish(err); 29 | 30 | // fs race condition 31 | setTimeout(function () { 32 | gm(filename).options({imageMagick}).identify(function (err) { 33 | if (err) return finish(err); 34 | 35 | const geo2 = imageMagick ? '460x155+0+0' : '460x155'; 36 | assert.equal(geo2, this.data.Geometry); 37 | 38 | finish(err); 39 | }); 40 | }, 200); 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /test/background.js: -------------------------------------------------------------------------------- 1 | const assert =require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .crop(140,100) 8 | .background("#FF0000") 9 | .extent(340,300) 10 | 11 | var args = m.args(); 12 | assert.equal('convert', args[0]); 13 | assert.equal('-background', args[1]); 14 | assert.equal('#FF0000', args[2]); 15 | assert.equal('-crop', args[4]); 16 | assert.equal('140x100+0+0', args[5]); 17 | assert.equal('-extent', args[6]); 18 | assert.equal('340x300', args[7]); 19 | 20 | if (!GM.integration) 21 | return finish(); 22 | 23 | const backgroundPathName = path.join(dir, 'background.jpg'); 24 | 25 | m.write(backgroundPathName, function (err) { 26 | finish(err); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /test/bezier.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("red", 3) 9 | .fill("#ffffffbb") 10 | .drawBezier([0, 10], [183, 163], [183, 10], [0, 10]) 11 | 12 | var args = m.args(); 13 | assert.equal('convert', args[0]); 14 | assert.equal('-blur', args[2]); 15 | assert.equal('8x4', args[3]); 16 | assert.equal('-strokewidth', args[4]); 17 | assert.equal(3, args[5]); 18 | assert.equal('-stroke', args[6]); 19 | assert.equal('red', args[7]); 20 | assert.equal('-fill', args[8]); 21 | assert.equal('#ffffffbb', args[9]); 22 | assert.equal('-draw', args[10]); 23 | assert.equal('bezier 0,10,183,163,183,10,0,10', args[11]); 24 | 25 | if (!GM.integration) 26 | return finish(); 27 | 28 | m 29 | .write(path.join(dir, 'bezier.png'), function bezier (err) { 30 | finish(err); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/bitdepth.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .bitdepth(2); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-depth', args[2]); 12 | assert.equal(2, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const outpath = path.join(dir, 'bitdepth.png'); 18 | m.write(outpath, function bitdepth (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/blur.js: -------------------------------------------------------------------------------- 1 | 2 | const assert = require('assert'); 3 | const path = require('path'); 4 | 5 | module.exports = function (gm, dir, finish, GM) { 6 | 7 | var m = gm 8 | .blur(18, 10); 9 | 10 | var args = m.args(); 11 | assert.equal('convert', args[0]); 12 | assert.equal('-blur', args[2]); 13 | assert.equal('18x10', args[3]); 14 | 15 | if (!GM.integration) 16 | return finish(); 17 | 18 | const outpath = path.join(dir, 'blur.png'); 19 | m.write(outpath, function blur (err) { 20 | finish(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /test/changeFormat.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function (gm, dir, finish, GM) { 4 | if (!GM.integration) 5 | return finish(); 6 | 7 | const outpath = path.join(dir, 'changedformat.png'); 8 | gm.write(outpath, function changeformat (err) { 9 | finish(err); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /test/charcoal.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .charcoal(1); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-charcoal', args[2]); 12 | assert.equal(1, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const outpath = path.join(dir, 'charcoal.png'); 18 | m.write(outpath, function charcoal (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/chop.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .chop(54, 1, 307, 1); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-chop', args[1]); 12 | assert.equal('54x1+307+1', args[2]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const outpath = path.join(dir, 'chop.png'); 18 | m.write(outpath, function chop (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/circle.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | var m = gm 6 | .blur(8, 4) 7 | .stroke("red", 1) 8 | .fill("#ffffffbb") 9 | .drawCircle(125, 45, 120, 5); 10 | 11 | var args = m.args(); 12 | assert.equal('convert', args[0]); 13 | assert.equal('-blur', args[2]); 14 | assert.equal('8x4', args[3]); 15 | assert.equal('-strokewidth', args[4]); 16 | assert.equal(1, args[5]); 17 | assert.equal('-stroke', args[6]); 18 | assert.equal('red', args[7]); 19 | assert.equal('-fill', args[8]); 20 | assert.equal('#ffffffbb', args[9]); 21 | assert.equal('-draw', args[10]); 22 | assert.equal('circle 125,45 120,5', args[11]); 23 | 24 | if (!GM.integration) 25 | return finish(); 26 | 27 | const outpath = path.join(dir, 'circle.png'); 28 | m.write(outpath, function circle (err) { 29 | finish(err); 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /test/colorize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .colorize(80, 0, 30) 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-colorize', args[2]); 12 | assert.equal('80,0,30', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const outpath = path.join(dir, 'colorize.png'); 18 | m.write(outpath, function colorize (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/colors.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .colors(16); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-colors', args[2]); 12 | assert.equal(16, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const outpath = path.join(dir, 'colors.png'); 18 | m.write(outpath, function colors (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/comment.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .comment("%m:%f %wx%h"); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-comment', args[2]); 12 | assert.equal('"%m:%f %wx%h"', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const outpath = path.join(dir, 'comment.png'); 18 | m.write(outpath, function comment (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/compare.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | module.exports = function (gm, dir, finish) { 5 | // Same image 6 | const originalJPGFilePath = path.join(dir, 'original.jpg'); 7 | const originalPNGFilePath = path.join(dir, 'original.png'); 8 | 9 | gm.compare(originalJPGFilePath, originalPNGFilePath, function(err, same) { 10 | if (err) return finish(err); 11 | if (!same) return finish(new Error('Compare should be the same!')); 12 | 13 | // Compare almost similar images for which ImageMagick 14 | // returns a exponent-style floating point number 15 | const compare1Path = path.join(__dirname, 'fixtures', 'compare_1.png'); 16 | const compare2Path = path.join(__dirname, 'fixtures', 'compare_2.png'); 17 | 18 | gm.compare(compare1Path, compare2Path, function(err, same, diff) { 19 | if (err) return finish(err); 20 | if (!same) return finish(new Error('Compare should be the same!')); 21 | 22 | // Create a new noisy image 23 | const noisePath = path.join(dir, 'noise3.png'); 24 | gm.noise(0.3).write(noisePath, function (err) { 25 | if (err) return finish(err); 26 | 27 | const options = { 28 | highlightColor: 'yellow', 29 | file: path.join(dir, `compare-test-${Date.now()}.png`), 30 | tolerance: 0.001 31 | }; 32 | 33 | // Compare these images and write to a file. 34 | gm.compare(originalJPGFilePath, noisePath, options, function(err) { 35 | if (err) return finish(err); 36 | 37 | fs.access(options.file, fs.constants.F_OK, function(err) { 38 | if (err) { 39 | finish(new Error('Diff file does not exist.')); 40 | } else { 41 | fs.unlink(options.file, () => finish()); 42 | } 43 | }); 44 | }); 45 | }); 46 | }); 47 | }); 48 | }; -------------------------------------------------------------------------------- /test/composite.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | const sourcePath = path.join(__dirname, 'fixtures', 'compare_1.png'); 6 | gm.source = sourcePath; 7 | 8 | const faviconPath = path.join(__dirname, 'fixtures', 'favicon.png'); 9 | const a = gm.composite(faviconPath) 10 | 11 | const args = a.args(); 12 | assert.equal('composite', args[0]); 13 | assert.equal(faviconPath, args[1]); 14 | assert.equal(sourcePath, args[2]); 15 | 16 | if (!GM.integration) 17 | return finish(); 18 | 19 | const destPath = path.join(dir, 'composite.png'); 20 | a.write(destPath, function(err) { 21 | finish(err); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /test/contrast.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | const m = gm.contrast(2); 6 | 7 | const args = m.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('+contrast', args[2]); 10 | assert.equal('+contrast', args[3]); 11 | 12 | if (!GM.integration) return finish(); 13 | 14 | const destPath = path.join(dir, 'contrast.png'); 15 | 16 | m.write(destPath, function contrast (err) { 17 | finish(err); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /test/crop.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM, imageMagick) { 5 | const m = gm.crop(200, 155, 300, 0); 6 | 7 | const args = m.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('-crop', args[2]); 10 | assert.equal('200x155+300+0', args[3]); 11 | 12 | const imagePath = path.join(dir, 'image.png'); 13 | const m2 = GM(imagePath).options({ imageMagick }).crop(200, 155, 300, 0, true); 14 | 15 | const args2 = m2.args(); 16 | assert.equal('200x155+300+0%', args2[3]); 17 | 18 | if (!GM.integration) 19 | return finish(); 20 | 21 | const destPath = path.join(dir, 'crop.png'); 22 | m.write(destPath, function crop (err) { 23 | finish(err); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /test/cycle.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | const m = gm.cycle(4); 6 | 7 | const args = m.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('-cycle', args[2]); 10 | assert.equal(4, args[3]); 11 | 12 | if (!GM.integration) 13 | return finish(); 14 | 15 | const destPath = path.join(dir, 'cycle.png'); 16 | m.write(destPath, function cycle (err) { 17 | finish(err); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /test/densityGm.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM, imageMagick) { 5 | var NUMBER = 100; 6 | var NUMBER2 = 200; 7 | var g = gm.density(NUMBER, NUMBER2); 8 | var gArgs = g.args(); 9 | assert.equal('convert', gArgs[0]); 10 | assert.equal('-density', gArgs[1]); 11 | assert.equal(NUMBER + 'x' + NUMBER2, gArgs[2]); 12 | 13 | if (imageMagick) { 14 | // graphicsmagick does not support density with two arguments 15 | var imArgs = GM().options({imageMagick}).density(NUMBER).args(); 16 | assert.equal('convert', imArgs[0]); 17 | assert.equal('-density', imArgs[1]); 18 | assert.equal(NUMBER, imArgs[2]); 19 | } 20 | 21 | if (!GM.integration) return finish(); 22 | 23 | const destPath = path.join(dir, 'density.png'); 24 | g.write(destPath, function density (err) { 25 | finish(err); 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /test/despeckle.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | var m = gm.despeckle(); 6 | 7 | var args = m.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('-despeckle', args[2]); 10 | 11 | if (!GM.integration) 12 | return finish(); 13 | 14 | const destPath = path.join(dir, 'despeckle.png'); 15 | m.write(destPath, function despeckle (err) { 16 | finish(err); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/dispose.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (img, dir, finish, gm, imageMagick) { 5 | var EventEmitter = require('events').EventEmitter; 6 | EventEmitter.prototype._maxListeners = 100; 7 | 8 | assert.equal(undefined, gm.prototype._options.disposers); 9 | assert.equal(undefined, img._options.disposers); 10 | 11 | var emitter = new EventEmitter(); 12 | 13 | var disposer = { 14 | emitter: emitter, 15 | events: ['pleaseDispose', 'readyToDispose'] 16 | }; 17 | 18 | var g = gm('test').options({ disposers: [ disposer ], imageMagick }); 19 | assert.deepEqual([disposer], g._options.disposers); 20 | 21 | var sub = gm.subClass({ disposers: [ disposer ], imageMagick }); 22 | assert.deepEqual([disposer], sub.prototype._options.disposers); 23 | 24 | if (!gm.integration) { 25 | return finish(); 26 | } 27 | 28 | const photoPath = path.join(dir, 'photo.JPG'); 29 | const disposePath = path.join(dir, 'dispose.png'); 30 | 31 | gm(photoPath).options({ disposers: [ disposer ], imageMagick }) 32 | .thumb(1000, 1000, disposePath, function (err) { 33 | assert.ok(err, "Expecting a disposed error"); 34 | }); 35 | 36 | emitter.emit('pleaseDispose'); 37 | 38 | noDispose(); 39 | 40 | function noDispose() { 41 | gm(photoPath).options({ disposers: [ disposer ], imageMagick }) 42 | .thumb(1000, 1000, disposePath, function (err) { 43 | finish(err); 44 | }); 45 | emitter.emit('disposeOK'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/dither.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | if (gm._options.imageMagick) 6 | return finish(); 7 | 8 | var g = gm.monochrome().dither(); 9 | 10 | var args = g.args(); 11 | assert.equal('convert', args[0]); 12 | assert.equal('-monochrome', args[2]); 13 | assert.equal('-dither', args[3]); 14 | 15 | if (!GM.integration) 16 | return finish(); 17 | 18 | const destPath = path.join(dir, 'dither.png'); 19 | g.write(destPath, function dither (err) { 20 | finish(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /test/edge.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .edge(2); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-edge', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'edge.png'); 17 | m.write(destPath, function edge (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/ellipse.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("blue", 1) 9 | .drawEllipse(155, 80, 130, 50); 10 | 11 | var args = m.args(); 12 | assert.equal('convert', args[0]); 13 | assert.equal('-blur', args[2]); 14 | assert.equal('8x4', args[3]); 15 | assert.equal('-strokewidth', args[4]); 16 | assert.equal(1, args[5]); 17 | assert.equal('-stroke', args[6]); 18 | assert.equal('blue', args[7]); 19 | assert.equal('-draw', args[8]); 20 | assert.equal('ellipse 155,80 130,50 0,360', args[9]); 21 | 22 | if (!GM.integration) 23 | return finish(); 24 | 25 | const destPath = path.join(dir, 'ellipse.png'); 26 | m.write(destPath, function ellipse (err) { 27 | finish(err); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /test/emboss.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .emboss(2); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-emboss', args[2]); 12 | assert.equal(2, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'emboss.png'); 18 | m.write(destPath, function emboss (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/enhance.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .enhance(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-enhance', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'enhance.png'); 17 | m.write(destPath, function enhance (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/equalize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .equalize(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-equalize', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'equalize.png'); 17 | m.write(destPath, function equalize (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/extent.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .scale(200, 100) 8 | .extent(300,300) 9 | 10 | var args = m.args(); 11 | assert.equal('convert', args[0]); 12 | assert.equal('-scale', args[2]); 13 | assert.equal('200x100', args[3]); 14 | assert.equal('-extent', args[4]); 15 | assert.equal('300x300', args[5]); 16 | 17 | if (!GM.integration) 18 | return finish(); 19 | 20 | const destPath = path.join(dir, 'extent.png'); 21 | m.write(destPath, function resize (err) { 22 | finish(err); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /test/fixtures/compare_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/compare_1.png -------------------------------------------------------------------------------- /test/fixtures/compare_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/compare_2.png -------------------------------------------------------------------------------- /test/fixtures/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/favicon.png -------------------------------------------------------------------------------- /test/fixtures/iptc-multiple.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/iptc-multiple.jpg -------------------------------------------------------------------------------- /test/fixtures/iptc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/iptc.jpg -------------------------------------------------------------------------------- /test/fixtures/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/loading.gif -------------------------------------------------------------------------------- /test/fixtures/nyancat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/nyancat.gif -------------------------------------------------------------------------------- /test/fixtures/test.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aheckmann/gm/6e43846ef7e3a52c0dafd466c7d5920513322500/test/fixtures/test.ico -------------------------------------------------------------------------------- /test/flatten.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | // graphicsmagick considers PSD broken 6 | // http://www.graphicsmagick.org/NEWS.html#may-30-2016 7 | if (!imageMagick) { 8 | return finish(); 9 | } 10 | 11 | const layersPath = path.join(dir, 'layers.psd'); 12 | var m = gm(layersPath) 13 | .options({ imageMagick }) 14 | .flatten(); 15 | 16 | var args = m.args(); 17 | assert.equal('convert', args[0]); 18 | assert.equal('-flatten', args[2]); 19 | 20 | if (!gm.integration) 21 | return finish(); 22 | 23 | const destPath = path.join(dir, 'unlayered.jpg'); 24 | m.write(destPath, function (err) { 25 | finish(err); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /test/flip.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .flip(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-flip', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'flip.png'); 17 | m.write(destPath, function flip (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/flop.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .flop(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-flop', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'flop.png'); 17 | m.write(destPath, function flop (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/fromBuffer.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const fs = require('fs') 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | 7 | const original = path.join(dir, 'original.jpg'); 8 | const result = path.join(dir, 'fromBuffer.png'); 9 | 10 | var buf = fs.readFileSync(original); 11 | 12 | var m = gm(buf).options({imageMagick}).rotate('red', 30); 13 | 14 | var args = m.args(); 15 | assert.equal('convert', args[0]); 16 | assert.equal('-', args[1]); 17 | assert.equal('-background', args[2]); 18 | assert.equal('red', args[3]); 19 | assert.equal('-rotate', args[4]); 20 | assert.equal(30, args[5]); 21 | 22 | if (!gm.integration) 23 | return finish(); 24 | 25 | m.write(result, function crop (err) { 26 | if (err) return finish(err); 27 | 28 | // tolerance defaults to 0.4 29 | m.compare(original, result, function (err, equal) { 30 | if (err) return finish(err); 31 | assert.ok(equal); 32 | 33 | // accepts tolerance argument 34 | m.compare(original, result, 0.1, function (err, equal, equality, raw) { 35 | if (err) return finish(err); 36 | assert.ok(!equal); 37 | assert.ok(equality > 0.1); 38 | assert.ok(raw); 39 | finish(); 40 | }) 41 | }) 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /test/gamma.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .gamma(1.7, 2.3, 1.3); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-gamma', args[2]); 12 | assert.equal('1.7,2.3,1.3', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'gamma.png'); 18 | m.write(destPath, function gamma (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/geometry.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert') 3 | 4 | module.exports = function (_, __, finish, GM, imageMagick) { 5 | var a = GM("dummy").options({imageMagick}).geometry("asdf"); // Custom geometry command 6 | var args = a.args(); 7 | assert.equal('-geometry', args[2]); 8 | assert.equal('asdf', args[3]); 9 | 10 | var b = GM("dummy").options({imageMagick}).geometry("", 100); 11 | var args = b.args(); 12 | assert.equal('-geometry', args[2]); 13 | assert.equal('x100', args[3]); // Keep-aspect-ratio command 14 | 15 | return finish(); 16 | } 17 | -------------------------------------------------------------------------------- /test/getterColor.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | const destPath = path.join(dir, 'blue.gif'); 9 | gm(destPath).options({imageMagick}).color(function (err, color) { 10 | if (err) return finish(err); 11 | 12 | assert.equal(1, color) 13 | assert.equal(this.data.color, color) 14 | 15 | finish(); 16 | 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/getterDepth.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert') 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | if (!GM.integration) 6 | return finish(); 7 | 8 | gm 9 | .depth(function getterdepth (err, depth) { 10 | if (err) return finish(err); 11 | if (this._options.imageMagick) { 12 | assert.equal(16, depth); 13 | assert.equal(16, this.data.depth); 14 | } else { 15 | assert.equal(8, depth); 16 | assert.equal(8, this.data.depth); 17 | } 18 | finish(); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/getterFilesize.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert') 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | if (!GM.integration) 6 | return finish(); 7 | 8 | gm 9 | .filesize(function getterfilesize (err, size) { 10 | if (err) return finish(err); 11 | 12 | if (this._options.imageMagick) { 13 | assert.equal('7792B', size, size); 14 | } else { 15 | assert.ok(/7.6K[i]{0,1}/.test(size)); 16 | } 17 | 18 | assert.equal(size, this.data.Filesize) 19 | 20 | // make sure we are reading from the data cache and not 21 | // hitting the fs again. 22 | this.identify = function () { 23 | assert.ok(false, 'Did not read from cache'); 24 | } 25 | 26 | this.filesize(function (err, size) { 27 | if (err) return finish(err); 28 | 29 | if (this._options.imageMagick) { 30 | assert.equal('7792B', size, size); 31 | } else { 32 | assert.ok(/7.6K[i]{0,1}/.test(size)); 33 | } 34 | 35 | assert.equal(size, this.data.Filesize) 36 | finish(); 37 | }); 38 | 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /test/getterFormat.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | if (!GM.integration) 6 | return finish(); 7 | 8 | gm 9 | .format(function getterformat (err, format) { 10 | if (err) return finish(err); 11 | 12 | assert.equal(format, 'JPEG'); 13 | assert.equal(gm.data.format, 'JPEG'); 14 | 15 | finish(); 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /test/getterFormatGIF.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | const destPath = path.join(dir, 'original.gif'); 9 | gm(destPath).options({imageMagick}) 10 | .format(function (err, type) { 11 | if (err) return finish(err); 12 | 13 | assert.equal(type, 'GIF'); 14 | assert.equal(this.data.format, 'GIF'); 15 | 16 | finish(); 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /test/getterIdentify.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const os = require('os') 4 | 5 | var isLinux = os.platform() === 'linux' 6 | // Be more lax with the errors if we're on linux 7 | var errorFactor = isLinux ? 10 : 1.1 8 | 9 | module.exports = function (_, dir, finish, gm, imageMagick) { 10 | if (!gm.integration) 11 | return finish(); 12 | 13 | const photoPath = path.join(dir, 'photo.JPG'); 14 | var test = gm(photoPath).options({ imageMagick }); 15 | 16 | test.identify(function (err) { 17 | if (err) return finish(err); 18 | 19 | var d = this.data; 20 | 21 | if (imageMagick) { 22 | assert.equal(d.Orientation, 'TopLeft'); 23 | assert.equal(d['Geometry'], '430x488+0+0'); 24 | assert.equal(d['Print size'], '5.97222x6.77778'); 25 | assert.ok(d['Channel depth'].Red || d['Channel depth'].red); 26 | assert.ok(d['Channel depth'].Green || d['Channel depth'].green); 27 | assert.ok(/0\s+\(0\)/.test(d['Channel statistics'].Red.min)); 28 | 29 | var sd = d['Channel statistics'].Red['standard deviation'].split(' ') 30 | var sd1 = parseFloat(sd[0]) 31 | var sd2 = parseFloat(sd[1].slice(1, -1)) 32 | assert.ok(sd1 && Math.abs(sd1 - 71.7079) < .01 * errorFactor) 33 | assert.ok(sd2 && Math.abs(sd2 - 0.281208) < .001 * errorFactor) 34 | 35 | var imageStat = parseFloat(d['Image statistics'].Overall.kurtosis) 36 | assert.ok(imageStat); 37 | 38 | if (!isLinux) { 39 | // This is undefined in Linux 40 | assert.equal(d['Rendering intent'], 'Perceptual'); 41 | } 42 | assert.equal(d.Properties['exif:DateTimeDigitized'], '2011:07:01 11:23:16'); 43 | assert.equal(d.Format, 'JPEG (Joint Photographic Experts Group JFIF format)'); 44 | 45 | } else { 46 | assert.equal(d.Orientation, 'TopLeft'); 47 | assert.equal(d['JPEG-Quality'], 96); 48 | assert.ok(/(0.2812)/.test(d['Channel Statistics'].Red['Standard Deviation'])); 49 | 50 | var ex = d['Profile-EXIF']; 51 | assert.equal(ex.Make, 'Apple'); 52 | assert.equal(ex.Model, 'iPad 2'); 53 | assert.equal(ex['GPS Info'], 558); 54 | assert.equal(ex['GPS Longitude'], '80/1,4970/100,0/1'); 55 | assert.equal(ex['GPS Time Stamp'], '15/1,23/1,945/1'); 56 | assert.equal(d.Format, 'JPEG (Joint Photographic Experts Group JFIF format)'); 57 | assert.equal(d['Geometry'], '430x488'); 58 | } 59 | 60 | gif(function () { 61 | pattern(); 62 | }); 63 | }); 64 | 65 | function gif (callback) { 66 | const bluePath = path.join(dir, 'blue.gif'); 67 | var test = gm(bluePath).options({ imageMagick }); 68 | 69 | test.identify(function (err) { 70 | if (err) return finish(err); 71 | 72 | if (imageMagick) { 73 | if (!isLinux) { 74 | assert.equal(1, this.data.color); 75 | } 76 | 77 | assert.ok(/blue/.test(this.data.Colormap['0'])); 78 | assert.ok(/black/.test(this.data.Colormap['1'])); 79 | 80 | } else { 81 | if (!isLinux) { 82 | assert.equal(2, this.data.color); 83 | } 84 | 85 | var blueWorks = this.data.Colors['0'] == '( 0, 0,255)\t blue'; 86 | var blackWorks = this.data.Colors['1'] == '( 0, 0, 0)\t black'; 87 | 88 | if (!blueWorks) { 89 | blueWorks = this.data.Colors['1'] == '( 0, 0,255)\t blue'; 90 | blackWorks = this.data.Colors['0'] == '( 0, 0, 0)\t black'; 91 | } 92 | 93 | assert.ok(blueWorks); 94 | assert.ok(blackWorks); 95 | } 96 | 97 | callback(); 98 | }); 99 | } 100 | 101 | function pattern () { 102 | const bluePath = path.join(dir, 'blue.gif'); 103 | var test = gm(bluePath); 104 | var format = '%f: %m, %wx%h'; 105 | var value = 'blue.gif: GIF, 100x200'; 106 | 107 | test.options({ imageMagick }); 108 | 109 | test.identify(format, function (err, result) { 110 | if (err) return finish(err); 111 | 112 | assert.equal(result, value); 113 | 114 | test.identify({ 115 | format: format 116 | }, function (err, result) { 117 | if (err) return finish(err); 118 | 119 | assert.equal(result, value); 120 | 121 | finish(); 122 | }) 123 | }); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /test/getterIptc.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | const iptcPath = path.join(__dirname, 'fixtures', 'iptc.jpg'); 9 | var test = gm(iptcPath).options({imageMagick}) 10 | 11 | test.identify(function (err) { 12 | if (err) return finish(err); 13 | 14 | var d = this.data; 15 | 16 | if (imageMagick) { 17 | var iptc = d['Profiles'] && d['Profiles']['Profile-iptc']; 18 | assert.equal(iptc['Caption[2,120]'], 'Some caption with colon space: for example'); 19 | } 20 | 21 | finish(); 22 | }); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /test/getterMultipleIptc.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | const iptcPath = path.join(__dirname, 'fixtures', 'iptc-multiple.jpg'); 9 | var test = gm(iptcPath).options({imageMagick}) 10 | 11 | test.identify(function (err) { 12 | if (err) return finish(err); 13 | 14 | var d = this.data; 15 | 16 | if (imageMagick) { 17 | var iptc = d['Profiles'] && d['Profiles']['Profile-iptc']; 18 | var keywords = iptc['Keyword[2,25]']; 19 | assert(Array.isArray(keywords)); 20 | assert.equal(keywords.length, 5); 21 | 22 | // just make sure another value 23 | assert(! Array.isArray(iptc['Headline[2,105]'])); 24 | } 25 | 26 | finish(); 27 | }); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /test/getterRes.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert') 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | if (!GM.integration) 6 | return finish(); 7 | 8 | gm 9 | .res(function getterres (err, res) { 10 | if (err) return finish(err); 11 | if (gm._options.imageMagick) { 12 | assert.equal('72x72', res); 13 | } else { 14 | assert.equal('72x72 pixels/inch', res); 15 | } 16 | assert.equal(res, this.data.Resolution) 17 | finish(); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /test/getterSize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | sizeJPEG(function (err) { 9 | if (err) return finish(err); 10 | 11 | sizeGIF(function (err) { 12 | if (err) return finish(err); 13 | 14 | sizePNG(finish); 15 | }) 16 | }) 17 | 18 | function sizeJPEG(done) { 19 | const originalPath = path.join(dir, 'original.jpg'); 20 | gm(originalPath).options({imageMagick}).size(function gettersize (err, size) { 21 | if (err) return done(err); 22 | 23 | assert.equal(size.width, 460); 24 | assert.equal(size.height, 155); 25 | 26 | const identifyParseErrPath = path.join(dir, 'identifyParseErr.jpg'); 27 | gm(identifyParseErrPath).options({imageMagick}).size(done); 28 | }); 29 | } 30 | 31 | function sizeGIF(done) { 32 | const originalGifPath = path.join(dir, 'original.gif'); 33 | gm(originalGifPath).options({imageMagick}).size(function (err, size) { 34 | if (err) return done(err); 35 | 36 | assert.equal(size.width, 192) 37 | assert.equal(size.height, 56) 38 | 39 | done() 40 | }) 41 | } 42 | 43 | function sizePNG(done) { 44 | const originalPngPath = path.join(dir, 'original.png'); 45 | gm(originalPngPath).options({imageMagick}).size(function (err, size) { 46 | if (err) return done(err); 47 | 48 | assert.equal(size.width, 460) 49 | assert.equal(size.height, 155) 50 | 51 | done() 52 | }) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /test/gh-17.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | var m = gm 6 | .crop(200, 155, 300, 0) 7 | .resize(58, 50, '%'); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-crop', args[2]); 12 | assert.equal('200x155+300+0', args[3]); 13 | assert.equal('-resize', args[4]); 14 | assert.equal('58x50%', args[5]); 15 | 16 | if (!GM.integration) 17 | return finish(); 18 | 19 | const destPath = path.join(dir, 'cropresize.png'); 20 | m.write(destPath, function crop (err) { 21 | finish(err); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /test/gifFrame.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function (_, dir, finish, gm, imageMagick) { 4 | if (!gm.integration) 5 | return finish(); 6 | 7 | const originalGifPath = path.join(dir, 'original.gif[0]'); 8 | const gifFramePath = path.join(dir, 'gifFrame.jpg'); 9 | gm(originalGifPath).options({imageMagick}) 10 | .write(gifFramePath, function gifFrame (err){ 11 | finish(err); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /test/gifFrameIdentify.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | const originalGifPath = path.join(dir, 'original.gif[0]'); 6 | var m = gm(originalGifPath).options({imageMagick}); 7 | 8 | if (!gm.integration) 9 | return finish(); 10 | 11 | m.identify('%n', function (err, stdout) { 12 | if (err) return finish(err); 13 | 14 | assert.equal(parseInt(stdout.toString(), 10), 1); 15 | finish(); 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /test/gifFrameStream.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | const originalGifPath = path.join(dir, 'original.gif'); 7 | const readStream = fs.createReadStream(originalGifPath); 8 | const m = gm(readStream, "original.gif[0]").options({imageMagick}); 9 | 10 | var args = m.args(); 11 | assert.equal('convert', args[0]); 12 | assert.equal('-[0]', args[1]); 13 | 14 | if (!gm.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'gifFrameStream.jpg'); 18 | m.write(destPath, function gifFrame (err){ 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/gravity.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (img, dir, finish, gm) { 5 | var changed = gm('whatever.png').gravity("Souths") 6 | assert.equal(changed._out[1], 'NorthWest'); 7 | 8 | var m = img 9 | .scale(200, 100) 10 | .gravity("South") 11 | .extent(300,300); 12 | 13 | var args = m.args(); 14 | assert.equal('convert', args[0]); 15 | args= args.slice(2); 16 | assert.deepEqual(args, [ 17 | '-scale', 18 | '200x100', 19 | '-gravity', 20 | 'South', 21 | '-extent', 22 | '300x300', 23 | '-' ]) 24 | 25 | if (!gm.integration) 26 | return finish(); 27 | 28 | const destPath = path.join(dir, 'gravity.png'); 29 | m.write(destPath, function resize (err) { 30 | finish(err); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/implode.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .implode(0.8); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-implode', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'implode.png'); 17 | m.write(destPath, function implode (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | const cp = require('child_process'); 2 | const path = require('path'); 3 | const Async = require('async'); 4 | const dir = path.join(__dirname, '..', 'examples', 'imgs'); 5 | const gm = require('..'); 6 | const fs = require('fs'); 7 | const os = require('os'); 8 | 9 | const only = process.argv.slice(2); 10 | gm.integration = !! ~process.argv.indexOf('--integration'); 11 | if (gm.integration) only.shift(); 12 | 13 | let files = fs.readdirSync(__dirname).filter(filter); 14 | if (files.length === 0) { 15 | console.log('No tests found matching', only); 16 | } 17 | 18 | function filter (file) { 19 | if (!/\.js$/.test(file)) return false; 20 | if ('index.js' === file) return false; 21 | if (only.length && !~only.indexOf(file)) return false; 22 | 23 | var filename = path.join(__dirname, file); 24 | if (!fs.statSync(filename).isFile()) return false; 25 | return true; 26 | } 27 | 28 | const originalPathName = path.join(dir, 'original.jpg'); 29 | 30 | function test (imageMagick) { 31 | return gm(originalPathName).options({ imageMagick }); 32 | } 33 | 34 | function finish (filename) { 35 | return function (err) { 36 | if (err) { 37 | console.error('\n\nError occured with file: ' + filename); 38 | throw err; 39 | } 40 | } 41 | } 42 | 43 | function isGraphicsMagickInstalled() { 44 | try { 45 | cp.execSync('gm -version'); 46 | return true; 47 | } catch (_) { 48 | return false; 49 | } 50 | } 51 | 52 | function isConvertInstalled() { 53 | try { 54 | cp.execSync('convert -version'); 55 | return true; 56 | } catch (_) { 57 | return false; 58 | } 59 | } 60 | 61 | function isMagickInstalled() { 62 | try { 63 | cp.execSync('magick -version'); 64 | return true; 65 | } catch (_) { 66 | return false; 67 | } 68 | } 69 | 70 | const isWindows = () => os.platform() === 'win32'; 71 | 72 | var q = Async.queue(function (task, callback) { 73 | var filename = task.filename; 74 | var im = task.imagemagick; 75 | 76 | console.log(`Testing ${filename} ..`); 77 | require(filename)(test(im), dir, function (err) { 78 | finish(filename)(err); 79 | callback(); 80 | }, gm, im); 81 | }, 1); 82 | 83 | q.drain = function(){ 84 | console.log("\n\u001B[32mAll tests passed\u001B[0m"); 85 | }; 86 | 87 | files = files.map(function (file) { 88 | return path.join(__dirname, file); 89 | }); 90 | 91 | if (isGraphicsMagickInstalled()) { 92 | console.log('gm is installed'); 93 | files.forEach(function (filename) { 94 | q.push({ 95 | imagemagick: false, 96 | filename 97 | }) 98 | }); 99 | } 100 | 101 | if (!isWindows() && isConvertInstalled()) { 102 | // windows has a different convert binary 103 | 104 | console.log('convert is installed'); 105 | files.forEach(function (filename) { 106 | q.push({ 107 | imagemagick: true, 108 | filename 109 | }) 110 | }); 111 | } 112 | 113 | if (isMagickInstalled()) { 114 | console.log('magick is installed'); 115 | 116 | files.forEach(function (filename) { 117 | q.push({ 118 | imagemagick: '7+', 119 | filename 120 | }) 121 | }); 122 | } -------------------------------------------------------------------------------- /test/inputIs.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm) { 5 | var err; 6 | 7 | try { 8 | const blahPath = path.join('path', 'to', 'blah.gif') ; 9 | var gif = gm(blahPath); 10 | assert.equal(true, gif.inputIs('gif')); 11 | assert.equal(false, gif.inputIs('jpg')); 12 | assert.equal(false, gif.inputIs('crazy')); 13 | 14 | var png = gm('png.png'); 15 | assert.equal(true, png.inputIs('png')); 16 | assert.equal(false, png.inputIs('gif')); 17 | assert.equal(false, png.inputIs('tif')); 18 | 19 | const jpgPath = path.join('super', 'duper.jpeg') 20 | var jpg = gm(jpgPath); 21 | assert.equal(true, jpg.inputIs('jpg')); 22 | assert.equal(true, jpg.inputIs('jpeg')); 23 | assert.equal(false, jpg.inputIs('gif')); 24 | assert.equal(false, jpg.inputIs('tif')); 25 | assert.equal(false, jpg.inputIs('gif')); 26 | 27 | var unknown = gm('super.unknown'); 28 | assert.equal(true, unknown.inputIs('unknown')); 29 | assert.equal(true, unknown.inputIs('.unknown')); 30 | assert.equal(false, unknown.inputIs()); 31 | assert.equal(false, unknown.inputIs('')); 32 | assert.equal(false, unknown.inputIs('png')); 33 | assert.equal(false, unknown.inputIs('pngasdf')); 34 | } catch (e) { 35 | err = e; 36 | console.error(e.stack); 37 | } 38 | 39 | finish(err); 40 | } 41 | -------------------------------------------------------------------------------- /test/interlace.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .interlace(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-interlace', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'interlace.png'); 17 | m.write(destPath, function interlace (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/label.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .label("%m:%f %wx%h") 8 | 9 | var args= m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-label', args[2]); 12 | assert.equal('"%m:%f %wx%h"', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'label.png'); 18 | m.write(destPath, function label (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/limit.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .limit("memory", "32MB") 8 | .limit("map", "64MB") 9 | 10 | var args = m.args() 11 | assert.equal('convert', args[0]); 12 | assert.equal('-limit', args[2]); 13 | assert.equal('memory', args[3]); 14 | assert.equal('32MB', args[4]); 15 | assert.equal('-limit', args[5]); 16 | assert.equal('map', args[6]); 17 | assert.equal('64MB', args[7]); 18 | 19 | if (!GM.integration) 20 | return finish(); 21 | 22 | const destPath = path.join(dir, 'limit.png'); 23 | m.write(destPath, function limit (err) { 24 | finish(err); 25 | }); 26 | } 27 | -------------------------------------------------------------------------------- /test/line.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("red", 3) 9 | .drawLine(20, 10, 50, 40); 10 | 11 | var args = m.args(); 12 | assert.equal('-blur', args[2]); 13 | assert.equal('8x4', args[3]); 14 | assert.equal('-strokewidth', args[4]); 15 | assert.equal(3, args[5]); 16 | assert.equal('-stroke', args[6]); 17 | assert.equal('red', args[7]); 18 | assert.equal('-draw', args[8]); 19 | assert.equal('line 20,10 50,40', args[9]); 20 | 21 | if (!GM.integration) 22 | return finish(); 23 | 24 | const destPath = path.join(dir, 'line.png'); 25 | m.write(destPath, function line (err) { 26 | finish(err); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /test/lower.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .lower(10, 14); 8 | 9 | var args= m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('+raise', args[2]); 12 | assert.equal('10x14', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'lower.png'); 18 | m.write(destPath, function lower (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/magnify.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | if (gm._options.imageMagick) 7 | return finish(); 8 | 9 | var m = gm 10 | .magnify(); 11 | 12 | var args = m.args(); 13 | assert.equal('convert', args[0]); 14 | assert.equal('-magnify', args[1]); 15 | assert.equal(4, args.length); 16 | 17 | if (!GM.integration) 18 | return finish(); 19 | 20 | const destPath = path.join(dir, 'magnify.png'); 21 | m.write(destPath, function magnify (err) { 22 | finish(err); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /test/median.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .median(4); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-median', args[2]); 12 | assert.equal(4, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'median.png'); 18 | m.write(destPath, function media (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/minify.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | if (gm._options.imageMagick) return finish(); 6 | 7 | var m = gm 8 | .minify(); 9 | 10 | var args = m.args(); 11 | assert.equal('convert', args[0]); 12 | assert.equal('-minify', args[1]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'minify.png'); 18 | m.write(destPath, function minify (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/minifyIM.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | var m = gm.minify(); 6 | 7 | var args = m.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('-minify', args[1]); 10 | 11 | if(gm._options.imageMagick) { 12 | assert.throws( 13 | function() { 14 | const destPath = path.join(dir, 'minify.png'); 15 | m.write(destPath, function minify (err) { throw err;}) 16 | }, 17 | Error 18 | ); 19 | } 20 | return finish(); 21 | 22 | } -------------------------------------------------------------------------------- /test/modulate.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .modulate(120, 100, 80); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-modulate', args[2]); 12 | assert.equal('120,100,80', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'modulate.png'); 18 | m.write(destPath, function modulate (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/monochrome.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .monochrome(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-monochrome', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'monochrome.png'); 17 | m.write(destPath, function monochrome (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/montage.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | const fixturesPath = path.join(__dirname, 'fixtures'); 6 | const srcPath = path.join(fixturesPath, 'compare_1.png'); 7 | 8 | gm.source = srcPath; 9 | const faviconPath = path.join(fixturesPath, 'favicon.png'); 10 | var a = gm.montage(faviconPath); 11 | 12 | var args = a.args(); 13 | assert.equal('montage', args[0]); 14 | assert.equal(faviconPath, args[1]); 15 | assert.equal(srcPath, args[2]); 16 | 17 | if (!GM.integration) 18 | return finish(); 19 | 20 | const destPath = path.join(dir, 'montage.png'); 21 | a.write(destPath, function(err) { 22 | finish(err); 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /test/morph-more.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function (gm, dir, finish, GM) { 4 | 5 | if (gm._options.imageMagick) return finish(); 6 | 7 | if (!GM.integration) 8 | return finish(); 9 | 10 | const morpherPath = path.join(dir, 'morpher.jpg'); 11 | const originalPath = path.join(dir, 'original.png'); 12 | const morphedPath = path.join(dir, 'morphed2.jpg'); 13 | 14 | gm 15 | .morph([morpherPath, originalPath], morphedPath, function morph (err) { 16 | finish(err); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/morph.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function (gm, dir, finish, GM) { 4 | 5 | if (gm._options.imageMagick) return finish(); 6 | 7 | if (!GM.integration) 8 | return finish(); 9 | 10 | const morpherPath = path.join(dir, 'morpher.jpg'); 11 | const morphedPath = path.join(dir, 'morphed.jpg'); 12 | 13 | gm.morph(morpherPath, morphedPath, function morph (err) { 14 | finish(err); 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /test/negative.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = GM('temp.jpg').negative(true); 7 | var args = m.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('+negate', args[2]); 10 | 11 | m = gm.negative(); 12 | args = m.args(); 13 | assert.equal('convert', args[0]); 14 | assert.equal('-negate', args[2]); 15 | 16 | if (!GM.integration) 17 | return finish(); 18 | 19 | const destPath = path.join(dir, 'negative.png'); 20 | m.write(destPath, function negative (err) { 21 | finish(err); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /test/new.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | 6 | var m = gm(525, 110, "#00ff55aa") 7 | .options({imageMagick}) 8 | .fontSize(68) 9 | .stroke("#efe", 2) 10 | .fill("#555") 11 | .drawText(20, 72, "graphics") 12 | .fill("#fa0") 13 | .drawText(274, 72, " magick"); 14 | 15 | var args = m.args(); 16 | assert.deepEqual(args, [ 17 | 'convert', 18 | '-size', 19 | '525x110', 20 | 'xc:#00ff55aa', 21 | '-pointsize', 22 | 68, 23 | '-strokewidth', 24 | 2, 25 | '-stroke', 26 | '#efe', 27 | '-fill', 28 | '#555', 29 | '-draw', 30 | 'text 20,72 "graphics"', 31 | '-fill', 32 | '#fa0', 33 | '-draw', 34 | 'text 274,72 "magick"', 35 | '-' 36 | ]) 37 | 38 | if (!gm.integration) 39 | return finish(); 40 | 41 | const destPath = path.join(dir, 'new.png'); 42 | m.write(destPath, function New (err){ 43 | finish(err); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /test/newImage.js: -------------------------------------------------------------------------------- 1 | // https://github.com/aheckmann/gm/issues/127 2 | 3 | const path = require('path'); 4 | const fs = require('fs') 5 | 6 | module.exports = function (_, dir, finish, gm, imageMagick) { 7 | if (!gm.integration) 8 | return finish(); 9 | 10 | const dest1Path = path.join(dir, 'ignore.me.png'); 11 | createImage().write(dest1Path, function (err) { 12 | if (err) return finish(err); 13 | 14 | createImage().stream(function (err, stdout) { 15 | if (err) return finish(err); 16 | 17 | const dest2Path = path.join(dir, 'ignore.me.2.png'); 18 | stdout.pipe(fs.createWriteStream(dest2Path)) 19 | 20 | stdout.on('error', finish) 21 | stdout.on('end', finish) 22 | }) 23 | }) 24 | 25 | function createImage() { 26 | return gm(70, 30, '#000') 27 | .options({imageMagick}) 28 | .font("arial", 20) 29 | .stroke("#fff", 2) 30 | .fill("#888") 31 | .drawText(10, 22, 'Some text') 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/noise1.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .noise(0.3); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-noise', args[2]); 12 | assert.equal(0.3, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'noise1.png'); 18 | m.write(destPath, function noise1 (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/noise2.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .noise('laplacian'); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('+noise', args[2]); 12 | assert.equal('laplacian', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | 18 | const destPath = path.join(dir, 'noise2.png'); 19 | m.write(destPath, function noise2 (err) { 20 | finish(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /test/options.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | const checkCmd = (cmd, imageMagick) => { 6 | switch (imageMagick) { 7 | case true: 8 | assert.ok(/^convert /.test(cmd)); 9 | break; 10 | case '7+': 11 | assert.ok(/^magick "convert" /.test(cmd)); 12 | break; 13 | default: 14 | assert.ok(/^gm "convert" /.test(cmd)); 15 | break; 16 | } 17 | } 18 | 19 | module.exports = function (_, dir, finish, gm, imageMagick) { 20 | 21 | var sub = gm.subClass({ subclassed: true }); 22 | var s = sub('test').options({ setWithMethod: 2 }); 23 | var g = gm('test').options({ hellowwww: 'there' }); 24 | 25 | assert.equal(2, s._options.setWithMethod); 26 | assert.equal(true, s._options.subclassed); 27 | assert.equal('there', g._options.hellowwww); 28 | assert.equal(undefined, g._options.setWithMethod); 29 | assert.equal(undefined, s._options.hellowwww); 30 | assert.equal(undefined, g._options.subclassed); 31 | 32 | /// subclass options 33 | var s2 = sub('another'); 34 | assert.equal(true, s2._options.subclassed); 35 | assert.equal(undefined, s2._options.setWithMethod); 36 | 37 | if (!gm.integration) 38 | return finish(); 39 | 40 | // test commands 41 | // test with subclass 42 | 43 | const photoPath = path.join(dir, 'photo.JPG'); 44 | const writeFile = path.join(dir, `options${Math.random()}.png`); 45 | const instance = gm.subClass({ imageMagick }); 46 | 47 | instance(photoPath) 48 | .negative() 49 | .write(writeFile, function (err, _1, _2, cmd) { 50 | if (err) return finish(err); 51 | 52 | checkCmd(cmd, imageMagick); 53 | 54 | fs.stat(writeFile, function (err) { 55 | if (err) return finish(new Error('did not write file')); 56 | 57 | try { 58 | fs.unlinkSync(writeFile); 59 | } catch (e) {} 60 | 61 | /// inline options 62 | gm(photoPath) 63 | .negative() 64 | .options({ imageMagick }) 65 | .write(writeFile, function (err, _1, _2, cmd) { 66 | if (err) return finish(err); 67 | 68 | checkCmd(cmd, imageMagick); 69 | 70 | fs.stat(writeFile, function (err) { 71 | if (err) return finish(new Error('did not write 2nd file')); 72 | try { 73 | fs.unlinkSync(writeFile); 74 | } catch (e) {} 75 | finish(); 76 | }); 77 | }); 78 | }); 79 | }); 80 | } 81 | -------------------------------------------------------------------------------- /test/paint.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .paint(2); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-paint', args[2]); 12 | assert.equal(2, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'paint.png'); 18 | m.write(destPath, function paint (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/polygon.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("red", 3) 9 | .fill("#ffffffbb") 10 | .drawPolygon([60, 10], [183, 73], [185, 13], [167, 35], [165, 17], [163, 19]); 11 | 12 | var args = m.args(); 13 | assert.equal('convert', args[0]); 14 | args = args.slice(2); 15 | assert.deepEqual(args, [ 16 | '-blur', 17 | '8x4', 18 | '-strokewidth', 19 | 3, 20 | '-stroke', 21 | 'red', 22 | '-fill', 23 | '#ffffffbb', 24 | '-draw', 25 | 'polygon 60,10,183,73,185,13,167,35,165,17,163,19', 26 | '-' 27 | ]) 28 | 29 | if (!GM.integration) 30 | return finish(); 31 | 32 | const destPath = path.join(dir, 'polygon.png'); 33 | m.write(destPath, function polygon (err) { 34 | finish(err); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /test/polyline.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("red", 3) 9 | .fill("#ffffffbb") 10 | .drawPolyline([40, 10], [143, 153], [185, 53], [147, 15], [145, 17], [43, 19]); 11 | 12 | var args = m.args(); 13 | assert.equal('convert', args[0]); 14 | args = args.slice(2); 15 | assert.deepEqual(args, [ 16 | '-blur', 17 | '8x4', 18 | '-strokewidth', 19 | 3, 20 | '-stroke', 21 | 'red', 22 | '-fill', 23 | '#ffffffbb', 24 | '-draw', 25 | 'polyline 40,10,143,153,185,53,147,15,145,17,43,19', 26 | '-' 27 | ]) 28 | 29 | if (!GM.integration) 30 | return finish(); 31 | 32 | const destPath = path.join(dir, 'polyline.png'); 33 | m.write(destPath, function polyline (err) { 34 | finish(err); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /test/quality.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .quality(5); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-quality', args[1]); 12 | assert.equal(5, args[2]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'quality.png'); 18 | m.write(destPath, function quality (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/raise.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .raise(10,14); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-raise', args[2]); 12 | assert.equal('10x14', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'raise.png'); 18 | m.write(destPath, function raise (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/rectangle.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .stroke("red", 3) 9 | .fill("#ffffffbb") 10 | .drawRectangle(40, 10, 251, 120) 11 | .drawRectangle(160, 10, 270, 220, 3); 12 | 13 | var args = m.args(); 14 | assert.equal('convert', args[0]); 15 | args = args.slice(2); 16 | assert.deepEqual(args, [ 17 | '-blur', 18 | '8x4', 19 | '-strokewidth', 20 | 3, 21 | '-stroke', 22 | 'red', 23 | '-fill', 24 | '#ffffffbb', 25 | '-draw', 26 | 'rectangle 40,10 251,120 ', 27 | '-draw', 28 | 'roundRectangle 160,10 270,220 3,3', 29 | '-' 30 | ]) 31 | 32 | if (!GM.integration) 33 | return finish(); 34 | 35 | const destPath = path.join(dir, 'rectangle.png'); 36 | m.write(destPath, function rectangle (err) { 37 | finish(err); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /test/region.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .region(130, 170, 307, 00); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-region', args[2]); 12 | assert.equal('130x170+307+0', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'region.png'); 18 | m.write(destPath, function region (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/repagePlus.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .repage('+'); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('+repage', args[2]); 12 | 13 | if (!GM.integration) 14 | return finish(); 15 | 16 | const destPath = path.join(dir, 'repage.png'); 17 | m.write(destPath, function blur (err) { 18 | finish(err); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/resample.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .resample(420, 120); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-resample', args[2]); 12 | assert.equal('420x120', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'resample.png'); 18 | m.write(destPath, function resample (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/resize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM, imageMagick) { 5 | 6 | var a = GM('img.png').options({imageMagick}).resize(10); 7 | var args = a.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('-resize', args[2]); 10 | if (imageMagick) { 11 | assert.equal('10', args[3]); 12 | } else { 13 | assert.equal('10x', args[3]); 14 | } 15 | 16 | var a = GM('img.png').options({imageMagick}).resize(10, 20); 17 | var args = a.args(); 18 | assert.equal('convert', args[0]); 19 | assert.equal('-resize', args[2]); 20 | assert.equal('10x20', args[3]); 21 | 22 | var a = GM('img.png').options({imageMagick}).resize(10, false, '%'); 23 | var args = a.args(); 24 | assert.equal('convert', args[0]); 25 | assert.equal('-resize', args[2]); 26 | if (imageMagick) { 27 | assert.equal('10%', args[3]); 28 | } else { 29 | assert.equal('10x%', args[3]); 30 | } 31 | 32 | var a = GM('img.png').options({imageMagick}).resize('10%'); 33 | var args = a.args(); 34 | assert.equal('convert', args[0]); 35 | assert.equal('-resize', args[2]); 36 | if (imageMagick) { 37 | assert.equal('10%', args[3]); 38 | } else { 39 | assert.equal('10%x', args[3]); 40 | } 41 | 42 | var m = gm.options({imageMagick}).resize(58, 50, '%'); 43 | var args= m.args(); 44 | assert.equal('convert', args[0]); 45 | assert.equal('-resize', args[2]); 46 | assert.equal('58x50%', args[3]); 47 | 48 | if (!GM.integration) 49 | return finish(); 50 | 51 | const destPath = path.join(dir, 'resize.png'); 52 | m.write(destPath, function resize (err) { 53 | finish(err); 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /test/resizeAndAutoOrientFromBuffer.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const fs = require('fs') 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | 7 | const original = path.join(dir, 'orientation', 'Portrait_7.jpg'); 8 | const result = path.join(dir, 'resizeAutoOrientFromBuffer.png'); 9 | 10 | var buf = fs.readFileSync(original); 11 | 12 | var m = gm(buf, 'resizefrombuffer.jpg') 13 | .options({imageMagick}) 14 | .autoOrient() 15 | .resize('20%') 16 | 17 | const expectedArgs = imageMagick ? 18 | ['convert', '-', '-auto-orient', '-resize', '20%', '-'] : 19 | ['convert', '-', '-resize', '20%x', '-']; 20 | 21 | assert.deepEqual(m.args(), expectedArgs); 22 | 23 | if (!gm.integration) 24 | return finish(); 25 | 26 | size(original, imageMagick, function (err, origSize) { 27 | if (err) return finish(err); 28 | 29 | m 30 | .write(result, function resizeFromBuffer (err) { 31 | if (err) return finish(err); 32 | 33 | size(result, imageMagick, function (err, newSize) { 34 | if (err) return finish(err); 35 | assert.ok(origSize.width / 2 >= newSize.width); 36 | assert.ok(origSize.height / 2 >= newSize.height); 37 | finish(); 38 | }); 39 | }); 40 | }); 41 | 42 | 43 | function size (file, imageMagick, cb) { 44 | gm(file).options({imageMagick}).identify(function (err, data) { 45 | if (err) return cb(err); 46 | cb(err, data.size); 47 | }); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/resizeBuffer.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const fs = require('fs') 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | 7 | var original = path.join(dir, 'original.jpg'); 8 | var result = path.join(dir, 'resizeFromBuffer.png'); 9 | 10 | var buf = fs.readFileSync(original); 11 | 12 | var m = gm(buf, 'resizefrombuffer.jpg') 13 | .options({imageMagick}) 14 | .resize('48%') 15 | 16 | var args = m.args(); 17 | assert.equal('convert', args[0]); 18 | assert.equal('-', args[1]); 19 | assert.equal('-resize', args[2]); 20 | if (m._options.imageMagick) { 21 | assert.equal('48%', args[3]); 22 | } else { 23 | assert.equal('48%x', args[3]); 24 | } 25 | 26 | if (!gm.integration) 27 | return finish(); 28 | 29 | size(original, imageMagick, function (err, origSize) { 30 | if (err) return finish(err); 31 | 32 | m 33 | .write(result, function resizeFromBuffer (err) { 34 | if (err) return finish(err); 35 | 36 | size(result, imageMagick, function (err, newSize) { 37 | if (err) return finish(err); 38 | assert.ok(origSize.width / 2 >= newSize.width); 39 | assert.ok(origSize.height / 2 >= newSize.height); 40 | finish(); 41 | }); 42 | }); 43 | }); 44 | 45 | 46 | function size (file, imageMagick, cb) { 47 | gm(file).options({imageMagick}).identify(function (err, data) { 48 | if (err) return cb(err); 49 | cb(err, data.size); 50 | }); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /test/resizeWrong.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = function (_, dir, finish, gm, imageMagick) { 4 | if (!gm.integration) 5 | return finish(); 6 | 7 | const original = path.join(dir, 'original.png'); 8 | const resized = path.join(dir, 'resize'); 9 | var widths = [300, 700, 400, 800, 200], i, cb; 10 | var resizeExact = function (width, index) { 11 | var name = resized + index + '.png'; 12 | 13 | if (index == widths.length) { 14 | return finish(); 15 | } else { 16 | index++; 17 | } 18 | gm(original) 19 | .options({imageMagick}) 20 | .resizeExact(width) 21 | .write(name, function(err){ 22 | if (err) return finish(err); 23 | 24 | gm(name).options({imageMagick}) 25 | .size(function (err, size) { 26 | if (err) return finish(err); 27 | if (size.width !== width) { 28 | return finish("Wrong resizing on requested:" + width + ", resized:" + size.width); 29 | } 30 | 31 | if (cb) return cb(); 32 | resizeExact(widths[index], index); 33 | }); 34 | }); 35 | }; 36 | 37 | resizeExact(widths[0], 0); 38 | } -------------------------------------------------------------------------------- /test/roll.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .roll(40,-100); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-roll', args[2]); 12 | assert.equal('+40-100', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'roll.png'); 18 | m.write(destPath, function roll (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/rotate.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .rotate('red', -40); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-background', args[2]); 12 | assert.equal('red', args[3]); 13 | assert.equal('-rotate', args[4]); 14 | assert.equal(-40, args[5]); 15 | 16 | if (!GM.integration) 17 | return finish(); 18 | 19 | const destPath = path.join(dir, 'rotate.png'); 20 | m.write(destPath, function rotate (err, _0, _1, cmd) { 21 | assert.ok(/"-rotate" "-40"/.test(cmd)); 22 | 23 | m 24 | .rotate('red', 0) 25 | .write(destPath, function rotate (err, _0, _1, cmd) { 26 | assert.ok(!/"-rotate" "-40"/.test(cmd)); 27 | assert.ok(/"-rotate" "0"/.test(cmd)); 28 | finish(err); 29 | }); 30 | 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/scale.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM, imageMagick) { 5 | 6 | var a = GM('img.png').options({imageMagick}).scale(100); 7 | var args = a.args(); 8 | assert.equal('convert', args[0]); 9 | assert.equal('-scale', args[2]); 10 | if (a._options.imageMagick) { 11 | assert.equal('100', args[3]); 12 | } else { 13 | assert.equal('100x', args[3]); 14 | } 15 | 16 | var a = GM('img.png').options({imageMagick}).scale(100, 200, '%'); 17 | var args = a.args(); 18 | assert.equal('convert', args[0]); 19 | assert.equal('-scale', args[2]); 20 | assert.equal('100x200%', args[3]); 21 | 22 | var a = GM('img.png').options({imageMagick}).scale(100, '200%'); 23 | var args = a.args(); 24 | assert.equal('convert', args[0]); 25 | assert.equal('-scale', args[2]); 26 | assert.equal('100x200%', args[3]); 27 | 28 | var m = gm.options({imageMagick}).scale(100, 100); 29 | var args = m.args(); 30 | assert.equal('convert', args[0]); 31 | assert.equal('-scale', args[2]); 32 | assert.equal('100x100', args[3]); 33 | 34 | if (!GM.integration) 35 | return finish(); 36 | 37 | const destPath = path.join(dir, 'scale.png'); 38 | m.write(destPath, function scale (err) { 39 | finish(err); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /test/selectFrame.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | const gifPath = path.join(dir, 'original.gif[0]'); 6 | var m = gm(gifPath); 7 | 8 | if (!gm.integration) 9 | return finish(); 10 | 11 | m.options({imageMagick}).identify('%#', function (err, hash1) { 12 | if (err) return finish(err); 13 | 14 | m.selectFrame(2).identify('%#', function (err, hash2) { 15 | if (err) return finish(err); 16 | 17 | assert.ok(hash1.toString().trim() !== hash2.toString().trim()) 18 | finish(); 19 | }) 20 | }) 21 | } -------------------------------------------------------------------------------- /test/sepia.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .sepia(); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-modulate', args[2]); 12 | assert.equal('115,0,100', args[3]); 13 | assert.equal('-colorize', args[4]); 14 | assert.equal('7,21,50', args[5]); 15 | 16 | if (!GM.integration) 17 | return finish(); 18 | 19 | const destPath = path.join(dir, 'sepia.png'); 20 | m.write(destPath, function sepia (err) { 21 | finish(err); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /test/setFormat.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .setFormat('png'); 8 | 9 | assert.equal('png', m._outputFormat); 10 | 11 | if (!GM.integration) 12 | return finish(); 13 | 14 | const destPath = path.join(dir, 'setFormat.png'); 15 | m.write(destPath, function setformat (err) { 16 | finish(err); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/sharpen.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .sharpen(19, 10); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-sharpen', args[2]); 12 | assert.equal('19x10', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'sharpen.png'); 18 | m.write(destPath, function sharpen (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/solarize.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .solarize(68.5); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-solarize', args[2]); 12 | assert.equal('68.5%', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'solarize.png'); 18 | m.write(destPath, function solarize (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/spread.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .spread(12); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-spread', args[2]); 12 | assert.equal(12, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'spread.png'); 18 | m.write(destPath, function spread (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/streamIn.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | 7 | const originalPath = path.join(dir, 'original.jpg'); 8 | const stream = fs.createReadStream(originalPath); 9 | const m = gm(stream, "original.jpg").options({imageMagick}); 10 | 11 | assert.equal(stream, m.sourceStream); 12 | assert.equal('original.jpg', m.source); 13 | 14 | if (!gm.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'streamIn.png'); 18 | m.write(destPath, function streamIn (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/streamInGetter.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | if (!gm.integration) 6 | return finish(); 7 | 8 | const originalPath = path.join(dir, 'original.jpg'); 9 | gm(fs.createReadStream(originalPath)) 10 | .options({imageMagick}) 11 | .size({bufferStream: true}, function (err, size) { 12 | const destPath = path.join(dir, 'streamInGetter.png'); 13 | this.write(destPath, function streamInGetter (err){ 14 | finish(err); 15 | }); 16 | }); 17 | } -------------------------------------------------------------------------------- /test/streamInOut.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | 6 | if (!gm.integration) 7 | return finish(); 8 | 9 | const originalPath = path.join(dir, 'original.jpg'); 10 | gm(fs.createReadStream(originalPath), "original.jpg") 11 | .options({imageMagick}) 12 | .stream(function streamOut (err, stdout, stderr) { 13 | if (err) return finish(err); 14 | const destPath = path.join(dir, 'streamInOut.jpg'); 15 | stdout.pipe(fs.createWriteStream(destPath)); 16 | stdout.on('error', finish); 17 | stdout.on('close', finish); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /test/streamOut.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | if (!GM.integration) 7 | return finish(); 8 | 9 | withCallback(function (err) { 10 | if (err) return finish(err); 11 | 12 | withoutCallback(finish); 13 | }); 14 | 15 | function withCallback(done) { 16 | gm 17 | .stream(function streamOut (err, stdout, stderr) { 18 | if (err) return done(err); 19 | const destPath = path.join(dir, 'streamOut.png'); 20 | stdout.pipe(fs.createWriteStream(destPath)); 21 | stdout.on('error', done); 22 | stdout.on('close', done); 23 | }); 24 | } 25 | 26 | function withoutCallback(done) { 27 | var stream = gm.stream() 28 | stream.on('error', done) 29 | const destPath = path.join(dir, 'streamOut2.png'); 30 | stream.pipe(fs.createWriteStream(destPath)) 31 | stream.on('end', done) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/streamOutFormat.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert') 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | 5 | module.exports = function (gm, dir, finish, GM, imageMagick) { 6 | if (!GM.integration) 7 | return finish(); 8 | 9 | withCallback(function (err) { 10 | if (err) return finish(err); 11 | 12 | withoutCallback(function (err) { 13 | if (err) return finish(err); 14 | 15 | checkOutputFormat(finish); 16 | }); 17 | }); 18 | 19 | function withCallback(done) { 20 | gm 21 | .stream('PNG', function streamOut (err, stdout, stderr) { 22 | if (err) return done(err); 23 | const destPath = path.join(dir, 'streamOutFormat.png'); 24 | stdout.pipe(fs.createWriteStream(destPath)); 25 | stdout.on('error', done); 26 | stdout.on('close', done); 27 | }); 28 | } 29 | 30 | function withoutCallback(done) { 31 | var stream = gm.stream('PNG') 32 | stream.on('error', done) 33 | const destPath = path.join(dir, 'streamOutFormat2.png'); 34 | stream.pipe(fs.createWriteStream(destPath)) 35 | stream.on('end', done) 36 | } 37 | 38 | function checkOutputFormat(done) { 39 | var stream = gm.stream('PNG') 40 | stream.on('error', done) 41 | GM(stream).options({imageMagick}).format(function (err, value) { 42 | if (err) 43 | return done(err) 44 | 45 | assert.equal(value.toLowerCase(), 'png') 46 | done() 47 | }) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /test/strip.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | if (!gm._options.imageMagick) return finish(); 7 | 8 | var m = gm 9 | .strip(); 10 | 11 | var args = m.args(); 12 | assert.equal('convert', args[0]); 13 | assert.equal('-strip', args[2]); 14 | 15 | if (!GM.integration) 16 | return finish(); 17 | 18 | const destPath = path.join(dir, 'strip.png'); 19 | m.write(destPath, function strip (err) { 20 | finish(err); 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /test/subclass.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (_, dir, finish, gm, imageMagick) { 5 | assert.equal('gm', gm('test').constructor.name); 6 | assert.equal(undefined, gm.prototype._options.imageMagick); 7 | 8 | var sub = gm.subClass({ imageMagick: true }); 9 | 10 | assert.equal('gm', sub('test').constructor.name); 11 | assert.equal(true, sub.prototype._options.imageMagick); 12 | assert.equal(undefined, gm.prototype._options.imageMagick); 13 | 14 | var s = sub('test'); 15 | assert.equal(true, s._options.imageMagick); 16 | 17 | var g = gm('test'); 18 | assert.equal(undefined, g._options.imageMagick); 19 | 20 | var imageMagick7 = gm.subClass({ imageMagick: '7+'}); 21 | assert.equal('7+', imageMagick7.prototype._options.imageMagick); 22 | 23 | if (!gm.integration) 24 | return finish(); 25 | 26 | const sourcePath = path.join(dir, 'photo.JPG'); 27 | const destPath = path.join(dir, 'subclass.png'); 28 | const m = gm.subClass({ imageMagick }); 29 | m(sourcePath) 30 | .thumb(50, 80, destPath, function subthumb (err) { 31 | if (err) return finish(err); 32 | finish(); 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /test/swirl.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .swirl(129); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-swirl', args[2]); 12 | assert.equal(129, args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'swirl.png'); 18 | m.write(destPath, function swirl (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/text.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .blur(8, 4) 8 | .fontSize(68) 9 | .stroke("#efe", 2) 10 | .fill("#888") 11 | .drawText(-20, 98, "graphics magick"); 12 | 13 | var args = m.args(); 14 | assert.equal('convert', args[0]); 15 | args = args.slice(2) 16 | assert.deepEqual(args, [ 17 | '-blur', 18 | '8x4', 19 | '-pointsize', 20 | 68, 21 | '-strokewidth', 22 | 2, 23 | '-stroke', 24 | '#efe', 25 | '-fill', 26 | '#888', 27 | '-draw', 28 | 'text -20,98 "graphics magick"', 29 | '-' 30 | ]); 31 | 32 | if (!GM.integration) 33 | return finish(); 34 | 35 | const destPath = path.join(dir, 'text.png'); 36 | m.write(destPath, function text (err) { 37 | finish(err); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /test/thumb.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | if (!GM.integration) 7 | return finish(); 8 | 9 | const destPath = path.join(dir, 'thumb.png'); 10 | gm.thumb(150, 40, destPath, function thumb (err) { 11 | finish(err); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /test/thumbnail.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | var m = gm 7 | .thumbnail(200, 201); 8 | 9 | var args = m.args(); 10 | assert.equal('convert', args[0]); 11 | assert.equal('-thumbnail', args[2]); 12 | assert.equal('200x201', args[3]); 13 | 14 | if (!GM.integration) 15 | return finish(); 16 | 17 | const destPath = path.join(dir, 'thumbnail.png'); 18 | m.write(destPath, function thumbnail (err) { 19 | finish(err); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /test/timeout.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | 4 | module.exports = function (img, dir, finish, gm, imageMagick) { 5 | 6 | assert.equal(undefined, gm.prototype._options.timeout); 7 | assert.equal(undefined, img._options.timeout); 8 | 9 | var g = gm('test').options({ timeout: 100 }); 10 | assert.equal(100, g._options.timeout); 11 | 12 | var sub = gm.subClass({ timeout: 2000 }); 13 | assert.equal(2000, sub.prototype._options.timeout); 14 | 15 | 16 | if (!gm.integration) 17 | return finish(); 18 | 19 | const sourcePath = path.join(dir, 'photo.JPG'); 20 | const timeoutPath = path.join(dir, 'timeout.png'); 21 | gm(sourcePath).options({ timeout: 1, imageMagick }) 22 | .thumb(50, 80, timeoutPath, function subthumb (err) { 23 | assert.ok(err, "Expecting a timeout error"); 24 | noTimeout(); 25 | }); 26 | 27 | 28 | function noTimeout() { 29 | gm(sourcePath).options({ timeout: 0, imageMagick }) 30 | .thumb(50, 80, timeoutPath, function subthumb (err) { 31 | finish(err); 32 | }); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /test/toBuffer.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var fs = require('fs'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | if (!GM.integration) 7 | return finish(); 8 | 9 | gm 10 | .toBuffer(function (err, buffer) { 11 | if (err) return finish(err); 12 | 13 | assert.ok(buffer instanceof Buffer); 14 | assert.ok(buffer.length); 15 | 16 | finish(); 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /test/toBufferFormat.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var fs = require('fs'); 3 | 4 | module.exports = function (gm, dir, finish, GM) { 5 | 6 | if (!GM.integration) 7 | return finish(); 8 | 9 | gm 10 | .toBuffer('PNG', function (err, buffer) { 11 | if (err) return finish(err); 12 | 13 | assert.ok(buffer instanceof Buffer); 14 | assert.ok(buffer.length); 15 | 16 | finish(); 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /test/utils.js: -------------------------------------------------------------------------------- 1 | 2 | var assert = require('assert') 3 | 4 | module.exports = function (_, dir, finish, gm) { 5 | 6 | assert.equal('function', typeof gm.utils.escape); 7 | assert.equal('function', typeof gm.utils.unescape); 8 | finish(); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /test/webp.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const path = require('path'); 3 | const fs = require('fs') 4 | 5 | module.exports = function (_, dir, finish, gm, imageMagick) { 6 | if (!gm.integration) return finish() 7 | 8 | // Don't know how to install IM with WEBP on ubuntu 9 | // if (require('os').platform() === 'linux') return finish() 10 | 11 | // GraphicsMagick currently does not support webp :( 12 | // if (!im) return finish() 13 | 14 | gm = gm.subClass({ 15 | imageMagick 16 | }) 17 | 18 | const imagePath = path.join(dir, 'original.png'); 19 | 20 | write(function (err) { 21 | if (err) return finish(err) 22 | 23 | stream(finish) 24 | }) 25 | 26 | function write(done) { 27 | const webpPath = path.join(dir, 'original.x.webp'); 28 | gm(imagePath) 29 | .write(webpPath, function (err) { 30 | if (err) return done(err) 31 | 32 | gm(webpPath).identify(function (err, value) { 33 | if (err) return done(err) 34 | 35 | assert.ok(value) 36 | assert.equal(value.format, 'WEBP') 37 | done() 38 | }) 39 | }) 40 | } 41 | 42 | function stream(done) { 43 | gm(imagePath) 44 | .stream('webp', function (err, stdout) { 45 | if (err) return done(err) 46 | 47 | gm(stdout).identify(function (err, value) { 48 | if (err) return done(err) 49 | 50 | assert.ok(value) 51 | assert.equal(value.format, 'WEBP') 52 | 53 | done() 54 | }) 55 | }) 56 | } 57 | } --------------------------------------------------------------------------------