입력 :는 RGBA 육각 색 c
(예. FFFF00FF
) 및 정수> 0 <(1000) n
(예. 200
).
출력 : 원시는 PNG 파일의 출력은 이미지 뷰어에서 파일에 저장하고 열 때 같은 것을 바이트 n
에 의해 n
컬러로 채워진 이미지가 c
표시됩니다.
사양 : 프로그램이 정확하게 출력해야 합니다 :
- PNG 헤더 (
89504E470D0A1A0A
16 진수) IHDR
이러한 사양을 포함 하는 청크 :- 너비 : 이전 입력
n
- 높이 : 이전 입력
n
- 비트 심도 :
8
(RGBA
) - 색상 유형 :
6
(알파와 트루 컬러) - 압축 방법 :
0
- 필터 방법 :
0
- 인터레이스 방식 :
0
- 너비 : 이전 입력
IDAT
이미지 데이터를 포함하는 하나 이상의 청크 (이전에 입력 된 컬러의 실선 이미지c
); 압축되거나 압축되지 않을 수 있습니다IEND
화상 최종 청크
추가 정보는 Wikipedia , W3 사이트 또는 Google 검색을 통해 제공됩니다.
제한 사항 :
- 어떤 종류의 이미지에도 작동하도록 설계된 이미지 라이브러리 또는 함수를 사용할 수 없습니다.
- 프로그램은 3 분 이내에 실행되어야하며 모든 입력에 대해 10MB 미만의 파일을 출력해야합니다 (위생성 검사).
- 이것은 code-golf 이므로 바이트 단위의 가장 짧은 코드가 이길 것입니다!
답변
펄, 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의 답변에 감사드립니다 .
-
기능
k
: 함수 의 첫 번째pack
템플릿Na*N
을 사용하여 호출을 제거 할 수 있습니다pack
. -
pack
NNCV
4 개의 값이있는 템플릿 은NNC3n
6 개의 값으로 최적화 됩니다.
많은 팁과 함께 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
더 이상 압축 할 수 없음).
답변
PHP 214
저는 PHP 전문가가 아니며 골프를 할 수있는 곳이 있습니다. 팁을 환영합니다.
<?function c($d){echo pack("Na*N",strlen($d)-4,$d,crc32($d));}echo"\x89PNG\r\n\x1a\n";c("IHDR".pack("NNCV",$n=$argv[1],$n,8,6));c("IDATx^".gzdeflate(str_repeat("\0".str_repeat(hex2bin($argv[2]),$n),$n)));c("IEND");
PNG 파일을 생성하십시오.
php png.php 20 FFFF00FF > output.png
base64 스트림 생성 (브라우저 주소 표시 줄에 결과 붙여 넣기)
echo "data:image/png;base64,`php png.php 200 0000FFFF | base64`"
언 골프 버전 :
<?php
//function used to create a PNG chunck
function chunck($data) {
return pack("Na*N", //write a big-endian integer, a string and another integer
strlen($data)-4, //size of data minus the 4 char of the type
$data, //data
crc32($data)); //compute CRC of data
}
//png header
echo "\x89PNG\r\n\x1a\n";
//IHDR chunck
echo chunck("IHDR".pack("NNCV", //2 big-endian integer, a single byte and a little-endian integer
$n=$argv[1], $n,
8, 6)); //6 also write 3 zeros (little endian integer)
//IDAT chunck
//create a binary string of the raw image, each line begin with 0 (none filter)
$d = str_repeat("\0".str_repeat(hex2bin($argv[2]),$n),$n);
echo chunck("IDATx^".
gzdeflate($d)); //compress raw data
//IEND chunck
echo chunck("IEND");
답변
파이썬, 252 바이트
import struct,sys,zlib as Z
P=struct.pack
A=sys.argv
I=lambda i:P(">I",i)
K=lambda d:I(len(d)-4)+d+I(Z.crc32(d)&(2<<31)-1)
j=int(A[2])
print "\x89PNG\r\n\x1A\n"+K("IHDR"+P(">IIBI",j,j,8,6<<24))+K("IDAT"+Z.compress(("\0"+I(int(A[1],16))*j)*j))+K("IEND")
이 스크립트는 argv에서 입력을받습니다. 다음과 같이 명령 행에서이 스크립트를 실행하십시오.python 27086.py deadbeef 999