PGM(Portable Gray Map)이란?
PGM은 Portable Gray Map, 즉 휴대용 그레이스케일 이미지 형식을 의미합니다. C 언어에서 2차원 배열 데이터를 PNG나 JPEG처럼 일반적인 이미지 형식으로 저장하려면, 파일에 기록하기 전에 지정된 형식에 맞게 데이터를 인코딩하는 복잡한 작업이 필요합니다.
반면 Netpbm 포맷은 간단하면서도 이식성이 뛰어난 해결책을 제공합니다. Netpbm은 오픈 소스 그래픽 프로그램 패키지로, 주로 Linux나 Unix 환경에서 사용되며 Microsoft Windows 시스템에서도 문제없이 동작합니다.
매직 넘버(Magic Number)의 역할
모든 Netpbm 파일은 2바이트 크기의 매직 넘버로 시작합니다. 이 매직 넘버는 파일의 종류를 식별하는 데 사용되며, PBM, PGM, PPM 등의 유형뿐 아니라 ASCII 인코딩인지 바이너리 인코딩인지도 함께 나타냅니다. 매직 넘버는 대문자 'P' 뒤에 한 자리 숫자가 붙는 형태입니다.
- ASCII 인코딩: 사람이 직접 읽을 수 있고, 다른 플랫폼으로의 전송도 쉽습니다.
- 바이너리 인코딩: 파일 크기 면에서 더 효율적이지만, 바이트 순서(endianness) 문제가 발생할 수 있습니다.
PGM 파일 작성 절차
- 매직 넘버 P2를 설정합니다.
- 공백 문자(스페이스, 탭, CR, LF)를 추가합니다.
- 이미지의 너비(width)를 ASCII 10진수 형식으로 추가합니다.
- 공백을 추가합니다.
- 이미지의 높이(height)를 ASCII 10진수 형식으로 추가합니다.
- 공백을 추가합니다.
- 최대 회색값(max gray value)을 역시 ASCII 10진수로 추가합니다.
- 공백을 추가합니다.
- 너비 × 높이 개수만큼의 회색값을 각각 ASCII 10진수(0부터 최대값 사이 범위)로 기록하며, 값 사이는 공백으로 구분하고 왼쪽 위에서 오른쪽 아래 방향으로 나열합니다.
예제 코드
#include <stdio.h>
main() {
int i, j;
int w = 13, h = 13;
// 이 2D 배열은 13 x 13 크기의 이미지로 변환됩니다
int image[13][13] = {
{ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 },
{ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31},
{ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47},
{ 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63},
{ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79},
{ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95 },
{ 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111},
{ 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127},
{ 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143},
{ 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159},
{ 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175},
{ 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191},
{ 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207}
};
FILE* pgmimg;
pgmimg = fopen("my_pgmimg.pgm", "wb"); // 파일을 바이너리 모드로 열기
fprintf(pgmimg, "P2\n"); // 파일에 매직 넘버 기록
fprintf(pgmimg, "%d %d\n", w, h); // 너비와 높이 기록
fprintf(pgmimg, "255\n"); // 최대 회색값 기록
int count = 0;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
fprintf(pgmimg, "%d ", image[i][j]); // 배열의 회색값을 파일에 복사
}
fprintf(pgmimg, "\n");
}
fclose(pgmimg);
}위 코드를 실행하면 13×13 크기의 2차원 배열이 그레이스케일 값으로 변환되어 my_pgmimg.pgm 파일에 저장됩니다. 각 행은 서로 다른 밝기(15부터 207까지 16씩 증가)를 가지므로, 결과 이미지는 위에서 아래로 점점 밝아지는 그라데이션 패턴을 보여줍니다.
실행 결과
생성된 PGM 이미지는 아래와 같습니다.
