Menghasilkan file bitmap PBM dari teks ASCII


19

Format PBM (Portable BitMap) adalah format bitmap ASCII hitam dan putih yang sangat sederhana.

Berikut adalah contoh untuk huruf 'J' (disalin dari tautan wikipedia):

P1
# Ini adalah contoh bitmap dari huruf "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

Sudah saatnya kita membangun alat kecil untuk menghasilkan file dalam format kecil yang bagus ini!

Tujuan Anda adalah untuk menulis program terpendek (dalam bahasa apa pun) yang sesuai dengan aturan berikut:

  1. Program Anda mengambil satu string dari stdin (misalnya CODEGOLF.STACKEXCHANGE.COM!)
  2. Ini menghasilkan file PBM dengan representasi string yang dapat dibaca (dapat dibaca).
  3. Setiap karakter dibangun sebagai kotak 8x8.
  4. Anda harus mendukung karakter [AZ] (semua huruf besar), spasi, titik ('.') Dan tanda seru ('!').
  5. Tidak ada perpustakaan eksternal yang diizinkan (tentu saja tidak ada yang terkait dengan PBM)!
  6. Set karakter yang digunakan tidak boleh hanya eksternal untuk program Anda. Bagian dari tantangannya adalah menyimpan karakter secara efisien ...

Pengujian validitas format PBM dapat dilakukan dengan GIMP (atau lainnya). Pamerkan input dan output sampel!

Solusi terpendek akan diberikan poin jawaban pada 2012-01-31.

Bersenang-senang bermain golf!

PS: Saya telah menambahkan hadiah (persentase-bijaksana bagian besar dari reputasi codegolf saya) untuk (mudah-mudahan) menarik lebih banyak pesaing.


Dengan "representasi bitmapnya", maksud Anda representasi karakter yang dekat dengan sesuatu yang tampak seperti huruf? Betapa dekat? Apakah sesuatu seperti representasi bitmap dari kode biner atau kode braille atau morse diizinkan?
Howard

@ Howard: idenya adalah untuk menghasilkan gambar pbm yang berisi teks input asli dalam 'diberikan' (bitmap) tetapi masih dalam bentuk yang dapat dibaca manusia (dengan letterskata lain). Tidak berbeda dengan contoh yang ditautkan.
ChristopheD

Saya menambahkan tag kolmogorov-kompleksitas karena sebagian besar program akan menjadi 30 bitmap.
Peter Taylor

@ Peter Taylor: Poin bagus, terima kasih!
ChristopheD

Saya merasa kita akan memiliki perdebatan panjang dan menyakitkan tentang apa yang merupakan "perpustakaan eksternal."
JB

Jawaban:


9

GolfScript, 133 byte

Ini didasarkan pada solusi Perl 164-byte saya dan menggunakan font 4 by 5 pixel yang sama-mengemasi. Sekali lagi, saya akan memberikan versi yang dapat dibaca terlebih dahulu:

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

Di sini, FONT DATA HEREsingkatan dari 71 byte data font yang dikemas biner. Pengkodean sedikit berbeda dari pada versi Perl: alih-alih membelah string yang dikemas pada spasi putih, saya memperluasnya terlebih dahulu dan kemudian membaginya pada nibble 3(dipilih karena kebetulan tidak terjadi di mana pun di font).

Karena data font dalam skrip aktual berisi karakter yang tidak patut dicetak, saya berikan sebagai hex dump di bawah ini. Gunakan xxd -runtuk mengubah hex dump kembali menjadi kode GolfScript yang dapat dieksekusi:

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*

Tidak seperti script Perl, kode ini mencetak karakter apapun di luar set A- Z, !, ., spacesebagai coretan kecil yang lucu-cari. Mengganti coretan dengan kosong akan membutuhkan 2 karakter tambahan; menghapusnya seluruhnya akan memakan biaya 4.

Ini adalah program GolfScript pertama saya, jadi saya tidak akan terkejut jika masih ada ruang untuk optimasi. Begini cara kerjanya:

  • {91,65>"!. "+?}%:smemetakan karakter input yang valid ( A- Z, !, ., space) ke angka 0 - 28 dan ditunjuk hasilnya ke s. Setiap karakter di luar set yang valid dipetakan ke -1, yang menghasilkan coretan ketika dicetak.

  • "P4"\,8*8mendorong nilai "P4", 8 kali panjang input, dan 8 ke tumpukan. Saat dicetak di bagian akhir, ini akan membentuk header PBM.

  • {16base}%[3]/mengambil string sebelumnya dari data font, membagi setiap byte dari itu menjadi dua camilan, dan membagi hasilnya menjadi blok-blok yang dibatasi oleh nilai 3. {:p;{[p=0]0=}s%}%kemudian lompati blok-blok ini, pertama-tama menugaskan setiap blok ke variabel pdan kemudian mengulangi string input yang dipetakan kembali s, mengganti setiap karakter dengan nilai pada offset yang sesuai di p. Konstruk yang tampak lucu [p=0]0=melakukan hal yang sama p=, kecuali bahwa ia mengembalikan 0 untuk setiap offset melewati akhir p; Saya tidak begitu menyukainya, tetapi saya belum bisa menemukan cara yang lebih pendek untuk mengatasinya.

  • Akhirnya, ]n*ambil semua yang ada di tumpukan (tiga nilai header dan array data gambar) dan gabungkan dengan baris baru untuk dicetak.


Serius pendek (berdasarkan metrik apa pun). Bagus!
ChristopheD

12

Perl, 164 byte, tidak ada kompresi zlib / gzip

Setelah tidur pada masalah, saya berhasil menemukan solusi yang jauh lebih pendek daripada yang pertama. Caranya adalah dengan memanfaatkan celah kecil dalam aturan: karakter harus masing-masing pas dengan 8 x 8 piksel, tetapi tidak ada yang mengatakan mereka harus mengisi semua ruang itu. Jadi saya menggambar font 4 x 5 pixel saya sendiri, memungkinkan saya untuk mengemas dua karakter menjadi 5 byte.

Outputnya terlihat seperti ini:

"HALO DUNIA!" (diskalakan x 4)

    "OH! FOX COKLAT CEPAT MELOMPAT DARI ANJING LAZY." (ukuran asli)

Sebelum memberikan kode aktual dengan data font yang disematkan, izinkan saya menunjukkan versi de-golf:

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

Dalam kode aktual, PACKED FONT DATAdigantikan oleh string biner yang terdiri dari delapan baris ruang-dibatasi (empat baris 14-byte dan satu 13-byte, ditambah tiga byte nol tunggal untuk baris kosong). Saya sengaja mendesain font saya sehingga data yang dikemas tidak mengandung spasi, tanda kutip tunggal atau garis miring terbalik, sehingga bisa dikodekan dalam qw'...'.

Karena string font yang dikemas berisi karakter yang tidak patut, saya telah menyediakan skrip aktual sebagai hex dump. Gunakan xxd -runtuk mengubahnya kembali menjadi kode Perl yang dapat dieksekusi:

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}

Begini cara kerjanya:

  • Baris pertama (dalam versi de-golf) membaca satu baris input, membaginya menjadi sebuah array karakter (dengan mudah menghilangkan setiap baris baru) dan memetakan huruf Ake Zdan karakter !dan .ke kode karakter 0 hingga 28, yang biasanya sesuai dengan karakter kontrol yang tidak diinginkan dalam ASCII / Unicode. (Efek samping minor dari ini adalah bahwa setiap tab pada input dapat dicetak sebagai Js.) Karakter spasi dibiarkan tidak dipetakan, karena loop output mengubah kode di atas 28 menjadi kosong.

  • Baris kedua hanya mencetak header PBM. Ini menggunakan fitur Perl 5.10 say, jadi Anda perlu menjalankan skrip ini perl -M5.010agar bisa berfungsi.

  • Output loop mengambil daftar baris gambar yang dipisahkan spasi-putih dan menugaskan masing-masing dari mereka $psecara bergantian. (Saya mendesain font agar data yang dikemas tidak mengandung spasi atau 'karakter apa pun .) Kemudian loop di atas karakter input masuk @a, menggunakan vecperintah Perl untuk mengekstrak nibble 4-bit yang sesuai dengan kode karakter yang dipetakan dari baris gambar, membalutnya ke byte 8-bit dan mencetaknya.


Jawaban lama, 268 byte:

Ini adalah upaya pertama yang cepat dan kotor. Saya mencuri font PleaseStand dan mengompresnya bersama dengan kode sumber saya. Karena skrip yang dihasilkan sebagian besar tidak dapat dicetak, inilah hexdump; gunakan xxd -runtuk mengubahnya menjadi kode Perl yang dapat dieksekusi:

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'

Kode Perl yang terdekompresi terdiri dari pembukaan berikut:

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

diikuti oleh delapan pengulangan kode berikut:

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

dengan BITMAP DATA HEREdiganti dengan 29 byte encoding satu baris font.


Solusi yang lebih baru sangat bagus. Tidak pernah membayangkan ini bisa dilakukan dalam 165 karakter.
ChristopheD

6

8086 Kode Mesin

190 Bytes (122 Bytes menggunakan BIOS)

Inilah file BaseX yang dikodekan oleh WinXP / MSDos .COM:

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

(Gunakan sesuatu seperti ini ) untuk memecahkan kode teks dan simpan sebagai "pbm.com". Kemudian, pada prompt perintah, ketik:

teks pbm untuk menyandikan> outputfilename.pbm

Saya sudah menguji ini pada mesin WinXP saya menggunakan prompt perintah standar dan DosBox V0.74.

MEMPERBARUI

Versi ini adalah 190 byte dan menggunakan font kecil Ilmari Karonen (tidak ada akses bios di sini!): -

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

Solusi yang sangat bagus. Saat ini inilah pesaing untuk hadiah yang akan diberikan dalam waktu sekitar 20 jam. Sudah selesai dilakukan dengan baik!
ChristopheD

Bisakah Anda memposting kode perakitan untuk ini juga?
Sir_Lagsalot

1
Setelah melihat pembongkaran dan menguji kodenya, tampaknya Anda hanya menggunakan font bitmap yang disediakan oleh bios. Ini dapat dikonfirmasi oleh fakta bahwa program Anda dapat menampilkan huruf kecil, simbol, dan tanda baca yang tidak diperlukan oleh tantangan. Dengan demikian, font tersebut eksternal untuk program Anda dan tidak disimpan olehnya (setidaknya menurut saya).
Sir_Lagsalot

@ Skizz: dapatkah Anda mengkonfirmasi ini? Itu masih membuat solusi yang sangat bagus tetapi sedikit melawan spesifikasi.
ChristopheD

1
@ChristopheD: Yah, JB berkomentar, "Saya merasa kita akan memiliki perdebatan panjang dan menyakitkan tentang apa yang merupakan perpustakaan eksternal." - orang bisa berpendapat bahwa putsdi Ruby adalah perpustakaan eksternal. Ya, itu memang menggunakan font bios, diakses melalui pointer derefence (tidak ada loadoperasi untuk mendapatkan font ke dalam RAM). Membengkokkan aturan terlalu jauh mungkin. Saya akan lolos begitu saja kalau bukan karena anak-anak sial ;-)
Skizz

6

Skrip shell (kode + data = 295 karakter)

Saya harap tail, gzip, dan dd tidak dihitung sebagai "perpustakaan eksternal." Jalankan sebagai echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. Font yang saya gunakan adalah Small Fonts ukuran 7.5, walaupun saya memang harus memotong descender dari Q.

Contoh output

FOX COKLAT CEPAT MELOMPAT LEBIH DARI ANJING LAZY.  BETULKAH!

Kode (137 karakter)

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

Script lengkap

(gunakan xxd -runtuk membuat ulang file asli)

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                        .....>.

Penjelasan

  • odadalah program utilitas standar "octal dump". The -tu1pilihan mengatakan itu untuk menghasilkan dump desimal byte individu, bukan (solusi yang cukup karena kurangnya bash dari bawah ke atas (), Ord (), .charCodeAt (), dll)
  • P4adalah angka ajaib untuk file PBM format biner, yang mengemas delapan piksel ke dalam setiap byte (dibandingkan P1dengan file PBM format ASCII). Anda akan melihat bagaimana ini terbukti bermanfaat.
  • Per baris hasil akhir, program ini menarik byte delapan piksel (sesuai dengan kode ASCII dan nomor baris) dari bagian data yang dikompresi gzip di bagian akhir menggunakan dd. ( tail -2 $0mengekstrak dua baris terakhir skrip; data yang dikompresi mencakup satu byte linefeed 0x0a.) Kebetulan delapan piksel adalah lebar karakter tunggal. Bytes nol yang mengisi celah antara karakter yang didukung mudah dikompres karena semuanya sama.
  • Semua ini ditulis ke file bernama "8". Karena ada delapan baris (dan juga delapan piksel per byte), jumlah byte adalah lebar output dalam piksel. Ketinggian keluaran juga termasuk dalam yang wc -cmencetak nama file input "8" setelah jumlah byte-nya.
  • Sekarang setelah header selesai, data gambar dicetak. Bash hanya pemberitahuan bahwa dua baris terakhir bukan perintah yang valid (yang terakhir benar-benar tidak valid UTF-8) setelah telah mengeksekusi semua yang datang sebelumnya.
  • Saya menggunakan KZIP hanya untuk mengompresi bagian data, seperti yang dilakukan Ilmari Karonen untuk seluruh pengiriman ke tantangan 12 Hari Natal. Seperti dijelaskan di sana, pada dasarnya perlu menggunakan hex editor untuk mengganti format header ZIP dengan header gzip. Termasuk CRC-32 dan ukuran file dari header ZIP asli tampaknya tidak perlu.

2
Solusi yang sangat bagus (dan singkat)! Dalam skrip shell, penggunaan dd, tail, dan gzip tidak boleh dianggap sebagai imho eksternal.
ChristopheD

1
Pikiran menambahkan penjelasan tentang cara kerjanya? Akan sangat dihargai.
Tn. Llama

2
Bagus sekali, terima kasih banyak untuk penjelasannya. Namun menggunakan versi 'P4' adalah tidak benar-benar menghargai apa yang OP katakan " format bitmap ASCII hitam dan putih yang sangat sederhana ".
eregon

5

Python 2, 248 247 byte

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)

Menggunakan font 3x5, dikemas dalam string yang dapat dicetak, 3 byte per karakter. Font jelas terbaca, meskipun n adalah huruf kecil dan v mungkin keliru untuk au jika tidak terlihat dalam konteks.

Ukuran sebenarnya:
ukuran sebenarnya

Zoom x3:
diperbesar x3

Outputnya adalah tipe P1 PBM, sesuai contoh dalam tantangan. Itu adalah tantangan yang menyenangkan.


4

Ruby 1.9, 346 byte (122 kode + 224 byte data)

Inilah hasilnya:

CODEGOLF

(Ini menyenangkan, bukan?)

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]}}*' '}

Font dihasilkan oleh figlet -f banner -w 1000 $LETTERSdan skrip ini .

Jalankan dengan echo -n 'CODEGOLF.STACKEXCHANGE.COM!' | ruby script.rb > image.pbm.

Script menghasilkan semua baris dan cukup mencetaknya.

Berikut adalah hexdump (gunakan 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]}}*' '}

Dibutuhkan 93 byte kode saat menggunakan goruby:

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]}}*' '}

Menggunakan ZLib memangkas ukuran data menjadi 142 byte, bukan 224, tetapi menambahkan 43 byte dalam kode, jadi 307 byte:

#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]}}*' '}

Yang memberi total 268 saat menggunakan goruby:

#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:

Ini pendekatan yang berbeda. Saya pikir 'awt' tidak dihitung sebagai lib eksternal.

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

Dan ungolfed:

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

Robot adalah cara Jawa yang agak aneh untuk memanggil getPixel. Saya membuat Label dengan alfabet, dan mengukur di mana piksel untuk setiap huruf.

Dalam metode cat, int py = (y < 3) ? y : y +1;dan (8*a+x+17+x/4, py+81)merupakan cara yang rumit, untuk menyesuaikan posisi di font. Huuuh! lain itu akan membutuhkan 9 baris, dan setiap huruf ke-4, ada pixel tambahan secara horizontal. Trial and error membawa saya ke solusi ini.

Kemudian header PBM ditulis, dan setiap baris pesan. Pesan diteruskan sebagai judul bingkai.

Itu dia. Bukan kode terpendek, tetapi tidak perlu lukisan font manual.

Mungkin bisa lebih pendek di BeanShell atau Scala.

Dan sekarang - bagaimana tampilannya?

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

Beberapa zoom diterapkan: java.cafe sayang PNG

Unzoomed: java.cafe sayang JPG

Bukan berarti jumlah karakter adalah jumlah karakter dari solusi Perl yang dikocok.

(bermain golf sedikit lebih. Membuat Robot statis, yang menghindari satu deklarasi Pengecualian.)


Pendekatan orisinal, bagus sekali!
ChristopheD

1
+1 untuk orisinalitas, tetapi baru ... jika Anda ingin meningkatkan bitmap, gunakan interpolasi tetangga terdekat.
Ilmari Karonen

Saya menggunakan eog(Eye of Gnome) dan tangkapan layar. Saya akan mengunggah versi yang tidak berskala jpg; mungkin browser Anda menggunakan interpolasi tetangga terdekat :).
pengguna tidak diketahui

1

C ++ TERLALU BESAR UNTUK MENANG

Saya menulis program menggambar PPM berfitur lengkap di C ++, dengan font bitmap saya sendiri. Bahkan menghapus semua fungsi yang tidak perlu itu masih besar dibandingkan dengan jawaban di sini karena definisi untuk font.

Bagaimanapun, ini adalah output untuk HELLO WORLD: masukkan deskripsi gambar di sini

Dan kodenya:

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

Makefile

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

Jika Anda tertarik, pustaka PPMDraw lengkap ada di sini :


1
Saya menemukan font Anda sangat berguna!
Ludwik

1

SmileBASIC, 231 byte

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

masukkan deskripsi gambar di sini

Setiap karakter hanya berisi 2 pola baris yang berbeda, dipilih dari "palet" dari 8 kombinasi. Data untuk setiap simbol disimpan dalam 1 byte, dengan palet disimpan secara terpisah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.