Проблема с этим алгоритмом RLE в том, что он слишком прост. Он префикс каждого байта указывает, сколько раз он повторяется, но это означает, что в длинных диапазонах неповторяющихся байтов каждый отдельный байт имеет префикс «1». Для данных без повторов это будет double размер файла.
Этого можно избежать, используя взамен RLE кодового типа; «Код» (также называемый «токен») будет байтом, который может иметь два значения; либо он указывает, сколько раз повторяется один следующий байт, либо указывает, сколько последующих неповторяющихся байтов следует скопировать, как они есть. Разница между этими двумя кодами достигается за счет включения старшего бита, что означает, что для значения по-прежнему доступно 7 битов, а это означает, что количество копируемых или повторяющихся кодов для такого кода может составлять до 127.
Это означает, что даже в наихудших сценариях окончательный размер может быть только примерно на 1/127 больше исходного размера файла.
Хорошее объяснение всей концепции, плюс полностью рабочий (и фактически сильно оптимизированный) код C #, можно найти здесь:
http://www.shikadi.net/moddingwiki/RLE_Compression
Обратите внимание, что иногда данные в конечном итоге будут больше, чем исходные , в любом случае , просто потому, что в нем недостаточно повторяющихся байтов для работы RLE. Хороший способ справиться с такими ошибками сжатия - добавить заголовок к окончательным данным. Если вы просто добавляете дополнительный байт в начале, который равен 0 для несжатых данных и 1 для сжатых данных RLE, то, когда RLE не дает меньшего результата, вы просто сохраняете его без сжатия, с 0 впереди, и ваши окончательные данные будет ровно на один байт больше оригинала. Затем система на другой стороне может прочитать этот начальный байт и использовать его, чтобы определить, следует ли распаковывать или просто копировать следующие данные.