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}

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

  • 첫 번째 줄 (골프가 제거 된 버전)은 한 줄의 입력을 읽고, 문자 배열로 분할하고 (편리한 줄 바꿈 생략) 문자 A를 Z문자 !와 문자 및 .문자 코드 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.