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;
}
}


728x90
반응형
'Education > Edu | .net' 카테고리의 다른 글
# 2.5) [Win32API] 오각형 타이머 설정하여 회전시키기 (0) | 2021.01.04 |
---|---|
# 2.4) [Win32API] 오각형 그리기 (0) | 2020.12.31 |
# 2.3) [Win32API] 윈도우즈 데스크톱 애플리케이션 코드 설명(2) (0) | 2020.12.31 |
# 2.2) [Win32API] 윈도우즈 데스크톱 애플리케이션 코드 설명(1) (0) | 2020.12.31 |
# 2.1) [Win32API] 윈도우즈 데스크톱 애플리케이션 코드 설명(0) (0) | 2020.12.28 |