Нет необходимости разбивать соединенный ushort и соединять результат обратно.Вы можете вычислить вывод напрямую, используя
filtered[i + 602] = (ushort)(joined - ((joined >> 3) & 0x18e3));
Позвольте мне объяснить это: в вашем примере синий использует биты 0-4, зеленый использует 5-10, а красный использует 11-15.Биты соединения (в порядке с прямым порядком байтов)
rrrr rggg gggb bbbb
join >> 3 сдвигают все компоненты (красный, зеленый, синий) на 3.Т.е. объединенный >> 3 имеет формат
000r rrrr gggg ggbb
Мы хотим замаскировать биты из одного компонента, которые перетекают в другой компонент.Это делается с помощью 0x18e3.Т.е. (объединено >> 3) & 0x18e3 имеет формат
000r r000 ggg0 00bb
Далее вы делаете вычитание
joined - ((joined >> 3) & 0x18e3)
Thisвычитает сдвинутые компоненты RGB из оригинала за один шаг.Тем не менее, вы должны учитывать недостатки.Т.е. вы не хотите, чтобы нижняя часть зеленого компонента распространялась на красный компонент.Небольшая мысль показывает, что это не проблема.Все сдвинутые компоненты меньше, чем их первоначальное значение, и, следовательно, не может быть недопущения.Другими словами, одно приведенное выше утверждение должно работать нормально.(Конечно, вам все равно придется тщательно проверять).
Для большей скорости эту операцию можно выполнить на нескольких пикселях параллельно.Т.е. если бы вы упаковали 4 пикселя в uint64, то эту операцию было бы так же легко выполнить для всех 4 пикселей одновременно.(Но я не уверен, легко ли возможно приведение типов коротких массивов к массивам uint64).