Tạo tệp bitmap PBM từ văn bản ASCII


19

Các PBM (Portable bitmap) định dạng là một màu đen ASCII rất đơn giản và định dạng bitmap trắng.

Đây là một ví dụ cho chữ 'J' (được sao chép từ liên kết wikipedia):

P1
# Đây là một ví dụ bitmap của chữ "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

Đã đến lúc chúng ta xây dựng một công cụ nhỏ để tạo các tệp theo định dạng nhỏ tiện lợi này!

Mục tiêu của bạn là viết chương trình ngắn nhất (bằng bất kỳ ngôn ngữ nào) tuân thủ các quy tắc sau:

  1. Chương trình của bạn lấy một chuỗi từ stdin (ví dụ CODEGOLF.STACKEXCHANGE.COM!)
  2. Nó tạo ra một tệp PBM với biểu diễn chuỗi bitmap (có thể đọc được) của chuỗi.
  3. Mỗi nhân vật được xây dựng như một lưới 8x8.
  4. Bạn phải hỗ trợ các ký tự [AZ] (tất cả chữ hoa), dấu cách, dấu ('.') Và dấu chấm than ('!').
  5. Không cho phép thư viện bên ngoài (chắc chắn không có thư viện liên quan đến PBM)!
  6. Bộ ký tự được sử dụng không chỉ đơn giản là bên ngoài chương trình của bạn. Một phần của thử thách là lưu trữ các nhân vật một cách hiệu quả ...

Việc kiểm tra tính hợp lệ của định dạng PBM có thể được thực hiện với GIMP (hoặc các định dạng khác). Đừng khoe mẫu đầu vào và đầu ra!

Giải pháp ngắn nhất sẽ được trao điểm trả lời vào ngày 2012-01-31.

Chúc bạn chơi golf vui vẻ!

Tái bút: Tôi đã thêm tiền thưởng (phần trăm khôn ngoan, một phần rất lớn trong danh tiếng tiền mã hóa của tôi) để (hy vọng) thu hút được nhiều đối thủ cạnh tranh hơn.


Theo "đại diện bitmap của nó", bạn có nghĩa là một đại diện nhân vật gần với một cái gì đó trông giống như các chữ cái? Làm thế nào gần? Liệu một cái gì đó giống như một đại diện bitmap của mã nhị phân hoặc mã chữ nổi hoặc mã morse được phép?
Howard

@Howard: ý tưởng là tạo ra một hình ảnh pbm có chứa văn bản đầu vào ban đầu ở dạng 'render' (bitmap) nhưng vẫn ở dạng người có thể đọc được ( lettersnói cách khác). Không giống như ví dụ liên kết đến.
BarsheD

Tôi đã thêm thẻ kolmogorov-độ phức tạp vì phần lớn chương trình sẽ là 30 bitmap.
Peter Taylor

@Peter Taylor: Điểm tốt, cảm ơn!
BarsheD

Tôi cảm thấy chúng ta sẽ có cuộc tranh luận lâu dài và đau đớn về những gì tạo nên một "thư viện bên ngoài".
JB

Câu trả lời:


9

GolfScript, 133 byte

Điều này dựa trên giải pháp Perl 164 byte của tôi và sử dụng cùng một phông chữ 4 x 5 pixel. Một lần nữa, tôi sẽ đưa ra phiên bản dễ đọc trước:

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

Ở đây, FONT DATA HERElà viết tắt của 71 byte dữ liệu phông chữ đóng gói nhị phân. Mã hóa hơi khác so với trong phiên bản Perl: thay vì chia chuỗi được đóng gói trên khoảng trắng, tôi mở rộng nó trước và sau đó tách nó trên nibble 3(được chọn vì nó không xảy ra ở bất kỳ đâu trong phông chữ).

Vì dữ liệu phông chữ trong tập lệnh thực tế chứa các ký tự không thể in được, tôi cung cấp nó dưới dạng kết xuất hex bên dưới. Sử dụng xxd -rđể biến kết xuất hex trở lại thành mã GolfScript thực thi:

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*

Không giống như kịch bản Perl, mã này in bất kỳ ký tự bên ngoài các thiết lập A- Z, !, ., spacenhư squiggles chút hài hước nhìn. Thay thế các squiggles bằng khoảng trống sẽ tốn thêm 2 ký tự; loại bỏ chúng hoàn toàn sẽ có giá 4.

Đây là chương trình GolfScript đầu tiên của tôi từ trước đến nay, vì vậy tôi sẽ không ngạc nhiên nếu còn một số chỗ để tối ưu hóa. Đây là cách nó hoạt động:

  • {91,65>"!. "+?}%:sbản đồ các nhân vật đầu vào hợp lệ ( A- Z, !, ., space) để những con số 0-28 và chuyển nhượng kết quả đến s. Bất kỳ ký tự nào bên ngoài tập hợp lệ sẽ được ánh xạ tới -1, đó là những gì tạo ra các hình vuông khi được in.

  • "P4"\,8*8đẩy các giá trị "P4", gấp 8 lần chiều dài của đầu vào và 8 vào ngăn xếp. Khi được in ở cuối, chúng sẽ tạo thành tiêu đề PBM.

  • {16base}%[3]/lấy chuỗi dữ liệu phông chữ trước đó, chia từng byte của nó thành hai nibble và chia kết quả thành các khối được phân định bởi giá trị 3. {:p;{[p=0]0=}s%}%sau đó lặp qua các khối này, đầu tiên gán từng khối cho biến pvà sau đó lặp qua chuỗi đầu vào được ánh xạ lại s, thay thế từng ký tự bằng giá trị ở phần bù tương ứng p. Cấu trúc trông buồn cười [p=0]0=thực hiện tương tự p=, ngoại trừ việc nó trả về 0 cho bất kỳ sự bù trừ nào trước khi kết thúc p; Tôi không thực sự thích nó, nhưng tôi không thể tìm ra cách nào ngắn hơn để xử lý việc đó.

  • Cuối cùng, ]n*lấy tất cả mọi thứ trên ngăn xếp (ba giá trị tiêu đề và mảng dữ liệu hình ảnh) và nối chúng lại với nhau bằng các dòng mới để in.


Nghiêm túc ngắn (bởi bất kỳ số liệu). Tốt đẹp!
BarsheD

12

Perl, 164 byte, không nén zlib / gzip

Sau khi ngủ về vấn đề này, tôi đã tìm ra một giải pháp ngắn hơn nhiều so với giải pháp đầu tiên của tôi. Bí quyết là tận dụng một lỗ hổng nhỏ trong các quy tắc: các nhân vật cần phải phù hợp với 8 x 8 pixel mỗi cái, nhưng không có gì nói rằng họ phải lấp đầy tất cả khoảng trống đó. Vì vậy, tôi đã vẽ phông chữ 4 x 5 pixel của riêng mình, cho phép tôi đóng gói hai ký tự thành 5 byte.

Đầu ra trông như thế này:

"CHÀO THẾ GIỚI!" (tỷ lệ x 4)

    "OH! MỘT NHỮNG FOX NHANH CHÓNG NHANH CHÓNG VỀ DOG LAZY." (Kích thước ban đầu)

Trước khi đưa ra mã thực tế với dữ liệu phông chữ được nhúng, hãy để tôi hiển thị phiên bản khử 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;
}

Trong mã thực tế, chuỗi PACKED FONT DATAđược thay thế bằng một chuỗi nhị phân bao gồm tám hàng được phân tách bằng khoảng trắng (bốn hàng 14 byte và một hàng 13 byte, cộng với ba byte rỗng cho các hàng trống). Tôi cố tình thiết kế phông chữ của mình để dữ liệu được đóng gói không chứa khoảng trắng, dấu ngoặc đơn hoặc dấu gạch chéo ngược, để nó có thể được mã hóa qw'...'.

Vì chuỗi phông chữ được đóng gói chứa các ký tự không thể in được, tôi đã cung cấp tập lệnh thực tế dưới dạng kết xuất hex. Sử dụng xxd -rđể biến nó trở lại thành mã Perl thực thi:

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}

Đây là cách nó hoạt động:

  • Dòng đầu tiên (trong phiên bản khử golf) đọc một dòng đầu vào, chia nó thành một mảng các ký tự (bỏ qua bất kỳ dòng mới nào) và ánh xạ các chữ cái Ađến Zvà các ký tự !.mã ký tự từ 0 đến 28, thường tương ứng với các ký tự điều khiển không thể in được trong ASCII / Unicode. (Một tác dụng phụ của việc này là bất kỳ tab nào trong đầu vào đều được in dưới dạng Js.) Ký tự khoảng trắng không được ánh xạ, vì vòng lặp đầu ra biến bất kỳ mã nào trên 28 thành khoảng trống.

  • Dòng thứ hai chỉ in tiêu đề PBM. Nó sử dụng saytính năng Perl 5.10 , vì vậy bạn cần chạy tập lệnh này perl -M5.010để nó hoạt động.

  • Vòng lặp đầu ra lấy một danh sách được phân định bằng khoảng trắng của các hàng hình ảnh được đóng gói và $plần lượt gán từng hàng cho chúng . (Tôi đã thiết kế phông chữ sao cho dữ liệu được đóng gói sẽ không chứa bất kỳ khoảng trắng hoặc 'ký tự nào.) Sau đó, nó lặp lại các ký tự đầu vào @a, sử dụng veclệnh của Perl để trích xuất nibble 4 bit tương ứng với mã ký tự được ánh xạ từ hàng hình ảnh, đệm nó vào một byte 8 bit và in nó.


Câu trả lời cũ, 268 byte:

Đây là một nỗ lực đầu tiên nhanh chóng và bẩn thỉu. Tôi đã đánh cắp phông chữ của PleaseStand và nén nó cùng với mã nguồn của tôi. Vì tập lệnh kết quả hầu như không thể in được, đây là một hexdump; sử dụng xxd -rđể biến nó thành mã Perl thực thi:

0000000: 7573 6520 436f 6d70 7265 7373 275a 6c69  use Compress'Zli
0000010: 623b 6576 616c 2075 6e63 6f6d 7072 6573  b;eval uncompres
0000020: 7320 2778 da85 d03d 4b03 4118 85d1 452c  s 'x...=K.A...E,
0000030: b69c 72cb 7519 4894 552c 2c02 3319 ee5c  ..r.u.H.U,,.3..\
0000040: d7b8 5a89 6093 4634 7e82 c490 6c91 8597  ..Z.`.F4~...l...
0000050: 80fe 7267 d660 23ae e52d 0e0f dcd6 f8c3  ..rg.`#..-......
0000060: e9d1 5e6e ccec a15c ddb5 c5d5 495e 94a3  ..^n...\....I^..
0000070: 83b7 c7f9 73f3 5216 f9a8 787a 5fea 666c  ....s.R...xz_.fl
0000080: 9dd1 b763 dd98 76f8 2df6 0799 5811 7144  ...c..v.-...X.qD
0000090: 4acc ee9d b8b0 c90f 7e4a 8264 6016 cbd7  J.......~J.d`...
00000a0: 79f3 1b91 047c 4055 409e 9e54 1dda ed41  y....|@U@..T...A
00000b0: 9a20 8080 6adc 5c47 8488 7495 f621 01d7  . ..j.\G..t..!..
00000c0: 6b6c 902e b6c8 2a6a 6643 f56f e99c 115d  kl....*jfC.o...]
00000d0: 5c7a f1b2 13d0 3453 790f da74 c813 751d  \z....4Sy..t..u.
00000e0: 11ce d821 ad90 247f 2292 5b54 c14f 3c4e  ...!..$.".[T.O<N
00000f0: 49c5 4c53 a1a7 c478 391c 714c f113 0747  I.LS...x9.qL...G
0000100: ab6c 4482 9fd2 177a 5677 6327            .lD....zVwc'

Mã Perl được giải nén bao gồm phần mở đầu sau:

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

theo sau là tám lần lặp lại của đoạn mã sau:

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

được BITMAP DATA HEREthay thế bằng 29 byte mã hóa một hàng phông chữ.


Giải pháp mới hơn là cực kỳ tốt đẹp. Không bao giờ tưởng tượng điều này có thể được thực hiện trong 165 ký tự.
BarsheD

6

Mã máy 8086

190 byte (122 byte sử dụng BIOS)

Đây là tệp WinXP / MSDos .COM được mã hóa Base64:

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

(Sử dụng một cái gì đó như thế này ) để giải mã văn bản và lưu dưới dạng "pbm.com". Sau đó, tại dấu nhắc lệnh, gõ:

văn bản pbm để mã hóa> outputfilename.pbm

Tôi đã thử nghiệm điều này trên máy WinXP của mình bằng cả dấu nhắc lệnh tiêu chuẩn và DosBox V0.74.

CẬP NHẬT

Phiên bản này là 190 byte và sử dụng phông chữ nhỏ của Ilmari Karonen (không có quyền truy cập bios ở đây!): -

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

Giải pháp cực kỳ tốt đẹp. Tại thời điểm này, đây là ứng cử viên cho tiền thưởng sẽ được trao trong khoảng 20 giờ. Làm tốt!
BarsheD

Bạn có thể gửi mã lắp ráp của bạn cho điều này là tốt?
Sir_Lagsalot

1
Sau khi xem xét việc phân tách và kiểm tra mã, có vẻ như bạn chỉ đang sử dụng phông chữ bitmap do bios cung cấp. Điều này có thể được xác nhận bởi thực tế là chương trình của bạn có thể xuất các chữ cái viết thường, ký hiệu và dấu câu không được yêu cầu bởi thử thách. Do đó, phông chữ nằm ngoài chương trình của bạn và không được lưu trữ bởi nó (ít nhất là theo ý kiến ​​của tôi).
Sir_Lagsalot

@Skizz: bạn có thể xác nhận điều này? Nó vẫn làm cho một giải pháp cực kỳ tốt đẹp nhưng nó hơi chống lại thông số kỹ thuật.
BarsheD

1
@ChristopheD: Vâng, JB đã bình luận "Tôi cảm thấy chúng ta sẽ có cuộc tranh luận dài và đau đớn về những gì tạo nên một thư viện bên ngoài." - người ta có thể lập luận rằng putstrong Ruby là một thư viện bên ngoài. Có, nó sử dụng các phông chữ bios, được truy cập thông qua việc hủy bỏ con trỏ (không có loadthao tác nào để đưa các phông chữ vào RAM). Uốn quy tắc quá xa có lẽ. Tôi đã thoát khỏi nó nếu nó không dành cho những đứa trẻ phiền phức đó ;-)
Skizz

6

Shell script (mã + dữ liệu = 295 ký tự)

Tôi hy vọng đuôi, gzip và dd không được tính là "thư viện bên ngoài." Chạy như echo -n 'YOUR TEXT HERE' | ./text.sh > out.pbm. Phông chữ tôi đã sử dụng là Phông chữ nhỏ cỡ 7.5, mặc dù tôi đã phải cắt bỏ phần tắt của Q.

Ví dụ đầu ra

NHỮNG FOX NHANH CHÓNG NHANH CHÓNG TRÊN LAZY DOGS.  CÓ THẬT KHÔNG!

Mã (137 ký tự)

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

Kịch bản hoàn chỉnh

(sử dụng xxd -rđể tạo lại tập tin gốc)

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

Giải trình

  • odlà chương trình tiện ích "bát phân" tiêu chuẩn. Thay vào đó, -tu1tùy chọn yêu cầu nó tạo ra một kết xuất thập phân của từng byte riêng lẻ (một cách giải quyết đủ cho việc bash thiếu asc (), ord (), .charCodeAt (), v.v.)
  • P4là số ma thuật cho tệp PBM định dạng nhị phân, gói tám pixel vào mỗi byte (so với P1tệp PBM định dạng ASCII). Bạn sẽ thấy điều này chứng tỏ hữu ích.
  • Trên mỗi hàng của đầu ra cuối cùng, chương trình sẽ kéo một byte tám pixel (tương ứng với mã ASCII và số dòng) từ phần dữ liệu được nén bằng gzip ở cuối bằng cách sử dụng dd. ( tail -2 $0trích xuất hai dòng cuối cùng của tập lệnh; dữ liệu nén bao gồm một byte nguồn cấp dòng 0x0a.) Điều đó xảy ra rằng tám pixel là chiều rộng của một ký tự. Các byte rỗng lấp đầy khoảng trống giữa các ký tự được hỗ trợ có thể dễ dàng nén được vì chúng đều giống nhau.
  • Tất cả điều này được ghi vào một tập tin có tên "8". Vì có chính xác tám hàng (và cũng là tám pixel cho mỗi byte), số byte là chiều rộng của đầu ra tính bằng pixel. Chiều cao của đầu ra cũng được bao gồm trong đó wc -cin tên tệp đầu vào "8" sau số byte của nó.
  • Bây giờ tiêu đề đã hoàn thành, dữ liệu hình ảnh được in. Bash chỉ lưu ý rằng hai dòng cuối cùng không phải là các lệnh hợp lệ (dòng cuối cùng thực sự không hợp lệ UTF-8) sau khi nó đã thực hiện mọi thứ đến trước đó.
  • Tôi chỉ sử dụng KZIP để nén phần dữ liệu, như Ilmari Karonen đã làm cho toàn bộ bài nộp cho thử thách 12 ngày Giáng sinh. Như được mô tả ở đó, về cơ bản cần phải sử dụng trình soạn thảo hex để thay thế định dạng tiêu đề ZIP bằng tiêu đề gzip. Bao gồm CRC-32 và kích thước tệp từ tiêu đề ZIP ban đầu dường như là không cần thiết.

2
Giải pháp thực sự tốt đẹp (và ngắn)! Trong kịch bản shell, việc sử dụng dd, tail và gzip không nên được coi là imho bên ngoài.
BarsheD

1
Tâm trí thêm một lời giải thích làm thế nào điều này làm việc? Sẽ được nhiều đánh giá cao.
Ông Llama

2
Rất đẹp, cảm ơn rất nhiều vì lời giải thích. Tuy nhiên, sử dụng phiên bản 'P4' không thực sự tôn trọng những gì OP nói "một định dạng bitmap đen trắng rất đơn giản ASCII ".
eregon

5

Python 2, 248 247 byte

s=raw_input();k=len(s);print"P1",k*8,8
for i in range(k*24):a=s[i/3%k];j=max(".!".find(a)+1,ord(a)-62)*3;print int("00080084IMVAENBSIFERBSUF4UFQQEMVDT4NAP4MNDSI9MRTMRBARA4NBQRAMNBE4E94NURDARDNRDMLD95DSL7"[j:j+3],32)>>(i/3/k*3+i%3)&1," 0"*(i%3/2*5)

Sử dụng phông chữ 3x5, được đóng gói thành một chuỗi có thể in, 3 byte cho mỗi ký tự. Phông chữ rõ ràng dễ đọc, mặc dù chữ n là chữ thường và v có thể bị nhầm với chữ au nếu nó không được nhìn thấy trong ngữ cảnh.

Kích thước thực sự:
Kích thước thực sự

Thu phóng x3:
phóng to x3

Đầu ra là PBM loại P1, theo ví dụ trong thử thách. Đó là một thử thách thú vị.


4

Ruby 1.9, 346 byte (mã 122 + dữ liệu 224 byte)

Đây là kết quả:

CODEGOLF

(Thật tuyệt phải không?)

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

Phông chữ được tạo bởi figlet -f banner -w 1000 $LETTERStập lệnh này .

Chạy với echo -n 'CODEGOLF.STACKEXCHANGE.COM!' | ruby script.rb > image.pbm.

Kịch bản tạo tất cả các hàng và chỉ cần in chúng.

Đây là một hexdump (sử dụng 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]}}*' '}

Phải mất 93 byte mã khi sử dụng 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]}}*' '}

Sử dụng ZLib cắt kích thước dữ liệu thành 142 byte thay vì 224, nhưng thêm 43 byte vào mã, vì vậy 307 byte:

#coding:binary
require'zlib';z=0..7;puts"P1\n#{(s=gets).size*8} 8",z.map{|i|s.bytes.flat_map{|o|z.map{|j|Zlib.inflate("DATA").unpack('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

Cung cấp tổng cộng 268 khi sử dụng goruby:

#coding:binary
rq'zlib';ps"P1\n#{(s=gt).sz*8} 8",8.mp{|i|s.y.fl{|o|8.mp{|j|Zlib.if("DATA").ua('Q<*')[o>64?o-63:o/46][i*8+j]}}*' '}

2

Java 862 826:

Đây là một cách tiếp cận khác nhau. Tôi nghĩ rằng 'awt' không được tính là lib bên ngoài.

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

Và vô lương tâm:

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 là cách tò mò nào đó của Java để gọi getPixel. Tôi tạo một Nhãn với bảng chữ cái và đo vị trí của một pixel cho mỗi chữ cái.

Trong phương pháp sơn, int py = (y < 3) ? y : y +1;(8*a+x+17+x/4, py+81)là cách phức tạp, để điều chỉnh vị trí trong phông chữ. Hữuuh! ngoài ra, nó sẽ cần 9 dòng, và cứ sau 4 chữ cái, sẽ có thêm một pixel theo chiều ngang. Thử và sai đã đưa tôi đến giải pháp này.

Sau đó, tiêu đề của PBM được viết và từng dòng thông báo. Thông điệp được truyền dưới dạng tiêu đề của khung.

Đó là nó. Không phải là mã ngắn nhất, nhưng không cần vẽ phông chữ thủ công.

Có lẽ nó có thể ngắn hơn trong BeanShell hoặc Scala.

Và bây giờ - nó trông như thế nào?

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

Nhiều zoom được áp dụng: java.cafe bé PNG

Không che giấu: java.cafe bé JPG

Không phải số lượng ký tự là số ký tự từ giải pháp Perl bị xáo trộn.

(đánh gôn thêm một chút nữa. Làm cho Robot tĩnh, tránh một tuyên bố Ngoại lệ.)


Cách tiếp cận ban đầu, được thực hiện độc đáo!
BarsheD

1
+1 cho tính nguyên bản, nhưng eww ... nếu bạn định mở rộng một bitmap, hãy sử dụng phép nội suy lân cận gần nhất.
Ilmari Karonen

Tôi đã sử dụng eog(Eye of Gnome) và một ảnh chụp màn hình. Tôi sẽ tải lên một chuyển đổi không được đánh giá jpg; có thể trình duyệt của bạn sử dụng phép nội suy lân cận gần nhất :).
người dùng không xác định

1

C ++ QUÁ LỚN ĐỂ CHIẾN THẮNG

Tôi đã viết một chương trình vẽ PPM đầy đủ tính năng trong C ++, với phông chữ bitmap của riêng tôi. Ngay cả khi loại bỏ tất cả các chức năng không cần thiết, nó vẫn rất lớn so với các câu trả lời ở đây vì định nghĩa cho phông chữ.

Dù sao, đây là đầu ra cho HELLO WORLD: nhập mô tả hình ảnh ở đây

Và mã:

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

Nếu bạn quan tâm, thư viện PPMDraw đầy đủ có ở đây :


1
Tôi thấy phông chữ của bạn rất hữu ích!
Ludwik

1

SmileBASIC, 231 byte

LINPUT C$?"P1
?8,LEN(C$)*8WHILE""<C$A=ASC(SHIFT(C$))D=ASC("*N.JZ`;O:²ÞøäüÄho"[A-65+12*(A<34)+47*(A<47)])FOR I=0TO 4B$=BIN$(VAL("7535712074617252"[D>>5<<1OR 1AND D>>I]),8)WHILE""<B$?POP(B$),
WEND?NEXT?"0 "*24WEND

nhập mô tả hình ảnh ở đây

Mỗi ký tự chỉ chứa 2 mẫu hàng khác nhau, được chọn từ "bảng màu" gồm 8 kết hợp. Dữ liệu cho mỗi ký hiệu được lưu trữ trong 1 byte, với bảng màu được lưu trữ riêng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.