TRANSFORM: Add Cubic B-Spline with Prefilter Algorithm
Open, NormalPublic


Adds an extremely high quality scaling algorithm to the Transform scaling node implemented by Sergey.



Added an information wiki page for curious minds.

Correct me if I'm wrong, but I think line 237 of your patch should be if(ibuf && obuf && (fbuf || filter_type != 3)) instead of if(ibuf && obuf && fbuf) as fbuf is uninitialized if filter_type != 3.

Quite correct. Good spot. I shifted allocation late in the game to being only if required.

I've also changed the coefficients array to use the outbuf. There isn't any overlap, and seeing as how it is single threaded, it is fine.

If it were threaded it would need to operate on the rows then columns per thread I'd think.

Thanks again for taking time to look.

Fixes typo. Patches named in YYMMDDHHMM.

Another thing : line 70 you do float *coeff = out->rect_float so, unless I've missed something, line 176 to 183 are unneeded (and if needed, a memcpy() is propably better than three nested for loops to copy data) .

OBuf is most certainly assigned to rect_float of stackbuf, so the values are empty.

I'd like to use IMB_dupImBuf, but the way the code in the node_composite_transform.c works leaves it difficult as the ImBuf* is initialized and then the values are assigned.

Using IMB_dupImBuf instead of a loop to copy the ImBuf. Also added cubic b-spline with prefilter to the Stabilize 2D node.

Typo in (fbuf || filter_type != 3) wasn't showing Bilinear / Bicubic / Nearest results.

Ugh. Non square images are corrupted. Looking into the issue. Perhaps Julien you can spot the issue?

Fixes for non square images and minor change to memcpy instead of a loop for copying to output buffer.

Optimization to follow.

About final patch methinks.

Refactoring of the code to support potentially threaded versions. Tidier as well.

Fixes the one pixel gutter in Bicubic scaling (may already be committed by Sergey) as the algorithm relies on the Bicubic pass.

I'd really like to see this in trunk.
Especially since the Transform node is currently using the worst method possible (unprefiltered B-Spline is even more blurry than bilinear).

Minor remark about performance:
For threading, as I said, you'd need to tile the image (and add a 12px margin).
I think if you really need a faster prefilter, you could trivially gain 4x speedup by using SIMD to process the 4 channels in parallel.
Also I don't understand why you manually unrolled the loop on channels? It hurts the code clarity and genericity for no reason.

Updated to new compositor. Full information is still available at

Located the prefilter within imageprocess.c as opposed to a node operation to enable application of the approach system wide.

I'm glad you're not giving up on this.
I'm not sure why a change which improves quality without any work doesn't attract any more interest.
I'll hope you'll manage to lobby until this get in trunk ;)
Don't hesitate to contact me if I can be of any help.