Generando archivos de mapa de bits PBM a partir de texto ASCII

19

El formato PBM (Portable BitMap) es un formato de mapa de bits ASCII en blanco y negro muy simple.

Aquí hay un ejemplo para la letra 'J' (copiado y pegado del enlace de wikipedia):

P1
# Este es un mapa de bits de ejemplo de la letra "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 hora de construir una pequeña herramienta para generar archivos en este pequeño e ingenioso formato!

Su objetivo es escribir el programa más corto (en cualquier idioma) que cumpla con las siguientes reglas:

  1. Su programa toma una cadena de stdin (por ejemplo CODEGOLF.STACKEXCHANGE.COM!)
  2. Genera un archivo PBM con una representación de mapa de bits (legible) de la cadena.
  3. Cada personaje se construye como una cuadrícula de 8x8.
  4. Debe admitir los caracteres [AZ] (todo en mayúsculas), espacio, un punto ('.') Y un signo de exclamación ('!').
  5. ¡No se permiten bibliotecas externas (ciertamente no hay bibliotecas relacionadas con PBM)!
  6. El conjunto de caracteres utilizado no debe ser simplemente externo a su programa. Parte del desafío es almacenar los personajes de manera eficiente ...

Las pruebas de validez del formato PBM se pueden hacer con el GIMP (u otros). ¡Muestra muestras de entrada y salida!

La solución más corta recibirá los puntos de respuesta el 31/01/2012.

Diviértete jugando al golf!

PD: He agregado una recompensa (en términos de porcentaje, una gran parte de mi reputación de codegolf) para (con suerte) atraer a más competidores.

ChristopheD
fuente
Por "su representación de mapa de bits", ¿te refieres a una representación de caracteres que está cerca de algo que parece letras? ¿Qué cerca? ¿Se permitiría algo como una representación de mapa de bits de un código binario o de código braille o morse?
Howard
@Howard: la idea es generar una imagen pbm que contenga el texto de entrada original en 'renderizado' (mapa de bits) pero aún en forma legible por humanos ( lettersen otras palabras). No muy diferente del ejemplo vinculado a.
ChristopheD
Agregué la etiqueta kolmogorov-complex porque la mayor parte del programa serán los 30 mapas de bits.
Peter Taylor
@ Peter Taylor: Buen punto, ¡gracias!
ChristopheD
Siento que tendremos un largo y doloroso debate sobre lo que constituye una "biblioteca externa".
JB

Respuestas:

9

GolfScript, 133 bytes

Esto se basa en mi solución Perl de 164 bytes y utiliza la misma fuente de 4 por 5 píxeles llena de nibbles. Nuevamente, primero daré la versión legible:

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

Aquí FONT DATA HERErepresenta 71 bytes de datos de fuente empaquetados binarios. La codificación es ligeramente diferente que en la versión de Perl: en lugar de dividir la cadena empaquetada en el espacio en blanco, primero la expando y luego la divido en el mordisco 3(elegido porque simplemente no ocurre en ninguna parte de la fuente).

Dado que los datos de la fuente en el script real contienen caracteres no imprimibles, lo doy como un volcado hexadecimal a continuación. Use xxd -rpara volver a convertir el volcado hexadecimal en código ejecutable de GolfScript:

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

A diferencia de la secuencia de comandos Perl, este código imprime los caracteres fuera del conjunto A- Z, !, ., spacecomo pequeños garabatos de aspecto gracioso. Reemplazar los garabatos con espacios en blanco costaría 2 caracteres adicionales; eliminarlos por completo costaría 4.

Este es mi primer programa GolfScript, por lo que no me sorprendería si queda algo de espacio para la optimización. Así es como funciona:

  • {91,65>"!. "+?}%:sasigna los caracteres de entrada válidos ( A- Z, !, ., space) a los números 0 - 28 y asigna el resultado a s. Cualquier carácter fuera del conjunto válido se asigna a -1, que es lo que produce los garabatos cuando se imprime.

  • "P4"\,8*8empuja los valores "P4", 8 veces la longitud de la entrada y 8 en la pila. Cuando se imprime al final, estos formarán el encabezado PBM.

  • {16base}%[3]/toma la cadena de datos de fuente anterior, divide cada byte en dos nibbles y divide el resultado en bloques delimitados por el valor 3. {:p;{[p=0]0=}s%}%luego recorre estos bloques, primero asigna cada bloque a la variable py luego recorre la cadena de entrada reasignada s, reemplazando cada carácter con el valor en el desplazamiento correspondiente en p. La construcción de aspecto divertido [p=0]0=hace lo mismo que p=, excepto que devuelve 0 para cualquier compensación más allá del final de p; Realmente no me gusta, pero no he podido encontrar una forma más corta de manejar eso.

  • Finalmente, ]n*toma todo en la pila (los tres valores de encabezado y la matriz de datos de imagen) y los une con nuevas líneas para imprimir.

Ilmari Karonen
fuente
En serio corto (por cualquier métrica). ¡Agradable!
ChristopheD
12

Perl, 164 bytes, sin compresión zlib / gzip

Después de dormir sobre el problema, logré encontrar una solución mucho más corta que la primera. El truco consiste en aprovechar una laguna menor en las reglas: los personajes deben caber en 8 por 8 píxeles cada uno, pero nada dice que tengan que llenar todo ese espacio. Así que dibujé mi propia fuente de 4 por 5 píxeles, lo que me permitió empaquetar dos caracteres en 5 bytes.

El resultado se ve así:

"¡HOLA MUNDO!" (escalado x 4)

    "¡OH! UN FOX BROWN RÁPIDO SALTA SOBRE EL PERRO PEREZOSO". (tamaño original)

Antes de dar el código real con los datos de fuente incrustados, permítanme mostrar una versión 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;
}

En el código real, PACKED FONT DATAse reemplaza por una cadena binaria que consta de ocho filas delimitadas por espacios en blanco (cuatro filas de 14 bytes y una de 13 bytes, más tres bytes nulos individuales para las filas en blanco). Diseñé deliberadamente mi fuente para que los datos empaquetados no contengan espacios en blanco, comillas simples o barras inclinadas invertidas, para que puedan codificarse qw'...'.

Como la cadena de fuente empaquetada contiene caracteres no imprimibles, proporcioné el script real como un volcado hexadecimal. Use xxd -rpara volverlo a convertir en código ejecutable de Perl:

0000000: 792f 412d 5a21 2e2f 002d 1b2f 666f 7240  y/A-Z!./.-./for@
0000010: 613d 3c3e 3d7e 2f2e 2f67 3b73 6179 2250  a=<>=~/./g;say"P
0000020: 3420 222e 382a 4061 2e22 2038 223b 666f  4 ".8*@a." 8";fo
0000030: 7224 7028 7177 2700 20e6 e6ff 9612 8999  r$p(qw'. .......
0000040: e6e6 7759 99f5 0420 9999 8898 128a df99  ..wY... ........
0000050: 9928 5999 1504 20ef 98ee fb12 8cb9 e9e9  .(Y... .........
0000060: 2659 6965 0420 9999 8899 928a 9989 ab21  &Yie. .........!
0000070: 599f 8220 e9e6 8f96 62f9 9986 972e 2699  Y.. ....b.....&.
0000080: f284 2000 2000 2729 7b70 7269 6e74 2063  .. . .'){print c
0000090: 6872 2076 6563 2470 2c6f 7264 2c34 666f  hr vec$p,ord,4fo
00000a0: 7240 617d                                r@a}

Así es como funciona:

  • La primera línea (en la versión de golf) lee una sola línea de entrada, la divide en una serie de caracteres (omitiendo convenientemente las nuevas líneas finales) y asigna las letras Aa Zlos caracteres !y .a los códigos de caracteres 0 a 28, que normalmente corresponden a caracteres de control no imprimibles en ASCII / Unicode. (Un efecto secundario menor de esto es que las pestañas en la entrada se imprimen como Js.) El carácter de espacio se deja sin asignar, ya que el bucle de salida convierte cualquier código superior a 28 en espacios en blanco de todos modos.

  • La segunda línea solo imprime el encabezado PBM. Utiliza la función Perl 5.10 say, por lo que debe ejecutar este script perl -M5.010para que funcione.

  • El bucle de salida toma una lista delimitada por espacios en blanco de filas de imágenes empaquetadas y asigna cada una de ellas a $psu vez. (Diseñé la fuente para que los datos empaquetados no contuvieran ningún espacio en blanco o 'caracteres). Luego, recorre los caracteres de entrada @a, usando el veccomando de Perl para extraer el mordisco de 4 bits correspondiente al código de caracteres mapeado de la fila de la imagen, lo agrega a un byte de 8 bits y lo imprime.


Antigua respuesta, 268 bytes:

Este es un primer intento rápido y sucio. Robé la fuente de PleaseStand y la comprimí junto con mi código fuente. Como la secuencia de comandos resultante no se puede imprimir, aquí hay un hexdump; use xxd -rpara convertirlo en código ejecutable de Perl:

0000000: 7573 6520 436f 6d70 7265 7373 275a 6c69  use Compress'Zli
0000010: 623b 6576 616c 2075 6e63 6f6d 7072 6573  b;eval uncompres
0000020: 7320 2778 da85 d03d 4b03 4118 85d1 452c  s 'x...=K.A...E,
0000030: b69c 72cb 7519 4894 552c 2c02 3319 ee5c  ..r.u.H.U,,.3..\
0000040: d7b8 5a89 6093 4634 7e82 c490 6c91 8597  ..Z.`.F4~...l...
0000050: 80fe 7267 d660 23ae e52d 0e0f dcd6 f8c3  ..rg.`#..-......
0000060: e9d1 5e6e ccec a15c ddb5 c5d5 495e 94a3  ..^n...\....I^..
0000070: 83b7 c7f9 73f3 5216 f9a8 787a 5fea 666c  ....s.R...xz_.fl
0000080: 9dd1 b763 dd98 76f8 2df6 0799 5811 7144  ...c..v.-...X.qD
0000090: 4acc ee9d b8b0 c90f 7e4a 8264 6016 cbd7  J.......~J.d`...
00000a0: 79f3 1b91 047c 4055 409e 9e54 1dda ed41  y....|@[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'

El código Perl descomprimido consta del siguiente preámbulo:

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

seguido de ocho repeticiones del siguiente código:

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

con BITMAP DATA HEREreemplazado por 29 bytes que codifican una fila de la fuente.

Ilmari Karonen
fuente
La solución más nueva es extremadamente agradable. Nunca imaginé que esto podría hacerse en 165 caracteres.
ChristopheD
6

Código de máquina 8086

190 bytes (122 bytes que usan BIOS)

Aquí está el archivo .COM codificado Base64 WinXP / MSDos:

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

(Use algo como esto ) para decodificar el texto y guardar como "pbm.com". Luego, en el símbolo del sistema, escriba:

texto pbm para codificar> nombrearchivo_salida.pbm

He probado esto en mi máquina WinXP usando el símbolo del sistema estándar y DosBox V0.74.

ACTUALIZAR

Esta versión es de 190 bytes y utiliza la pequeña fuente de Ilmari Karonen (¡aquí no hay acceso a la BIOS!):

voAArf7Iflq7YwG/vgG6Cg20Bfbk9vIAZfsy5PbyAUX5Vqw48HQoLEFzCDQG/sAMGSQfM8
nQ6NfA0QPS6IjEsQSwJtDsENCq4vewMKrr04DDEF6A+7N1ycYFJLqzAbQJzSHDdnb/loIZ
mXZ2flmZ9QAAIJmZEZGCFb+ZmSFZmYUPDy9/kXf9ghPZeXkmWWllAAAgmZkRmZIVmRldKF
mfEgAAAHl2H5Zi+ZkWnicmmfIAICBQMQoNMDAwIDUKDQ==
Skizz
fuente
Muy buena solución. Por el momento, este es el candidato para la recompensa que se otorgará en aproximadamente 20 horas. ¡Bien hecho!
ChristopheD el
¿Puedes publicar tu código de ensamblaje para esto también?
Sir_Lagsalot
1
Después de mirar el desensamblaje y probar el código, parece que solo está utilizando una fuente de mapa de bits proporcionada por la BIOS. Esto puede confirmarse por el hecho de que su programa puede generar letras minúsculas, símbolos y signos de puntuación no requeridos por el desafío. Por lo tanto, la fuente es externa a su programa y no la almacena (al menos en mi opinión).
Sir_Lagsalot
@Skizz: ¿puedes confirmar esto? Todavía es una solución extremadamente agradable, pero está un poco en contra de las especificaciones.
ChristopheD
1
@ChristopheD: Bueno, JB comentó "Siento que vamos a tener un largo y doloroso debate sobre lo que constituye una biblioteca externa". - Se podría argumentar que putsen Ruby hay una biblioteca externa. Sí, utiliza las fuentes de BIOS, a las que se accede a través de una desreferencia de puntero (no hay ninguna loadoperación para obtener las fuentes en la RAM). Doblar las reglas demasiado lejos tal vez. Me habría salido con la suya si no hubiera sido por esos niños molestos ;-)
Skizz
6

Script de shell (código + datos = 295 caracteres)

Espero que tail, gzip y dd no cuenten como "bibliotecas externas". Corre como echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. La fuente que usé es Small Fonts tamaño 7.5, aunque tuve que recortar el descendiente de la Q.

Salida de ejemplo

EL RÁPIDO BROWN FOX SALTA SOBRE PERROS PEREZOSOS.  ¡DE VERDAD!

Código (137 caracteres)

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

Guión completo

(se usa xxd -rpara recrear el archivo original)

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

Explicación

  • odes el programa de utilidad estándar "volcado octal". La -tu1opción le dice que produzca un volcado decimal de bytes individuales en su lugar (una solución suficiente para la falta de asc de bash (), ord (), .charCodeAt (), etc.)
  • P4es el número mágico para un archivo PBM de formato binario, que incluye ocho píxeles en cada byte (en comparación P1con el archivo PBM de formato ASCII). Verá cómo esto resulta útil.
  • Por fila de salida final, el programa extrae un byte de ocho píxeles (correspondiente al código ASCII y el número de línea) de la sección de datos comprimidos de gzip al final usando dd. (tail -2 $0 extrae las dos últimas líneas del script; los datos comprimidos incluyen un byte de salto de línea 0x0a). Ocurre que ocho píxeles es el ancho de un solo carácter. Los bytes nulos que llenan los espacios entre los caracteres admitidos son fácilmente comprimibles porque son todos iguales.
  • Todo esto está escrito en un archivo llamado "8". Debido a que hay exactamente ocho filas (y también ocho píxeles por byte), el número de bytes es el ancho de la salida en píxeles. La altura de la salida también se incluye en que wc -cimprime el nombre de archivo de entrada "8" después de su recuento de bytes.
  • Ahora que el encabezado está completo, se imprimen los datos de la imagen. Bash solo se da cuenta de que las dos últimas líneas no son comandos válidos (el último UTF-8 realmente inválido) después de haber ejecutado todo lo anterior.
  • Usé KZIP solo para comprimir la sección de datos, como lo hizo Ilmari Karonen para una presentación completa al desafío de los 12 días de Navidad. Como se describe allí, es esencialmente necesario usar un editor hexadecimal para reemplazar el formato del encabezado ZIP con un encabezado gzip. Incluir el CRC-32 y el tamaño del archivo del encabezado ZIP original parece ser innecesario.
Por favor levantese
fuente
2
¡Una solución realmente agradable (y corta)! En las secuencias de comandos de shell, el uso de dd, tail y gzip no debe considerarse como una imho externa.
ChristopheD
1
¿Le importaría agregar una explicación de cómo funciona esto? Sería muy apreciado
Sr. Llama
2
Muy bien, muchas gracias por la explicación. Sin embargo, el uso de la versión 'P4' no respeta realmente lo que el OP dijo "un formato de mapa de bits ASCII en blanco y negro muy simple ".
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)

Utiliza una fuente 3x5, empaquetada en una cadena imprimible, 3 bytes por carácter. La fuente es claramente legible, aunque la n es minúscula y la v podría confundirse con au si no se ve en contexto.

Tamaño real:
tamaño real

Zoom x3:
zoom x3

La salida es un PBM tipo P1, según el ejemplo en el desafío. Fue un reto divertido.

Chuck Morris
fuente
4

Ruby 1.9, 346 bytes (código 122 + datos de 224 bytes)

Aquí está el resultado:

CODEGOLF

(Está bien, ¿no?)

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 fuente fue generada por figlet -f banner -w 1000 $LETTERSy este script .

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

El script genera todas las filas y simplemente las imprime.

Aquí hay un hexdump (uso 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]}}*' '}

Se necesitan 93 bytes de código cuando se usa 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]}}*' '}

Usando ZLib, recorte el tamaño de los datos a 142 bytes en lugar de 224, pero agrega 43 bytes en el código, por lo que 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]}}*' '}

Lo que da un total de 268 cuando se usa 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
fuente
2

Java 862 826:

Aquí hay un enfoque diferente. Creo que 'awt' no cuenta como lib externo.

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

Y sin golfos:

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 es la forma algo curiosa de Java para llamar a getPixel. Creo una etiqueta con el alfabeto y mido dónde está un píxel para cada letra.

En el método de pintura, int py = (y < 3) ? y : y +1;y (8*a+x+17+x/4, py+81)es la forma complicada, ajustar la posición en la fuente. Huuuh! de lo contrario, necesitaría 9 líneas, y cada cuarta letra, hay un píxel adicional horizontalmente. La prueba y el error me llevaron a esta solución.

Luego se escribe el encabezado del PBM y cada línea del mensaje. El mensaje se pasa como título del marco.

Eso es. No es el código más corto, pero no fue necesaria la pintura manual de fuentes.

Tal vez podría ser más corto en BeanShell o Scala.

Y ahora, ¿cómo se ve?

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

Múltiples zooms aplicados: java.cafe bebé PNG

Sin zoom: java.cafe bebé JPG

No es que el número de caracteres sea el número de caracteres de la solución Perl barajada.

(Golf un poco más. Hecho Robot estático, que evita una declaración de excepción).

usuario desconocido
fuente
Enfoque original, bien hecho!
ChristopheD
1
+1 para originalidad, pero eww ... si vas a escalar un mapa de bits, usa la interpolación de vecino más cercano.
Ilmari Karonen
Usé eog(Eye of Gnome) y una captura de pantalla. Cargaré una jpgversión sin escala; tal vez su navegador utiliza una interpolación vecina más cercana :).
usuario desconocido el
1

C ++ DEMASIADO GRANDE PARA GANAR

Escribí un programa de dibujo PPM con todas las funciones en C ++, con mi propia fuente de mapa de bits. Incluso eliminar todas las funciones no necesarias sigue siendo enorme en comparación con las respuestas aquí debido a la definición de la fuente.

De todos modos, aquí está la salida de HELLO WORLD: ingrese la descripción de la imagen aquí

Y el codigo:

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 está interesado, la biblioteca completa PPMDraw está aquí :

usuario137
fuente
1
¡Encontré sus fuentes muy útiles!
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

ingrese la descripción de la imagen aquí

Cada personaje contiene solo 2 patrones de fila diferentes, elegidos de una "paleta" de 8 combinaciones. Los datos para cada símbolo se almacenan en 1 byte, con la paleta almacenada por separado.

12Me21
fuente