猫の情報を隠す


24

あなたはあなたの祖国と通信しようとしている秘密のエージェントです。もちろん、情報を隠して、だれもメッセージを落とさないようにする必要があります。猫よりも適しているものは何ですか?誰もが猫の面白い写真を愛している[要出典]ので、彼らはそこに隠れている秘密の情報を疑うことはありません!


ゲームのモナコが共有レベルのレベル情報を保存するために使用するアルゴリズムに触発され画像の色の最下位ビットに情報をエンコードするプログラムを作成するのはあなたのタスクです。

エンコード形式:

  • 最初の24ビットは、残りのエンコードされたバイト文字列の長さをビット単位で決定します
  • 画像は左から右、上から下に読み取られ、明らかに左上のピクセルから始まります。
  • チャンネルは赤から緑、青に読み取られます
  • 各チャネルの最下位ビットが読み取られます
  • ビットはビッグエンディアン順に保存されます

ルール:

  • プログラムは、エンコードされる単一のバイト文字列と、ベースイメージの単一のイメージファイル名を受け取ります
  • 結果の画像はトゥルーカラーPNGファイルとして出力される必要があります
  • プログラムの使用方法を述べる限り、好きな形式(ARGV、STDIN、STDOUT、ファイルの書き込み/読み取り)でI / Oを使用できます。
  • 面白い猫のランダムな画像を選択し、プログラムをエンコードして、プログラムが機能することを示す必要があります
  • 有効な入力のみが提供され、ビットの量が十分でない場合、画像がトゥルーカラー形式ではない場合、画像が存在しない場合、または同様の問題が発生する場合があります
  • 提供された画像にはアルファチャンネルが含まれていないと想定できます
  • 長さはBOMなしのUTF-8バイトでカウントされます

この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では、画像は実際には他のすべての式にすぎないため、技術的にはこの仕様により、計算を実行するコードの外部でファイルをロードできます(入力パラメータは画像のファイル名ではなく実際の画像です) 。そのようなものが必要ない場合は、プログラムが入力としてイメージのファイル名を取る必要があることを指定することができます。
マーティンエンダー14

4
ME helpimtrappedinacatfactory OW
TheDoctor

また、エンコードに使用されないビットはそのままにする必要がありますか?または、それらを必要なものに設定することができます(これは実際に画質に影響を与えず、デコードには関係ありません)?
マーティンエンダー14

1
PythonのPILなど、非組み込みライブラリを使用してpngファイルをロードおよび保存できますか?
クラウディ14

1
@TimWolla猫から?屋内に保管し、ごみトレイを監視します。写真から?十分に高い解像度のX線写真を撮ると、フラッシュチップ内の個々のトランジスタの状態を確認できる場合があります。これは、これまで考案された秘密情報を渡す最も効率的な方法でなければならないことは確かですが、猫は他のアイデアを持っているかもしれません。
ソニックアトム

回答:


3

PerlおよびImageMagick(Linux)、198 190

編集:偶然にも、ImageMagickのQ8(8ビット深度)バージョンがインストールされたコンピューターでテストしました。「標準」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から読み取り、最初の行にイメージファイル名、「secret」メッセージが続き、で終了し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

Mathematica、255 234 206バイト

私は255これをテストしている間に非常に多くを見てきましたが、コードのサイズについては不当に満足しています。:)それから、ゴルフをしたいという私の野望は、さらに最高になりました...

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

必要な例を次に示します。

ここに画像の説明を入力してください

ここでデコードされたメッセージを表示したいと思いますが、それは適合しません... OPのデコーダーを介して実行します。;)

ところで、私はそれだけで7バイト(変更のUTF-8の秘密を動作させることができ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"]
)

「ここにデコードされたメッセージを表示したいのですが、収まりません...だから、OPのデコーダーを介して実行してください。;)」-しました。「????????? ??? +++++++ ?? ++++++++++++++++++++ =================〜 ===〜============〜::::: ~~~~~~ = [... 9773文字の場合] "
TessellatingHeckler 14

1
@TessellatingHeckler、それは正しい。等幅フォントで試してみて、そこにUNIXスタイルの改行があることに注意してください(たとえば、幅が180文字以上の端末またはPowerShellで試してください。ブラウザでWebスクリプトとして実行している場合は、その後、ソースを表示);)
マーティン・エンダー14

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
あなたは短縮することができます0xff255
ティムウォラ

短いタグを想定すると、4バイトを節約できます<?function
nyuszika7h 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.