Base64를 BMP로 변환하는 방법
- Base64나
data:image/bmp;base64,...URI 전체를 붙여넣거나, 문자열이 담긴.txt파일을 여세요. 비트맵은 수 MB짜리 문자열이 흔하며, 여기서는 문제없습니다. - 상태 표시줄의 감지된 형식이 BMP여야 합니다. 미리보기에 이미지와 픽셀 크기가 나오고, 크기에는 디코딩된 파일 크기가 바이트 단위로 표시됩니다.
- 파일 다운로드를 눌러
.bmp를 저장하세요.
브라우저는 <img>로 BMP를 디코딩하며, 1비트 흑백, 8비트 팔레트, 24비트, 대부분의 32비트 파일을 지원합니다.
가로세로로 계산하는 BMP 파일 크기
BMP는 14바이트 파일 헤더, 정보 헤더(흔한 버전은 40바이트), 선택적인 팔레트, 그리고 픽셀 행으로 이루어집니다. 각 행은 4바이트의 배수로 패딩됩니다. 팔레트 없는 24비트 이미지라면 다음과 같습니다.
file size = 54 + height × (width × 3, rounded up to a multiple of 4)
| 이미지 | 행 크기 | BMP 파일 | Base64 길이 |
|---|---|---|---|
| 33×10, 24비트 | 99 → 100바이트 | 1,054바이트 | 1,408자 |
| 100×100, 24비트 | 300바이트 | 30,054바이트 | 40,072자 |
| 800×600, 24비트 | 2,400바이트 | 1,440,054바이트 | 1,920,072자 |
| 1920×1080, 24비트 | 5,760바이트 | 6,220,854바이트 | 8,294,472자 |
| 1920×1080, 1비트 | 240바이트 | 259,262바이트 | 345,684자 |
1비트 행에는 8바이트짜리 2색 팔레트가 더해집니다. 수치가 정해져 있으므로 비트맵은 검사하기 쉽습니다. 파일 헤더의 2–5번째 바이트에 전체 크기가 저장됩니다. 100×100 예시의 hex 덤프에서는 66 75 00 00이고, 리틀 엔디언 숫자로 0x7566 = 30,054입니다. 크기가 이보다 작게 나온다면 Base64가 잘린 것입니다. BMP 행은 기본적으로 아래에서 위로 저장되므로, 잘린 비트맵은 그림의 윗부분이 사라집니다.
BMP Base64의 생김새
모든 BMP는 BM이라는 글자로 시작하므로 Base64는 Qk로 시작합니다. 세 번째 글자는 파일 크기에 따라 0, 1, 2, 3 중 하나이며, Qk02와 Qk1m이 흔합니다. 감지기는 14번째 바이트의 정보 헤더 크기도 확인하므로, 우연히 BM으로 시작하는 랜덤 데이터를 비트맵으로 오인하지 않습니다.
헤더 없는 비트맵 (DIB)
어떤 출처는 BM 파일 헤더 없이 비트맵을 넘겨줍니다. 이것이 DIB로, Windows 클립보드(CF_DIB), ICO 파일 안의 이미지, 일부 장치 SDK가 쓰는 형식입니다. Base64는 40바이트 정보 헤더 크기 28 00 00 00을 인코딩한 KAAAA로 시작합니다.
파일 헤더가 없으면 바이트가 올바른 이미지 파일이 아니므로 도구는 미리보기를 보여 주지 못하고 바이너리 데이터라고 알립니다. 빠진 14바이트를 앞에 붙이면 해결됩니다.
import base64, struct
def dib_to_bmp(dib: bytes) -> bytes:
header_size, = struct.unpack_from("<I", dib, 0)
bpp, = struct.unpack_from("<H", dib, 14)
compression, colors = struct.unpack_from("<I", dib, 16)[0], struct.unpack_from("<I", dib, 32)[0]
if bpp <= 8 and colors == 0:
colors = 1 << bpp
masks = 12 if header_size == 40 and compression == 3 else 0
offset = 14 + header_size + masks + colors * 4
return b"BM" + struct.pack("<IHHI", 14 + len(dib), 0, 0, offset) + dib
b64 = open("dib.txt").read()
with open("image.bmp", "wb") as f:
f.write(dib_to_bmp(base64.b64decode(b64)))
헤더에는 전체 파일 크기와 픽셀 데이터의 오프셋이 필요합니다. 픽셀 데이터는 정보 헤더, 16비트와 32비트 비트필드 이미지의 색상 마스크, 팔레트 다음에 옵니다. 결과를 다시 텍스트로 써야 한다면 BMP를 Base64로로 인코딩하거나 여기서 확인하세요. ICO 파일에서 나온 DIB는 특수한 경우로, 투명도 마스크를 담기 위해 높이가 두 배로 되어 있습니다. 바이너리 데이터 디코딩은 Python에서 Base64에 더 자세히 있습니다.
자주 생기는 문제
- “BMP이(가) 아니라 PNG(으)로 보입니다.” 보낸 쪽이 이미 이미지를 변환했거나, 시스템이 그냥 비트맵이라고 부를 뿐입니다. .png(으)로 다운로드로 PNG로 저장하세요. 더 작고 모든 프로그램이 읽습니다.
- 다른 프로그램에서 색이 뒤바뀌거나 이미지가 뒤집혀 보입니다. BMP는 픽셀을 파랑-초록-빨강 순서로, 보통 아래에서 위로 저장합니다. 헤더의 높이가 음수면 위에서 아래로 저장된 행입니다. 브라우저는 이를 모두 처리하지만, 간단한 자작 리더는 그렇지 못할 때가 있습니다.
- 장치가 디코딩한 파일을 거부합니다. 장치가 받은 파일과 SHA-256을 비교한 뒤, hex 덤프에서 비트 깊이와 헤더 버전을 확인하세요. 오래된 리더는 40바이트 헤더(오프셋 14의
28 00 00 00)와 알파 채널 없는 이미지를 기대합니다.
자주 묻는 질문
비트맵 Base64 문자열은 왜 이렇게 긴가요?
BMP는 원시 픽셀을 압축 없이 저장합니다. 1920×1080 24비트 비트맵은 그림 내용과 상관없이 6,220,854바이트이며, Base64로는 8,294,472자입니다.
Base64가 Qk가 아니라 KAAAA로 시작합니다. 무엇인가요?
14바이트 파일 헤더가 없는 비트맵으로, DIB라고 부릅니다. Windows 클립보드, 일부 장치 SDK, ICO 파일에서 나옵니다. 이 페이지의 Python 코드로 헤더를 붙이면 일반 .bmp가 됩니다.
BMP 문자열이 완전한지 어떻게 알 수 있나요?
파일의 2–5번째 바이트에 전체 크기가 들어 있습니다. hex 덤프 표시를 열어 이 값을 리틀 엔디언 숫자로 읽고 크기 행과 비교하세요. 디코딩된 크기가 더 작다면 문자열이 잘린 것입니다.
BMP 대신 PNG로 받을 수 있나요?
이 페이지는 비트맵을 있는 그대로 저장합니다. 변환하려면 다운로드한 파일을 BMP를 Base64로에 놓고 변환 형식을 PNG로 고르세요. PNG는 무손실이고 대개 훨씬 작습니다.