고양이 정보 숨기기


24

귀하는 조국과 의사 소통을 시도하는 비밀 요원입니다. 물론 정보를 숨겨야하기 때문에 아무도 도청하는 메시지가 없습니다. 고양이보다 무엇이 더 좋을까요? 모두 고양이의 웃긴 사진을 좋아 합니다. [인용 필요] 비밀 정보가 숨겨져있는 것으로 의심되지 않습니다!


Monaco가 공유 레벨의 레벨 정보를 저장하기 위해 사용하는 알고리즘에서 영감을 얻은 것은 정보를 이미지의 최소 색상 비트로 인코딩하는 프로그램을 작성하는 것입니다.

인코딩 형식 :

  • 처음 24 비트는 나머지 인코딩 된 바이트 문자열의 길이를 결정 비트
  • 이미지는 왼쪽에서 오른쪽으로, 위에서 아래로 읽히고 분명히 왼쪽 위 픽셀에서 시작합니다.
  • 채널은 빨간색에서 녹색, 파란색으로 읽습니다.
  • 각 채널에서 최하위 비트를 읽습니다.
  • 비트는 빅 엔디안 순서로 저장됩니다

규칙 :

  • 프로그램은 단일 바이트 문자열을 인코딩하고 기본 이미지의 단일 이미지 파일 이름을 사용합니다.
  • 결과 이미지는 실제 색상 PNG 파일로 나와야합니다.
  • 프로그램 사용 방법을 명시하는 한 I / O를 원하는 형식 (ARGV, STDIN, STDOUT, 파일 쓰기 / 읽기)으로 사용할 수 있습니다.
  • 재미있는 고양이의 임의의 이미지를 선택하고 프로그램을 인코딩하여 프로그램이 작동 함을 보여 주어야합니다.
  • 비트 수가 충분하지 않거나 이미지가 트루 컬러 형식이 아니거나 이미지가 존재하지 않거나 원하는 문제를 수행 할 수있는 유사한 문제가있는 경우 유효한 입력 만 제공한다고 가정 할 수 있습니다.
  • 제공된 이미지에 알파 채널이 포함되어 있지 않다고 가정 할 수 있습니다.
  • 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에서 이미지는 실제로 다른 모든 것과 같은 표현이므로 기술적 으로이 사양을 사용하면 계산을 수행하는 코드 외부에서 파일로드를 수행 할 수 있습니다 (입력 매개 변수는 이미지의 파일 이름 대신 실제 이미지 임) . 그런 것을 원하지 않으면 프로그램이 이미지의 파일 이름을 입력해야하도록 지정할 수 있습니다.
Martin Ender

4
ME helpimtrappedinacatfactory OW
TheDoctor

또한 인코딩에 사용되지 않은 비트는 그대로 유지해야합니까? 또는 이미지 품질에 실제로 영향을 미치지 않고 디코딩에 중요하지 않기 때문에 원하는대로 설정할 수 있습니까?
Martin Ender

1
내장 라이브러리가 아닌 라이브러리를 사용하여 png 파일 (예 : PIL in Python)을로드하고 저장할 수 있습니까?
Claudiu

1
@TimWolla 고양이에서? 실내에 보관하고 쓰레기통을 모니터링하십시오. 사진에서? 충분히 높은 해상도의 X-ray 사진을 찍으면 플래시 칩의 개별 트랜지스터 상태를 볼 수 있습니다. 고양이가 다른 아이디어를 가지고있을지라도 이것이 비밀 정보를 전달하는 가장 효율적인 방법이어야한다고 확신합니다.
Sonic Atom

답변:


3

Perl & ImageMagick (Linux), 198 190

편집 : 우연히, 이전에 Q8 (8 비트 깊이) 버전의 ImageMagick이 설치된 컴퓨터에서 테스트했습니다. '표준'Q16 버전은 -depth 8명령 행에 명시 적이어야합니다 . Linux에서는 identify결과도 개행을 제거해야합니다. 두 가지 요소 모두 코드 크기 증가로 이어 지므로 Linux (아마도 Mac도 가능) 버전을 수정 사항으로 적용하고 일부 Windows 전용 항목 (cr-lf 변환, 이진 대 텍스트 등)을 제거하여 답변합니다. 휴대용 (약간 더 긴) 버전이 거의 끝에 게시됩니다.

가독성을위한 개행 :

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

매쓰, 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의 디코더를 통해 실행하십시오. ;)

Btw, 나는 단지 7 바이트 (변경) ToCharacterCode@#로 UTF-8 비밀로 작동하게 만들 수 있습니다 #~ToCharacterCode~"utf8".

Ungolfed 코드 :

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

1
@TessellatingHeckler, 맞습니다. 고정 폭 글꼴로 시도하고 거기에 UNIX 스타일의 새 줄이 있는지 확인하십시오 (예 : 너비가 180 자 이상인 터미널 또는 PowerShell에서 시도하거나 브라우저에서 웹 스크립트로 실행중인 경우, ;)
Martin Ender

2
내가 참조! 매우 메타. 내가 KiTTY 버전의 PuTTY에있는 것을 도와줍니다. 😸
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

샘플 이미지에 ungolfed 코드가 숨겨져 있습니다. OP의 디코더로 테스트했습니다. 웃긴 고양이 사진이 없어서 죄송합니다.


1
답에 ungolfed 코드를 추가하십시오.
AL

1
을 (를) 단축 0xff할 수 있습니다 255.
TimWolla

짧은 태그를 가정하면 4 바이트를 절약 할 수 있습니다 <?function.
nyuszika7 시간
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.