Erzeugen von PBM-Bitmap-Dateien aus ASCII-Text

19

Das PBM-Format (Portable BitMap) ist ein sehr einfaches ASCII-Schwarzweiß-Bitmap-Format.

Hier ist ein Beispiel für den Buchstaben 'J' (vom Wikipedia-Link kopiert und eingefügt):

P1
# Dies ist eine Beispiel-Bitmap des Buchstabens "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

Es ist Zeit, ein kleines Tool zu erstellen, um Dateien in diesem kleinen Format zu generieren!

Ihr Ziel ist es, das kürzeste Programm (in jeder Sprache) zu schreiben, das den folgenden Regeln entspricht:

  1. Ihr Programm nimmt einen String von stdin (zum Beispiel CODEGOLF.STACKEXCHANGE.COM!)
  2. Es wird eine PBM-Datei mit einer Bitmap-Darstellung (lesbar) der Zeichenfolge generiert.
  3. Jedes Zeichen ist als 8x8-Gitter aufgebaut.
  4. Sie müssen die Zeichen [AZ] (Großbuchstaben), ein Leerzeichen, einen Punkt ('.') Und ein Ausrufezeichen ('!') Unterstützen.
  5. Keine externen Bibliotheken erlaubt (sicherlich keine PBM-bezogenen)!
  6. Der verwendete Zeichensatz darf nicht einfach außerhalb Ihres Programms liegen. Ein Teil der Herausforderung besteht darin, die Charaktere effizient zu speichern ...

Das Testen der Gültigkeit des PBM-Formats kann mit dem GIMP (oder anderen) durchgeführt werden. Führen Sie die Ein- und Ausgabe der Samples vor!

Die kürzeste Lösung erhält am 31.01.2012 die Antwortpunkte.

Viel Spaß beim Golfen!

PS: Ich habe ein Kopfgeld (prozentual gesehen einen großen Teil meines Codegolf-Rufs) hinzugefügt, um (hoffentlich) mehr Konkurrenten anzuziehen.

ChristopheD
quelle
Mit "seiner Bitmap-Darstellung" meinen Sie eine Zeichendarstellung, die etwas ähnelt, das wie Buchstaben aussieht? Wie knapp? Wäre so etwas wie eine Bitmap-Darstellung eines Binärcodes oder eines Braille- oder Morsecodes erlaubt?
Howard
@Howard: Die Idee ist, ein pbm-Bild zu generieren, das den ursprünglichen Eingabetext in 'gerenderter' (Bitmap), aber immer noch lesbarer Form (mit lettersanderen Worten) enthält. Nicht anders als das Beispiel, das mit verknüpft ist.
ChristopheD
Ich habe das Tag kolmogorov-complexity hinzugefügt, da der Hauptteil des Programms die 30 Bitmaps sein werden.
Peter Taylor
@ Peter Taylor: Guter Punkt, danke!
ChristopheD
Ich glaube, wir werden lange und schmerzhafte Debatten darüber führen, was eine "externe Bibliothek" ausmacht.
JB

Antworten:

9

GolfScript, 133 Bytes

Dies basiert auf meiner 164-Byte-Perl-Lösung und verwendet dieselbe 4 x 5-Pixel-Nibble-gepackte Schriftart. Nochmals, ich gebe zuerst die lesbare Version:

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

Hier FONT DATA HEREstehen 71 Bytes für binär gepackte Schriftdaten. Die Codierung unterscheidet sich geringfügig von der in der Perl-Version: Anstatt die gepackte Zeichenfolge in Leerzeichen zu teilen, erweitere ich sie zuerst und teile sie dann im Nibble auf 3(ausgewählt, weil sie zufällig nirgendwo in der Schriftart vorkommt).

Da die Schriftdaten im eigentlichen Skript nicht druckbare Zeichen enthalten, gebe ich sie unten als Hex-Dump aus. Verwenden Sie xxd -rdas Hex - Dump zurück in ausführbaren GolfScript Code zu aktivieren:

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*

Im Gegensatz zu dem Perl - Script, druckt dieser Code alle Zeichen außerhalb der eingestellten A- Z, !, ., spacewie lustig aussehenden kleine Kringel. Das Ersetzen der Schnörkel durch Leerzeichen würde 2 zusätzliche Zeichen kosten; Eine vollständige Entfernung würde 4 kosten.

Dies ist mein erstes GolfScript-Programm überhaupt, daher würde ich mich nicht wundern, wenn noch Optimierungsbedarf besteht. So funktioniert das:

  • {91,65>"!. "+?}%:sordnet die gültigen Eingabezeichen ( A- Z, !, ., space) auf die Zahlen 0-28 und weist das Ergebnis s. Alle Zeichen außerhalb des gültigen Satzes werden mit -1 verknüpft, was beim Drucken zu Kringeln führt.

  • "P4"\,8*8schiebt die Werte "P4", 8 mal die Länge der Eingabe und 8 auf den Stapel. Wenn diese am Ende gedruckt werden, bilden sie den PBM-Header.

  • {16base}%[3]/Nimmt die vorhergehende Zeichenfolge von Schriftartdaten, teilt jedes Byte in zwei Halbbytes auf und teilt das Ergebnis in durch den Wert begrenzte Blöcke auf 3. Durchlaufen Sie {:p;{[p=0]0=}s%}%dann diese Blöcke, indem Sie zuerst jeden Block der Variablen pzuweisen und dann die neu zugeordnete Eingabezeichenfolge durchlaufen sund jedes Zeichen durch den Wert am entsprechenden Offset in ersetzen p. Das witzig aussehende Konstrukt [p=0]0=macht dasselbe wie p=, außer dass es für alle Offsets nach dem Ende von 0 zurückgibt p; Ich mag es nicht wirklich, aber ich konnte keinen kürzeren Weg finden, um damit umzugehen.

  • Zum Schluss ]n*nimmt man alles auf den Stapel (die drei Header-Werte und das Bilddaten-Array) und fügt sie mit Zeilenumbrüchen zum Drucken zusammen.

Ilmari Karonen
quelle
Ernsthaft kurz (nach jeder Metrik). Nett!
ChristopheD
12

Perl, 164 Bytes, keine zlib / gzip-Komprimierung

Nachdem ich über das Problem geschlafen hatte, fand ich eine viel kürzere Lösung als meine erste. Der Trick besteht darin, eine kleine Lücke in den Regeln auszunutzen: Die Zeichen müssen jeweils 8 x 8 Pixel groß sein, aber nichts sagt, dass sie den ganzen Raum ausfüllen müssen . Also habe ich meine eigene 4 mal 5 Pixel große Schrift gezeichnet, mit der ich zwei Zeichen in 5 Bytes packen kann.

Die Ausgabe sieht folgendermaßen aus:

"HALLO WELT!" (skaliert x 4)

    "OH! EIN SCHNELLBRAUNER FUCHS SPRINGT ÜBER DEN FALSCHEN HUND." (Originalgröße)

Lassen Sie mich vor der Eingabe des eigentlichen Codes mit den eingebetteten Schriftartdaten eine de-golfed-Version anzeigen:

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

Im eigentlichen Code wird das PACKED FONT DATAdurch eine Binärzeichenfolge ersetzt, die aus acht Zeilen mit Leerzeichen (vier Zeilen mit 14 Byte und eine Zeile mit 13 Byte sowie drei einzelnen Nullbytes für die leeren Zeilen) besteht. Ich habe meine Schriftart bewusst so gestaltet, dass die gepackten Daten keine Leerzeichen, einfachen Anführungszeichen oder Backslashes enthalten, sodass sie in codiert werden können qw'...'.

Da die gepackte Schriftzeichenfolge nicht druckbare Zeichen enthält, habe ich das eigentliche Skript als Hex-Dump bereitgestellt. Verwandle xxd -res wieder in ausführbaren Perl-Code:

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}

So funktioniert das:

  • Die erste Zeile (in der de-golfed Version) liest eine einzige Zeile eingegeben wird , teilt sie in einer Reihe von Zeichen (bequem alle nachgestellten newlines Weglassen) und ordnet die Buchstaben Aan Zund die Zeichen !und .den Zeichencodes 0-28, die Normalerweise entsprechen nicht druckbare Steuerzeichen in ASCII / Unicode. (Ein geringfügiger Nebeneffekt davon ist, dass alle Tabulatoren in der Eingabe als Js gedruckt werden .) Das Leerzeichen wird nicht zugeordnet, da die Ausgabeschleife ohnehin alle Codes über 28 in Leerzeichen verwandelt.

  • In der zweiten Zeile wird nur der PBM-Header gedruckt. Es verwendet die Perl 5.10- sayFunktion, sodass Sie dieses Skript ausführen müssen, damit perl -M5.010es funktioniert.

  • Die Ausgabeschleife erstellt eine durch Leerzeichen getrennte Liste gepackter Bildzeilen und ordnet diese der $pReihe nach zu. (Ich habe die Schriftart so entworfen, dass die gepackten Daten keine Leerzeichen oder 'Zeichen enthalten.) Anschließend werden die eingegebenen Zeichen in einer Schleife @amit dem Perl- vecBefehl überflogen, um das 4-Bit-Halbbyte zu extrahieren, das dem zugeordneten Zeichencode aus der Bildzeile entspricht. Füllt es mit einem 8-Bit-Byte auf und druckt es aus.


Alte Antwort, 268 Bytes:

Dies ist ein schneller und schmutziger erster Versuch. Ich habe PleaseStands Schriftart gestohlen und zusammen mit meinem Quellcode komprimiert. Da das resultierende Skript größtenteils nicht druckbar ist, ist hier ein Hexdump. verwendet xxd -res in ausführbaren Perl - Code zu aktivieren:

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....|@[email protected]
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'

Der dekomprimierte Perl-Code besteht aus der folgenden Präambel:

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

gefolgt von acht Wiederholungen des folgenden Codes:

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

wird BITMAP DATA HEREdurch 29 Bytes ersetzt, die eine Zeile der Schriftart codieren.

Ilmari Karonen
quelle
Die neuere Lösung ist extrem nett. Ich hätte nie gedacht, dass dies mit 165 Zeichen möglich ist.
ChristopheD
6

8086 Maschinencode

190 Bytes (122 Bytes im BIOS)

Hier ist die Base64-codierte WinXP / MSDos .COM-Datei:

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

(Verwenden Sie etwas wie diese ) , um den Text zu entschlüsseln und speichern als „pbm.com“. Geben Sie dann an der Eingabeaufforderung Folgendes ein:

pbm Zu codierender Text> Ausgabedateiname.pbm

Ich habe dies auf meinem WinXP-Rechner sowohl mit der Standard-Eingabeaufforderung als auch mit DosBox V0.74 getestet.

AKTUALISIEREN

Diese Version ist 190 Bytes groß und verwendet Ilmari Karonens winzige Schrift (hier kein Zugang zum BIOS!): -

voAArf7Iflq7YwG/vgG6Cg20Bfbk9vIAZfsy5PbyAUX5Vqw48HQoLEFzCDQG/sAMGSQfM8
nQ6NfA0QPS6IjEsQSwJtDsENCq4vewMKrr04DDEF6A+7N1ycYFJLqzAbQJzSHDdnb/loIZ
mXZ2flmZ9QAAIJmZEZGCFb+ZmSFZmYUPDy9/kXf9ghPZeXkmWWllAAAgmZkRmZIVmRldKF
mfEgAAAHl2H5Zi+ZkWnicmmfIAICBQMQoNMDAwIDUKDQ==
Skizz
quelle
Sehr schöne Lösung. Im Moment ist dies der Anwärter auf die Prämie, die in etwa 20 Stunden vergeben werden soll. Gut gemacht!
ChristopheD
Können Sie auch hierfür Ihren Assembler-Code posten?
Sir_Lagsalot
1
Nachdem Sie sich die Demontage angesehen und den Code getestet haben, scheint es, dass Sie nur eine Bitmap-Schriftart verwenden, die vom BIOS bereitgestellt wird. Dies kann durch die Tatsache bestätigt werden, dass Ihr Programm Kleinbuchstaben, Symbole und Satzzeichen ausgeben kann, die für die Abfrage nicht erforderlich sind. Somit ist die Schriftart extern zu Ihrem Programm und wird von diesem nicht gespeichert (zumindest meiner Meinung nach).
Sir_Lagsalot
@Skizz: kannst du das bestätigen? Es ist immer noch eine sehr schöne Lösung, aber ein bisschen gegen die Spezifikation.
ChristopheD
1
@ChristopheD: Nun, JB hat kommentiert: "Ich glaube, wir werden lange und schmerzhafte Debatten darüber führen, was eine externe Bibliothek ausmacht." - Man könnte argumentieren, dass es sich putsbei Ruby um eine externe Bibliothek handelt. Ja, es werden die BIOS-Schriftarten verwendet, auf die über eine Zeiger-Dereferenzierung zugegriffen wird (es gibt keine loadOperation, um die Schriftarten in den RAM zu laden ). Vielleicht die Regeln zu weit verbiegen. Ich wäre damit durchgekommen, wenn diese
nervigen
6

Shell-Skript (Code + Daten = 295 Zeichen)

Ich hoffe, tail, gzip und dd zählen nicht als "externe Bibliotheken". Führen Sie so echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. Die Schriftart, die ich verwendete, ist Small Fonts Größe 7,5, obwohl ich den Abseiler vom Q abschneiden musste.

Beispielausgabe

DER SCHNELLE BRAUNE FUCHS SPRINGT ÜBER LAZY DOGS.  JA WIRKLICH!

Code (137 Zeichen)

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

Komplettes Drehbuch

( xxd -rzum erneuten Erstellen der Originaldatei verwenden)

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

Erläuterung

  • odist das Standard-Dienstprogramm "octal dump". Die -tu1Option weist es an, stattdessen einen dezimalen Speicherauszug einzelner Bytes zu erstellen (eine ausreichende Umgehung für das Fehlen von asc (), ord (), .charCodeAt () usw. durch Bash).
  • P4ist die magische Zahl für eine PBM-Datei im Binärformat, die acht Pixel in jedes Byte packt (im Gegensatz P1zur PBM-Datei im ASCII-Format). Sie werden sehen, wie nützlich dies ist.
  • Pro Zeile der endgültigen Ausgabe zieht das Programm am Ende mit ein 8-Pixel-Byte (entsprechend dem ASCII-Code und der Zeilennummer) aus dem mit gzip komprimierten Datenabschnitt dd. ( tail -2 $0Extrahiert die letzten beiden Zeilen des Skripts. Die komprimierten Daten enthalten ein 0x0a-Zeilenvorschubbyte.) Es kommt vor, dass acht Pixel die Breite eines einzelnen Zeichens sind. Die Null-Bytes, die die Lücken zwischen den unterstützten Zeichen füllen, können leicht komprimiert werden, da sie alle gleich sind.
  • All dies wird in eine Datei mit dem Namen "8" geschrieben. Da genau acht Zeilen (und auch acht Pixel pro Byte) vorhanden sind, entspricht die Anzahl der Bytes der Breite der Ausgabe in Pixel. Die Höhe der Ausgabe ist auch darin enthalten, dass wc -cder eingegebene Dateiname "8" nach der Anzahl der Bytes ausgegeben wird .
  • Nachdem der Header vollständig ist, werden die Bilddaten gedruckt. Bash merkt nur, dass die letzten beiden Zeilen keine gültigen Befehle sind (der letzte tatsächlich ungültige UTF-8), nachdem er alles ausgeführt hat, was vorher kam.
  • Ich habe KZIP nur zum Komprimieren des Datenbereichs verwendet, wie es Ilmari Karonen für eine vollständige Einreichung bei der 12 Days of Christmas-Challenge getan hat . Wie dort beschrieben, ist es grundsätzlich erforderlich, einen Hex-Editor zu verwenden, um das ZIP-Header-Format durch einen gzip-Header zu ersetzen. Das Einfügen des CRC-32 und der Dateigröße aus dem ursprünglichen ZIP-Header scheint nicht erforderlich zu sein.
PleaseStand
quelle
2
Wirklich schöne (und kurze) Lösung! In Shell-Skripten sollte die Verwendung von dd, tail und gzip nicht als externes Imho betrachtet werden.
ChristopheD
1
Möchten Sie eine Erklärung hinzufügen, wie dies funktioniert? Würde mich sehr freuen.
Mr. Llama
2
Sehr schön, vielen Dank für die Erklärung. Die Verwendung der 'P4'-Version entspricht jedoch nicht dem, was das OP sagte "einem sehr einfachen ASCII- Schwarzweiß-Bitmap-Format".
Eregon
5

Python 2, 248 247 Bytes

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)

Verwendet eine 3x5-Schriftart, die in eine druckbare Zeichenfolge mit 3 Bytes pro Zeichen gepackt ist. Die Schriftart ist gut lesbar, obwohl das n in Kleinbuchstaben geschrieben ist und das v möglicherweise mit au verwechselt wird, wenn es nicht im Kontext gesehen wird.

Tatsächliche Größe:
tatsächliche Größe

X3 gezoomt:
x3 gezoomt

Der Ausgang ist ein PBM vom Typ P1, wie im Beispiel in der Challenge gezeigt. Es war eine lustige Herausforderung.

Chuck Morris
quelle
4

Ruby 1.9, 346 Bytes (122 Code + 224 Bytes Daten)

Hier ist das Ergebnis:

CODEGOLF

(Es ist schön, nicht wahr?)

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

Die Schriftart wurde von figlet -f banner -w 1000 $LETTERSund dieses Skript generiert .

Laufen Sie mit echo -n 'CODEGOLF.STACKEXCHANGE.COM!' | ruby script.rb > image.pbm.

Das Skript generiert alle Zeilen und druckt sie einfach aus.

Hier ist ein Hexdump (Verwendung 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]}}*' '}

Bei Verwendung von goruby werden 93 Byte Code benötigt:

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

Wenn Sie ZLib verwenden, reduzieren Sie die Datengröße auf 142 Bytes anstatt auf 224, aber fügen Sie dem Code 43 Bytes hinzu, also 307 Bytes:

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

Das ergibt insgesamt 268 bei Verwendung von 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]}}*' '}
Eregon
quelle
2

Java 862 826:

Hier ist ein anderer Ansatz. Ich denke 'awt' zählt nicht als externe 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]);}}

Und 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 ist die irgendwie merkwürdige Art von Java, getPixel aufzurufen. Ich erstelle eine Beschriftung mit dem Alphabet und messe, wo sich für jeden Buchstaben ein Pixel befindet.

Bei der Malmethode int py = (y < 3) ? y : y +1;und (8*a+x+17+x/4, py+81)ist es die komplizierte Art, die Position in der Schrift anzupassen. Huuuh! Andernfalls werden 9 Zeilen benötigt, und bei jedem vierten Buchstaben wird ein zusätzliches Pixel horizontal eingefügt. Versuch und Irrtum brachten mich zu dieser Lösung.

Dann wird der Header der PBM und jede Zeile der Nachricht geschrieben. Die Nachricht wird als Titel des Frames übergeben.

Das ist es. Nicht der kürzeste Code, aber kein manuelles Zeichnen der Schrift war erforderlich.

Vielleicht könnte es in BeanShell oder Scala kürzer sein.

Und jetzt - wie sieht es aus?

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

Mehrere Zooms angewendet: java.cafe Babe PNG

Unzoomed: java.cafe Babe JPG

Nicht, dass die Anzahl der Zeichen der Anzahl der Zeichen entspricht, die von der Perl-Lösung gemischt wurden.

(Ein bisschen mehr Golf gespielt. Robot statisch gemacht, wodurch eine Ausnahmeerklärung vermieden wird.)

Benutzer unbekannt
quelle
Origineller Ansatz, schön gemacht!
ChristopheD
1
+1 für Originalität, aber eww ... Wenn Sie eine Bitmap vergrößern möchten, verwenden Sie die Interpolation des nächsten Nachbarn.
Ilmari Karonen
Ich habe eog(Eye of Gnome) und einen Screenshot verwendet. Ich werde eine unskalierte jpg-Version hochladen ; Möglicherweise verwendet Ihr Browser eine Interpolation nach dem nächsten Nachbarn :).
Benutzer unbekannt
1

C ++ ZU GROSS, UM ZU GEWINNEN

Ich habe ein voll ausgestattetes PPM-Zeichenprogramm in C ++ geschrieben, mit meiner eigenen Bitmap-Schriftart. Selbst wenn alle nicht benötigten Funktionen wegfallen, ist es im Vergleich zu den Antworten hier aufgrund der Definition für die Schriftart immer noch riesig.

Wie auch immer, hier ist die Ausgabe für HELLO WORLD: Bildbeschreibung hier eingeben

Und der Code:

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

Wenn Sie interessiert sind, dann ist die volle PPMDraw Bibliothek hier :

user137
quelle
1
Ich fand deine Schriften sehr nützlich!
Ludwik
1

SmileBASIC, 231 Bytes

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

Bildbeschreibung hier eingeben

Jedes Zeichen enthält nur 2 verschiedene Zeilenmuster, ausgewählt aus einer "Palette" von 8 Kombinationen. Die Daten für jedes Symbol werden in 1 Byte gespeichert, wobei die Palette separat gespeichert wird.

12Me21
quelle