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
サイズは180バイトで、オプション-p
が必要です(+1)。スコアは181です。
引数は、スペース、16進数値としての色(16文字)、および幅/高さのピクセル数で区切られた行でSTDINを介して与えられます。例:
echo "FFFF00FF 200" | perl -p solidpng.pl >yellow200.png

ファイルサイズは832バイトです。同じ色の最大サイズの画像(n = 999)は、6834バイト(10 MB未満)です。
ソリューションは2つのライブラリを使用します。
use Digest::CRC crc32;
チャンクの終わりのCRC32値の場合。
use IO::Compress::Deflate deflate;
画像データを圧縮します。
両方のライブラリは画像に関連していません。
ゴルフをしていない:
# 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');
編集
use IO::Compress::Deflate':all';
はに置き換えられuse Compress::Zlib;
ます。後者はcompress
デフォルトでdeflate関数をエクスポートします。関数は引数として参照を必要とせず、結果を直接返します。それは変数を取り除くことを可能にします$o
。
マイケルの答えをありがとう:
多くのヒントを備えたVadimRのコメントをありがとう:
use String::CRC32;
はより短いuse Digest::CRC crc32;
。
y///c-4
はより短い-4+y///c
。
- スキャンラインは
CH*
、値に繰り返しを含むテンプレートによって構築されます。
$i
値参照を使用した削除。
- チャンクタイプの文字列の代わりに裸の単語。
- STDIN入力行(オプション
-p
)とスペース区切り文字を一致させることで、オプションが読み取られるようになりました/ /
。次に、最初のオプションが入力され$`
、2番目の引数が入力され$'
ます。
- オプション
-p
も自動的に印刷し$_
ます。
"\cZ"
はより短い"\x1a"
。
より良い圧縮
フィルタリングが適用される場合、コードサイズを犠牲にして画像データをさらに圧縮できます。
フィルタリングされていないファイルサイズFFFF0FF
200
:832バイト
フィルターSub
(水平ピクセル差):560バイト
$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
Sub
最初の行とUp
残りの行のフィルター:590バイト
$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);
最初にフィルタリングされていない行、次にフィルタリングUp
:586バイト
$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);
Compress::Zlib
調整することもできます。最高の圧縮レベルはcompress
、2バイトのコストで機能の圧縮レベルの追加オプションによって設定できます。
compress ..., 9;
yellow200.png
フィルタリングなしの例のファイルサイズは、832バイトから472バイトに減少します。Sub
フィルタを使用した例に適用すると、ファイルサイズは560バイトから445バイトに縮小します(pngcrush -brute
これ以上圧縮できません)。
999x999
それは自己矛盾しているようだように、ファイルには、以上の30720個の画素を有します。