Приховування інформації в Кішок


24

Ви секретний агент, який намагається спілкуватися зі своєю вітчизною. Звичайно, інформацію потрібно приховати, щоб ніхто не підпускав ваші повідомлення. Що б краще підходило, ніж кішка? Усі люблять смішні фотографії котів [потрібна цитата] , тому вони не підозрюють, що там ховається таємна інформація!


Надихнувшись алгоритмом, який гра Монако використовує для збереження інформації про рівень загальних рівнів , ваші завдання - написати програму, яка закодувала інформацію в найменш значущий біт кольорів зображення.

Формат кодування:

  • Перші 24 біти визначають довжину решти закодованого байтового рядка в бітах
  • Зображення читається зліва направо і зверху вниз, очевидно, починаючи з верхнього лівого пікселя
  • Канали читаються від червоного до зеленого до синього
  • Зчитується найменш значущий біт з кожного каналу
  • Біти зберігаються в порядку Big Endian

Правила:

  • У вашій програмі використовується один байт-рядок для кодування та одне ім'я файлу зображення для базового зображення
  • Отримане зображення має вийти як справжній кольоровий PNG-файл
  • Ви можете використовувати введення-виведення в будь-якій формі, яку вам подобається (ARGV, STDIN, STDOUT, запис / читання з файлу), поки ви заявляєте, як користуватися програмою
  • Ви повинні вибрати випадкове зображення смішної кішки і закодувати її в програму, щоб показати, що ваша програма працює
  • Ви можете припустити, що вам надається лише дійсний ввід, якщо кількість бітів недостатня, зображення не в справжньому кольоровому форматі, зображення не існує або подібні проблеми ви можете робити те, що вам потрібно
  • Ви можете припустити, що надане зображення не містить альфа-каналу
  • Довжина підраховується в байтах UTF-8 без BOM

Ви можете використовувати цей скрипт PHP для тестування свого рішення, вказуючи ім'я файлу PNG як перший аргумент командного рядка:

<?php
if ($argc === 1) die('Provide the filename of the PNG to read from');
$imageSize = @getimagesize($argv[1]);

if ($imageSize === false) die('Not a PNG file');
list($width, $height) = $imageSize;

$image = imagecreatefrompng($argv[1]);
$read = 0;
$bits = '';
for ($y = 0; $y < $height; $y++) {
    for ($x = 0; $x < $width; $x++) {
        $colorAt = imagecolorat($image, $x, $y);
        $red = ($colorAt >> 16) & 0xFF;
        $green = ($colorAt >> 8) & 0xFF;
        $blue = ($colorAt >> 0) & 0xFF;

        $bits .= ($red & 1).($green & 1).($blue & 1);
        $read += 3;
        if ($read == 24) {
            $length = (int) bindec($bits);
            $bits = '';
        }
        else if ($read > 24 && ($read - 24) > $length) {
            $bits = substr($bits, 0, $length);
            break 2;
        }
    }
}
if (strlen($bits) !== $length) die('Not enough bits read to fulfill the length');
$parts = str_split($bits, 8);
foreach ($parts as $part) {
    echo chr(bindec($part));
}

У вашій специфікації сказано, що "ваша програма бере за основу одне зображення". У Mathematica зображення насправді є лише виразом, як і все інше, тому технічно ця специфікація дозволить мені здійснити завантаження файлів поза кодом, який виконує обчислення (при цьому вхідний параметр є фактичним зображенням замість імені файлу зображення) . Якщо ви не хочете подібних матеріалів, можливо, ви захочете вказати, що програма повинна взяти ім'я файлу зображення як вхідне.
Мартін Ендер

4
ME helpimtrappedinacatfactory OW
TheDoctor

Також, чи повинні біти, які не використовуються для кодування, залишатися недоторканими? Або ми можемо встановити їх на все, що ми хочемо (оскільки це насправді не вплине на якість зображення і не має значення для декодування)?
Мартін Ендер

1
Чи можу я використовувати невбудовану бібліотеку для завантаження та збереження png-файлу, наприклад, PIL у Python?
Клавдіу

1
@TimWolla Від кота? Тримайте його в приміщенні і стежте за лотком для сміття. З фотографії? Якщо ви зробите рентгенівську фотографію досить високої роздільної здатності, ви можете побачити стан окремих транзисторів у флеш-мікросхемі. Я впевнений, що це повинен бути найефективніший метод передачі секретної інформації, коли-небудь придуманий, хоча у кішки можуть бути інші ідеї.
Sonic Atom

Відповіді:


3

Perl & ImageMagick (Linux), 198 190

Редагувати: За деяким збігом обставин раніше я тестував на комп’ютері з встановленою версією ImageMagick Q8 (8 бітною глибиною). Версія 'Standard' Q16 вимагає явного -depth 8в командному рядку. В Linux identifyрезультат також потребує видалення нового рядка. Обидва фактори призводять до збільшення розміру коду, тому я розміщую версію Linux (мабуть, також для Mac) як відповідь, із застосованими виправленнями, а також із видаленими лише елементами Windows (CR-lf конверсія, бінарний vs текст тощо). Портативна (трохи довша) версія розміщена наприкінці.

З новими рядками для читабельності:

$/=$1;
<>=~/\n/;
$_=`identify -format %wx%h $\``;
chop;
open O,"|convert -size $_ -depth 8 rgb: $`.png";
$_=`convert $\` rgb:`;
print O$_&y//\376/cr|unpack('B*',pack(NX,2048*length$').$')&y//\1/cr

Виконати:

perl cat.pl

Він читає з STDIN, ім'я файлу зображення в першому рядку, наступне повідомлення «секрет», яке закінчується ctrl-D. Назва вихідного файлу оригінальна із .pngдодаванням - не дуже приємно, це робиться лише для стислості.

Ось зображення з дуже секретною інформацією, прихованою всередині:

введіть тут опис зображення

І з деякими коментарями:

# Undef input record separator, because we'll slurp input.

$/=$1;

# Read from STDIN, separate first line. 
# $` (prematch) contains image file name,
# $' (postmatch) - text to encode.

<>=~/\n/;

# Get IM's 'identify' output, width and height of the image. 
# Note: we don't have to separate them, \d+x\d+ string will 
# do just fine.

$_=`identify -format %wx%h $\``;
chop;

# Open output pipe - IM's 'convert' command that takes raw RGB data from 
# STDIN and writes output to PNG file. Interpolated into this command
# line is previous IM's 'identify' result. Convert wants '-size' command
# option in case of raw RGB input - for obvious reason.

open O,"|convert -size $_ -depth 8 rgb: $`.png";

# Get raw RGB data into $_.

$_=`convert $\` rgb:`;

# Last line does all the job. 

# y//\376/cr --- create string same length as $_, fill with 0xFE
# $_&y//\376/cr --- zero least significant bit for all image bytes (1).
# pack(NX,2048*length$') --- multiply by 8 (bytes to bits count) and 
#         shift left by 8 (because we'll pack long integer into 3 bytes) -
#         i.e. multiply by 2048.
# unpack('B*',pack(NX,2048*length$').$') ---- append 'secret text' to 
#       its encoded length and convert to 'binary' (consisting of 1 and 
#       0 characters) string.
# ... &y//\1/cr --- equivalent of tr/01/\0\1/. We don't have to worry 
#       that raw RGB length is larger than encoded text length, because
#       '&' truncates longer string argument (2).
# Then bitwise-'or' (1) and (2) strings.

print O$_&y//\376/cr|unpack('B*',pack(NX,2048*length$').$')&y//\1/cr

Далі - портативна версія, працює як в Windows (використовується ctrl-Zдля припинення введення), так і в Linux, кількість байтів - 244.

$_=do{local$/;<>};
/\n/;
$_=`identify -format %wx%h $\``;
chomp;
open I,'-|:raw',"convert $` rgb:";
open O,'|-:raw',"convert -size $_ -depth 8 rgb: $`.png";
$_=do{local$/;<I>};
print O$_&y//\376/cr|unpack('B*',pack(NX,2048*length$').$')&y//\1/cr

10

Математика, 255 234 206 байт

Я бачив стільки 255s під час тестування цього, я нерозумно радий розміру коду. :) І тоді моя амбіція пограти в гольф ще більше отримала від мене найкраще ...

f=(j=ImageData[Import@#2,t="Byte"];k=(d=IntegerDigits)[j,2,8]~Flatten~2;n=1;(k[[n++,-1]]=#)&/@d[Length@#,2,24]~Join~#&[Join@@d[ToCharacterCode@#,2,8]];ArrayReshape[#~FromDigits~2&/@k,Dimensions@j]~Image~t)&

Технічно це функція, а не "програма", але знову ж таки це майже так, як ви пишете "програми" в Mathematica, якщо ця концепція навіть там дійсна. Називай це так

f["my secret", "fully/qualified/cat.png"]

Він поверне фактичний вираз зображення (тому що це найбільш природний спосіб повернути зображення в Mathematica), тому, якщо ви хочете файл, вам потрібно експортувати його:

Export["output-cat.png", f["my secret", "input-cat.png"]]

Ось необхідний приклад:

введіть тут опис зображення

Я хотів би показати вам розшифроване повідомлення тут, але воно не підходить ... тому запустіть його через декодер ОП. ;)

До речі, я міг би змусити його працювати з UTF-8 секретів для всього 7 байт (зміна ToCharacterCode@#в #~ToCharacterCode~"utf8").

Невикористаний код:

f[secret_, filename_] := (
  bits = Join @@ IntegerDigits[ToCharacterCode[secret], 2, 8];
  bits = Join[d[Length @ bits, 2, 24], bits];
  data = ImageData[Import@#2, "Byte"];
  dims = Dimensions@data;
  data = Flatten[IntegerDigits[data, 2, 8], 2];
  m = n = 1;
  While[m <= Length @ bits,
    data[[n++, -1]] = bits[[m++]]
  ];
  Image[ArrayReshape[FromDigits[#, 2] & /@ data, dims], "Byte"]
)

"Я хотів би показати вам розшифроване повідомлення тут, але воно не підходить ... тому запустіть його через декодер ОП.)" - Я це зробив, і він дає мені "????????? ??? +++++++ ?? ++++++++++++++++++++================== ~ === ~ ============ ~ :::: ~~~~~ = [... для 9773 символів] "
TessellationHeckler

1
@TessellatingHeckler, це правильно. спробуйте його з односхилим шрифтом і пам’ятайте, що там є нові рядки в стилі UNIX (наприклад, спробуйте в терміналі або PowerShell шириною не менше 180 символів, або якщо ви використовуєте його як веб-скрипт у своєму браузері, потім перегляньте джерело);)
Мартін Ендер

2
Розумію! Дуже мета. Допомагає, що я теж у версії PuTTY KiTTY 😸
TessellatingHeckler

5

PHP, 530 байт

<?php function p($i,$j){return str_pad(decbin($i),$j,0,0);}extract(getopt("i:o:t:"));$t=file_get_contents($t);$_=imagecreatefrompng($i);list($w,$h)=getimagesize($i);$b="";for($i=0;$i<strlen($t);)$b.=p(ord($t[$i++]),8);$l=strlen($b);$b=p($l,24).$b;$l+=24;for($i=$x=$y=0;$y<$h;$y++){for(;$x<$w;){$C=imagecolorat($_,$x,$y);$R=($C>>16)&0xff;$G=($C>>8)&0xff;$B=$C&0xff;$i<$l&&$R=$b[$i++]|$R&~1;$i<$l&&$G=$b[$i++]|$G&~1;$i<$l&&$B=$b[$i++]|$B&~1;imagesetpixel($_,$x++,$y,imagecolorallocate($_,$R,$G,$B));if($i>$l){imagepng($_,$o);die;}}}

Бігай, як php 25443.php -i<input image> -o<output image> -t<file to hide>.

І ось зразок зображення.

http://i.imgur.com/hevnrbm.png

Код без вольфу прихований у зразковому зображенні. Випробуваний за допомогою декодера OP. Вибачте за не смішну картинку кота.


1
Будь-ласка, додайте у відповідь код, який не використовується.
AL

1
Можна скоротити 0xffдо 255.
TimWolla

Ви можете зберегти 4 байта , якщо ви припускаєте , короткі теги: <?function.
nyuszika7h
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.