I agree that the difference in speed can be resolved by changing the dynamic array call from
tmp := copy(img, imgp, nx);
to
Move(img^[imgp], tmp^[0], nx * 4);
Again, you did not understand me. The problem is that the functions with a dynamic and static array are different. That is, they do not the same thing. That is, it is useless to compare them, no matter what tricks you do with Move. They are different!
In my first message, I just showed where the error is located, and pointed out that if make them logically the same, then the difference in speed disappears.
Was
tmp := copy(img, imgp, imgp + nx - 1);
After correction (this is similar to the version without a dynamic array)
tmp := copy(img, imgp, nx);
Imagine that imgp equal 100000 to understand where the error is, and why there is such a difference in speed.