안녕하세요 c언어를 배우고 있는 학생입니다. 코드와 관련되어 질문 여쭈어 봅니다.

조회수 1290회
#include <stdio.h>
#include <stdlib.h>

#define WIDTH 512
#define HEIGH 512  // WIDTH, HEIGH 각각에 512이란 값으로 정의
typedef unsigned char BYTE;  // unsigned char를 BYTE로 표현 

int main()
{
    FILE *fp_in = 0, *fp_out = 0;     // fp_in과 fp_out에 쓰레기값 0을 대입후 포인터 생성.
    BYTE **img_in = 0, **img_out = 0;     // img_in과 img_out에 쓰레기값 0을 대입, 더블 포인터 생성
    int i = 0, j = 0;      // 반복문을 위한 변수.

    fp_in = fopen("Lena_512.raw", "rb"); // 레나 데이터가 binary 형태로 읽어오고 fp_in이 가르키는 주소에 저장.
    if (fp_in == NULL) {
        printf("File open failed\n"); //fp_in에 아무런 데이터가 입력되지 않았을 때 다음과같은 문구가 뜸.
    }

    img_in = (BYTE **)malloc(sizeof(BYTE *)*HEIGH); // img_in에 HEIGH만큼 1byte의 크기로 메모리 할당.
    for (i = 0; i < HEIGH; i++) {
        img_in[i] = (BYTE *)malloc(sizeof(BYTE)*HEIGH); // 각 block에 있는 포인터 1개가 하나의 행역할을 하여 최종적으로 2차원 배열 생성.
    }
    for (i = 0; i < HEIGH; i++) {
        fread(img_in[i], sizeof(BYTE), WIDTH, fp_in);  // fp_in에 있는 데이터를 1byte 크기로 WIDTH의 횟수만큼 img_in[i]에 읽어옴.
    }

    img_out = (BYTE **)malloc(sizeof(BYTE*)*HEIGH);  // img_in과 마찬가지로 메모리 할당.
    for (i = 0; i < HEIGH; i++) {
        img_out[i] = (BYTE *)malloc(sizeof(BYTE)*WIDTH);
    }
    for (i = 0; i < HEIGH; i++) {
        for (j = 0; j < WIDTH; j++) {
            img_out[i][j] = img_in[i][j]; //img_in의 데이터를 img_out에 가져옴.
        }
    }
    fp_out = fopen("[Output]Lena(512X512).raw", "wb"); // 레나 데이터의 출력을 binary형태로 쓰고 그 파일을 연다. 그리고 fp_out의 주소에 저장.
    if (fp_out == NULL) {
        printf("File open failed\n"); // 데이터가 들어오지 않았을 때 다음과 같은 문구가 나옴. 
    }
    for (i = 0; i < HEIGH; i++) {
        fwrite(img_out[i], sizeof(BYTE), WIDTH, fp_out); //img_out의 배열에 1열의 각 첫번째 요소에 저장된 내용을 1바이트의 크기로 512번 ( 즉 512 바이트 ) < fp_out이 가리키는곳 -> [Output]Lena(512X512).raw >에 데이터를 쓴다.
    }

    for (i = 0; i < HEIGH; i++) {
        free(img_in[i]);
        free(img_out[i]);
    }
    free(img_in);
    free(img_out);
    // 동적할당을 해제.
    fclose(fp_in);
    fclose(fp_out);
    // 작업을 마친후에 파일을 닫는 함수.

    return 0;
}

Lena_512.raw 라는 사진 파일의 크기를 바꾸어 주는 프로그램을 설계중인데 빌드를 해보면

이미지

다고 뜨면서 그 이후

이미지

와같이 됩니다.

디버그하지않고 시작을 누르면

이미지

위와같이 뜨는데
혹시 해결방안을 알 수 있을까요 ?ㅠㅠ

1 답변

  • 우선 잘못되어 있는 코드부터 설명드리겠습니다.

    • 메모리 크기
    img_in = (BYTE **)malloc(sizeof(BYTE *)*HEIGH); // img_in에 HEIGH만큼 1byte의 크기로 메모리 할당.
    

    BYTE * 는 포인터 타입이기 때문에 1 Byte가 아니라 4 Bytes입니다.

    즉, 4 x HEIGHT Bytes 만큼 할당한 것입니다.

    • HEIGHT -> WIDTH
        for (i = 0; i < HEIGH; i++) {
            img_in[i] = (BYTE *)malloc(sizeof(BYTE)*HEIGH); // 각 block에 있는 포인터 1개가 하나의 행역할을 하여 최종적으로 2차원 배열 생성.
        }
    

    여기서는 WIDTH 가 되어야 합니다. output file은 맞게 하셨는데 source file은 잘못 넣으셨네요.

    img_in[i] = (BYTE *)malloc(sizeof(BYTE)*WIDTH);     
    
    • 포인터 접근

    img_in, img_in[i] 와같은 변수들은 포인터 변수입니다. malloc이 항상 성공한다는 보장이 없기 때문에 포인터를 접근하기 전에는 항상 유효한 주소인지 검사를 해야 합니다.

    if(NULL != img_in)
    ...
    
    if(NULL != img_in[i]) 
    ...
    
    • error 발생 시 종료 처리
        fp_in = fopen("Lena_512.raw", "rb"); // 레나 데이터가 binary 형태로 읽어오고 fp_in이 가르키는 주소에 저장.
        if (fp_in == NULL) {
            printf("File open failed\n"); //fp_in에 아무런 데이터가 입력되지 않았을 때 다음과같은 문구가 뜸.
        }
        ...
    
        fp_out = fopen("[Output]Lena(512X512).raw", "wb"); // 레나 데이터의 출력을 binary형태로 쓰고 그 파일을 연다. 그리고 fp_out의 주소에 저장.
        if (fp_out == NULL) {
            printf("File open failed\n"); // 데이터가 들어오지 않았을 때 다음과 같은 문구가 나옴. 
        }
    
    

    file을 open하지 못한 경우에 적절한 종료처리가 되지 않아서 계속해서 아래 루틴이 실행되게 됩니다.

    error가 발생하거나 포인터가 NULL인 경우에는 정상적으로 처리할 수 없기 때문에 바로 return -1 등으로 종료 처리 해주시는게 좋습니다.

    P.S.

    그런데 결과적으로 이 코드는 사진의 크기를 줄여주지 못합니다. 현재 이 코드는 원본 파일에서 512 x 512 픽셀 만큼 읽어와서 512 x 512 크기의 이미지로 저장하는 기능밖에 하지 못합니다.

    사진의 크기를 줄이기 위해서는 원본 파일의 실제 width x height 만큼 읽어서 512 x 512 로 변환하는 작업이 필요한데 이 경우에는 픽셀 보간이 필요합니다. 직접 구현하시는 것보다는 openCV 등의 라이브러리를 이용하시는 것이 좋습니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)