Génération de fichiers bitmap PBM à partir de texte ASCII

19

Le format PBM (Portable BitMap) est un format bitmap ASCII noir et blanc très simple.

Voici un exemple pour la lettre «J» (copiée-collée à partir du lien wikipedia):

P1
# Ceci est un exemple de bitmap de la lettre "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

Il est temps de construire un petit outil pour générer des fichiers dans ce petit format astucieux!

Votre objectif est d'écrire le programme le plus court (dans n'importe quelle langue) conforme aux règles suivantes:

  1. Votre programme prend une chaîne de stdin (par exemple CODEGOLF.STACKEXCHANGE.COM!)
  2. Il génère un fichier PBM avec une représentation bitmap (lisible) de la chaîne.
  3. Chaque personnage est construit comme une grille 8x8.
  4. Vous devez prendre en charge les caractères [AZ] (tout en majuscules), l'espace, un point ('.') Et un point d'exclamation ('!').
  5. Aucune bibliothèque externe autorisée (certainement pas de bibliothèques liées à PBM)!
  6. Le jeu de caractères utilisé ne doit pas simplement être externe à votre programme. Une partie du défi consiste à stocker efficacement les personnages ...

Les tests de validité du format PBM peuvent être effectués avec GIMP (ou autres). Montrez les échantillons d'entrée et de sortie!

La solution la plus courte obtiendra les points de réponse le 31-01-2012.

Amusez-vous au golf!

PS: J'ai ajouté une prime (en pourcentage une énorme partie de ma réputation de codegolf) pour (espérons-le) attirer plus de concurrents.

ChristopheD
la source
Par "sa représentation bitmap", voulez-vous dire une représentation de caractère qui est proche de quelque chose qui ressemble à des lettres? A quelle distance? Est-ce que quelque chose comme une représentation bitmap d'un code binaire ou d'un code braille ou morse serait autorisé?
Howard
@Howard: l'idée est de générer une image pbm qui contient le texte d'entrée original sous une forme 'rendue' (bitmap) mais toujours lisible par l'homme (avec lettersen d'autres termes). Un peu comme l'exemple lié à.
ChristopheD
J'ai ajouté la balise kolmogorov-complex car la majeure partie du programme sera constituée de 30 bitmaps.
Peter Taylor
@Peter Taylor: Bon point, merci!
ChristopheD
Je pense que nous allons avoir un débat long et douloureux sur ce qui constitue une «bibliothèque externe».
JB

Réponses:

9

GolfScript, 133 octets

Ceci est basé sur ma solution Perl de 164 octets et utilise la même police 4 x 5 pixels pleine de quartets. Encore une fois, je vais d'abord donner la version lisible:

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

Ici, FONT DATA HEREreprésente 71 octets de données de police compressées binaires. L'encodage est légèrement différent de celui de la version Perl: au lieu de diviser la chaîne compressée sur des espaces, je la développe d'abord, puis la divise sur le quartet 3(choisi car il se trouve que cela ne se produit nulle part dans la police).

Étant donné que les données de police dans le script réel contiennent des caractères non imprimables, je les donne sous forme de vidage hexadécimal ci-dessous. Utilisez xxd -rpour transformer le vidage hexadécimal en code GolfScript exécutable:

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

A la différence du script Perl, ce code imprime des caractères en dehors du jeu A- Z, !, ., spaceaussi peu gribouillis drôles prospectifs. Remplacer les gribouillis par des blancs coûterait 2 caractères supplémentaires; les supprimer entièrement coûterait 4.

Il s'agit de mon tout premier programme GolfScript, donc je ne serais pas surpris s'il reste de la place pour l'optimisation. Voici comment ça fonctionne:

  • {91,65>"!. "+?}%:scartes les caractères d'entrée valides ( A- Z, !, ., space) aux numéros 0 - 28 et affecte le résultat à s. Tous les caractères en dehors de l'ensemble valide sont mappés à -1, ce qui produit les gribouillis lors de l'impression.

  • "P4"\,8*8pousse les valeurs "P4", 8 fois la longueur de l'entrée et 8 sur la pile. Une fois imprimés à la fin, ceux-ci formeront l'en-tête PBM.

  • {16base}%[3]/prend la chaîne de données de police précédente, divise chaque octet en deux quartets et divise le résultat en blocs délimités par la valeur 3. {:p;{[p=0]0=}s%}%boucle ensuite sur ces blocs, affectant d'abord chaque bloc à la variable p, puis bouclant sur la chaîne d'entrée remappée s, en remplaçant chaque caractère par la valeur au décalage correspondant dans p. La construction amusante [p=0]0=fait la même chose que p=, sauf qu'elle renvoie 0 pour tous les décalages après la fin de p; Je n'aime pas vraiment ça, mais je n'ai pas été en mesure de trouver un moyen plus court de gérer cela.

  • Enfin, ]n*prend tout sur la pile (les trois valeurs d'en-tête et le tableau de données d'image) et les joint avec des retours à la ligne pour l'impression.

Ilmari Karonen
la source
Sérieusement court (par n'importe quelle métrique). Agréable!
ChristopheD
12

Perl, 164 octets, pas de compression zlib / gzip

Après avoir dormi sur le problème, j'ai réussi à trouver une solution beaucoup plus courte que la première. L'astuce consiste à profiter d'une faille mineure dans les règles: les personnages doivent tenir dans 8 x 8 pixels chacun, mais rien ne dit qu'ils doivent remplir tout cet espace. J'ai donc dessiné ma propre police de 4 x 5 pixels, ce qui m'a permis de regrouper deux caractères en 5 octets.

La sortie ressemble à ceci:

"BONJOUR LE MONDE!" (mis à l'échelle x 4)

    "OH! UN RENARD RAPIDE BRUN SAUT SUR LE CHIEN PARESSE." (format original)

Avant de donner le code réel avec les données de police intégrées, permettez-moi de montrer une version dé-golfée:

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

Dans le code réel, le PACKED FONT DATAest remplacé par une chaîne binaire composée de huit lignes délimitées par des espaces (quatre lignes de 14 octets et une de 13 octets, plus trois octets nuls simples pour les lignes vides). J'ai délibérément conçu ma police pour que les données compressées ne contiennent aucun espace, guillemets simples ou barres obliques inverses, afin qu'elles puissent être encodées qw'...'.

Étant donné que la chaîne de police compressée contient des caractères non imprimables, j'ai fourni le script réel sous forme de vidage hexadécimal. Utilisez-le xxd -rpour le reconvertir en code Perl exécutable:

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}

Voici comment ça fonctionne:

  • La première ligne (dans la version dé-golfée) lit une seule ligne d'entrée, la divise en un tableau de caractères (en omettant commodément tous les retours à la ligne) et mappe les lettres Aà Zet les caractères !et .les codes de caractères 0 à 28, qui correspondent normalement aux caractères de contrôle non imprimables en ASCII / Unicode. (Un effet secondaire mineur de cela est que tous les onglets de l'entrée sont imprimés en tant que Js.) Le caractère d'espace n'est pas mappé, car la boucle de sortie transforme tous les codes supérieurs à 28 en blancs de toute façon.

  • La deuxième ligne imprime simplement l'en-tête PBM. Il utilise la fonctionnalité Perl 5.10 say, vous devez donc exécuter ce script avec perl -M5.010pour qu'il fonctionne.

  • La boucle de sortie prend une liste délimitée par des espaces des lignes d'image compressées et les affecte chacune $pà son tour. (J'ai conçu la police pour que les données compressées ne contiennent aucun espace ni 'caractère.) Elle passe ensuite en boucle les caractères d'entrée dans @a, en utilisant la veccommande de Perl pour extraire le quartet de 4 bits correspondant au code de caractère mappé de la ligne d'image, le remplit sur un octet 8 bits et l'imprime.


Ancienne réponse, 268 octets:

Il s'agit d'une première tentative rapide et sale. J'ai volé la police de PleaseStand et l'ai compressée avec mon code source. Étant donné que le script résultant n'est pas imprimable, voici un hexdump; utiliser xxd -rpour le transformer en code Perl exécutable:

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'

Le code Perl décompressé se compose du préambule suivant:

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

suivi de huit répétitions du code suivant:

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

avec BITMAP DATA HEREremplacé par 29 octets codant une ligne de la police.

Ilmari Karonen
la source
La nouvelle solution est extrêmement agréable. Je n'aurais jamais imaginé que cela pouvait se faire en 165 caractères.
ChristopheD
6

8086 Code machine

190 octets (122 octets en utilisant le BIOS)

Voici le fichier .COM WinXP / MSDos encodé en Base64:

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

(Utilisez quelque chose comme ça ) pour décoder le texte et l'enregistrer sous "pbm.com". Ensuite, à l'invite de commandes, tapez:

texte pbm à coder> nomfichier_produit.pbm

J'ai testé cela sur ma machine WinXP en utilisant à la fois l'invite de commande standard et DosBox V0.74.

MISE À JOUR

Cette version est de 190 octets et utilise la petite police d'Ilmari Karonen (pas d'accès bios ici!): -

voAArf7Iflq7YwG/vgG6Cg20Bfbk9vIAZfsy5PbyAUX5Vqw48HQoLEFzCDQG/sAMGSQfM8
nQ6NfA0QPS6IjEsQSwJtDsENCq4vewMKrr04DDEF6A+7N1ycYFJLqzAbQJzSHDdnb/loIZ
mXZ2flmZ9QAAIJmZEZGCFb+ZmSFZmYUPDy9/kXf9ghPZeXkmWWllAAAgmZkRmZIVmRldKF
mfEgAAAHl2H5Zi+ZkWnicmmfIAICBQMQoNMDAwIDUKDQ==
Skizz
la source
Solution extrêmement agréable. Pour le moment, c'est le candidat à la prime qui sera décerné dans environ 20 heures. Bien joué!
ChristopheD
Pouvez-vous également publier votre code d'assemblage?
Sir_Lagsalot
1
Après avoir examiné le démontage et testé le code, il semble que vous utilisez simplement une police bitmap fournie par le bios. Cela peut être confirmé par le fait que votre programme peut produire des lettres minuscules, des symboles et des signes de ponctuation non requis par le défi. Ainsi, la police est externe à votre programme et n'est pas stockée par lui (du moins à mon avis).
Sir_Lagsalot
@Skizz: pouvez-vous confirmer cela? Cela fait toujours une solution extrêmement agréable, mais c'est un peu contre la spécification.
ChristopheD
1
@ChristopheD: Eh bien, JB a commenté "Je pense que nous allons avoir un débat long et douloureux sur ce qui constitue une bibliothèque externe." - on pourrait dire que putsRuby est une bibliothèque externe. Oui, il utilise les polices bios, accessibles via une déréférence de pointeur (il n'y a aucune loadopération pour obtenir les polices dans la RAM). Plier les règles trop loin peut-être. J'aurais pu m'en tirer si ça n'avait pas été pour ces gamins embêtants ;-)
Skizz
6

Script shell (code + données = 295 caractères)

J'espère que tail, gzip et dd ne comptent pas comme des "bibliothèques externes". Exécuter en tant que echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. La police que j'ai utilisée est de petite taille 7,5, même si j'ai dû couper le descendeur du Q.

Exemple de sortie

LE FOX BRUN RAPIDE SAUT SUR LES CHIENS PARES.  VRAIMENT!

Code (137 caractères)

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 complet

(utiliser xxd -rpour recréer le fichier d'origine)

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

Explication

  • odest le programme utilitaire standard "octal dump". L' -tu1option lui dit de produire un vidage décimal d'octets individuels à la place (une solution de contournement suffisante pour le manque de bash de asc (), ord (), .charCodeAt (), etc.)
  • P4est le nombre magique pour un fichier PBM au format binaire, qui contient huit pixels dans chaque octet (par rapport P1au fichier PBM au format ASCII). Vous verrez comment cela s'avère utile.
  • Par ligne de sortie finale, le programme extrait un octet de huit pixels (correspondant au code ASCII et au numéro de ligne) de la section de données compressées par gzip à la fin en utilisant dd. ( tail -2 $0extrait les deux dernières lignes du script; les données compressées incluent un octet de saut de ligne 0x0a.) Il se trouve que huit pixels correspondent à la largeur d'un seul caractère. Les octets nuls qui remplissent les espaces entre les caractères pris en charge sont facilement compressibles car ils sont tous identiques.
  • Tout cela est écrit dans un fichier nommé "8". Puisqu'il y a exactement huit lignes (et également huit pixels par octet), le nombre d'octets est la largeur de la sortie en pixels. La hauteur de la sortie est également incluse dans celle qui wc -cimprime le nom de fichier d'entrée "8" après son nombre d'octets.
  • Maintenant que l'en-tête est terminé, les données d'image sont imprimées. Bash remarque seulement que les deux dernières lignes ne sont pas des commandes valides (la dernière en fait non valide UTF-8) après avoir exécuté tout ce qui précède.
  • J'ai utilisé KZIP uniquement pour compresser la section des données, comme Ilmari Karonen l'a fait pour une soumission entière au défi des 12 jours de Noël. Comme décrit ici, il est essentiellement nécessaire d'utiliser un éditeur hexadécimal pour remplacer le format d'en-tête ZIP par un en-tête gzip. Il ne semble pas nécessaire d'inclure le CRC-32 et la taille de fichier de l'en-tête ZIP d'origine.
Veuillez vous lever
la source
2
Solution vraiment sympa (et courte)! Dans les scripts shell, l'utilisation de dd, tail et gzip ne doit pas être considérée comme un imho externe.
ChristopheD
1
Vous voulez ajouter une explication sur la façon dont cela fonctionne? Serait très apprécié.
M. Llama
2
Très bien, merci beaucoup pour l'explication. Cependant, l'utilisation de la version 'P4' ne respecte pas vraiment ce que l'OP disait "un format bitmap ASCII noir et blanc très simple ".
eregon
5

Python 2, 248 247 octets

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)

Utilise une police 3x5, regroupée dans une chaîne imprimable, 3 octets par caractère. La police est clairement lisible, bien que le n soit en minuscule et que le v puisse être confondu avec au s'il n'est pas vu dans son contexte.

Taille actuelle:
taille actuelle

Zoomé x3:
zoomé x3

La sortie est un PBM de type P1, selon l'exemple du défi. C'était un défi amusant.

Chuck Morris
la source
4

Ruby 1.9, 346 octets (code 122 + données 224 octets)

Voici le résultat:

CODEGOLF

(C'est bien, non?)

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

La police a été générée par figlet -f banner -w 1000 $LETTERSet ce script .

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

Le script génère toutes les lignes et les imprime simplement.

Voici un hexdump (utilisation 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]}}*' '}

Il faut 93 octets de code lors de l'utilisation de 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]}}*' '}

L'utilisation de ZLib réduit la taille des données à 142 octets au lieu de 224, mais ajoute 43 octets dans le code, donc 307 octets:

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

Ce qui donne un total de 268 lors de l'utilisation de 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
la source
2

Java 862 826:

Voici une approche différente. Je pense que «awt» ne compte pas comme une bibliothèque externe.

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

Et non golfé:

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 est la façon curieuse de Java d'appeler getPixel. Je crée une étiquette avec l'alphabet et mesure où se trouve un pixel pour chaque lettre.

Dans la méthode de peinture, int py = (y < 3) ? y : y +1;et (8*a+x+17+x/4, py+81)c'est la manière compliquée, pour ajuster la position dans la police. Huuuh! sinon, il faudrait 9 lignes, et toutes les 4 lettres, il y a un pixel supplémentaire horizontalement. Les essais et les erreurs m'ont amené à cette solution.

Ensuite, l'en-tête du PBM est écrit, et chaque ligne du message. Le message est transmis comme titre du cadre.

C'est ça. Pas le code le plus court, mais aucune peinture de police manuelle n'était nécessaire.

Peut-être qu'il pourrait être plus court dans BeanShell ou Scala.

Et maintenant - à quoi ça ressemble?

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

Plusieurs zooms appliqués: java.cafe babe PNG

Sans zoom: java.cafe babe JPG

Non pas que le nombre de caractères soit le nombre de caractères de la solution Perl mélangés.

(Il a joué un peu plus au golf. Il a rendu le robot statique, ce qui évite une déclaration d'exception.)

Utilisateur inconnu
la source
Approche originale, bien réalisée!
ChristopheD
1
+1 pour l'originalité, mais eww ... si vous voulez agrandir une image bitmap, utilisez l'interpolation du plus proche voisin.
Ilmari Karonen
J'ai utilisé eog(Eye of Gnome) et une capture d'écran. Je vais télécharger une version non mise à l'échelle jpg; votre navigateur utilise peut-être une interpolation du voisin le plus proche :).
utilisateur inconnu
1

C ++ TROP GRAND POUR GAGNER

J'ai écrit un programme de dessin PPM complet en C ++, avec ma propre police bitmap. Même en supprimant toutes les fonctions non nécessaires, c'est toujours énorme par rapport aux réponses ici en raison de la définition de la police.

Quoi qu'il en soit, voici la sortie pour HELLO WORLD: entrez la description de l'image ici

Et le 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

Si vous êtes intéressé, la bibliothèque PPMDraw complète est ici :

user137
la source
1
J'ai trouvé vos polices très utiles!
Ludwik
1

SmileBASIC, 231 octets

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

entrez la description de l'image ici

Chaque caractère ne contient que 2 motifs de lignes différents, choisis dans une "palette" de 8 combinaisons. Les données de chaque symbole sont stockées dans 1 octet, la palette étant stockée séparément.

12Me21
la source