Первое, что нужно сделать, - это конвертировать из RGB в YUV, или YCrCb, или что-то в этом порядке. Сделав это, вы обычно можете избежать частичной дискретизации каналов U и V (или Cr / Cb) до половины разрешения. Это довольно часто встречается в большинстве типов изображений (например, JPEG и MPEG оба делают это, как и датчики в большинстве цифровых камер).
Реально, начиная с 800 байтов данных, большинство других форм сжатия будут пустой тратой времени и усилий. Тебе придется проделать немало работы, прежде чем ты достигнешь многого (и поддерживать его достаточно быстро на Arduino тоже не будет тривиально).
Редактировать: хорошо, если вы абсолютно уверены, что вообще не можете изменить данные, все очень быстро усложняется. На данный момент реальный вопрос в том, с каким вкладом вы имеете дело. Другие уже упоминали о возможности чего-то порядка прогностического дельта-сжатия - например, основываясь на предыдущих пикселях, прогнозируют, каким будет следующий, и затем кодируют только разницу между прогнозом и фактическим значением. Однако для получения максимальной отдачи от этого обычно требуется выполнить результат с помощью какого-либо алгоритма, основанного на энтропии, такого как сжатие Шеннона-Фанно или Хаффмана. Однако, к сожалению, это не самый быстрый способ распаковать.
Если ваши данные в большинстве своем похожи на диаграммы или графики, где вы можете ожидать, что у вас будут большие области идентичных пикселей, кодирование по длине (или концу) может работать довольно хорошо. Это имеет то преимущество, что на самом деле очень просто распаковать.
Я сомневаюсь, что сжатие на основе LZ будет работать так хорошо, хотя. Сжатие на основе LZ работает (в общем) путем создания словаря строк байтов, которые были замечены, и когда / если снова видна та же строка байтов, передавая код, назначенный предыдущему экземпляру, вместо повторной передачи всего строка. Проблема в том, что вы не можете передавать несжатые байты - вы начинаете с отправки кодового слова, которое представляет этот байт в словаре. В вашем случае вы можете использовать (например) 10-битное кодовое слово. Это означает, что в первый раз, когда вы отправляете какой-либо конкретный символ, вам нужно отправить его как 10 битов, а не только 8. Вы начинаете получать некоторое сжатие только тогда, когда вы можете создать более длинный (двухбайтовый, трехбайтовый и т. Д.) Строки в вашем словаре, и , найдут соответствующую строку позже во входных данных.
Это означает, что сжатие на основе LZ обычно получает довольно слабое сжатие для первых нескольких сотен байтов или около того, затем даже без перерыва на некоторое время, и только после того, как оно какое-то время проходит по некоторому вводу, оно действительно начинает хорошо сжиматься , Имея дело только с 800 байтами за раз, я вовсе не уверен, что вы когда-нибудь увидите сильное сжатие - фактически, работая в таких маленьких блоках, не было бы особенно удивительно видеть, как данные расширяются на довольно регулярное основание (особенно если оно очень случайное).