웹버그라고도 불리는 1x1 GIF 이미지파일은 그 크기가 35 바이트 혹은 투명인 경우 43 바이트라고 알고있었습니다. http://www.perlmonks.org/?node_id=7974 (by turnstep이 링크가 원래의 출처이며 http://stackoverflow.com/questions/2933251/code-golf-1x1-black-pixel 링크를 통해 알게된 내용입니다.

그런데 최근 이보다 더 작은 크기의 GIF도 있다는 것을 알게 되었습니다. (다음은 텀블러에서 사용하는 1x1 GIF)


http://www.bignosebird.com/docs/h3.shtml ftp://ftp.bignosebird.com/spacer.gif 이 이미지는 텀블러에서 사용하는 이미지와 약간의 차이가 있으며 42바이트의 최소 크기로 텀블러 GIF 이미지 크기와 동일합니다.


그러면 43바이트 GIF 파일과의 차이점은 무엇일까 궁금해서 살펴보았는데, 두 파일은 다음과 같이 별로 다를 것이 없었고 이미지 마지막 부분의 바이트에 약간의 실수가 있었던 모양이었습니다.


이것이 42바이트의 GIF이미지이고,

0000000: 4749 4638 3961 0100 0100 8000 0000 0000  GIF89a..........
0000010: ffff ff21 f904 0100 0000 002c 0000 0000  ...!.......,....
0000020: 0100 0100 0002 0144 003b                 .......D.;

이것이 43바이트의 GIF이미지입니다.

0000000: 4749 4638 3961 0100 0100 9000 0000 0000  GIF89a..........
0000010: 0000 0021 f904 0510 0000 002c 0000 0000  ...!.......,....
0000020: 0100 0100 0002 0104 0100 3b              ..........;

얼핏 봐서는 거의 차이가 없어보이는데, 마지막쪽의 바이트가 차이가 있음을 볼 수 있습니다.


두 이미지가 정상적인 이미지인지 테스트를 하기위해 테스트를 해보면 두번째 이미지는 giftopnm 프로그램을 사용하였을때에 다음과 같은 경고 메시지가 나오는 것을 알 수 있습니다.

$ giftopnm --verbose 43b.gif giftopnm: GIF format version is '89a' giftopnm: GIF Width = 1 GIF Height = 1 Pixel aspect ratio = 0 (1.000000:1) giftopnm: Colors = 2 Color Resolution = 3 giftopnm: Color map doesn't contain grays, doesn't contain colors giftopnm: got a 'Graphic Control' extension giftopnm: transparent background color: rgb:00/00/00 Index 0 giftopnm: reading 1 by 1 GIF image giftopnm: too much input data, ignoring extra... giftopnm: writing a PBM file P4 1 1

간단히 0x10을 제거하니 위의 경고 오류는 사라지더군요.


호기심이 생겨서 검색을 더 해보니 스택오버플로우에 다음과 같은 링크를 찾을 수 있었다. http://stackoverflow.com/questions/2570633/smallest-filesize-for-transparent-single-pixel-image 질문에 대한 http://stackoverflow.com/a/15960901/1696120 답변 내용에 의하면 가장 작은 크기의 투명 GIF 이미지는 32바이트라고 되어있습니다. 답변을 살펴보면, The Global Color Table can be removed safely by disabling it in the Logical Screen Descriptor라고 되어있는데 즉 Logical Screen Descriptor를 조정해서 Global Color Table을 제거할 수 있다는 내용이 있습니다.


xxd를 이용해서 바이트열로 변환해 살펴보면 다음과 같습니다.


0000000: 4749 4638 3961 0100 0100 0000 0021 f904  GIF89a.......!..
0000010: 0100 0000 002c 0000 0000 0100 0100 0002  .....,..........

이것을 43바이트 GIF 이미지와 쉽게 비교하기 위해 다시 써보면

0000000: 4749 4638 3961 0100 0100 8000 0000 0000  GIF89a..........
0000010: ffff ff21 f904 0100 0000 002c 0000 0000  ...!.......,....
0000020: 0100 0100 0002 0144 003b                 .......D.;

즉 Logical Screen Descriptor 값이 0x00으로 되어있고, Global 컬러 테이블을 없애서 6바이트가 줄어들었습니다. 또한 마지막의 바이트도 삭제되어있는데, 위의 답변 내용에 보면 Only 3 bytes of the LZW data are required and the bytes can be almost anything. Though only the first byte of 0x02 is strictly required. 라고 되어있으며 LZW 데이터인 0x02 이후의 0x10, x44,0x00 3 바이트가 제거되어 있으며, 마지막으로 파일의 끝을 알려주는 0x3b 1바이트 총 4바이트가 제거되어있습니다.


단, 32바이트의 경우에 원문에는 대부분의 브라우저에서 작동한다고 되어있으나, giftopnm 혹은 gifinfo(libgif) 등등의 프로그램으로 테스트할 경우에 오류를 뿜었습니다.

32바이트의 GIF는 http://stackoverflow.com/a/15960901/1696120 에 다음과 같이 나오며, 이는 대부분의 브라우저에서 잘 작동합니다.

GIF 스펙(http://www.w3.org/Graphics/GIF/spec-gif89a.txt)을 보니 GIF89a버전의 경우 옵션으로 처리 가능하므로, GIF스펙상 문제 없는 웹버그는 34바이트까지가 가능합니다.)


http://u229.no/stuff/GIFFormat/ 이 문서에 의하면 몇가지 조정이 가능한 값들이 있는데 예를 들어 delay time 값이 2바이트인데, 이 값을 조정하면 65,536가지의 조합을 만들 수 있습니다. 또한 Background color index가 안쓰이는데, 이 값을 조정하게되면 2^24(16,777,216)개의 조합도 가능합니다. (더 많은 개수의 웹버그 조합이 필요하다면 컬러테이블 6바이트를 추가한 42바이트짜리 GIF를 만들어서 이미지 색상 팔레트값을 임의로 조정하면 될 것입니다.)

웹버그를 만들어주는 간단한 PHP 스크립트를 같이 참고하시기 바랍니다.

<?php
$transparency = 1;
printf("GIF89a\1\0\1\0%c%c\0%s,\0\0\0\0\1\0\1\0\0%s",
0x00 /* packed field */,
0xff /* background color index */,
($transparency ? pack("c8",0x21,0xf9,4,1,0,0,0,0) : ''),
"\2\1\x44\0\x3b"); # LZW data 4 bytes + ";"


by dumpcookie 2015. 10. 16. 10:10
| 1 |