Сохранение данных в картинке

This commit is contained in:
2024-11-19 19:58:01 +03:00
parent 2097a70cbf
commit ae0bc951aa

View File

@@ -270,6 +270,41 @@ bitsToInt bits =
Для работы с изображениями использовалась библиотека \texttt{JuicyPixels}~\cite{JuicyPixels}. С её помощью можно как прочитать изображение в любом популярном формате, так и сохранить его. В частности в работе использовались функции: \texttt{readImage} -- для чтения изображения из указанного файла, \texttt{saveBmpImage} -- для сохранения изображения в формате bmp.
\subsection{Сохранение зашифрованных данных в изображении}
Код функций для создания изображения с закодированными данными представлен в листинге~\ref{lst:genImg}. Функция \texttt{encodePixel} отвечает за кодирование последовательности бит в определённый пиксель изображения. Она принимает количество бит данных, которое будет сохранено в каждый байт изображения, исходное изображение, вектор бит зашифрованных данных, координаты пикселя (\(x, y\)) и возвращает новый пиксель с закодированными данными. Для этого функция вычисляет индекс пикселя в изображении, извлекает соответствующую часть вектора бит данных, преобразует её в целые числа, накладывает битовую маску, которая соответствует количество изменяемых бит в байте, и записывает закодированные данные. Для создания маски используется вспомогательная функция \texttt{createMask}.
Функция \texttt{encodePixel} затем используется вместе с функцией \texttt{generateImage} из библиотеки JuicyPixels для генерации нового изображения.
При сохранении изображения в файл, в его названии сохраняется смещение шифра Цезаря и количество бит в байте, отведённых для хранения зашифрованных данных. Например, название изображения \texttt{david\_2\_10.bmp} означает, что при кодировании использовался код Цезаря со смещением 10, а для хранения закодированных данных в каждом байте изображения использовалось 2 бита.
\begin{lstlisting}[caption={Функции для создания изображения с закодированными данными.}, label={lst:genImg}]
createMask :: Int -> Int
createMask shift = shiftL (complement 0) shift .&. complement 0
encodePixel :: Int -> Image PixelRGB8 -> VU.Vector Int -> Int -> Int -> PixelRGB8
encodePixel bitsPerByte img bits x y = PixelRGB8 newR newG newB
where
width = imageWidth img
index = x + y * width
startPos = index * 3 * bitsPerByte
pixelBits = VU.slice startPos (3 * bitsPerByte) bits
bitsIntR = bitsToInt $ VU.slice 0 bitsPerByte pixelBits
bitsIntG = bitsToInt $ VU.slice bitsPerByte bitsPerByte pixelBits
bitsIntB = bitsToInt $ VU.slice (2 * bitsPerByte) bitsPerByte pixelBits
mask = createMask bitsPerByte
PixelRGB8 r g b = pixelAt img x y
newR = intToWord8 $ ((word8ToInt r) .&. mask) .|. bitsIntR
newG = intToWord8 $ ((word8ToInt g) .&. mask) .|. bitsIntG
newB = intToWord8 $ ((word8ToInt b) .&. mask) .|. bitsIntB
\end{lstlisting}
\newpage
\section {Результаты работы программы}