본문으로 건너뛰기
AZ Tools

GIF 구조 분석기

GIF를 디코더와 같은 방식으로, 13바이트 헤더에서 0x3B 트레일러까지 블록 단위로 훑습니다. 헤더에서는 버전(GIF87a는 확장 블록 자체가 없고, 애니메이션이 가능한 쪽은 GIF89a입니다), 프레임이 합성되는 논리 화면 크기, 배경색 인덱스, 지난 30년간 어떤 브라우저도 반영하지 않은 픽셀 종횡비 바이트, 그리고 전역 색상표의 유무와 항목 수·비트 수를 읽습니다. 이어서 모든 프레임을 재생 방식을 결정하는 두 값, 즉 지연과 폐기 방식과 함께 나열합니다. GIF가 느려 보이는 원인은 대개 지연입니다. 지연은 1/100초 단위로 저장되는데 브라우저는 약 20ms 미만의 값을 조용히 100ms로 바꾸므로, 프레임당 5ms로 만든 파일은 의도보다 다섯 배 느리게 재생됩니다. 그래서 선언된 합계와 실제로 보게 될 시간을 함께 표시합니다. 폐기 방식은 잔상과 깜빡임의 원인입니다. 배경으로 복원은 다음 프레임 전에 해당 사각형을 지우고, 이전으로 복원은 캔버스를 되돌리며, 그대로 두기는 바뀐 픽셀만 저장하는 최적화를 가능하게 합니다. 그 최적화의 흔적도 함께 드러납니다. 논리 화면보다 작은 프레임에는 표시가 붙고, 위치와 지역 색상표 유무, 인터레이스 여부, 투명 인덱스가 같이 나옵니다. 서브블록 사슬을 추정 없이 정확히 따라가기 때문에 프레임별 바이트 비용이 정확하며, 표는 이를 정렬해 파일을 20MB로 만든 프레임을 맨 위에 보여줍니다. 나머지 바이트는 색상표, LZW 이미지 데이터, 블록 오버헤드로 나뉘고 그래픽 제어·주석·평문 텍스트·애플리케이션 확장 블록은 NETSCAPE 반복 카운터와 알 수 없는 블록까지 오프셋·크기·본문과 함께 나열됩니다. 다만 픽셀은 복호화하지 않습니다. LZW 스트림은 크기만 재므로 색 정확도나 디더링, 프레임 간 유사도는 알 수 없습니다. 잘렸거나 블록 길이가 파일 끝을 넘는 파일은 절반만 읽는 대신 이름이 붙은 오류로 거절합니다. 그 지점 이후의 오프셋은 모두 추측일 뿐이기 때문입니다.

사용법

  1. .gif 파일을 상자에 끌어다 놓거나 클릭해 선택하세요. 바이트는 페이지 안에서만 읽히고 업로드되지 않습니다.
  2. 먼저 개요를 보세요. 헤더 버전, 논리 화면, 프레임 수, 브라우저가 실제로 재생할 길이, 반복 방식이 한눈에 나옵니다.
  3. 재생 경고가 뜬다면 프레임 지연이 브라우저 하한 아래입니다. 20ms 이상으로 올리지 않으면 파일은 언제나 표시된 것보다 느리게 재생됩니다.
  4. 용량 문제는 프레임 표에서 확인하세요. 바이트 열과 막대가 비싼 프레임을 보여주고, 크기에 *가 붙으면 캔버스의 일부만 다시 그리는 프레임입니다.
  5. 확장 블록 목록에서 NETSCAPE 반복 블록, 인코더가 남긴 주석, 예상하지 못한 애플리케이션 블록을 확인하세요.

자주 묻는 질문

지연을 짧게 설정했는데 왜 더 느리게 재생되나요?
브라우저가 아주 짧은 지연을 거부하기 때문입니다. 지연 값은 프레임마다 그래픽 제어 확장에 1/100초 단위로 저장되므로 0이 아닌 최솟값은 10ms인데, Blink와 WebKit은 11ms 미만을, Gecko는 20ms 미만을 100ms로 바꿉니다. 그래서 "50fps"로 내보낸 파일이 실제로는 10fps로, 열 배 느리게 돌아갑니다. 이를 무시하게 만드는 플래그는 없습니다. 이 제한은 한 프레임짜리 GIF를 여백용으로 쓰던 시절부터 이어진 것이고 지금도 모든 엔진이 적용합니다. 이 도구는 선언된 합계와 브라우저가 실제로 쓰는 시간을 함께 보여주어 제한에 걸린 파일과 원래 느린 파일을 구분해 줍니다. 정말 빠른 움직임이 필요하다면 GIF가 아니라 동영상 코덱을 써야 합니다.
반복 횟수는 정확히 무슨 뜻인가요?
반복은 GIF 표준에 아예 없습니다. 1995년 넷스케이프가 추가한 애플리케이션 확장으로, 11바이트 식별자 NETSCAPE2.0 뒤에 16비트 횟수를 담은 서브블록이 옵니다. 0은 무한 반복이고 거의 모든 인코더가 이 값을 씁니다. 0이 아닌 값은 첫 재생 이후의 추가 재생 횟수라서 1이면 크롬과 파이어폭스에서 두 번 재생되지만, 일부 옛 뷰어는 이를 총 횟수로 해석했습니다. 블록이 아예 없으면 애니메이션은 딱 한 번 재생되고 마지막 프레임에서 멈춥니다. 알 수 없는 확장을 버리는 도구를 거친 파일에서 흔히 겪는 일입니다.
GIF 용량이 왜 이렇게 큰가요?
대개 각 프레임이 바뀐 부분이 아니라 화면 전체를 저장하기 때문입니다. 이 도구의 바이트 열은 그래픽 제어 확장, 이미지 디스크립터, 지역 색상표, LZW 데이터까지 프레임이 쓰는 모든 비용을 합산하므로 순위가 추정이 아니라 정확합니다. 비용을 지배하는 것은 세 가지입니다. 매 프레임이 논리 화면 크기 그대로인 전체 프레임 재작성, 256색 기준 768바이트씩 드는 지역 색상표(60프레임이면 픽셀을 담기도 전에 45KB), 그리고 사진이나 디더링된 그림에서 원본 인덱스보다도 커질 수 있는 LZW 자체입니다. 바이트 요약이 이 셋을 나눠 보여줍니다.
폐기 방식이 무엇이고 왜 잔상이 남나요?
GIF 프레임은 이전 프레임이 남긴 캔버스 위에 그려집니다. 폐기 방식은 다음 프레임을 그리기 전에 그 프레임을 어떻게 처리할지 정합니다. 0(지정 없음)과 1(그대로 둠)은 화면을 유지하며, 바뀐 픽셀만 저장하는 델타 프레임이 가능한 이유가 바로 이것입니다. 2는 프레임 사각형을 배경으로 지웁니다. 투명 픽셀이 누적되면 안 될 때 필요하지만, 매번 화면 전체를 지우면 깜빡임이 보입니다. 3은 프레임을 그리기 전 상태로 되돌리는데 비용이 크고 구현도 일관되지 않습니다. 꼬리처럼 남는 잔상은 거의 항상 2를 써야 할 자리에 1을 썼거나, 한 번도 지워지지 않은 화면 위에 투명 픽셀을 겹쳐 그린 경우입니다.
투명한 가장자리가 왜 계단처럼 보이나요?
GIF의 투명도는 알파 채널이 아니라 팔레트 인덱스 하나입니다. 프레임은 색상표의 한 항목을 투명으로 지정할 수 있고 그 인덱스를 가진 픽셀은 합성 때 건너뜁니다. 완전 불투명과 완전 투명 사이에는 아무것도 없습니다. 그래서 PNG의 안티에일리어싱된 가장자리는 갈 곳이 없어, 내보내기 도구가 가정한 배경색과 섞여 흰색이나 회색 테두리로 남거나 투명 인덱스로 눌려 계단이 됩니다. 색도 한 칸 소모합니다. 투명도가 있는 이미지는 256색이 아니라 255색만 쓸 수 있습니다. 투명 인덱스는 프레임마다 따로 있으므로 디코더는 항상 현재 프레임 값만 보고합니다.
GIF87a와 GIF89a는 무엇이 다르고, 인터레이스는 아직 쓸모가 있나요?
GIF87a는 1987년 원본 형식으로 확장 블록이 전혀 없습니다. 즉 지연도, 투명도도, 반복 카운터도, 주석도 없습니다. GIF89a가 확장 메커니즘을 더했고 우리가 GIF의 특징이라 여기는 것은 모두 거기에 있습니다. 둘 다 어디서나 읽히며, 89a 고유 기능이 필요 없을 때 인코더가 87a를 쓰는 것은 자연스러운 선택입니다. 정지 이미지 한 장이면 대개 그렇습니다. 인터레이스는 프레임별 별도 플래그로, 행을 네 번에 나눠 저장해 덜 받은 상태에서도 그림 전체의 거친 모습을 보여줍니다. 요즘 회선에서는 이득이 없고 이웃 행의 상관관계를 끊어 LZW 스트림을 오히려 조금 키웁니다. 인터레이스된 프레임이 보인다면 대개 오래된 도구를 거친 파일이라는 신호입니다.

관련 도구