У меня есть встраиваемое приложение, где сканер изображения отсылает поток 16-разрядных пикселей, которые позже собраны к полутоновому изображению. Поскольку я должен и сохранить эти данные локально и передать их сетевому интерфейсу, я хотел бы сжать поток данных для сокращения необходимого пространства памяти и сетевой пропускной способности.
Существует ли простой алгоритм, который я могу использовать для без потерь сжатия пиксельных данных?
Я сначала думал о вычислениях различия между двумя последовательными пикселями и затем кодированием этого различия с кодом Хаффмана. К сожалению, пиксели являются неподписанными 16-разрядными количествами, таким образом, различие может быть где угодно в диапазоне-65535.. +65535, который приводит к потенциально огромным длинам кодовой комбинации. Если несколько действительно долгих ключевых слов произойдут подряд, то я столкнусь с проблемами переполнения буфера.
Обновление: моей платформой является FPGA
PNG обеспечивает бесплатное сжатие изображений без потерь с открытым исходным кодом в стандартном формате с использованием стандартных инструментов. PNG использует zlib
как часть сжатия. Также существует libpng
. Если ваша платформа очень не является необычной, перенести на нее этот код не составит труда.
Сколько ресурсов доступно на вашей встроенной платформе?
Не могли бы вы перенести zlib и выполнить сжатие gzip? Даже с ограниченными ресурсами вы сможете портировать что-то вроде LZ77 или LZ88 .
Существует множество доступных библиотек сжатия изображений. Например, эта страница не содержит ничего, кроме библиотек / наборов инструментов для изображений PNG. Какой формат / библиотека лучше всего подходит для вас, скорее всего, будет зависеть от конкретных ограничений ресурсов, с которыми вы работаете (в частности, от того, может ли ваша встроенная система выполнять арифметические операции с плавающей запятой).
Какое «без потерь» вам нужно?
Если это настоящий сканер, есть ограничение на пропускную способность / разрешение, поэтому даже если он может отправлять значения +/- 64K, для соседних пикселей может быть нефизичным иметь разницу более, чем, скажем, 8 бит.
В этом случае вы можете задать значение начального пикселя для каждой строки, а затем сделать различия между каждым пикселем.
Это приведет к размыванию пиков, но может случиться так, что любые пики больше N бит в любом случае являются шумом.
Целью сжатия без потерь является возможность предсказать следующий пиксель на основе предыдущих пикселей, а затем закодировать разницу между вашим предсказанием и реальным значением. пикселя.Это то, что вы изначально думали сделать, но вы использовали только один предыдущий пиксель и сделали прогноз, что следующий пиксель будет таким же.
Имейте в виду, что если у вас есть все предыдущие пиксели, у вас есть более релевантная информация, чем только предыдущий пиксель. То есть, если вы пытаетесь предсказать значение X, вы должны использовать пиксели O:
.. OOO ...
.. OX
Кроме того, вам не нужно использовать предыдущий пиксель B в потоке для прогнозирования X в следующей ситуации:
OO ... B <- Конец строки
X <- Начало следующей строки
Вместо этого вы должны делать свои прогнозы на основе ОС.
Хороший гибрид LZ77 / RLE с колокольчиками и свистками может получить прекрасное сжатие, которое довольно быстро распаковывается. Они также будут более крупными и плохими компрессорами для файлов меньшего размера из-за отсутствия накладных расходов библиотеки. Для хорошей, но GPLd реализации этого, ознакомьтесь с PUCrunch