Я бы ещё попробовал транспонировать все вычисления. Навскидку не скажу, будет ли это действовать без поворота, но в исходном алгоритме вычисления производились по столбцам, что может быть неоптимальным со стороны процессорного кэша, и если проводить вычисления по строкам, результат может оказаться гораздо лучше.
Ещё возможным недостатком может быть большое количество выделений/освобождений памяти. Оригинальный алгоритм очень долго сидел в сборке мусора, несколько раз даже выполнялась полная остановка потоков. Возможно, если бы промежуточные буферы переиспользовались активнее, быстродействие ещё бы значительно выросло.
Ускоряем код на Android'е