Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add joinChannel and toColourspace commands #513

Merged
merged 13 commits into from
Aug 17, 2016
Merged

Add joinChannel and toColourspace commands #513

merged 13 commits into from
Aug 17, 2016

Conversation

mhirsch
Copy link
Contributor

@mhirsch mhirsch commented Jul 17, 2016

This PR is a little large -- sorry for that. These two features are somewhat entangled, and I ended up writing toColourspace() in service of what I was trying to do with joinChannels().

Add feature toColourspace / toColorspace to write output in desired colorspace

This implements a feature very much like the one described in #218. This code is tested in colourspace.js and joinChannel.js, but by its nature adds the potential for a lot of complexity. I expect some additional tests will be required. This supersedes #503, which I'll close.

Add feature joinChannels to add additional image channels to the input image

This allows you to join additional channels onto the image. In some cases it is necessary to use toColourspace() to set the output to what you intend. For example, if you open a grayscale image and add three channels, by default that will be interpreted as an sRGB image with an alpha channel. It is necessary to also call toColourspace('cmyk') to ask the image to be interpreted as a CMYK image.

Matt Hirsch added 2 commits July 16, 2016 23:50
…olorspace

Add feature joinChannels to add additional image channels to the input image
@lovell
Copy link
Owner

lovell commented Jul 18, 2016

Hello, thanks Matt, this doesn't seem to compile at the moment due to the use of an unordered_set keyed on VipsInterpretation - see https://travis-ci.org/lovell/sharp/builds/145304825

@mhirsch
Copy link
Contributor Author

mhirsch commented Jul 18, 2016

I don't have xcode, so it's hard to say what the problem is. I tried changing unordered_map to map. There's a small performance penalty for using map but it probably won't matter.

@@ -7,6 +7,7 @@
"beforeEach": true,
"afterEach": true,
"describe": true,
"it": true
"it": true,
"Promise": true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Promises aren't natively supported in older versions of Node - please use var Promise = require('bluebird'); in any files that need it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok -- that makes sense. Thanks

@lovell
Copy link
Owner

lovell commented Jul 19, 2016

The Buffer-or-filesystem approach of joinChannels feels a bit clunky. Does your use-case require both? Perhaps we could support one only to start with, e.g. Buffer only?

* CMYK: 0: Magenta, 1: Cyan, 2: Yellow, 3: Black, 4: Alpha

Buffers may be any of the image formats supported by sharp: JPEG, PNG, WebP, GIF, SVG, TIFF or raw pixel image data. In the case of a RAW buffer, the `options` object should contain a `raw` attribute, which follows the format of the attribute of the same name in the `sharp()` constructor. See `sharp()` for details. See `raw()` for pixel ordering.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to include information that the images to be joined must be the same dimension?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They actually don't have to be of the same dimension -- vips will expand the image to fit the largest channel.

@lovell
Copy link
Owner

lovell commented Jul 19, 2016

This PR definitely proves I need to abstract away the image loading logic copypasta (filesystem vs compressed Buffer vs raw Buffer) as there are now four occurrences :)

@mhirsch
Copy link
Contributor Author

mhirsch commented Jul 19, 2016

If you were to abstract the image loading logic it would perhaps make it simpler to have buffers or filespaths as inputs. What in particular feels clunky about it? I tried to mimic the file or buffer input options in other functions that accept image input. Would it be easier if they weren't in an array -- i.e. you need to call joinChannels() once per channel?

use BluebirdPromise instead of Promise to support old versions of node
@lovell
Copy link
Owner

lovell commented Jul 19, 2016

(Tomorrow) I'll attempt to extract the common logic (in both JS and C++) for image loading so it can be used by any operation that requires another image as part of its input.

@mhirsch
Copy link
Contributor Author

mhirsch commented Aug 8, 2016

@lovell I've updated this to be based on the pencil branch, taking advantage of your new OpenInput() system. This removes the awkward restriction of having to load either files or buffers and not both.

@mhirsch
Copy link
Contributor Author

mhirsch commented Aug 8, 2016

Actually -- what's the best way to handle this. Should I close this and open a new pull request against pencil?

@lovell
Copy link
Owner

lovell commented Aug 8, 2016

Thanks for the updates - I'll be merging pencil to master in a couple of days so please leave this open until then :)

@lovell
Copy link
Owner

lovell commented Aug 13, 2016

Matt, the upstream/master branch now has the CreateInputDescriptor logic - please can you rebase against it.

@mhirsch
Copy link
Contributor Author

mhirsch commented Aug 13, 2016

Yes -- today or tomorrow! Thanks!

@mhirsch
Copy link
Contributor Author

mhirsch commented Aug 14, 2016

When I git pull from your master in my master branch and run npm install and npm test I get the following:

/home/mhirsch/sharp/index.js:9
__cov_8cTnvYcP2ESJD5pY6tEvog.s['1']++;var path=require('path');__cov_8cTnvYcP2ESJD5pY6tEvog.s['2']++;var util=require('util');__cov_8cTnvYcP2ESJD5pY6tEvog.s['3']++;var stream=require('stream');__cov_8cTnvYcP2ESJD5pY6tEvog.s['4']++;var events=require('events');__cov_8cTnvYcP2ESJD5pY6tEvog.s['5']++;var semver=require('semver');__cov_8cTnvYcP2ESJD5pY6tEvog.s['6']++;var color=require('color');__cov_8cTnvYcP2ESJD5pY6tEvog.s['7']++;var BluebirdPromise=require('bluebird');__cov_8cTnvYcP2ESJD5pY6tEvog.s['8']++;var sharp=require('./build/Release/sharp');__cov_8cTnvYcP2ESJD5pY6tEvog.s['9']++;var versions={vips:sharp.libvipsVersion()};__cov_8cTnvYcP2ESJD5pY6tEvog.s['10']++;(function(){__cov_8cTnvYcP2ESJD5pY6tEvog.f['1']++;__cov_8cTnvYcP2ESJD5pY6tEvog.s['11']++;var libvipsVersionMin=require('./package.json').config.libvips;__cov_8cTnvYcP2ESJD5pY6tEvog.s['12']++;if(semver.lt(versions.vips,libvipsVersionMin)){__cov_8cTnvYcP2ESJD5pY6tEvog.b['1'][0]++;__cov_8cTnvYcP2ESJD5pY6tEvog.s['13']++;th

Error: Found libvips 8.3.2 but require at least 8.3.3
    at /home/mhirsch/sharp/index.js:9:996
    at Object.<anonymous> (/home/mhirsch/sharp/index.js:9:1265)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions.(anonymous function) [as .js] (/home/mhirsch/sharp/node_modules/istanbul/lib/hook.js:107:24)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/home/mhirsch/sharp/test/fixtures/index.js:5:13)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Object.Module._extensions.(anonymous function) [as .js] (/home/mhirsch/sharp/node_modules/istanbul/lib/hook.js:109:37)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/home/mhirsch/sharp/test/unit/alpha.js:4:16)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Object.Module._extensions.(anonymous function) [as .js] (/home/mhirsch/sharp/node_modules/istanbul/lib/hook.js:109:37)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at /home/mhirsch/sharp/node_modules/mocha/lib/mocha.js:220:27
    at Array.forEach (native)
    at Mocha.loadFiles (/home/mhirsch/sharp/node_modules/mocha/lib/mocha.js:217:14)
    at Mocha.run (/home/mhirsch/sharp/node_modules/mocha/lib/mocha.js:485:10)
    at Object.<anonymous> (/home/mhirsch/sharp/node_modules/mocha/bin/_mocha:405:18)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Object.Module._extensions.(anonymous function) [as .js] (/home/mhirsch/sharp/node_modules/istanbul/lib/hook.js:109:37)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)
    at runFn (/home/mhirsch/sharp/node_modules/istanbul/lib/command/common/run-with-cover.js:122:16)
    at /home/mhirsch/sharp/node_modules/istanbul/lib/command/common/run-with-cover.js:251:17
    at /home/mhirsch/sharp/node_modules/istanbul/lib/util/file-matcher.js:68:16
    at /home/mhirsch/sharp/node_modules/async/dist/async.js:486:20
    at /home/mhirsch/sharp/node_modules/async/dist/async.js:1074:13
    at /home/mhirsch/sharp/node_modules/async/dist/async.js:952:25
    at iteratorCallback (/home/mhirsch/sharp/node_modules/async/dist/async.js:997:17)
    at /home/mhirsch/sharp/node_modules/async/dist/async.js:847:20
    at /home/mhirsch/sharp/node_modules/async/dist/async.js:1071:17
    at LOOP (fs.js:1530:14)
    at nextTickCallbackWith0Args (node.js:420:9)
    at process._tickCallback (node.js:349:13)
npm ERR! Test failed.  See above for more details.

Is it possible that the new version of vips hasn't been pushed? Anyway, I merged your master back to this branch and pushed, though I haven't tested things yet.

@lovell
Copy link
Owner

lovell commented Aug 14, 2016

Removing the sharp/lib and sharp/include directories should fix this. npm run clean will do this for you. Perhaps it should do this automagically when there's a version mismatch?

@mhirsch
Copy link
Contributor Author

mhirsch commented Aug 14, 2016

Yes, that fixes it. I don't think running it automatically sounds right. I wasn't aware npm had a clean command. Thanks ;)

Anyway, it appears all the tests pass on this merged branch. Does this look good to you?

Sharp.prototype.joinChannel = function(images, options) {
if (Array.isArray(images)) {
images.forEach(function(image, index) {
this.options.joinChannelIn[index] = this._createInputDescriptor(image, options);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use push() rather than be index based? This would allow .joinChannel(array1).joinChannel(array2).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Woops. I'll make that change.

@lovell
Copy link
Owner

lovell commented Aug 15, 2016

Looking great, thanks. Always a pleasure to see a new feature PR with more lines of tests and documentation than the code to implement it :)

@lovell lovell added this to the v0.16.0 milestone Aug 15, 2016
@coveralls
Copy link

coveralls commented Aug 16, 2016

Coverage Status

Changes Unknown when pulling 6f79a99 on mhirsch:joinChannel_and_toColourspace into * on lovell:master*.

@lovell lovell merged commit 5c5d74a into lovell:master Aug 17, 2016
@lovell
Copy link
Owner

lovell commented Aug 17, 2016

Thanks again Matt!

@mhirsch mhirsch deleted the joinChannel_and_toColourspace branch August 17, 2016 14:58
@lovell
Copy link
Owner

lovell commented Aug 17, 2016

Added 7ada9db to fix a small InputDescriptor leak.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants