Menyembunyikan informasi dalam Kucing


24

Anda adalah agen rahasia yang mencoba berkomunikasi dengan tanah air Anda. Tentu saja informasi itu perlu disembunyikan sehingga tidak ada orang yang mencuri pesan Anda. Apa yang lebih cocok daripada kucing? Semua orang suka gambar lucu kucing [rujukan?] , Jadi mereka tidak akan curiga ada informasi rahasia yang bersembunyi di sana!


Terinspirasi oleh algoritme permainan yang digunakan Monako untuk menyimpan informasi level dari level bersama , tugas Anda adalah menulis program yang menyandikan informasi ke dalam warna warna yang paling tidak signifikan.

Format pengodean:

  • 24 bit pertama menentukan panjang byte-string yang tersisa dalam bit
  • Gambar dibaca dari kiri ke kanan dan dari atas ke bawah, jelas dimulai dari piksel kiri atas
  • Saluran dibaca dari merah ke hijau ke biru
  • Bit paling signifikan dari setiap saluran dibaca
  • Bit disimpan dalam urutan Big Endian

Aturan:

  • Program Anda membutuhkan byte-string tunggal untuk dikodekan dan nama file gambar tunggal untuk gambar dasar
  • Gambar yang dihasilkan harus keluar sebagai file PNG warna asli
  • Anda dapat menggunakan I / O dalam bentuk apa pun yang Anda suka (ARGV, STDIN, STDOUT, menulis / membaca dari file), selama Anda menyatakan bagaimana menggunakan program Anda
  • Anda harus memilih gambar acak kucing lucu dan menyandikan program Anda ke dalamnya untuk menunjukkan bahwa program Anda berfungsi
  • Anda dapat mengasumsikan bahwa Anda hanya memberikan input yang valid, jika jumlah bit tidak mencukupi, gambar tidak dalam format warna yang sebenarnya, gambar tidak ada atau masalah serupa Anda dapat melakukan apa yang Anda inginkan
  • Anda dapat mengasumsikan bahwa gambar yang disediakan tidak mengandung saluran alfa
  • Panjangnya dihitung dalam UTF-8 byte tanpa BOM

Anda dapat menggunakan skrip PHP ini untuk menguji solusi Anda, berikan nama file PNG sebagai argumen baris perintah pertama:

<?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));
}

Spesifikasi Anda mengatakan "program Anda mengambil gambar tunggal sebagai basis". Dalam Mathematica gambar sebenarnya hanya ekspresi seperti yang lainnya, jadi secara teknis spesifikasi ini akan memungkinkan saya untuk melakukan pemuatan file di luar kode yang melakukan perhitungan (dengan parameter input menjadi gambar aktual dan bukan nama file gambar) . Jika Anda tidak ingin hal-hal seperti itu, Anda mungkin ingin menentukan bahwa program perlu mengambil nama file gambar sebagai input.
Martin Ender

4
AKU membantu saya terjebak di pabrik OW
TheDoctor

Juga, apakah bit yang tidak digunakan untuk pengkodean harus tetap tidak tersentuh? Atau bisakah kita mengaturnya ke apa pun yang kita inginkan (karena itu tidak akan benar-benar mempengaruhi kualitas gambar dan tidak masalah untuk decoding)?
Martin Ender

1
Dapatkah saya menggunakan pustaka non-built-in untuk memuat dan menyimpan file png, misalnya PIL dengan Python?
Claudiu

1
@TimWolla Dari kucing? Simpan di dalam ruangan dan pantau baki sampah. Dari foto itu? Jika Anda mengambil foto X-ray resolusi cukup tinggi, Anda mungkin dapat melihat status masing-masing transistor dalam chip flash. Saya yakin ini pasti metode yang paling efisien untuk menyampaikan informasi rahasia yang pernah dibuat, walaupun kucing mungkin punya ide lain.
Sonic Atom

Jawaban:


3

Perl & ImageMagick (Linux), 198 190

Sunting: Secara kebetulan, sebelumnya saya menguji pada komputer dengan Q8 (kedalaman 8 bit) versi diinstal ImageMagick. Versi Q16 'Standar' membutuhkan eksplisit -depth 8pada baris perintah. Di Linux, identifyhasilnya juga harus menghapus baris baru. Kedua faktor menyebabkan peningkatan ukuran kode, oleh karena itu saya memposting versi Linux (mungkin Mac juga) sebagai jawaban, dengan perbaikan diterapkan, dan juga dengan beberapa hal yang hanya Windows yang dihapus (konversi cr-lf, konversi biner vs teks, dll.). Versi portabel (sedikit lebih panjang) diposting di dekat akhir.

Dengan baris baru untuk keterbacaan:

$/=$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

Menjalankan:

perl cat.pl

Bunyinya dari STDIN, nama file gambar di baris pertama, pesan 'rahasia' berikut, diakhiri dengan ctrl-D. Nama file keluaran asli dengan .pngditambahkan - tidak terlalu bagus, itu hanya dilakukan untuk singkatnya.

Berikut gambar dengan beberapa informasi rahasia yang tersembunyi di dalamnya:

masukkan deskripsi gambar di sini

Dan dengan beberapa komentar:

# 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

Berikutnya adalah versi portabel, berjalan pada Windows (digunakan ctrl-Zuntuk mengakhiri input) dan Linux, jumlah byte adalah 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

Mathematica, 255 234 206 byte

Saya telah melihat begitu banyak 255saat menguji ini, saya sangat senang tentang ukuran kode. :) Dan kemudian ambisi saya untuk bermain golf lebih jauh lagi mendapatkan yang terbaik dari saya ...

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)&

Secara teknis fungsi dan bukan "program", tetapi sekali lagi ini cukup banyak bagaimana Anda menulis "program" di Mathematica, jika konsep itu bahkan berlaku di sana. Sebut saja seperti

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

Ini akan mengembalikan ekspresi gambar yang sebenarnya (karena itu cara paling alami untuk mengembalikan gambar di Mathematica), jadi jika Anda menginginkan file, Anda perlu mengekspornya:

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

Ini adalah contoh yang diperlukan:

masukkan deskripsi gambar di sini

Saya ingin menunjukkan pesan yang diterjemahkan kepada Anda di sini, tetapi tidak cocok ... jadi jalankan melalui dekoder OP. ;)

Btw, saya bisa membuatnya bekerja dengan rahasia UTF-8 hanya 7 byte (berubah ToCharacterCode@#menjadi #~ToCharacterCode~"utf8").

Kode tidak dikunci:

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"]
)

"Saya ingin menunjukkan kepada Anda pesan yang diterjemahkan itu di sini, tetapi tidak cocok ... jadi jalankan melalui dekoder OP;;)" - Saya lakukan dan itu memberi saya "?????????? ??? +++++++ ?? ++++++++++++++++++++ ================= ~ === ~ ============ ~ :::: ~~~~~ = [... untuk 9773 karakter] "
TessellatingHeckler

1
@ TessellatingHeckler, itu benar. coba dengan font monospace dan ketahuilah bahwa ada baris baru UNIX di sana (mis. coba di terminal atau PowerShell dengan lebar setidaknya 180 karakter, atau jika Anda menjalankannya sebagai skrip web di browser Anda, kemudian lihat sumbernya);)
Martin Ender

2
Saya melihat! Sangat meta. Membantu saya juga dalam versi Putty Putty, 😸
TessellatingHeckler

5

PHP, 530 byte

<?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;}}}

Jalankan seperti php 25443.php -i<input image> -o<output image> -t<file to hide>.

Dan inilah contoh gambar.

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

Kode yang tidak digabungkan disembunyikan dalam gambar sampel. Diuji dengan decoder OP. Maaf untuk gambar kucing tidak lucu.


1
Harap tambahkan kode yang tidak dipisahkan dalam jawaban Anda.
AL

1
Anda dapat mempersingkat 0xffmenjadi 255.
TimWolla

Anda dapat menyimpan 4 byte jika Anda menganggap tag pendek: <?function.
nyuszika7h
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.