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

feat: exposing vips_affine operation #2336

Merged
merged 8 commits into from
Nov 16, 2020
Merged

feat: exposing vips_affine operation #2336

merged 8 commits into from
Nov 16, 2020

Conversation

guillevc
Copy link
Contributor

@guillevc guillevc commented Aug 25, 2020

This PR is #2320 re-opened, as it was automatically closed due to the destination branch (zoom) being removed.


Exposes vips_affine operation as discussed in #2095. Supports making an affine transformation from a 2x2 matrix and optional offsets, background color and any supported interpolator.

This is my first PR to this project so please propose any changes or ask any questions.

Here is the proposed API implemented in this PR:

affine

Perform an affine transform on an image. This operation will always occur after resizing, extraction and rotation, if any.

You must provide a 2x2 affine transformation matrix.
By default, new pixels are filled with a black background. You can provide a background color with the background option.
A particular interpolator may also be specified. Set the interpolator option to an attribute of the sharp.interpolator Object e.g. sharp.interpolator.nohalo.

The transform is:

  • X = matrix[0, 0] * (x + idx) + matrix[0, 1] * (y + idy) + odx
  • Y = matrix[1, 0] * (x + idx) + matrix[1, 1] * (y + idy) + ody

where:

  • x and y are the coordinates in input image.
  • X and Y are the coordinates in output image.
  • (0,0) is the upper left corner.

Parameters

  • matrix [Array][7]<[Array][7]<[number][1]>> 2x2 affine transformation matrix
  • options [Object][2]? if present, is an Object with optional attributes.
    • options.background ([String][3] | [Object][2]) parsed by the [color][4] module to extract values for red, green, blue and alpha. (optional, default "#000000")
    • options.idx [Number][1] input horizontal offset (optional, default 0)
    • options.idy [Number][1] input vertical offset (optional, default 0)
    • options.odx [Number][1] output horizontal offset (optional, default 0)
    • options.ody [Number][1] output vertical offset (optional, default 0)
    • options.interpolator [String][3] interpolator (optional, default sharp.interpolators.bicubic)

Examples

const pipeline = sharp()
  .affine([[1, 0.3], [0.1, 0.7]], {
     background: 'white',
     interpolate: sharp.interpolators.nohalo
  })
  .toBuffer((err, outputBuffer, info) => {
     // outputBuffer contains the transformed image
     // info.width and info.height contain the new dimensions
  });

inputStream
  .pipe(pipeline)
  .pipe(outputStream);

interpolators

An Object containing the available interpolators and their proper values

Type: [string][2]

nearest

[Nearest neighbour interpolation][3]. Suitable for image enlargement only.

bilinear

[Bilinear interpolation][4]. Faster than bicubic but with less smooth results.

bicubic

[Bicubic interpolation][5] (the default).

locallyBoundedBicubic

[LBB interpolation][6]. Prevents some "[acutance][7]" but typically reduces performance by a factor of 2.

nohalo

[Nohalo interpolation][8]. Prevents acutance but typically reduces performance by a factor of 3.

vertexSplitQuadraticBasisSpline

[VSQBS interpolation][9]. Prevents "staircasing" when enlarging.

@coveralls
Copy link

coveralls commented Aug 26, 2020

Coverage Status

Coverage remained the same at 100.0% when pulling d03bac4 on guillevc:affine into fbe48d7 on lovell:master.

@infacto
Copy link

infacto commented Oct 2, 2020

Great work. Just for clarification: This feature does not have projective transformation, right? Can you post some example images?
demo

A use case for perspective transformation is to fit an image to a screen on a photo of a tablet or smartphone. #2388
If this PR does not include it, we should consider to reopen this issue. Or will this feature also works for this use case? 🤔

@guillevc
Copy link
Contributor Author

guillevc commented Oct 3, 2020

@infacto hello! this PR exposes the vips_affine operation, which can only make affine transformations. As far as I know, libvips doesn't provide any way of making projective transformations.

@lovell
Copy link
Owner

lovell commented Oct 3, 2020

@guillevc I haven't forgotten this PR - it's on my watch list for the next release.

Copy link
Owner

@lovell lovell left a comment

Choose a reason for hiding this comment

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

Muchas gracias for this PR Guillermo, and apologies for the time it's taken to get around to reviewing it, especially as you've made lots of effort to include tests for everything - it's always a pleasure to see these. I've left a few questions/comments inline that may need addressing.

Copy link
Owner

@lovell lovell left a comment

Choose a reason for hiding this comment

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

Brilliant, thank you for the updates, I've left a couple of minor comments inline but otherwise this is good to merge.

@guillevc guillevc requested a review from lovell October 18, 2020 15:12
Copy link
Owner

@lovell lovell left a comment

Choose a reason for hiding this comment

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

Marvellous, thank you for persisting with this. I'll merge this PR after the avif branch (and will look after any conflicts should they arise).

@lovell lovell added this to the v0.27.0 milestone Oct 18, 2020
@lovell lovell mentioned this pull request Nov 5, 2020
@lovell lovell modified the milestones: v0.27.0, v0.26.3 Nov 16, 2020
@lovell lovell merged commit 0f473fe into lovell:master Nov 16, 2020
@lovell
Copy link
Owner

lovell commented Nov 16, 2020

Thanks, this will be in v0.26.3

lovell added a commit that referenced this pull request Nov 16, 2020
@lovell
Copy link
Owner

lovell commented Nov 16, 2020

v0.26.3 now available

@guillevc
Copy link
Contributor Author

@lovell Thank you! It was such a pleasure to collaborate in this project. I'd be happy to help with something else in the future 😄

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.

4 participants