Perl, 181
/ /;use String::CRC32;use Compress::Zlib;sub k{$_=pop;pack'Na*N',y///c-4,$_,crc32$_}$_="\x89PNG\r\n\cZ\n".k(IHDR.pack NNCV,$',$',8,6).k(IDAT.compress pack('CH*',0,$`x$')x$').k IEND
Kích thước là 180 byte và tùy chọn -plà cần thiết (+1). Điểm số sau đó là 181.
Các đối số được đưa ra thông qua STDIN trong một dòng, được phân tách bằng khoảng trắng, màu dưới dạng giá trị hex (16 ký tự) và số pixel cho chiều rộng / chiều cao, ví dụ:
echo "FFFF00FF 200" | perl -p solidpng.pl >yellow200.png

Kích thước tệp là 832 byte. Hình ảnh có kích thước tối đa (n = 999) có cùng màu có 6834 byte (cách dưới 10 MB).
Giải pháp sử dụng hai thư viện:
use Digest::CRC crc32; cho các giá trị CRC32 ở cuối chunk.
use IO::Compress::Deflate deflate; để nén dữ liệu hình ảnh.
Cả hai thư viện không liên quan đến hình ảnh.
Ung dung:
# Perl option "-p" adds the following around the program:
# LINE:
# while (<>) {
# ... # the program goes here
# } continue {
# print or die "-p destination: $!\n";
/ /; # match the separator of the arguments in the input line
# first argument, color in hex: $`
# second argument, width/height: $' #'
# load the libraries for the CRC32 fields and the data compression
use String::CRC32;
use Compress::Zlib;
# function that generates a PNG chunk:
# N (4 bytes, big-endian: data length
# N: chunk type
# a* (binary data): data
# N: CRC32 of chunk type and data
sub k {
$_ = pop; # chunk data including chunk type and
# excluding length and CRC32 fields
pack 'Na*N',
y///c - 4, # chunk length #/
# netto length without length, type, and CRC32 fields
$_, # chunk type and data
crc32($_) # checksum field
}
$_ = # $_ is printed by option "-p".
"\x89PNG\r\n\cZ\n" # PNG header
# IHDR chunk: image header with
# width, height,
# bit depth (8), color type (6),
# compresson method (0), filter method (0), interlace method (0)
. k('IHDR' . pack NNCV, $', $', 8, 6)
# IDAT chunk: image data
. k('IDAT' .
compress # compress/deflate data
pack('CH*', # scan line with filter byte
0, # filter byte: None
($` x $') # pixel data for one scan line #'`
) x $' # n lines #'
)
# IHDR chunk: image end
. k('IEND');
Chỉnh sửa
use IO::Compress::Deflate':all';được thay thế bởi use Compress::Zlib;. Cái sau không xuất chức năng def def compresstheo mặc định. Hàm không cần tham chiếu làm đối số và cũng trả về kết quả trực tiếp. Điều đó cho phép thoát khỏi biến $o.
Cảm ơn câu trả lời của Michael :
Cảm ơn bình luận của VadimR với rất nhiều lời khuyên:
use String::CRC32;ngắn hơn use Digest::CRC crc32;.
y///c-4ngắn hơn -4+y///c.
- Dòng quét hiện được xây dựng bởi mẫu
CH*với sự lặp lại trong giá trị.
- Loại bỏ
$ibằng cách sử dụng một tham chiếu giá trị.
- Từ trần thay vì chuỗi cho các loại chunk.
- Bây giờ các tùy chọn được đọc bằng cách khớp dòng đầu vào STDIN (tùy chọn
-p) với khớp dấu cách / /. Sau đó, tùy chọn đầu tiên là trong $`và đối số thứ hai đi vào $'.
- Tùy chọn
-pcũng tự động in $_.
"\cZ"ngắn hơn "\x1a".
Nén tốt hơn
Với chi phí kích thước mã, dữ liệu hình ảnh có thể được nén thêm, nếu lọc được áp dụng.
Kích thước tệp chưa được lọc cho FFFF0FF 200: 832 byte
Bộ lọc Sub(chênh lệch pixel ngang): 560 byte
$i = ( # scan line:
"\1" # filter "Sub"
. pack('H*',$c) # first pixel in scan line
. ("\0" x (4 * $n - 4)) # fill rest of line with zeros
) x $n; # $n scan lines
Bộ lọc Subcho dòng đầu tiên và Upcho các dòng còn lại: 590 byte
$i = # first scan line
"\1" # filter "Sub"
. pack('H*',$c) # first pixel in scan line
. ("\0" x (4 * $n - 4)) # fill rest of line with zeros
# remaining scan lines
. (
"\2" # filter "Up"
. "\0" x (4 * $n) # fill rest of line with zeros
) x ($n - 1);
Dòng chưa được lọc đầu tiên, sau đó lọc Up: 586 byte
$i = # first scan line
pack('H*', ("00" . ($c x $n))) # scan line with filter byte: none
# remaining scan lines
. (
"\2" # filter "Up"
. "\0" x (4 * $n) # fill rest of line with zeros
) x ($n - 1);
Cũng Compress::Zlibcó thể được điều chỉnh; mức nén cao nhất có thể được đặt bằng tùy chọn bổ sung cho mức nén trong hàm compressvới chi phí là hai byte:
compress ..., 9;
Kích thước tệp của ví dụ yellow200.pngmà không lọc giảm từ 832 byte xuống 472 byte. Áp dụng cho ví dụ với Subbộ lọc, kích thước tệp thu nhỏ từ 560 byte thành 445 byte ( pngcrush -brutekhông thể nén thêm).
999x999tệp có hơn 30720 pixel, do đó có vẻ như tự mâu thuẫn.