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
อาร์กิวเมนต์ถูกกำหนดผ่าน STDIN ในบรรทัดคั่นด้วยช่องว่างสีเป็นค่าฐานสิบหก (16 ตัวอักษร) และจำนวนพิกเซลสำหรับความกว้าง / ความสูงเช่น:
echo "FFFF00FF 200" | perl -p solidpng.pl >yellow200.png

ขนาดไฟล์คือ 832 ไบต์ ภาพขนาดสูงสุด (n = 999) ที่มีสีเดียวกันมี 6834 ไบต์ (ทางด้านล่าง 10 MB)
โซลูชันใช้ไลบรารีสองรายการ:
use Digest::CRC crc32;
สำหรับค่า CRC32 ที่ชิ้นส่วนสิ้นสุด
use IO::Compress::Deflate deflate;
เพื่อบีบอัดข้อมูลภาพ
ไลบรารีทั้งสองไม่เกี่ยวข้องกับรูปภาพ
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');
การแก้ไข
use IO::Compress::Deflate':all';
use Compress::Zlib;
จะถูกแทนที่ด้วย หลังจะส่งออกฟังก์ชันการยุบcompress
ตามค่าเริ่มต้น ฟังก์ชั่นไม่จำเป็นต้องมีการอ้างอิงเป็นข้อโต้แย้งและส่งกลับผลลัพธ์โดยตรง ที่ช่วยให้สามารถกำจัดตัวแปร$o
ได้
ขอบคุณสำหรับคำตอบของไมเคิล:
ขอบคุณสำหรับความคิดเห็น VadimR พร้อมด้วยเคล็ดลับมากมาย:
use String::CRC32;
use Digest::CRC crc32;
จะสั้นกว่า
y///c-4
-4+y///c
จะสั้นกว่า
- ตอนนี้บรรทัดสแกนถูกสร้างโดยเทมเพลตที่
CH*
มีการทำซ้ำในค่า
- การลบ
$i
โดยใช้การอ้างอิงค่า
- คำเปลือยแทนสตริงสำหรับประเภทก้อน
- ตัวเลือกในขณะนี้อ่านโดยการจับคู่สายป้อนข้อมูล STDIN (ตัวเลือก
-p
) / /
กับการจับคู่คั่นพื้นที่ จากนั้นตัวเลือกแรกจะอยู่ใน$`
และอาร์กิวเมนต์ที่สองจะเข้า$'
มา
- ตัวเลือกนี้ยังพิมพ์โดยอัตโนมัติ
-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
ที่ราคาสองไบต์:
compress ..., 9;
ขนาดไฟล์ตัวอย่างที่yellow200.png
ไม่มีตัวกรองจะลดลงจาก 832 ไบต์เป็น 472 ไบต์ นำไปใช้กับตัวอย่างด้วยSub
ตัวกรองขนาดไฟล์ย่อจาก 560 ไบต์ถึง 445 ไบต์ ( pngcrush -brute
ไม่สามารถบีบอัดเพิ่มเติมได้)
999x999
ไฟล์มีมากกว่า 30720 พิกเซลเพื่อให้ดูเหมือนว่าตนเองขัดแย้ง