Kedilerde bilgiyi gizleme


24

Sen anavatanınla iletişim kurmaya çalışan gizli bir ajansın. Elbette bilgilerin gizlenmesi gerekiyor, böylece hiç kimse mesajınızı bırakmıyor. Bir kediden daha uygun ne olabilir ki? Herkes kedilerin komik resimlerini sever [alıntı gerekli] , bu yüzden orada saklanan gizli bilgilerden şüphelenmezler!


Monaco oyunu, paylaşılan seviyelerin seviye bilgilerini kaydetmek için kullandığı algoritmadan esinlenerek, bilgileri bir resmin renklerinin en az anlamlı bitine kodlanmış bir program yazmak sizin görevinizdir.

Kodlama formatı:

  • İlk 24 bit, kalan kodlanmış bayt dizesinin bit cinsinden uzunluğunu belirler.
  • Görüntü soldan sağa ve yukarıdan aşağıya okunur, açık bir şekilde sol üst pikselden başlayarak okunur
  • Kanallar kırmızıdan yeşile maviye okunur
  • Her kanaldan en az anlamlı bit okunur
  • Bitler Big Endian sırasına göre kaydedilir

Kurallar:

  • Programınız kodlanacak tek bir bayt dizisi ve temel görüntü için tek bir görüntü dosya adı alır.
  • Ortaya çıkan görüntü, gerçek bir renkli PNG dosyası olarak ortaya çıkmalıdır
  • Programınızı nasıl kullanacağınızı belirttiğiniz sürece, G / Ç'yi istediğiniz biçimde (ARGV, STDIN, STDOUT, bir dosyadan yazma / okuma) kullanabilirsiniz.
  • Komik bir kedinin rastgele görüntüsünü seçmeli ve programınızın çalıştığını göstermek için programınıza kodlamalısınız.
  • Yalnızca geçerli girdi sağladığınızı, bitlerin miktarı yeterli değilse, resmin gerçek renk biçiminde olmadığını, resmin mevcut olmadığını veya istediğiniz gibi yapabileceğiniz benzer sorunları olduğunu varsayabilirsiniz.
  • Sağlanan görüntünün alfa kanalı içermediğini varsayabilirsiniz.
  • Uzunluk BOM olmadan UTF-8 bayt olarak sayılır

Çözümünüzü test etmek için bu PHP betiğini kullanabilir, PNG dosyasının adını ilk komut satırı argümanı olarak kullanabilirsiniz:

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

Spesifikasyonunuz "programınız temel olarak tek bir görüntü alıyor" diyor. Mathematica'da bir görüntü aslında sadece her şey gibi bir ifadedir, bu nedenle teknik olarak bu özellik hesaplamayı yapan kodun dışında dosya yükleme yapmama izin verir (giriş parametresi görüntünün dosya adı yerine gerçek bir görüntüdür) . Böyle bir şey istemiyorsanız, programın bir görüntünün dosya adını girdi olarak alması gerektiğini belirtmek isteyebilirsiniz.
Martin Ender

4
ME helpimtrappedinacatfactory OW
TheDoctor

Ayrıca, kodlama için kullanılmayan bitlerin dokunulmaması gerekir mi? Veya onları istediğimiz şekilde ayarlayabilir miyiz (çünkü bu görüntü kalitesini gerçekten etkilemeyecek ve kod çözmenin önemi yoktur).
Martin Ender

1
Png dosyasını yüklemek ve kaydetmek için yerleşik olmayan bir kütüphane kullanabilir miyim, örneğin Python'daki PIL?
Claudiu

1
@TimWolla Kediden mi? İçeride tutun ve alt tepsiyi izleyin. Fotoğraftan Yeterince yüksek çözünürlüklü bir X-ışını fotoğrafı çekerseniz, flaş çipindeki ayrı transistörlerin durumunu görebilirsiniz. Kedinin başka fikirleri olsa da, bunun şimdiye kadar tasarlanan gizli bilgileri aktarmada en etkili yöntem olması gerektiğine eminim.
Sonic Atom

Yanıtlar:


3

Perl ve ImageMagick (Linux), 198 190

Düzenleme: Bir tesadüf eseri, daha önce ImageMagick'in Q8 (8 bit derinlik) versiyonunun yüklü olduğu bir bilgisayarda denedim. 'Standart' Q16 sürümü -depth 8komut satırında açık olmasını gerektirir . Linux'ta identifysonuç da yeni satırın kaldırılmasını gerektirir. Her iki faktör de kod büyüklüğünün artmasına neden oluyor, bu yüzden Linux (muhtemelen Mac de) versiyonunu bir cevap olarak, düzeltmeleri uygulayarak ve ayrıca yalnızca Windows'a özgü bazı şeyler kaldırılmış olarak (cr-lf dönüşümü, ikili vs metin vb.) Gönderiyorum. Taşınabilir (biraz daha uzun) sürüm sonlara yakın bir yerde yayınlanmaktadır.

Okunabilirlik için yeni satırlarla:

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

Koşmak:

perl cat.pl

STDIN'den okur, ilk satırdaki resim dosyası adı, 'gizli' mesajı ile sonlanır ctrl-D. Çıktı dosya adı .pngekli olarak orijinal - çok hoş değil, sadece kısalık için yapıldı.

İşte içine gizlenmiş bazı gizli bilgileri içeren bir resim:

görüntü tanımını buraya girin

Ve bazı yorumlar ile:

# 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

Sonraki taşınabilir sürümü, hem Windows ( ctrl-Zgirişi sonlandırmak için kullanın ) ve Linux üzerinde çalışır, bayt sayısı 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 bayt

Bunu 255test ederken çok fazla kişi gördüm , kodun boyutundan makul derecede mutluyum. :) Ve sonra onu daha da aşağı golf atma tutkum beni en iyi şekilde değerlendirdi ...

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

Teknik olarak bir "program" değil, bir fonksiyondur, ancak o zaman yine bu kavram orada geçerliyse, Mathematica'da "programları" nasıl yazdığınızla ilgili. Gibi ara

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

Gerçek bir resim ifadesi döndürür (çünkü bu, Mathematica'daki bir resmi döndürmenin en doğal yoludur), bu nedenle bir dosya istiyorsanız, dışa aktarmanız gerekir:

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

İşte gerekli örnek:

görüntü tanımını buraya girin

Size burada kodu çözülmüş iletiyi göstermeyi çok isterim, ama uymuyor ... bu yüzden OP'nin kod çözücüsünden geçir. ;)

BTW, UTF-8 sırlarıyla sadece 7 baytlık çalışmasını ToCharacterCode@#sağlayabilirim #~ToCharacterCode~"utf8".

Ungolfed kod:

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

“Size burada kodu çözülmüş iletiyi göstermeyi çok isterim, ancak uymuyor ... bu yüzden OP'nin kod çözücüsünü çalıştırın.;)” - Yaptım ve bana verdi ”????????? ??? +++++++ ?? ++++++++++++++++++++ ================= ~ === ~ ============ ~ :::: ~~~~~ = [... 9773 için karakter]"
TessellatingHeckler

1
@TessellatingHeckler, bu doğru. monospaced bir fontta deneyin ve orada UNIX stili yeni çizgiler olduğunu unutmayın (örneğin, en az 180 karakter genişliğinde bir terminalde veya PowerShell'de deneyin veya tarayıcınızda web komut dosyası olarak çalıştırıyorsanız, sonra kaynağı görüntüleyin);)
Martin Ender

2
Anlıyorum! Çok meta. 😸 Ben de PuTTY KiTTY sürümünde olduğumu yardımcı olur
TessellatingHeckler

5

PHP, 530 bayt

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

Gibi koş php 25443.php -i<input image> -o<output image> -t<file to hide>.

Ve işte örnek bir resim.

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

Örneklenmemiş kod örnek resimde gizlidir. OP kod çözücüyle test edilmiştir. Komik kedi resmi için üzgünüm.


1
Lütfen cevabınıza ungolfed kodunu ekleyin.
AL

1
Sen kısaltabilir 0xffiçin 255.
TimWolla

Eğer kısa etiketler varsayalım eğer 4 bayt kaydedebilirsiniz: <?function.
nyuszika7h
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.