ASCIIテキストからPBMビットマップファイルを生成する


19

PBM(ポータブルビットマップ)形式は、非常に単純なASCII白黒ビットマップ形式です。

文字「J」の例は次のとおりです(ウィキペディアのリンクからコピーアンドペースト):

P1
#これは、文字「J」のビットマップの例です
6 10
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
1 0 0 0 1 0
0 1 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0

今度は、この気の利いた小さな形式でファイルを生成する小さなツールを作成します。

あなたの目標は、次の規則に準拠する最短のプログラム(任意の言語)を作成することです。

  1. あなたのプログラムは、標準入力から1つの文字列を取ります(例えばCODEGOLF.STACKEXCHANGE.COM!
  2. 文字列のビットマップ(読み取り可能)表現でPBMファイルを生成します。
  3. 各キャラクターは8x8グリッドとして構成されています。
  4. 文字[AZ](すべて大文字)、スペース、ポイント( '。')および感嘆符( '!')をサポートする必要があります。
  5. 外部ライブラリは許可されていません(PBMに関連するものは確かにありません)!
  6. 使用される文字セットは、単にプログラムの外部にあるものであってはなりません。課題の一部は、キャラクターを効率的に保存することです...

PIMP形式の有効性のテストは、GIMP(またはその他)を使用して実行できます。サンプルの入力と出力を見せてください!

最も短いソリューションには、2012-01-31に回答ポイントが与えられます。

ゴルフをお楽しみください!

PS:(願わくば)より多くの競合他社を引き付けるために、賞金(パーセンテージで私のコードゴルフの評判の大きな部分)を追加しました。


「そのビットマップ表現」とは、文字のように見えるものに近い文字表現を意味しますか?どれだけ近いか?バイナリコードまたは点字またはモールス信号のビットマップ表現のようなものは許可されますか?
ハワード

@Howard:アイデアは、「レンダリング」(ビットマップ)された元の入力テキストを含むpbmイメージを生成することですが、それでも人間が読み取れる形式(letters言い換えれば)です。リンクされている例とは異なります。
クリストフ

プログラムの大部分が30個のビットマップになるため、タグkolmogorov-complexityを追加しました。
ピーターテイラー

@ピーターテイラー:良い点、ありがとう!
クリストフ

「外部ライブラリ」を構成するものについて、長く苦しい議論をすることになると思います。
JB

回答:


9

GolfScript、133バイト

これは、164バイトのPerlソリューションに基づいており、同じニブルパックの4 x 5ピクセルフォントを使用しています。繰り返しますが、まず読みやすいバージョンを提供します。

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

ここでFONT DATA HEREは、71バイトのバイナリパックフォントデータを表します。エンコーディングは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*

Perlのスクリプトとは異なり、このコードがセット以外の任意の文字を印刷しますA- 、Z、、! 面白いに見える少し波線として。波線を空白に置き換えると、2文字余分にかかります。それらを完全に削除するには4かかります。.space

これは私の初めてのGolfScriptプログラムであるため、最適化の余地が残っていても驚かないでしょう。仕組みは次のとおりです。

  • {91,65>"!. "+?}%:s(有効な入力文字をマップA- 、Z、、! 番号0に) - 28に結果を割り当てます。有効なセット外の文字はすべて-1にマップされ、これが印刷時に波線を生成します。.spaces

  • "P4"\,8*8値「P4」、入力の長さの8倍、および8をスタックにプッシュします。最後に印刷されると、これらはPBMヘッダーを形成します。

  • {16base}%[3]/フォントデータの先行文字列を取得し、その各バイトを2つのニブルに分割し、結果をvalueで区切られたブロックに分割します3{:p;{[p=0]0=}s%}%次に、これらのブロックをループ処理し、最初に各ブロックを変数に割り当ててからp、再マップされた入力文字列をループ処理し、s各文字をの対応するオフセットの値に置き換えますp。変な見た目の構造[p=0]0=は、と同じですがp=、の終わりを超えるオフセットに対して0を返す点が異なりますp。私はそれが本当に好きではありませんが、私はそれを処理するためのより短い方法を理解することができませんでした。

  • 最後]n*に、スタック上のすべて(3つのヘッダー値と画像データ配列)を取得し、それらを印刷用の改行で結合します。


真剣に短い(どんなメトリックでも)。いいね!
クリストフ

12

Perl、164バイト、zlib / gzip圧縮なし

問題で眠った後、私は最初の解決策よりもはるかに短い解決策を見つけることができました。秘Theは、ルールの小さな抜け穴を利用することです。文字はそれぞれ8 x 8ピクセルに収まる必要がありますが、そのスペースをすべて埋める必要はありません。そこで、私は自分で4 x 5ピクセルのフォントを描き、2つの文字を5バイトにパックできるようにしました。

出力は次のようになります。

"こんにちは世界!" (スケーリングx 4)

    「OH!A LAZY DOGのすぐにできる茶色のフォックスジャンプ」 (オリジナルサイズ)

フォントデータが埋め込まれた実際のコードを提供する前に、ゴルフのないバージョンを示します。

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つの単一NULLバイト)で構成されるバイナリ文字列に置き換えられます。圧縮されたデータに空白、一重引用符、バックスラッシュが含まれないように、意図的にフォントを設計し、でエンコードできるようにしました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}

仕組みは次のとおりです。

  • (デgolfedバージョンで)最初の行は、入力の単一の行を読み込む(好都合任意末尾の改行を省略)文字の配列にそれを分割し、文字をマッピングAするZ文字!.、文字コード0から28までれます通常、ASCII / Unicodeの印刷できない制御文字に対応します。(これの小さな副作用は、入力内のタブがJs として印刷されることです。)出力ループが28を超えるコードをブランクに変換するため、スペース文字はマップされないままになります。

  • 2行目はPBMヘッダーを出力するだけです。Perl 5.10 say機能を使用するため、このスクリプトを次のコマンドで実行する必要があります。perl -M5.010

  • 出力ループは、空白で区切られたパックされた画像行のリストを取得し、それぞれを$p順番に割り当てます。(パックされたデータに空白や'文字が含まれないようにフォントを設計しました。)次に@a、Perlのvecコマンドを使用しての入力文字をループ処理し、イメージ行からマップされた文字コードに対応する4ビットニブルを抽出し、 8ビットのバイトにパディングして印刷します。


古い回答、268バイト:

これは迅速で汚れた最初の試みです。PleaseStandのフォントを盗み、ソースコードとともに圧縮しました。結果のスクリプトはほとんど印刷できないため、hexdumpがあります。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文字で実現できるとは想像していませんでした。
クリストフ

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時間で授与されます。よくやった!
クリストフ

これについてもアセンブリコードを投稿できますか?
Sir_Lagsalot

1
分解を見てコードをテストした後、BIOSが提供するビットマップフォントを使用しているようです。これは、プログラムがチャレンジで不要な小文字、記号、および句読点を出力できるという事実によって確認できます。したがって、フォントはプログラムの外部にあり、それによって保存されません(少なくとも私の意見では)。
Sir_Lagsalot

@Skizz:これを確認できますか?それでも非常に優れたソリューションになりますが、仕様に少し反します。
クリストフ

1
@ChristopheD:そうですね、JBは「外部ライブラリを構成するものについて、長くてつらい議論をするつもりだ」とコメントしました。puts-Rubyでは外部ライブラリであると主張することができます。はい、それは、ポインタ参照を介してアクセスされるBIOSフォントを使用します(loadフォントをRAMに取り込む操作はありません)。ルールを曲げすぎるかもしれません。それはそれらの厄介な子供たちのためではなかった場合私はそれを取り去っただろう
;

6

シェルスクリプト(コード+データ= 295文字)

tail、gzip、およびddが「外部ライブラリ」としてカウントされないことを願っています。として実行しecho -n 'YOUR TEXT HERE' | ./text.sh > out.pbmます。使用したフォントはSmall Fontsサイズ7.5ですが、Qからディセンダーをクリップする必要がありました。

出力例

怠AZな犬を飛び越える迅速な茶色のJ。 本当に!

コード(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標準の「オクタルダンプ」ユーティリティプログラムです。この-tu1オプションは、代わりに個々のバイトの10進ダンプを生成するように指示します(bashにasc()、ord()、. charCodeAt()などがないための十分な回避策)
  • P4は、バイナリ形式のPBMファイルのマジック番号であり、各バイトに8ピクセルをパックします(P1ASCII形式のPBMファイルの場合とは異なります)。これがどのように役立つかがわかるでしょう。
  • 最終出力の行ごとに、プログラムは最後にgzipで圧縮されたデータセクションからを使用して、8ピクセルバイト(ASCIIコードと行番号に対応)を引き出しddます。(tail -2 $0スクリプトの最後の2行を抽出します。圧縮データには1つの0x0a改行バイトが含まれます。)1つの文字の幅は8ピクセルです。サポートされている文字間のギャップを埋めるヌルバイトは、すべて同じであるため、簡単に圧縮できます。
  • これらはすべて「8」という名前のファイルに書き込まれます。正確に8行(およびバイトあたり8ピクセル)であるため、バイト数は出力の幅(ピクセル単位)です。出力の高さも含まれてwc -cおり、バイト数の後に入力ファイル名「8」を出力します。
  • ヘッダーが完成したので、画像データが印刷されます。Bashは、前のすべての行を実行した後、最後の2行が有効なコマンド(最後の行は実際にはUTF-8を無効にしている)でないことにのみ気付きます。
  • Ilmari Karonenが 12日間のクリスマスチャレンジへの提出全体に対して行ったように、KZIPはデータセクションの圧縮にのみ使用ました。そこで説明されているように、ZIPヘッダー形式をgzipヘッダーに置き換えるには、16進エディターを使用することが本質的に必要です。元のZIPヘッダーからCRC-32とファイルサイズを含める必要はないようです。

2
本当に素晴らしい(そして短い)ソリューション!シェルスクリプティングでは、dd、tail、gzipの使用は外部の私見と見なされるべきではありません。
クリストフ

1
これがどのように機能するかの説明を追加することに注意してください?ありがたいです。
ラマ氏

2
非常に素晴らしい、説明をありがとう。しかし、「P4」バージョンを使用することは、OPが「非常に単純なASCII白黒ビットマップ形式」と言ったことを本当に尊重していません。
エレゴン

5

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

1文字あたり3バイトの印刷可能な文字列にパックされた3x5フォントを使用します。フォントは明らかに読みやすいですが、nは小文字であり、コンテキストで表示されない場合、vはauと間違われる可能性があります。

実際のサイズ:
実寸

ズームx3:
ズームx3

チャレンジの例に従って、出力はP1タイプのPBMです。楽しいチャレンジでした。


4

Ruby 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ます。

スクリプトはすべての行を生成し、単純に印刷します。

hexdumpを使用します(使用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

Java 862 826:

別のアプローチがあります。「awt」は外部ライブラリとしてカウントされないと思います。

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文字ごとに水平方向に1ピクセル追加されます。試行錯誤の結果、このソリューションが生まれました。

次に、PBMのヘッダーと、メッセージの各行が書き込まれます。メッセージはフレームのタイトルとして渡されます。

それでおしまい。最短のコードではありませんが、手動でフォントをペイントする必要はありませんでした。

たぶん、BeanShellやScalaの方が短いかもしれません。

そして今-それはどのように見えますか?

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

複数のズームが適用されました: java.cafe可愛いPNG

ズーム解除: java.cafe babe JPG

charsの数が、Perlソリューションのシャッフルされたcharsの数ではありません。

(もう少しゴルフをしました。1つの例外宣言を回避するために、ロボットを静的にしました。)


オリジナルのアプローチ、うまくやった!
クリストフ

1
独創性のために+1、しかしeww ...ビットマップを拡大する場合は、最近傍補間を使用します。
イルマリカロネン

私はeog(Eye of Gnome)とスクリーンショットを使用しました。スケールなしのjpgバージョンをアップロードします。おそらく、ブラウザは最近傍内挿を使用しています:)。
ユーザー不明

1

C ++が大きすぎて勝てない

私は独自のビットマップフォントを使用して、フル機能のPPM描画プログラムをC ++で作成しました。不要な機能をすべて削除したとしても、フォントの定義が原因で、ここでの回答と比べてまだ巨大です。

とにかく、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.