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
Boyut 180 bayttır ve seçenek -p
gereklidir (+1). Skor 181 olur.
Bağımsız değişkenler STDIN aracılığıyla boşlukla, onaltılık değer (16 karakter) olarak renk ve genişlik / yükseklik için piksel sayısı ile ayrılmış bir satırda verilir, örneğin:
echo "FFFF00FF 200" | perl -p solidpng.pl >yellow200.png
Dosya boyutu 832 bayttır. Aynı renkteki maksimum boyutlu görüntü (n = 999) 6834 bayta (10 MB'ın altında) sahiptir.
Çözüm iki kütüphane kullanır:
use Digest::CRC crc32;
yığın uçlarındaki CRC32 değerleri için.
use IO::Compress::Deflate deflate;
görüntü verilerini sıkıştırmak için.
Her iki kütüphane de görüntülerle ilgili değildir.
Ungolfed:
# 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');
Düzenlemeler
use IO::Compress::Deflate':all';
ile değiştirilir use Compress::Zlib;
. İkincisi, compress
varsayılan olarak deflate işlevini dışa aktarır . İşlev bağımsız değişken olarak başvuruya ihtiyaç duymaz ve sonucu doğrudan döndürür. Bu değişkenlerden kurtulmanızı sağlar $o
.
Michael'ın cevabı için teşekkürler :
İşlev k
: işlevindeki ilk pack
şablon Na*N
için çağrı kullanılarak çağrı kaldırılabilir pack
.
pack
NNCV
dört değer içeren şablon , NNC3n
altı değerle optimize eder .
VadimR'nin birçok ipucu içeren yorumu için teşekkürler :
use String::CRC32;
daha kısadır use Digest::CRC crc32;
.
y///c-4
daha kısadır -4+y///c
.
- Tarama çizgisi artık şablon tarafından
CH*
tekrar değeri ile oluşturulur.
$i
Bir değer başvurusu kullanarak kaldırılması .
- Öbek türleri için dizeler yerine çıplak kelimeler.
- Seçenekler artık STDIN giriş satırını (seçenek
-p
) boşluk ayırıcıyla eşleştirerek okunur / /
. Sonra ilk seçenek $`
girilir ve ikinci argüman devreye girer $'
.
- Seçenek
-p
ayrıca otomatik olarak yazdırılır $_
.
"\cZ"
daha kısadır "\x1a"
.
Daha iyi sıkıştırma
Kod boyutu pahasına, filtreleme uygulanırsa görüntü verileri daha fazla sıkıştırılabilir.
Filtrelenmemiş dosya boyutu FFFF0FF
200
: 832 bayt
Filtre Sub
(yatay piksel farklılıkları): 560 bayt
$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
İlk satır ve Up
kalan satırlar için filtre : 590 bayt
$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);
İlk filtrelenmemiş satır, ardından filtre Up
: 586 bayt
$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);
Ayrıca Compress::Zlib
ayarlanabilir; en yüksek sıkıştırma seviyesi compress
, iki bayt pahasına işlevdeki sıkıştırma seviyesi için ek seçenekle ayarlanabilir :
compress ..., 9;
yellow200.png
Filtrelemeden örneğin dosya boyutu 832 bayttan 472 bayta düşer. Sub
Filtreli örneğe uygulandığında, dosya boyutu 560 bayttan 445 bayta küçülür ( pngcrush -brute
daha fazla sıkıştırılamaz).
999x999
dosya 30720 pikselden fazla, bu yüzden kendinden çelişkili görünüyor.