728x90
반응형
#define \_CRT\_SECURE\_NO\_WARNINGS // fopen 보안 경고로 인한 컴파일 에러 방지  
#include <stdio.h> // fopen, fread, fseek, fprintf, fclose 함수가 선언된 헤더 파일  
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일  
#pragma pack(push, 1) // 구조체를 1바이트 크기로 정렬  
typedef struct \_BITMAPFILEHEADER // BMP 비트맵 파일 헤더 구조체  
{  
unsigned short bfType; // BMP 파일 매직 넘버  
unsigned int bfSize; // 파일 크기  
unsigned short bfReserved1; // 예약  
unsigned short bfReserved2; // 예약  
unsigned int bfOffBits; // 비트맵 데이터의 시작 위치  
} BITMAPFILEHEADER;  
typedef struct \_BITMAPINFOHEADER // BMP 비트맵 정보 헤더 구조체(DIB 헤더)  
{  
unsigned int biSize; // 현재 구조체의 크기  
int biWidth; // 비트맵 이미지의 가로 크기  
int biHeight; // 비트맵 이미지의 세로 크기  
unsigned short biPlanes; // 사용하는 색상판의 수  
unsigned short biBitCount; // 픽셀 하나를 표현하는 비트 수  
unsigned int biCompression; // 압축 방식  
unsigned int biSizeImage; // 비트맵 이미지의 픽셀 데이터 크기  
int biXPelsPerMeter; // 그림의 가로 해상도(미터당 픽셀)  
int biYPelsPerMeter; // 그림의 세로 해상도(미터당 픽셀)  
unsigned int biClrUsed; // 색상 테이블에서 실제 사용되는 색상 수  
unsigned int biClrImportant; // 비트맵을 표현하기 위해 필요한 색상 인덱스 수  
} BITMAPINFOHEADER;  
typedef struct tagRGBTRIPLE // 24비트 비트맵 이미지의 픽셀 구조체  
{  
unsigned char rgbtBlue; // 파랑  
unsigned char rgbtGreen; // 초록  
unsigned char rgbtRed; // 빨강  
} RGBTRIPLE;

#pragma pack(pop)  
#define PIXEL\_SIZE 3 // 픽셀 한 개의 크기 3바이트(24비트)  
#define PIXEL\_ALIGN 4 // 픽셀 데이터 가로 한 줄은 4의 배수 크기로 저장됨  
#define WIDTHBYTES(bits) (((bits)+31)/32\_4)  
int main()  
{  
FILE \*fpBmp; // 입력 비트맵 파일 포인터  
FILE \*fpreBmp; // 출력 비트맵 파일 포인터  
BITMAPFILEHEADER fileHeader; // 비트맵 파일 헤더 구조체 변수  
BITMAPINFOHEADER infoHeader; // 비트맵 정보 헤더 구조체 변수  
unsigned char \*inputImage; // 픽셀 데이터 포인터  
unsigned char \*outputImage;  
int size; // 픽셀 데이터 크기  
int width, height; // 비트맵 이미지 가로, 세로 크기  
int padding;  
fpBmp = fopen("src.bmp", "rb"); // 비트맵 파일 바이너리 모드로 열기 // 입력 filename  
if (fpBmp == NULL) // 파일 열기 실패 시  
{  
return 0; // 프로그램 종료  
}  
// 비트맵 파일 헤더 읽기.  
// 읽기에 실패하면 파일 포인터를 닫고 프로그램 종료.  
// (fread()로 sizeof(BITMAPFILEHEADER)를 1번 읽었을 때 성공하면 1 반환,  
// 실패 시 1보다 작은 수 반환.)  
if (fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fpBmp) < 1)  
{  
fclose(fpBmp);  
return 0;  
}  
// 매직 넘버가 MB가 맞는지 확인.  
// (2바이트 크기의 BM을 리틀 엔디언으로 읽었으므로 MB가 됨.)  
// 매직 넘버가 맞지 않으면 프로그램 종료  
if (fileHeader.bfType != 'MB')  
{  
fclose(fpBmp);  
return 0;  
}  
// 비트맵 정보 헤더 읽기.  
// 읽기 실패 시 파일 포인터를 닫고 프로그램 종료.  
if (fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fpBmp) < 1)  
{  
fclose(fpBmp);  
return 0;  
}  
// 24비트 비트맵이 아니면 프로그램 종료  
if (infoHeader.biBitCount != 24)  
{  
fclose(fpBmp);  
return 0;  
}  
// BMP Pallete  
RGBTRIPLE hRGB\[256\];  
fread(hRGB, sizeof(RGBTRIPLE), 256, fpBmp);  
// 자주 사용하는 변수 저장  
size = infoHeader.biSizeImage; // 픽셀 데이터 크기  
width = infoHeader.biWidth; // 비트맵 이미지 가로 크기  
height = infoHeader.biHeight; // 비트맵 이미지 세로 크기  
padding = (PIXEL\_ALIGN - ((width \* PIXEL\_SIZE) % PIXEL\_ALIGN)) % PIXEL\_ALIGN;  
//패딩값 출력  
//printf("%d", padding);  
if (size == 0) // 픽셀 데이터 크기가 0이라면  
{  
// 이미지의 가로 크기 \* 픽셀 크기에 남는 공간을 더해주면 완전한 가로 한 줄 크기가 나옴  
// 여기에 이미지의 세로 크기를 곱해주면 픽셀 데이터의 크기를 구할 수 있음  
size = (width \* PIXEL\_SIZE + padding) \* height;  
}  
inputImage = (unsigned char\_)malloc(size); // 픽셀 데이터의 크기만큼 동적 메모리 할당  
// 파일 포인터를 픽셀 데이터의 시작 위치로 이동  
fseek(fpBmp, fileHeader.bfOffBits, SEEK\_SET);  
// 파일 포인터를 픽셀 데이터의 시작 위치로 이동  
//fseek(fpBmp, fileHeader.bfOffBits, SEEK\_SET);  
// 파일에서 픽셀 데이터 크기만큼 읽음.  
// 읽기에 실패하면 파일 포인터를 닫고 프로그램 종료  
if (fread(inputImage, size, 1, fpBmp) < 1)  
{  
fclose(fpBmp);  
return 0;  
}  
// 비트맵 파일 닫기  
fclose(fpBmp);  
// 결과 출력용 비트맵 파일 열기  
fpreBmp = fopen("copy.bmp", "wb"); // 출력 file name  
//출력하기위해 리드했던것을 똑같이 라이트해줌.  
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fpreBmp);  
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fpreBmp);  
fwrite(inputImage, size, 1, fpreBmp);


outputImage = (unsigned char*)malloc(infoHeader.biSizeImage / 4);
int resize = WIDTHBYTES(infoHeader.biBitCount * infoHeader.biWidth);
int out_resize = WIDTHBYTES(infoHeader.biBitCount * infoHeader.biWidth / 2);

// 그레이스케일을 rgb값으로 변환해주는 코드 // 입력을 안하면 흑백으로 출력
for (int inputlow = 0, outputlow = 0; inputlow < infoHeader.biHeight; outputlow++, inputlow += 2)
{
    for (int incolumn = 0, outcolumn = 0; incolumn < infoHeader.biWidth * 3; outcolumn++, incolumn += 4)
    {
        for (int count = 0; count < 3; count++) //read Red(count == 0), Green(count == 1), Blue(count == 2) value --> rgb값을 받고 넘긴다
        {
            *(outputImage + (outputlow * out_resize + (outcolumn + count))) = *(inputImage + (inputlow * resize + (incolumn + count)));
        }
        outcolumn += 2; incolumn += 2;
    }
}

infoHeader.biWidth = infoHeader.biWidth / 2;
infoHeader.biHeight = infoHeader.biHeight / 2;

fpreBmp = fopen("copy.bmp", "wb"); 출력 file name // 위 출력네임과 똑같이 작성해야함

fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fpreBmp);
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fpreBmp);
fwrite(outputImage, size, 1, fpreBmp);


fclose(fpreBmp);     // 출력 비트맵 파일 close
free(inputImage);
free(outputImage);

printf("이미지 변환 완료\n");
// 파일 열기에 실패하면,
// 픽셀 데이터를 저장한 동적 메모리 해제, 종료
if (fpreBmp == NULL)
{
    free(inputImage);
    return 0;
}


}

축소된 bmp 파일(copy.bmp)

 

원본 bmp 파일(src.bmp)

 

728x90
반응형

+ Recent posts