Ẩn thông tin ở Mèo


24

Bạn là một đặc vụ bí mật cố gắng giao tiếp với tổ quốc của bạn. Tất nhiên thông tin cần phải được ẩn đi để không ai nghe thấy tin nhắn của bạn. Điều gì sẽ phù hợp hơn một con mèo? Mọi người đều thích những bức ảnh hài hước về mèo [cần dẫn nguồn] , vì vậy họ sẽ không nghi ngờ thông tin bí mật ẩn trong đó!


Lấy cảm hứng từ thuật toán mà trò chơi mà Monaco sử dụng để lưu thông tin cấp độ của các cấp độ được chia sẻ , nhiệm vụ của bạn là viết một chương trình mã hóa thông tin thành một chút ít màu sắc quan trọng nhất của hình ảnh.

Định dạng mã hóa:

  • 24 bit đầu tiên xác định độ dài của chuỗi byte được mã hóa còn lại tính bằng bit
  • Hình ảnh được đọc từ trái sang phải và từ trên xuống dưới, rõ ràng bắt đầu từ pixel phía trên bên trái
  • Các kênh được đọc từ đỏ sang xanh sang xanh
  • Bit ít quan trọng nhất từ ​​mỗi kênh được đọc
  • Các bit được lưu theo thứ tự Big Endian

Quy tắc:

  • Chương trình của bạn lấy một chuỗi byte đơn được mã hóa và một tên tệp hình ảnh duy nhất cho hình ảnh cơ sở
  • Hình ảnh thu được phải được đưa ra dưới dạng tệp PNG màu thực
  • Bạn có thể sử dụng I / O dưới bất kỳ hình thức nào bạn thích (ARGV, STDIN, STDOUT, viết / đọc từ một tệp), miễn là bạn nêu cách sử dụng chương trình của mình
  • Bạn phải chọn một hình ảnh ngẫu nhiên của một con mèo vui nhộn và mã hóa chương trình của bạn vào đó để cho thấy rằng chương trình của bạn hoạt động
  • Bạn có thể cho rằng bạn chỉ được cung cấp đầu vào hợp lệ, nếu số lượng bit không đủ, hình ảnh không ở định dạng màu thực, hình ảnh không tồn tại hoặc các vấn đề tương tự bạn có thể làm những gì bạn muốn
  • Bạn có thể cho rằng hình ảnh được cung cấp không chứa bất kỳ kênh alpha nào
  • Độ dài được tính bằng byte UTF-8 mà không cần BOM

Bạn có thể sử dụng tập lệnh PHP này để kiểm tra giải pháp của mình, cung cấp tên của tệp PNG làm đối số dòng lệnh đầu tiên:

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

Đặc điểm kỹ thuật của bạn cho biết "chương trình của bạn lấy một hình ảnh làm cơ sở". Trong Mathicala, một hình ảnh thực sự chỉ là một biểu thức như mọi thứ khác, vì vậy về mặt kỹ thuật, thông số kỹ thuật này sẽ cho phép tôi thực hiện tải tệp bên ngoài mã thực hiện tính toán (với tham số đầu vào là hình ảnh thực tế thay vì tên tệp của hình ảnh) . Nếu bạn không muốn những thứ như vậy, bạn có thể muốn chỉ định rằng chương trình cần lấy tên tệp của hình ảnh làm đầu vào.
Martin Ender

4
ME helpimtrappinginacatfactory OW
TheDoctor

Ngoài ra, các bit không được sử dụng để mã hóa có cần được giữ nguyên không? Hoặc chúng ta có thể đặt chúng thành bất cứ điều gì chúng ta muốn (vì điều đó sẽ không thực sự ảnh hưởng đến chất lượng hình ảnh và không quan trọng để giải mã)?
Martin Ender

1
Tôi có thể sử dụng thư viện không tích hợp để tải và lưu tệp png, ví dụ PIL trong Python không?
Claudiu

1
@TimWolla Từ con mèo? Giữ nó trong nhà và theo dõi khay xả rác. Từ bức ảnh? Nếu bạn chụp ảnh tia X có độ phân giải đủ cao, bạn có thể thấy trạng thái của các bóng bán dẫn riêng lẻ trong chip flash. Tôi chắc chắn đây phải là phương pháp truyền thông tin bí mật hiệu quả nhất từng được nghĩ ra, mặc dù con mèo có thể có những ý tưởng khác.
Sonic Atom

Câu trả lời:


3

Perl & ImageMagick (Linux), 198 190

Chỉnh sửa: Do một sự trùng hợp ngẫu nhiên, trước đó tôi đã thử nghiệm trên máy tính có cài đặt ImageMagick Q8 (độ sâu 8 bit). Phiên bản Q16 'tiêu chuẩn' yêu cầu rõ ràng -depth 8trên dòng lệnh. Trên Linux, identifykết quả cũng yêu cầu xóa dòng mới. Cả hai yếu tố dẫn đến tăng kích thước mã, do đó tôi đăng phiên bản Linux (có thể là Mac) như một câu trả lời, với các bản sửa lỗi được áp dụng, và với một số nội dung chỉ dành cho Windows đã bị xóa (chuyển đổi cr-lf, nhị phân so với văn bản, v.v.). Phiên bản di động (hơi dài hơn) được đăng gần cuối.

Với các dòng mới để dễ đọc:

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

Chạy:

perl cat.pl

Nó đọc từ STDIN, tên tệp hình ảnh trên dòng đầu tiên, thông báo 'bí mật' theo sau, chấm dứt với ctrl-D. Tên tệp đầu ra là bản gốc có .pnggắn thêm - không đẹp lắm, nó chỉ được thực hiện cho ngắn gọn.

Đây là một hình ảnh với một số thông tin rất bí mật ẩn bên trong:

nhập mô tả hình ảnh ở đây

Và với một số ý kiến:

# 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

Tiếp theo là phiên bản di động, chạy trên cả Windows (sử dụng ctrl-Zđể chấm dứt đầu vào) và Linux, số byte là 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

Toán học, 255 234 206 byte

Tôi đã thấy rất nhiều 255s trong khi thử nghiệm điều này, tôi rất vui về kích thước của mã. :) Và rồi tham vọng đánh gôn của tôi thậm chí còn khiến tôi cảm thấy tốt nhất ...

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

Về mặt kỹ thuật, đây là một chức năng và không phải là một "chương trình", nhưng một lần nữa, đây là cách bạn viết "chương trình" trong Mathicala, nếu khái niệm đó thậm chí còn hợp lệ ở đó. Gọi nó như thế

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

Nó sẽ trả về một biểu thức hình ảnh thực tế (vì đó là cách tự nhiên nhất để trả về một hình ảnh trong Mathicala), vì vậy nếu bạn muốn có một tệp, bạn cần xuất nó:

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

Dưới đây là ví dụ bắt buộc:

nhập mô tả hình ảnh ở đây

Tôi rất muốn cho bạn xem tin nhắn được giải mã ở đây, nhưng nó không phù hợp ... vì vậy hãy chạy nó qua bộ giải mã của OP. ;)

Btw, tôi có thể làm cho nó hoạt động với các bí mật UTF-8 chỉ với 7 byte (đổi ToCharacterCode@#thành #~ToCharacterCode~"utf8").

Mã bị đánh cắp:

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

"Tôi rất muốn cho bạn xem tin nhắn được giải mã ở đây, nhưng nó không phù hợp ... vì vậy hãy chạy nó qua bộ giải mã của OP.)" - Tôi đã làm và nó mang lại cho tôi "????????? ??? +++++++ ?? ++++++++++++++++++++ ================= ~ === ~ ============ ~ :::: ~~~~~ = [... cho 9773 ký tự] "
TessellatingHeckler

1
@TessellatingHeckler, đúng vậy. hãy thử nó trong một phông chữ đơn cách và lưu ý rằng có các dòng mới kiểu UNIX trong đó (ví dụ: thử trong một thiết bị đầu cuối hoặc PowerShell với độ rộng ít nhất 180 ký tự hoặc nếu bạn đang chạy nó dưới dạng tập lệnh web trong trình duyệt của mình, sau đó xem nguồn);)
Martin Ender

2
Tôi hiểu rồi! Rất meta. Cũng giúp tôi tham gia phiên bản KiTTY của 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;}}}

Chạy như thế php 25443.php -i<input image> -o<output image> -t<file to hide>.

Và đây là một hình ảnh mẫu.

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

Mã Ungolfed được ẩn trong hình ảnh mẫu. Đã thử nghiệm với bộ giải mã của OP. Xin lỗi vì hình ảnh con mèo không vui.


1
Vui lòng thêm mã không mã trong câu trả lời của bạn.
AL

1
Bạn có thể rút ngắn 0xffđể 255.
TimWolla

Bạn có thể lưu 4 byte nếu bạn giả sử các thẻ ngắn : <?function.
nyuszika7h
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.