-
Notifications
You must be signed in to change notification settings - Fork 798
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] Add bilinear resize to RawImage #1101
base: main
Are you sure you want to change the base?
[FEAT] Add bilinear resize to RawImage #1101
Conversation
The implementation of the algorithm could definitely be improved, because the Canvas API tends to have better results, however a bad implementation is better than none. If you are not happy with this, I am more than happy to improve it, but my current plans are to go through the current supported resampling methods and implement those in some respects - then improve them going forward. |
// Get the values of the new pixel area. | ||
// Always multiply by the width because we | ||
// storing the data in a 1D array. | ||
// To get the second row, we must add a full | ||
// width, then adding the x offset. | ||
const topLeft = this.data[(((y0 * this.width) + x0) * numChannels) + c]; | ||
const topRight = this.data[(((y0 * this.width) + x1) * numChannels) + c]; | ||
const bottomLeft = this.data[(((y1 * this.width) + x0) * numChannels) + c]; | ||
const bottomRight = this.data[(((y1 * this.width) + x1) * numChannels) + c]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if my comment makes sense, but basically if we had an area like this:
array
1 2 3 4 5 6 7 8 9 10 11 12
image
1 2 3 4
5 6 7 8
9 10 11 12
To get the element on the third row (3 - 1
since it is zero indexed) and second column (2 - 1
), we must multiply by the width (4
), then add the column.
In this case, we would do:
((row - 1) * width) + (column - 1) = index
((3 - 1) * 4) + (2 - 1) = 9
// Perform bilinear interpolation. | ||
// Find the horizontal position along the | ||
// top and bottom rows. | ||
const top = (topLeft * (1 - dx)) + (topRight * dx); | ||
const bottom = (bottomLeft * (1 - dx)) + (bottomRight * dx); | ||
// Find the value between these two values. | ||
const interpolatedValue = (top * (1 - dy)) + (bottom * dy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, we need to get the x
value for the top and bottom of the new resized area, then interpolate between these two values to find what the new y
value.
topLeft topRight
+--------T--------------+
| |
| |
| I |
| |
| |
+------------B----------+
bottomLeft bottomRight
Here, top
is represented by T
, bottom is represented by B
, and interpolatedValue
is represented by I
.
I wanted to make a start implementing various resizing algorithms for
RawImage
.Here is an example of the original canvas API implementation and this PR's bilinear implementation.
I have performed the same operation using both implementations, and cropped the same section to demonstrate the level of detail making it slightly easier to review.
Below is the original image.
And this is the code that I used to generate these images:
Additionally, I realised that it is possible that the
width
orheight
could technically be a float, and so I've added an exception if the user passes in a float, and just rounded the automatic value that is assigned if the "maintain aspect ratio" route is taken.