Skip to content

Conversation

@JimBobSquarePants
Copy link
Member

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following matches the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

Adds the ability to perform projective transforms (perspective, taper) on images

@JimBobSquarePants
Copy link
Member Author

@antonfirsov Surprising comparison results here. 32bit passing 64 bit failing? WTF?

@antonfirsov
Copy link
Member

@JimBobSquarePants the difference is not big however. I suspect the root cause is a difference between SIMD and software implementations of Vector4 operations.

Hope it's not CPU dependent & locally reproducible.

image.Mutate(i => { i.Transform(m); });

string testOutputDetails = $"{taperSide}-{taperCorner}";
image.DebugSave(provider, testOutputDetails);
Copy link
Member

Choose a reason for hiding this comment

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

@JimBobSquarePants added some tests to cover CreateTaperMatrix() parameters. I may get it wrong but the XxxOrYyy stuff might be the inverse of the intended. Can you check the output?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll have to do some tests locally to ensure the output is expected. The class is based on a Skia example and and old Charles Petzold blog post.

Copy link
Member

@antonfirsov antonfirsov left a comment

Choose a reason for hiding this comment

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

I think I managed to workaround the floating point issue. It is related to Vector2 again.

The API is perfect. If CreateTaperMatrix() parameters behave as you originally intended, we can add the reference images for Transform_WithTaperMatrix and merge the PR. (But we probably need to invert TaperCorner behavior.)

/// <param name="taperCorner">An enumeration that indicates on which corners to taper the rectangle.</param>
/// <param name="taperFraction">The amount to taper.</param>
/// <returns>The <see cref="Matrix4x4"/></returns>
public static Matrix4x4 CreateTaperMatrix(Size size, TaperSide taperSide, TaperCorner taperCorner, float taperFraction)
Copy link
Member

Choose a reason for hiding this comment

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

Cool suff! Covers basic cases & good for testing without getting outside the scope of the library.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for adding the extra tests, they affirm the expected output well.

@codecov
Copy link

codecov bot commented Apr 28, 2018

Codecov Report

Merging #546 into master will increase coverage by 0.41%.
The diff coverage is 98.19%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #546      +/-   ##
==========================================
+ Coverage   88.28%   88.69%   +0.41%     
==========================================
  Files         838      840       +2     
  Lines       35186    35300     +114     
  Branches     2538     2544       +6     
==========================================
+ Hits        31064    31310     +246     
+ Misses       3377     3243     -134     
- Partials      745      747       +2
Impacted Files Coverage Δ
...Sharp/Processing/Transforms/TransformExtensions.cs 54.54% <ø> (+18.18%) ⬆️
.../Transforms/Processors/AffineTransformProcessor.cs 100% <100%> (ø) ⬆️
...s/Processors/InterpolatedTransformProcessorBase.cs 100% <100%> (ø) ⬆️
...nsforms/Processors/ProjectiveTransformProcessor.cs 100% <100%> (+100%) ⬆️
...ests/Processing/Transforms/AffineTransformTests.cs 98.52% <100%> (-0.02%) ⬇️
.../Processing/Transforms/ProjectiveTransformTests.cs 97.22% <97.22%> (ø)
...Processing/Transforms/ProjectiveTransformHelper.cs 97.22% <97.22%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6b4de97...775aa90. Read the comment docs.

@JimBobSquarePants
Copy link
Member Author

@antonfirsov Back to you; do your magic please.

@antonfirsov
Copy link
Member

Bottom-LeftOrTop:
transform_withtapermatrix_rgba32_solid30x30_ 255 0 0 255 _bottom-leftortop

Bottom-RightOrBottom:
transform_withtapermatrix_rgba32_solid30x30_ 255 0 0 255 _bottom-rightorbottom

@JimBobSquarePants you sure TaperCorner works fine? Isn't it the inverse of the intended? Or I'm getting it wrong?

@JimBobSquarePants
Copy link
Member Author

Bottom-LeftOrTop:
transform_withtapermatrix_rgba32_solid30x30_ 255 0 0 255 _bottom-leftortop

Bottom-RightOrBottom:
transform_withtapermatrix_rgba32_solid30x30_ 255 0 0 255 _bottom-rightorbottom

@JimBobSquarePants you sure TaperCorner works fine? Isn't it the inverse of the intended? Or I'm getting it wrong?

@antonfirsov I think it's correct.

In the first example we are choosing to taper the "Bottom" side on either the "Left" or "Top" corner. Since "Left" is possible regardless of whether "Top" is impossible "Left" is chosen.

In the seconds example we are choosing to taper the "Bottom" side on either the "Right" or "Bottom" corner. Since "Right" is possible regardless of whether "Bottom" is possible "Right" is chosen.

The original article with source code for the class this is based on can be found here:

http://www.charlespetzold.com/blog/2009/07/Taper-Transforms-with-Matrix3DProjection-An-Analytical-Approach.html

SkiaSharp have an example here:
https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/transforms/non-affine

I can attempt to compare against the demos. (Feel free to have a look first though) https://developer.xamarin.com/samples/xamarin-forms/SkiaSharpForms/Demos/

@JimBobSquarePants
Copy link
Member Author

Behaviour confirmed 😄

taper-bottom-left-or-top
taper-bottom-right-or-bottom

@antonfirsov
Copy link
Member

LOL .. that image!

But isn't the first example tapering towards the right corner? Or should I start over my English courses? :D

@JimBobSquarePants
Copy link
Member Author

Yeah I felt a little guilty posting that 😄

Here's the comparative images side by side and scaled.

Bottom-LeftOrTop:
taper-bottom-left-or-top
taper-bottom-left-or-top

Bottom-RightOrBottom:

taper-bottom-right-or-bottom

@antonfirsov
Copy link
Member

It seems to me that the original definition is wrong, because the "tapered" edge is not on the left (but on the right!) corner of the image.

image

But again, it might be just my wrong understanding of the term "tapering".

@JimBobSquarePants
Copy link
Member Author

Ah no... I can see how this is confusing but the language is correct.

A classic definition of taper would be

to become progressively smaller toward one end.

You're tapering towards the bottom edge and choosing which corner to taper with.

@antonfirsov
Copy link
Member

I understand now.
The PR is in a perfect state, sorry for the long linguistic session! :)

@antonfirsov
Copy link
Member

Well .. almost. Haven't noticed, the tests are failing again, gonna check it out now.

@JimBobSquarePants
Copy link
Member Author

floating-points-from-hell

Haha! 🤣

It's amazing really the trouble we've had with this. Will be happy when MS push all their Vector2 fixes.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants