ASCII 텍스트에서 PBM 비트 맵 파일 생성


19

PBM (휴대용 맵) 형식은 매우 간단한 ASCII 흑백 비트 맵 형식입니다.

다음은 문자 'J'(위키 백과 링크에서 복사하여 붙여 넣기)의 예입니다.

P1
# 문자 "J"의 비트 맵 예입니다.
6 10
0 0 0 1 0
0 0 0 1 0
0 0 0 1 0
0 0 0 1 0
0 0 0 1 0
0 0 0 1 0
1000 년
0 1 1 0 0
0 0 0 0 0
0 0 0 0 0

이제이 멋진 작은 형식으로 파일을 생성하는 작은 도구를 만들 차례입니다!

당신의 목표는 다음과 같은 규칙에 (모든 언어)이 따르는 것으로 가장 짧은 프로그램을 작성하는 것입니다 :

  1. 귀하의 프로그램은 표준 입력에서 하나의 문자열을 사용합니다 (예를 들어 CODEGOLF.STACKEXCHANGE.COM!)
  2. 비트 맵 (읽기 가능한) 문자열 표현으로 PBM 파일을 생성합니다.
  3. 각 문자는 8x8 격자로 구성됩니다.
  4. 문자 [AZ] (모두 대문자), 공백, 점 ( '.') 및 느낌표 ( '!')를 지원해야합니다.
  5. 외부 라이브러리는 허용되지 않습니다 (확실히 PBM 관련 라이브러리는 없습니다)!
  6. 사용 된 문자 세트는 단순히 프로그램 외부에 있지 않아야합니다. 도전의 일부는 캐릭터를 효율적으로 저장하는 것입니다 ...

PBM 형식의 유효성을 테스트하려면 김프 (또는 기타)를 사용하십시오. 샘플 입력 및 출력을 과시하십시오!

가장 짧은 솔루션은 2012-01-31에 대한 답변 포인트를 수여합니다.

즐거운 골프 되세요!

추신 : 나는 더 많은 경쟁자를 끌어 들이기 위해 바운티 (내 코드 골프 명성의 상당 부분)를 추가했습니다.


"비트 맵 표현"이란 글자처럼 보이는 것에 가까운 문자 표현을 의미합니까? 얼마나 가까이? 이진 코드 나 점자 또는 모스 부호의 비트 맵 표현과 같은 것이 허용됩니까?
Howard

@Howard : 아이디어는 '렌더링 된'(비트 매핑)이지만 여전히 사람이 읽을 수있는 형식 ( letters다른 말로)으로 원래 입력 텍스트를 포함하는 pbm 이미지를 생성하는 것입니다 . 연결된 예제와는 다릅니다.
ChristopheD

프로그램의 대부분이 30 비트 맵이기 때문에 kolmogorov-complexity 태그를 추가했습니다 .
피터 테일러

@ 피터 테일러 : 좋은 지적, 감사합니다!
ChristopheD

"외부 도서관"이 무엇인지에 대해 길고도 고통스러운 토론을 할 것이라고 생각합니다.
JB

답변:


9

GolfScript, 133 바이트

이것은 내 164-byte Perl 솔루션을 기반으로 하며 같은 니블 팩 4 x 5 픽셀 글꼴을 사용합니다. 다시 한 번 읽을 수있는 버전을 제공하겠습니다.

{91,65>"!. "+?}%:s"P4"\,8*8'FONT DATA HERE'{16base}%[3]/{:p;{[p=0]0=}s%}%]n*

여기서는 FONT DATA HERE71 바이트의 이진 압축 글꼴 데이터를 나타냅니다. 인코딩은 Perl 버전과 약간 다릅니다. 공백으로 묶인 문자열을 분할하는 대신 먼저 확장 한 다음 니블에서 분할합니다 3(글꼴의 어느 곳에서도 발생하지 않기 때문에 선택됨).

실제 스크립트의 글꼴 데이터에는 인쇄 할 수없는 문자가 포함되어 있으므로 아래에 16 진 덤프로 표시합니다. xxd -r16 진수 덤프를 실행 가능한 GolfScript 코드로 다시 전환하는 데 사용하십시오 .

0000000: 7b39 312c 3635 3e22 212e 2022 2b3f 7d25  {91,65>"!. "+?}%
0000010: 3a73 2250 3422 5c2c 382a 3827 36e6 eff6  :s"P4"\,8*8'6...
0000020: 9219 8996 e6e7 7959 95f4 3999 9888 921a  ......yY..9.....
0000030: 8fd9 9998 2959 9514 3fe8 9eeb f21c 89b9  ....)Y..?.......
0000040: e9e6 2959 6564 3999 9889 929a 8999 8ba1  ..)Yed9.........
0000050: 295f 9283 9e6e f869 269f 9968 79e2 6299  )_...n.i&..hy.b.
0000060: 2f48 3327 7b31 3662 6173 657d 255b 335d  /H3'{16base}%[3]
0000070: 2f7b 3a70 3b7b 5b70 3d30 5d30 3d7d 7325  /{:p;{[p=0]0=}s%
0000080: 7d25 5d6e 2a                             }%]n*

펄 스크립트와는 달리,이 코드가 설정 이외의 모든 문자를 인쇄 A- Z, !, ., space재미 보이는 작은 구불 거리는 곡선으로. 구불 구불 한 부분을 공란으로 바꾸려면 2 개의 추가 문자가 필요합니다. 그것들을 완전히 제거하려면 4가 필요합니다.

이것은 내 첫 번째 GolfScript 프로그램이므로 최적화 할 여지가 남아 있어도 놀라지 않을 것입니다. 작동 방식은 다음과 같습니다.

  • {91,65>"!. "+?}%:s(유효한 입력 문자 매핑 A- Z, !, ., space28 및 양수인에 결과를 - 숫자 0을) s. 유효한 세트 외부의 모든 문자는 -1에 매핑되며, 이는 인쇄 할 때 구불 구불 한 소리를 생성합니다.

  • "P4"\,8*8"P4"값, 입력 길이의 8 배, 스택에 8을 푸시합니다. 마지막에 인쇄되면 PBM 헤더를 형성합니다.

  • {16base}%[3]/앞의 문자열 데이터 문자열을 가져 와서 각 바이트를 두 개의 니블로 나누고 결과를 값으로 구분 된 블록으로 나눕니다 3. {:p;{[p=0]0=}s%}%그런 다음 이러한 블록을 반복하여 먼저 각 블록을 변수에 할당 p한 다음 다시 매핑 된 입력 문자열을 반복 s하여 각 문자를의 해당 오프셋 값으로 바꿉니다 p. 재미있는 보이는 구조는 [p=0]0=동일하지 p=가의 끝을지나 어떤 오프셋 0 반환하는 것을 제외하고 p; 나는 그것을 정말로 좋아하지 않지만, 그것을 처리하는 더 짧은 방법을 알아낼 수 없었습니다.

  • 마지막으로 ]n*스택의 모든 항목 (세 개의 헤더 값과 이미지 데이터 배열)을 가져와 인쇄를 위해 줄 바꿈과 결합합니다.


매우 짧음 (모든 메트릭에 의해). 좋은!
ChristopheD

12

Perl, 164 바이트, zlib / gzip 압축 없음

문제를 자고 난 후 첫 솔루션보다 훨씬 짧은 솔루션을 찾아 낼 수있었습니다. 트릭은 규칙에서 작은 허점을 활용하는 것입니다. 문자는 각각 8 x 8 픽셀에 맞아야하지만 그 공간을 모두 채울 필요는 없습니다 . 그래서 나는 4 x 5 픽셀 글꼴을 직접 그려서 두 문자를 5 바이트로 묶을 수있었습니다.

결과는 다음과 같습니다.

"HELLO WORLD!" (스케일 x 4)

    "OH! 라지 독에 빠른 갈색 여우 점프." (원래 크기)

포함 된 글꼴 데이터로 실제 코드를 제공하기 전에 디 골프 버전을 보여 드리겠습니다.

y/A-Z!./\0-\033/ for @a = <> =~ /./g;
say "P4 " . 8*@a . " 8";
for $p (qw'PACKED FONT DATA') {
    print chr vec $p, ord, 4 for @a;
}

실제 코드에서는 PACKED FONT DATA공백으로 구분 된 8 개의 행 (14 바이트 행 4 개와 13 바이트 행 1 개와 공백 행 3 개 단일 널 바이트)으로 구성된 이진 문자열로 대체됩니다. 압축 된 데이터에 공백, 작은 따옴표 또는 백 슬래시가 포함되지 않도록 인코딩하여 글꼴을 의도적으로 설계했습니다 qw'...'.

압축 된 글꼴 문자열에는 인쇄 할 수없는 문자가 포함되어 있으므로 실제 스크립트를 16 진수 덤프로 제공했습니다. xxd -r다시 실행 가능한 Perl 코드로 바꾸려면 사용하십시오 .

0000000: 792f 412d 5a21 2e2f 002d 1b2f 666f 7240  y/A-Z!./.-./for@
0000010: 613d 3c3e 3d7e 2f2e 2f67 3b73 6179 2250  a=<>=~/./g;say"P
0000020: 3420 222e 382a 4061 2e22 2038 223b 666f  4 ".8*@a." 8";fo
0000030: 7224 7028 7177 2700 20e6 e6ff 9612 8999  r$p(qw'. .......
0000040: e6e6 7759 99f5 0420 9999 8898 128a df99  ..wY... ........
0000050: 9928 5999 1504 20ef 98ee fb12 8cb9 e9e9  .(Y... .........
0000060: 2659 6965 0420 9999 8899 928a 9989 ab21  &Yie. .........!
0000070: 599f 8220 e9e6 8f96 62f9 9986 972e 2699  Y.. ....b.....&.
0000080: f284 2000 2000 2729 7b70 7269 6e74 2063  .. . .'){print c
0000090: 6872 2076 6563 2470 2c6f 7264 2c34 666f  hr vec$p,ord,4fo
00000a0: 7240 617d                                r@a}

작동 방식은 다음과 같습니다.

  • 첫 번째 줄 (골프가 제거 된 버전)은 한 줄의 입력을 읽고, 문자 배열로 분할하고 (편리한 줄 바꿈 생략) 문자 AZ문자 !와 문자 및 .문자 코드 0 ~ 28에 매핑합니다. 일반적으로 ASCII / 유니 코드로 인쇄 할 수없는 제어 문자에 해당합니다. (이것의 작은 부작용은 입력의 모든 탭이 Js로 인쇄된다는 것 입니다.) 출력 루프는 28 이상의 코드를 공백으로 변환하기 때문에 공백 문자는 매핑되지 않은 상태로 남아 있습니다.

  • 두 번째 줄은 PBM 헤더를 인쇄합니다. Perl 5.10 say기능을 사용하므로 작동하려면이 스크립트를 실행해야합니다 perl -M5.010.

  • 출력 루프는 공백으로 구분 된 묶음 이미지 행 목록을 가져 와서 각각을 $p차례로 할당합니다 . (포장 된 데이터에 공백이나 '문자가 포함되지 않도록 글꼴을 디자인했습니다 .) 그런 다음 @aPerl의 vec명령을 사용하여 입력 문자를 반복 하여 이미지 행에서 매핑 된 문자 코드에 해당하는 4 비트 니블을 추출합니다. 8 비트 바이트로 채우고 인쇄합니다.


이전 답변, 268 바이트 :

이것은 빠르고 더러운 첫 번째 시도입니다. PleaseStand의 글꼴을 훔쳐서 소스 코드와 함께 압축했습니다. 결과 스크립트는 대부분 인쇄 할 수 없으므로 다음은 16 진 덤프입니다. xxd -r실행 가능한 Perl 코드로 바꾸는 데 사용하십시오 .

0000000: 7573 6520 436f 6d70 7265 7373 275a 6c69  use Compress'Zli
0000010: 623b 6576 616c 2075 6e63 6f6d 7072 6573  b;eval uncompres
0000020: 7320 2778 da85 d03d 4b03 4118 85d1 452c  s 'x...=K.A...E,
0000030: b69c 72cb 7519 4894 552c 2c02 3319 ee5c  ..r.u.H.U,,.3..\
0000040: d7b8 5a89 6093 4634 7e82 c490 6c91 8597  ..Z.`.F4~...l...
0000050: 80fe 7267 d660 23ae e52d 0e0f dcd6 f8c3  ..rg.`#..-......
0000060: e9d1 5e6e ccec a15c ddb5 c5d5 495e 94a3  ..^n...\....I^..
0000070: 83b7 c7f9 73f3 5216 f9a8 787a 5fea 666c  ....s.R...xz_.fl
0000080: 9dd1 b763 dd98 76f8 2df6 0799 5811 7144  ...c..v.-...X.qD
0000090: 4acc ee9d b8b0 c90f 7e4a 8264 6016 cbd7  J.......~J.d`...
00000a0: 79f3 1b91 047c 4055 409e 9e54 1dda ed41  y....|@U@..T...A
00000b0: 9a20 8080 6adc 5c47 8488 7495 f621 01d7  . ..j.\G..t..!..
00000c0: 6b6c 902e b6c8 2a6a 6643 f56f e99c 115d  kl....*jfC.o...]
00000d0: 5c7a f1b2 13d0 3453 790f da74 c813 751d  \z....4Sy..t..u.
00000e0: 11ce d821 ad90 247f 2292 5b54 c14f 3c4e  ...!..$.".[T.O<N
00000f0: 49c5 4c53 a1a7 c478 391c 714c f113 0747  I.LS...x9.qL...G
0000100: ab6c 4482 9fd2 177a 5677 6327            .lD....zVwc'

압축 해제 된 Perl 코드는 다음과 같은 프리앰블로 구성됩니다.

y;A-Z.! ;;cd,say"P4 ",8*length," 8"for$t=<>

다음 코드는 8 번 반복됩니다.

;$_=$t;y(A-Z.! )'BITMAP DATA HERE';print

BITMAP DATA HERE29 바이트 폰트의 하나 개의 로우를 인코딩 대체.


최신 솔루션은 매우 좋습니다. 이것이 165 자로 이루어질 수 있다고 상상하지 못했습니다.
ChristopheD

6

8086 기계 코드

190 바이트 (BIOS를 사용하는 122 바이트)

Base64로 인코딩 된 WinXP / MSDos .COM 파일은 다음과 같습니다.

M8COwCaKDoUEitEmxD4MAaCAAP7IfliK8MHgA7cK9ve9egEAZ
vy0APb3AUb6iMi0APb3AUb+x0YACg2DxQK+ggCK7qz24YvYJo
ohswjQ5LAwFACIRgBF/st18v7NdeRH/sp10sZGACS6cAG0Cc0
hw1AxCg0wMDAgMDA=

텍스트를 해독하고 "pbm.com"으로 저장 하려면 ( 이와 같은 것을 사용하십시오 ). 그런 다음 명령 프롬프트에서 다음을 입력하십시오.

인코딩 할 pbm 텍스트> outputfilename.pbm

표준 명령 프롬프트와 DosBox V0.74을 모두 사용하여 WinXP 컴퓨터에서 이것을 테스트했습니다.

최신 정보

이 버전은 190 바이트이며 Ilmari Karonen의 작은 글꼴을 사용합니다 (bios는 여기에 없습니다!) :-

voAArf7Iflq7YwG/vgG6Cg20Bfbk9vIAZfsy5PbyAUX5Vqw48HQoLEFzCDQG/sAMGSQfM8
nQ6NfA0QPS6IjEsQSwJtDsENCq4vewMKrr04DDEF6A+7N1ycYFJLqzAbQJzSHDdnb/loIZ
mXZ2flmZ9QAAIJmZEZGCFb+ZmSFZmYUPDy9/kXf9ghPZeXkmWWllAAAgmZkRmZIVmRldKF
mfEgAAAHl2H5Zi+ZkWnicmmfIAICBQMQoNMDAwIDUKDQ==

매우 좋은 해결책. 현재 이것은 바운티의 도전자이며 약 20 시간 안에 수여됩니다. 잘 했어!
ChristopheD

이것에 대한 어셈블리 코드도 게시 할 수 있습니까?
Sir_Lagsalot

1
디스 어셈블리를보고 코드를 테스트 한 후에는 바이오스에서 제공하는 비트 맵 글꼴을 사용하고있는 것 같습니다. 이것은 프로그램이 챌린지에 필요하지 않은 소문자, 기호 및 문장 부호를 출력 할 수 있다는 사실로 확인할 수 있습니다. 따라서 글꼴은 프로그램 외부에 있으며 저장하지 않습니다 (적어도 내 의견으로는).
Sir_Lagsalot

@ 스키즈 : 이것을 확인할 수 있습니까? 그것은 여전히 ​​매우 멋진 솔루션을 만들지 만 사양에 대해서는 약간 반대입니다.
ChristopheD

1
@ChristopheD : 음, JB는 "우리는 외부 라이브러리를 구성하는 것에 대해 길고도 고통스러운 토론을 할 것이라고 생각했습니다." puts루비에서는 외부 라이브러리 라고 주장 할 수 있습니다. 예, 포인터 역 참조를 통해 액세스되는 bios 글꼴을 사용합니다 ( load글꼴을 RAM으로 가져 오는 작업 은 없습니다 ). 규칙을 너무 많이 구부릴 수 있습니다. 그 성가신 아이들을위한 것이 아니라면 나는 그것을 멀리 얻었을 것이다 ;-)
Skizz

6

쉘 스크립트 (코드 + 데이터 = 295 자)

tail, gzip 및 dd가 "외부 라이브러리"로 계산되지 않기를 바랍니다. 로 실행하십시오 echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. 내가 사용한 글꼴은 Small Fonts size 7.5이지만 Q에서 내림차순을 잘라 내야했습니다.

출력 예

라지 독에 빠른 갈색 여우 점프.  정말!

코드 (137 자)

i=`od -tu1|cut -c9-`
echo P4
for a in {0..7}
do for b in $i
do tail -2 $0|zcat|dd bs=1 count=1 skip=$((8*b+a))
done
done>8
wc -c 8
cat 8

완전한 스크립트

( xxd -r원본 파일을 다시 만드는 데 사용 )

0000000: 693d 606f 6420 2d74 7531 7c63 7574 202d  i=`od -tu1|cut -
0000010: 6339 2d60 0a65 6368 6f20 5034 0a66 6f72  c9-`.echo P4.for
0000020: 2061 2069 6e20 7b30 2e2e 377d 0a64 6f20   a in {0..7}.do 
0000030: 666f 7220 6220 696e 2024 690a 646f 2074  for b in $i.do t
0000040: 6169 6c20 2d32 2024 307c 7a63 6174 7c64  ail -2 $0|zcat|d
0000050: 6420 6273 3d31 2063 6f75 6e74 3d31 2073  d bs=1 count=1 s
0000060: 6b69 703d 2428 2838 2a62 2b61 2929 0a64  kip=$((8*b+a)).d
0000070: 6f6e 650a 646f 6e65 3e38 0a77 6320 2d63  one.done>8.wc -c
0000080: 2038 0a63 6174 2038 0a1f 8b08 0000 0000   8.cat 8........
0000090: 0000 ffed cdb1 0a83 3014 8561 910e 8e8e  ........0..a....
00000a0: 193b dca1 631f 2084 9353 6ba3 a3e0 e2a8  .;..c. ..Sk.....
00000b0: 2fe0 d8e1 22d8 276f 9a50 e813 940e fdb8  /...".'o.P......
00000c0: 70f9 a753 247f 7829 f0b5 b9e2 c718 2322  p..S$.x)......#"
00000d0: 1ba9 e9a8 9688 6895 892a 7007 f0fe 701e  ......h..*p...p.
00000e0: b879 ef48 6e8c aa4f 219c d984 750d 0d91  .y.Hn..O!...u...
00000f0: e9b2 8c63 d779 3fcf c3d0 f76d eb7c e2d2  ...c.y?....m.|..
0000100: 1880 d4d7 4b6e 9296 b065 49ab 75c6 cc92  ....Kn...eI.u...
0000110: 1411 63f6 7de7 3489 9031 847c 3c9a 531d  ..c.}.4..1.|<.S.
0000120: e9a1 aa8f 803e 01                        .....>.

설명

  • od표준 "octal dump"유틸리티 프로그램입니다. 이 -tu1옵션은 대신 개별 바이트의 10 진수 덤프를 생성하도록 지시합니다 (bash의 asc (), ord (), .charCodeAt () 등의 부족에 대한 충분한 해결 방법)
  • P4이진 형식 PBM 파일의 마법 번호 P1는 ASCII 형식 PBM 파일 과 달리 각 바이트에 8 픽셀을 압축 합니다. 이것이 어떻게 유용한 지 알게 될 것입니다.
  • 최종 출력 행당 프로그램은를 사용하여 마지막에 gzip 압축 데이터 섹션에서 8 픽셀 바이트 (ASCII 코드 및 라인 번호에 해당)를 가져옵니다 dd. ( tail -2 $0스크립트의 마지막 두 줄을 추출합니다. 압축 된 데이터에는 하나의 0x0a 줄 바꿈 바이트가 포함됩니다.) 따라서 8 개의 픽셀이 단일 문자의 너비가됩니다. 지원되는 문자 사이의 간격을 채우는 널 바이트는 모두 동일하므로 쉽게 압축 할 수 있습니다.
  • 이 모든 것은 "8"이라는 파일에 기록됩니다. 정확히 8 개의 행 (및 바이트 당 8 개의 픽셀)이 있으므로 바이트 수는 출력 너비 (픽셀)입니다. wc -c바이트 수 다음에 입력 파일 이름 "8" 을 인쇄하는 출력 높이도 포함됩니다 .
  • 이제 헤더가 완성되었으므로 이미지 데이터가 인쇄됩니다. Bash는 마지막 두 줄이 이전의 모든 것을 실행 한 후에 유효한 명령 (마지막으로 유효하지 않은 UTF-8)이 아니라는 것을 알았습니다.
  • 나는 데이터 만 섹션을 압축하는 KZIP을 사용 Ilmari 카로 넨 그랬던 것처럼 에 대한 전체 제출 크리스마스 도전의 12 일에. 여기에 설명 된대로 ZIP 헤더 형식을 gzip 헤더로 바꾸려면 16 진 편집기를 사용해야합니다. 원본 ZIP 헤더의 CRC-32 및 파일 크기를 포함하는 것은 불필요합니다.

2
정말 좋은 (짧은) 솔루션! 쉘 스크립팅에서 dd, tail 및 gzip의 사용은 외부 imho로 간주되어서는 안됩니다.
ChristopheD

1
이것이 어떻게 작동하는지에 대한 설명을 추가 하시겠습니까? 많은 감사하겠습니다.
Mr. Llama 2016 년

2
설명해 주셔서 감사합니다. 그러나 'P4'버전을 사용하는 것은 OP가 "매우 간단한 ASCII 흑백 비트 맵 형식" 이라고 말한 것을 실제로 존중하지 않습니다 .
eregon

5

파이썬 2, 248 247 바이트

s=raw_input();k=len(s);print"P1",k*8,8
for i in range(k*24):a=s[i/3%k];j=max(".!".find(a)+1,ord(a)-62)*3;print int("00080084IMVAENBSIFERBSUF4UFQQEMVDT4NAP4MNDSI9MRTMRBARA4NBQRAMNBE4E94NURDARDNRDMLD95DSL7"[j:j+3],32)>>(i/3/k*3+i%3)&1," 0"*(i%3/2*5)

인쇄 가능한 문자열 (문자 당 3 바이트)로 압축 된 3x5 글꼴을 사용합니다. 글꼴은 명확하게 읽을 수 있지만 n은 소문자이며 v는 문맥에 표시되지 않으면 au로 오인 될 수 있습니다.

실제 크기:
실제 크기

확대 x3 :
확대 x3

도전 과제의 예에 따라 출력은 P1 유형 PBM입니다. 재미있는 도전이었습니다.


4

루비 1.9, 346 바이트 (122 코드 + 224 바이트 데이터)

결과는 다음과 같습니다.

코드 골프

(좋지 않습니까?)

z=0..7;puts"P1\n#{(s=gets).size*8} 8",z.map{|i|s.bytes.flat_map{|o|z.map{|j|'DATA'.unpack('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

글꼴에 의해 생성 figlet -f banner -w 1000 $LETTERS하고 이 스크립트 .

으로 실행합니다 echo -n 'CODEGOLF.STACKEXCHANGE.COM!' | ruby script.rb > image.pbm.

스크립트는 모든 행을 생성하고 간단히 인쇄합니다.

다음은 16 진수 덤프입니다 (use xxd -r).

0000000: 7a3d 302e 2e37 3b70 7574 7322 5031 5c6e  z=0..7;puts"P1\n
0000010: 237b 2873 3d67 6574 7329 2e73 697a 652a  #{(s=gets).size*
0000020: 387d 2038 222c 7a2e 6d61 707b 7c69 7c73  8} 8",z.map{|i|s
0000030: 2e62 7974 6573 2e66 6c61 745f 6d61 707b  .bytes.flat_map{
0000040: 7c6f 7c7a 2e6d 6170 7b7c 6a7c 271c 1c1c  |o|z.map{|j|'...
0000050: 0800 1c1c 0000 0000 001c 1c1c 0008 1422  ..............."
0000060: 417f 4141 003f 4141 3f41 413f 003e 4101  A.AA.?AA?AA?.>A.
0000070: 0101 413e 003f 4141 4141 413f 007f 0101  ..A>.?AAAAA?....
0000080: 1f01 017f 007f 0101 1f01 0101 003e 4101  .............>A.
0000090: 7941 413e 0041 4141 7f41 4141 001c 0808  yAA>.AAA.AAA....
00000a0: 0808 081c 0040 4040 4041 413e 0042 2212  .....@@@@AA>.B".
00000b0: 0e12 2242 0001 0101 0101 017f 0041 6355  .."B.........AcU
00000c0: 4941 4141 0041 4345 4951 6141 007f 4141  IAAA.ACEIQaA..AA
00000d0: 4141 417f 003f 4141 3f01 0101 003e 4141  AAA..?AA?....>AA
00000e0: 4151 215e 003f 4141 3f11 2141 003e 4101  AQ!^.?AA?.!A.>A.
00000f0: 3e40 413e 007f 0808 0808 0808 0041 4141  >@A>.........AAA
0000100: 4141 413e 0041 4141 4122 1408 0041 4949  AAA>.AAAA"...AII
0000110: 4949 4936 0041 2214 0814 2241 0041 2214  III6.A"..."A.A".
0000120: 0808 0808 007f 2010 0804 027f 0027 2e75  ...... ......'.u
0000130: 6e70 6163 6b28 2751 3c2a 2729 5b6f 3e36  npack('Q<*')[o>6
0000140: 343f 6f2d 3633 3a6f 2f34 365d 5b69 2a38  4?o-63:o/46][i*8
0000150: 2b6a 5d7d 7d2a 2720 277d                 +j]}}*' '}

goruby를 사용할 때 93 바이트의 코드가 필요합니다.

ps"P1\n#{(s=gt).sz*8} 8",8.mp{|i|s.y.fl{|o|8.mp{|j|'DATA'.ua('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

ZLib을 사용하면 데이터 크기를 224 대신 142 바이트로 자르지 만 코드에 43 바이트를 추가하므로 307 바이트 :

#coding:binary
require'zlib';z=0..7;puts"P1\n#{(s=gets).size*8} 8",z.map{|i|s.bytes.flat_map{|o|z.map{|j|Zlib.inflate("DATA").unpack('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

goruby를 사용할 때 총 268을 제공합니다.

#coding:binary
rq'zlib';ps"P1\n#{(s=gt).sz*8} 8",8.mp{|i|s.y.fl{|o|8.mp{|j|Zlib.if("DATA").ua('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

2

자바 862 826 :

다른 접근법이 있습니다. 'awt'는 외부 lib로 계산되지 않는다고 생각합니다.

import java.awt.*;
class B extends Frame{String s="ABCDEFGHIJKLMNOPQRSTUVWXYZ .!";int l=29;static Robot r;int[][][]m=new int[l][8][8];
public void paint(Graphics g){for(int y=0;y<8;++y){int py=(y<3)?y:y+1;for(int a=0;a<l;++a)
for(int x=0;x<8;++x)
m[a][x][y]=(r.getPixelColor(8*a+x+17+x/4,py+81)).getRGB()<-1?1:0;}
System.out.println("P1\n"+(getTitle().length()*8)+" 8");
for(int y=0;y<8;++y){for(char c:getTitle().toCharArray()){int a=s.indexOf(c);
for(int x=0;x<8;++x)System.out.print(m[a][x][y]);}
System.out.println();}
System.exit(0);}
public B(String p){super(p);
setBackground(Color.WHITE);
setSize(400,60);
Label l=new Label(s);
l.setFont(new Font("Monospaced",Font.PLAIN,13));
add(l);
setLocation(9,49);    
setVisible(true);}    
public static void main(String a[])throws Exception{r=new Robot();    
new B(a[0]);}}

그리고 골퍼되지 않은 :

import java.awt.*;

class PBM extends Frame
{
    String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ .!";
    int l=29;
    Robot robot;
    int[][][] map = new int[l][8][8];

    static boolean init = false;

    public void paint (Graphics g)
    {    
        for (int y = 0; y < 8; ++y)    
        {    
            int py = (y < 3) ? y : y +1;    
            for (int a = 0; a < l; ++a)
            {    
                for (int x = 0; x < 8; ++x)    
                {    
                    map[a][x][y] = (robot.getPixelColor (8*a+x+17+x/4, py+81)).getRGB () < -1 ? 1 : 0;    
                }    
            }    
        }

        System.out.println("P1\n"+(getTitle().length()*8)+" 8");

        for (int y = 0; y < 8; ++y) {    
            for (char c : getTitle ().toCharArray ()) {    
                int a = s.indexOf (c);    
                for (int x = 0; x < 8; ++x) {    
                    System.out.print (map[a][x][y]);    
                }
            }
            System.out.println ();
        }
        System.exit (0);
    }   

    public PBM (String p) throws Exception    
    {    
        super (p);    
        robot = new Robot ();    
        setBackground (Color.WHITE);    
        setSize (400, 60);    
        Label l=new Label(s);    
        l.setFont (new Font ("Monospaced", Font.PLAIN, 13));
        add(l);
        setLocation (9,49);
        setVisible (true);
    }

    public static void main (String args[]) throws Exception
    {
        new PBM (args[0]);
    }    
}

로봇은 어떻게 든 getPixel을 호출하는 Java의 흥미로운 방법입니다. 알파벳으로 레이블을 만들고 각 문자의 픽셀 위치를 측정합니다.

페인트 방법, int py = (y < 3) ? y : y +1;그리고 (8*a+x+17+x/4, py+81)글꼴의 위치를 조정하는 복잡한 방법이다. 허우! 그렇지 않으면 9 줄이 필요하며 4 번째 문자마다 수평으로 추가 픽셀이 있습니다. 시련과 오류로 인해이 솔루션에 도달했습니다.

그런 다음 PBM의 헤더와 메시지의 각 줄이 작성됩니다. 메시지는 프레임의 제목으로 전달됩니다.

그게 다야. 가장 짧은 코드는 아니지만 수동 글꼴 페인팅이 필요하지 않았습니다.

아마도 BeanShell 또는 Scala에서 더 짧을 수 있습니다.

그리고 지금-어떻게 생겼습니까?

java B "JAVA.CAFE BABE" > jcb.pbm

여러 줌이 적용되었습니다 : java.cafe 베이브 PNG

확대되지 않은 : java.cafe 베이브 JPG

문자 수는 Perl 솔루션의 문자 수를 섞은 것이 아닙니다.

(조금 더 골프를 쳤다. 로봇을 정적으로 만들었으므로 하나의 예외 선언을 피할 수있다.)


독창적 인 접근 방식, 멋지게 완료되었습니다!
ChristopheD

1
독창성을 위해 +1이지만 eww ... 비트 맵을 확장하려는 경우 가장 가까운 인접 보간을 사용하십시오.
Ilmari Karonen

나는 eog(그놈의 눈)과 스크린 샷을 사용했습니다. 스케일링되지 않은 버전을 업로드하겠습니다 jpg. 아마도 귀하의 브라우저는 가장 가까운 이웃 보간을 사용합니다 :).
사용자가 알 수 없음

1

C ++ 너무 큰 승리

필자는 자체 비트 맵 글꼴과 함께 C ++로 완전한 기능을 갖춘 PPM 드로잉 프로그램을 작성했습니다. 필요하지 않은 모든 기능을 제거하더라도 글꼴 정의 때문에 여기의 답변과 비교할 때 여전히 큽니다.

어쨌든, HELLO WORLD의 결과는 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

그리고 코드 :

ppmdraw.h

#ifndef PPMDRAW_H
#define PPMDRAW_H

#include <fstream>
#include <sstream>
#include <map>
#include <bitset>
#include <vector>

struct pixel{
    unsigned char r;
    unsigned char g;
    unsigned char b;

    bool equals(pixel p){
        return (r == p.r && g == p.g && b == p.b);
    }
};

class PPMDraw
{
    public:
        PPMDraw(int w, int h);

        virtual ~PPMDraw();

        void fill(unsigned char r, unsigned char g, unsigned char b);

        void set_color(unsigned char r, unsigned char g, unsigned char b);

        void draw_point(int x, int y);

        void draw_char(int x, int y, char c);
        void draw_string(int x, int y, std::string text);

        bool save(std::string file);

    private:

        int width;
        int height;

        pixel * image;

        std::vector<bool> checked;

        unsigned char red;
        unsigned char green;
        unsigned char blue;

        void init_alpha();
        std::map<char, std::bitset<48> > font;

};

#endif // PPMDRAW_H

ppmdraw.cpp

#include "PPMDraw.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cmath>
#include <map>
#include <bitset>
#include <vector>

// standard constructor
PPMDraw::PPMDraw(int w, int h){
    width = w;
    height = h;

    // make an array to hold all the pixels, r, g, b for each
    image = new pixel[width * height];

    // a bitset to use for functions that have to check which pixels have been worked on
    checked = std::vector<bool>();
    for(int i = 0; i < width * height; i++){
        checked.push_back(false);
    }

    init_alpha();
}


PPMDraw::~PPMDraw(){
    if(image != nullptr){
        delete[] image;
    }
}



void PPMDraw::fill(unsigned char r, unsigned char g, unsigned char b){
    for(int i = 0; i < width * height; i++){
        image[i + 0] = pixel{r, g, b};
    }
}

void PPMDraw::set_color(unsigned char r, unsigned char g, unsigned char b){
    red = r;
    green = g;
    blue = b;
}

void PPMDraw::draw_point(int x, int y){
    if(x >= 0 && x < width && y >= 0 && y < height){
        image[y * width + x] = pixel{red, green, blue};
    }
}

void PPMDraw::draw_char(int x, int y, char c){
    std::bitset<48> letter = font[c];
    int n = 47;
    for(int i = 0; i < 6; i++){
        for(int j = 0; j < 8; j++){
            if(letter[n]){
                draw_point(x + i, y + j);
            }
            n--;
        }
    }
}
void PPMDraw::draw_string(int x, int y, std::string text){
        for(unsigned int i = 0; i < text.length(); i++){
            draw_char(x + 6 * i, y, text[i]);
        }

}



bool PPMDraw::save(std::string file){
    std::ofstream save(file.c_str(), std::ios_base::out | std::ios_base::binary);
    if(save.is_open()){
        save << "P6" << std::endl;
        save << width << " " << height << std::endl;
        save << "255" << std::endl;
        unsigned char * temp = new unsigned char[height * width * 3];
        for(int i  = 0; i < height * width; i++){
            temp[i * 3 + 0] = image[i].r;
            temp[i * 3 + 1] = image[i].g;
            temp[i * 3 + 2] = image[i].b;
        }
        save.write(reinterpret_cast<const char *> (temp), height*width*3*sizeof(unsigned char));
        delete temp;
        save.close();
        return true;
    }else{
        return false;
    }


}

void PPMDraw::init_alpha(){
    // Define a simple font for drawing text
    font[' '] = std::bitset<48>  (std::string("000000000000000000000000000000000000000000000000"));
    font['!'] = std::bitset<48>  (std::string("000000000000000011110110000000000000000000000000"));
    font['"'] = std::bitset<48>  (std::string("000000001100000000000000110000000000000000000000"));
    font['#'] = std::bitset<48>  (std::string("001010001111111000101000111111100010100000000000"));
    font['$'] = std::bitset<48>  (std::string("001001000101010011111110010101000100100000000000"));
    font['%'] = std::bitset<48>  (std::string("000000100100110000010000011000001000010000000000"));
    font['&'] = std::bitset<48>  (std::string("000111001110001010110010110011000000001000000000"));
    font['\\'] = std::bitset<48>  (std::string("100000000110000000010000000011000000001000000000"));
    font['('] = std::bitset<48>  (std::string("000000000000000001111100100000100000000000000000"));
    font[')'] = std::bitset<48>  (std::string("000000001000001001111100000000000000000000000000"));
    font['*'] = std::bitset<48>  (std::string("010010000011000011100000001100000100100000000000"));
    font['+'] = std::bitset<48>  (std::string("000100000001000001111100000100000001000000000000"));
    font[','] = std::bitset<48>  (std::string("000000000000000000000110000000000000000000000000"));
    font['-'] = std::bitset<48>  (std::string("000100000001000000010000000100000001000000000000"));
    font['.'] = std::bitset<48>  (std::string("000000000000000000000100000000000000000000000000"));
    font['/'] = std::bitset<48>  (std::string("000000100000110000010000011000001000000000000000"));
    font['0'] = std::bitset<48>  (std::string("011111001000001010000010100000100111110000000000"));
    font['1'] = std::bitset<48>  (std::string("000000001000001011111110000000100000000000000000"));
    font['2'] = std::bitset<48>  (std::string("010011101001001010010010100100100111001000000000"));
    font['3'] = std::bitset<48>  (std::string("010001001000001010000010100100100110110000000000"));
    font['4'] = std::bitset<48>  (std::string("111100000001000000010000000100001111111000000000"));
    font['5'] = std::bitset<48>  (std::string("111001001001001010010010100100101001110000000000"));
    font['6'] = std::bitset<48>  (std::string("011111001001001010010010100100101000110000000000"));
    font['7'] = std::bitset<48>  (std::string("100000001000000010000110100110001110000000000000"));
    font['8'] = std::bitset<48>  (std::string("011011001001001010010010100100100110110000000000"));
    font['9'] = std::bitset<48>  (std::string("011000001001000010010000100100000111111000000000"));
    font[':'] = std::bitset<48>  (std::string("000000000000000001000100000000000000000000000000"));
    font[';'] = std::bitset<48>  (std::string("000000000000000001000110000000000000000000000000"));
    font['<'] = std::bitset<48>  (std::string("000000000001000000101000010001000000000000000000"));
    font['='] = std::bitset<48>  (std::string("001010000010100000101000001010000000000000000000"));
    font['>'] = std::bitset<48>  (std::string("000000000100010000101000000100000000000000000000"));
    font['?'] = std::bitset<48>  (std::string("010000001000000010001010100100000110000000000000"));
    font['@'] = std::bitset<48>  (std::string("011111001000001010111010101010100111001000000000"));
    font['A'] = std::bitset<48>  (std::string("011111101001000010010000100100000111111000000000"));
    font['B'] = std::bitset<48>  (std::string("111111101001001010010010100100100110110000000000"));
    font['C'] = std::bitset<48>  (std::string("011111001000001010000010100000100100010000000000"));
    font['D'] = std::bitset<48>  (std::string("111111101000001010000010100000100111110000000000"));
    font['E'] = std::bitset<48>  (std::string("111111101001001010010010100100101000001000000000"));
    font['F'] = std::bitset<48>  (std::string("111111101001000010010000100100001000000000000000"));
    font['G'] = std::bitset<48>  (std::string("011111001000001010000010100010100100110000000000"));
    font['H'] = std::bitset<48>  (std::string("111111100001000000010000000100001111111000000000"));
    font['I'] = std::bitset<48>  (std::string("100000101000001011111110100000101000001000000000"));
    font['J'] = std::bitset<48>  (std::string("000011000000001000000010000000101111110000000000"));
    font['K'] = std::bitset<48>  (std::string("111111100001000000010000001010001100011000000000"));
    font['L'] = std::bitset<48>  (std::string("111111100000001000000010000000100000001000000000"));
    font['M'] = std::bitset<48>  (std::string("111111101000000001100000100000001111111000000000"));
    font['N'] = std::bitset<48>  (std::string("111111100100000000100000000100001111111000000000"));
    font['O'] = std::bitset<48>  (std::string("011111001000001010000010100000100111110000000000"));
    font['P'] = std::bitset<48>  (std::string("111111101001000010010000100100001111000000000000"));
    font['Q'] = std::bitset<48>  (std::string("011111001000001010001010100001000111101000000000"));
    font['R'] = std::bitset<48>  (std::string("111111101001000010010000100110001111011000000000"));
    font['S'] = std::bitset<48>  (std::string("011000101001001010010010100100101000110000000000"));
    font['T'] = std::bitset<48>  (std::string("100000001000000011111110100000001000000000000000"));
    font['U'] = std::bitset<48>  (std::string("111111000000001000000010000000101111110000000000"));
    font['V'] = std::bitset<48>  (std::string("111110000000010000000010000001001111100000000000"));
    font['W'] = std::bitset<48>  (std::string("111111100000001000001100000000101111111000000000"));
    font['X'] = std::bitset<48>  (std::string("110001100010100000010000001010001100011000000000"));
    font['Y'] = std::bitset<48>  (std::string("110000000010000000011110001000001100000000000000"));
    font['Z'] = std::bitset<48>  (std::string("100001101000101010010010101000101100001000000000"));
    font['['] = std::bitset<48>  (std::string("000000001111111010000010100000100000000000000000"));
    font['\''] = std::bitset<48>  (std::string("100000000110000000010000000011000000001000000000"));
    font[']'] = std::bitset<48>  (std::string("000000001000001010000010111111100000000000000000"));
    font['^'] = std::bitset<48>  (std::string("001000000100000010000000010000000010000000000000"));
    font['_'] = std::bitset<48>  (std::string("000000100000001000000010000000100000001000000000"));
    font['`'] = std::bitset<48>  (std::string("000000001000000001000000000000000000000000000000"));
    font['a'] = std::bitset<48>  (std::string("000001000010101000101010001010100001111000000000"));
    font['b'] = std::bitset<48>  (std::string("111111100001001000010010000100100000110000000000"));
    font['c'] = std::bitset<48>  (std::string("000111000010001000100010001000100001010000000000"));
    font['d'] = std::bitset<48>  (std::string("000011000001001000010010000100101111111000000000"));
    font['e'] = std::bitset<48>  (std::string("000111000010101000101010001010100001101000000000"));
    font['f'] = std::bitset<48>  (std::string("000100000111111010010000100100000000000000000000"));
    font['g'] = std::bitset<48>  (std::string("001100100100100101001001010010010011111000000000"));
    font['h'] = std::bitset<48>  (std::string("111111100001000000010000000100000000111000000000"));
    font['i'] = std::bitset<48>  (std::string("000000000000000001011110000000000000000000000000"));
    font['j'] = std::bitset<48>  (std::string("000000100000000100000001010111100000000000000000"));
    font['k'] = std::bitset<48>  (std::string("111111100000100000010100001000100000000000000000"));
    font['l'] = std::bitset<48>  (std::string("000000000000000011111110000000000000000000000000"));
    font['m'] = std::bitset<48>  (std::string("000111100001000000001000000100000001111000000000"));
    font['n'] = std::bitset<48>  (std::string("001111100001000000010000000100000001111000000000"));
    font['o'] = std::bitset<48>  (std::string("000111000010001000100010001000100001110000000000"));
    font['p'] = std::bitset<48>  (std::string("001111110010010000100100001001000001100000000000"));
    font['q'] = std::bitset<48>  (std::string("000110000010010000100100001001000011111100000000"));
    font['r'] = std::bitset<48>  (std::string("000000000011111000010000000100000000000000000000"));
    font['s'] = std::bitset<48>  (std::string("000000000001001000101010001010100010010000000000"));
    font['t'] = std::bitset<48>  (std::string("000000000010000011111110001000000000000000000000"));
    font['u'] = std::bitset<48>  (std::string("000111000000001000000010000000100001110000000000"));
    font['v'] = std::bitset<48>  (std::string("000110000000010000000010000001000001100000000000"));
    font['w'] = std::bitset<48>  (std::string("000111100000001000000100000000100001111000000000"));
    font['x'] = std::bitset<48>  (std::string("001000100001010000001000000101000010001000000000"));
    font['y'] = std::bitset<48>  (std::string("001100000000100000000111000010000011000000000000"));
    font['z'] = std::bitset<48>  (std::string("010001100100101001010010011000100000000000000000"));
    font['{'] = std::bitset<48>  (std::string("000000000000000001101100100100100000000000000000"));
    font['|'] = std::bitset<48>  (std::string("000000000000000011111110000000000000000000000000"));
    font['}'] = std::bitset<48>  (std::string("000000000000000010010010011011000000000000000000"));
    font['~'] = std::bitset<48>  (std::string("000100000010000000010000000010000001000000000000"));
}

main.cpp

#include "PPMDraw.h"
#include <iostream>

int main(){
    // ask for input
    std::string input;
    std::cout << "ENTER YOUR TEXT" << std::endl;
    getline(std::cin, input);
   // get size for image
  int width = input.size() * 6;
   PPMDraw image = PPMDraw(width, 8);
   image.fill(255, 255, 255);
   image.set_color(0, 0, 0);
   image.draw_string(0, 0, input);
   image.save("text.ppm");
}

메이크 파일

CC = g++
CFLAGS = -Wall -c -std=c++11
LFLAGS = -Wall
OBJS = main.o PPMDraw.o

list: $(OBJS)
    $(CC) $(LFLAGS) $(OBJS) -o text2ppm

main.o: PPMDraw.h
    $(CC) $(CFLAGS) main.cpp

PPMDraw.o: PPMDraw.h
    $(CC) $(CFLAGS) PPMDraw.cpp

clean:
    rm *.o main

관심이 있으시면 전체 PPMDraw 라이브러리가 있습니다 .


1
나는 당신의 글꼴이 매우 유용하다는 것을 알았습니다!
Ludwik

1

SmileBASIC, 231 바이트

LINPUT C$?"P1
?8,LEN(C$)*8WHILE""<C$A=ASC(SHIFT(C$))D=ASC("*N.JZ`;O:²ÞøäüÄho"[A-65+12*(A<34)+47*(A<47)])FOR I=0TO 4B$=BIN$(VAL("7535712074617252"[D>>5<<1OR 1AND D>>I]),8)WHILE""<B$?POP(B$),
WEND?NEXT?"0 "*24WEND

여기에 이미지 설명을 입력하십시오

각 문자는 8 가지 조합의 "팔레트"에서 선택한 2 개의 다른 행 패턴 만 포함합니다. 각 심볼의 데이터는 1 바이트로 저장되며 팔레트는 별도로 저장됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.