펄, 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 진수 값 (16 자)으로 색상 및 너비 / 높이에 대한 픽셀 수로 구분됩니다. 예 :
echo "FFFF00FF 200" | perl -p solidpng.pl >yellow200.png
파일 크기는 832 바이트입니다. 동일한 색상의 최대 크기 이미지 (n = 999)는 6834 바이트 (10MB 미만)입니다.
이 솔루션은 두 개의 라이브러리를 사용합니다.
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
기본적으로 수축 기능 을 내 보냅니다 . 이 함수는 인수로 참조가 필요하지 않으며 결과를 직접 반환합니다. 변수를 제거 할 수 있습니다 $o
.
Michael의 답변에 감사드립니다 .
많은 팁과 함께 VadimR의 의견에 감사드립니다 .
use String::CRC32;
보다 짧습니다 use Digest::CRC crc32;
.
y///c-4
보다 짧습니다 -4+y///c
.
- 스캔 라인은 이제
CH*
값이 반복되는 템플릿 으로 구성됩니다 .
$i
값 참조를 사용하여 제거
- 청크 유형의 문자열 대신 맨손으로 단어를 표시하십시오.
- STDIN 입력 라인 (옵션
-p
)을 공백 구분 기호와 일치시켜 옵션을 읽습니다 / /
. 그런 다음 첫 번째 옵션은 in $`
이고 두 번째 인수는 in $'
입니다.
- 옵션
-p
도 자동으로 인쇄합니다 $_
.
"\cZ"
보다 짧습니다 "\x1a"
.
더 나은 압축
필터링이 적용되는 경우, 코드 크기의 비용으로 이미지 데이터를 추가로 압축 할 수 있습니다.
필터링되지 않은 파일 크기 FFFF0FF
200
: 832 bytes
필터 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
즉 자기 모순 보인다 있도록 파일이 이상 30,720 픽셀을 가지고 있습니다.