본문 바로가기
프로그램/C언어 1000제

C언어 202제] 그래픽 편집기(Graphical Editor)

by 건티 2024. 12. 24.
728x90

출처 : 반크_백제역사 유적지구 및 이스탐블역사 유적지구

 

문제]

포토샵 같은 그래픽 편집기를 이용하면 텍스트 편집기에서 문서를 수정하는 것처럼 비트맵 이미지를 수정할 수 있다. 이미지는 픽셀로 이루어진 M × N 배열로 표현되며 각 픽셀마다 색이 주어진다. 간단한 대화형 그래픽 편집기 흉내를 낼 수 있는 프로그램을 만들어보자.

입력
입력은 한 줄에 하나씩의 편집기 명령으로 구성된다. 각 명령은 줄 맨 앞에 잇는 대문자 한 개로 표현된다. 매개변수가 필요한 경우에는 그 명령과 같은 줄에 스페이스로 분리되어 매개변수가 입력된다.
픽셀 좌표는 1 이상 M 이하의 열 번호와 1 이상 N 이하의 행 번호, 이렇게 두 개의 정수로 푠현되며 이때 1<=M, N<=250라는 조건이 만족된다. 표의 왼쪽 위 꼭지점을 원점으로 삼는다. 색은 대문자로 지정된다.
편집기에서 받아륻이는 명령은 다음과 같다.

I M N 모든 픽셀이 흰색(O)으로 필해진 M × N 이미지를 새로 만든다.
C 모든 픽셀을 흰색(O)으로 칠해서 표를 지운다. 이미지의 크기는 바뀌지 않는다.
L X Y C (X, Y) 픽셀을 주어진 색(C)으로 칠한다.
V X Y1 Y2 C X열에 Y1행과 Y2행(Y1, Y2 포함) 사이에 주어진 색(C)으로 수직 방향 직선을 긋는다.
H X1 X2 Y C Y행에 X1행과 V2행(X1, X2 포함) 사이에 주어진 색(C)으로 수평 방향 직선을 긋는다.
K X1 Y1 X2 Y2 C 주어진 색(C)으로 채워진 직사각형을 그린다. (X1, Y1)은 왼쪽 위 끝점. (X2, Y2)은 오른쪽 아래 끝점 의미
F X Y C R영역을 주어진 색(C)으로 채우는데, 영역 R은 다음과 같이 정의된다. (X, Y) 픽셀은R에 속한다.
(X, Y)픽셀과 색이 같고 R에 포합된 픽셀과 맞닿은 부분이 하나라도 있다면 그 빅셀도 R 영역에 포함된다.
S Name 파일명을 MSDOS 8.3형식으로 출력하고 그 뒤에 현재 이미지의 내용을 출력한다.
X 세션을 종료한다.



출력
S NAMW이라는 명령이 있으 때마다 NAME으로 주어진 파일명을 출력하고 현재 이미지의 내용을 출력한다. 각 행은 각 픽셀의 색을 나타내는 문자로 표시된다. 출력 예를 참고하자.
I, C, L, V, H, K, F, S, X를 제외한 문자로 정의된 명령이 있으면 그 줄 전체를 무시하고 다음 명령으로 넘어간다. 다른 오류에 대해서는 프로그램의 행동을 예측할 수 없다.

입력 예
I 5 6
L 2 3 A
S one.bmp
G 2 3 J
F 3 3 J
V 2 3 4 W
H 3 4 2 Z
S two.bmp
X


츨력 예
one.bmp
OOOOO
OOOOO
OAOOO
OOOOO
OOOOO
OOOOO
two.bmp
JJJJJ
JJZZJ
JWJJJ
JWJJJ
JJJJJ
JJJJJ

출처]
Programming Challenges 알고리즘 트레이닝 북(한빛미디어) : 문제 5 그래픽 편집기(Graphical Editor) p44

 

 

참고풀이]

#include <stdio.h>
#include <string.h> //strlen(), strcpy(), strcmp()
#include <stdlib.h> //atoi()
#include <ctype.h> //toupper()

static char bitMap[251][251];
static int M=0, N=0;//픽셀좌표 열, 행 변수

struct Division{
   char dCom;
   int m1;
   int m2;
   int m3;
   int m4;
   char dColor;
   char dName[20];
} D;

void Swap(int *x, int *y)
{
   int t;


   t=*x;
   *x=*y;
   *y=t;
}

void DiChk(char *cStr,int n) 
{
   if(n==0) { 
      if(toupper(cStr[0])>='A' && toupper(cStr[0])<='Z') strcpy(D.dName,cStr);
      else D.m1=atoi(cStr);
   }
   else if(n==1) { D.m2=atoi(cStr); n++; }
   else if(n==2) { 
      if(toupper(cStr[0])>='A' && toupper(cStr[0])<='Z') D.dColor=cStr[0];
      else D.m3=atoi(cStr); 
   }
   else if(n==3) { 
      if(toupper(cStr[0])>='A' && toupper(cStr[0])<='Z') D.dColor=cStr[0];
      else D.m4=atoi(cStr); 
   }
   else
      D.dColor=cStr[0];
}

//입력된 문자열을 명령어 등등으로 나눈다.
void Division(char *Str)
{
   int i, j, k, n; 
   char Chk[20]={'\0'};//각 구분 문자열 변수 

   D.m1=0;
   D.m2=0;
   D.m3=0;
   D.m4=0;
   D.dColor='O';
   strcpy( D.dName,"");

   D.dCom=toupper(Str[0]);
   for(n=0,k=0,j=2;j<strlen(Str);j++)
      if(Str[j] != ' ') 
         Chk[k++]=Str[j];
      else
      {
         Chk[k]='\0';
         DiChk(Chk,n);
         k=0;
         n++;
      }
   if(Str[strlen(Str)-1] != ' ')
   {
      Chk[k]='\0';
      DiChk(Chk,n);
   }
}

//(i,j)위치에서 시작하여 color를 칠한다. 
void Fill(int i, int j, char org, char color)
{
   bitMap[i][j]=color;
   if(i>1 && bitMap[i-1][j]==org) //위 
      Fill(i-1, j, org, color);
   if(i<N && bitMap[i+1][j]==org) //아래 
      Fill(i+1, j, org, color);
   if(j>1 && bitMap[i][j-1]==org) //좌측 
      Fill(i, j-1, org, color);
   if(i<M && bitMap[i][j+1]==org) //우측 
      Fill(i, j+1, org, color);
}

int main()
{
   int i, n; 
   int r, rs, re;//행, 행시작, 행끝 변수
   int c, cs, ce;//열, 열시작, 열끝 변수
   char inStr[100][20]={'\0'};
   char com;//입력되는 명령어 변수
   char color;//색변수 
   char fileName[13]={'\0'};//파일명 변수

   //자료를 입력받는다.
   n=0;
   while(1)
   {
      gets(inStr[n]);
      if(strcmp(inStr[n],"X")==0) break;
      n++;
   }

 

   //입력 명령어를 기반으로 이미지를 처리한다.
   i=0;
   while(1) 
   {
      Division(inStr[i]);
      com=D.dCom;
      if(com=='X') break;
      switch(com)
      {
      case 'I':
         M=D.m1; N=D.m2;
      case 'C':
         for(r=1;r<=N;r++)
            for(c=1;c<=M;c++)
               bitMap[r][c]='O';
         break;
      case 'L':
         c=D.m1;
         r=D.m2;
         color=D.dColor;
         bitMap[r][c]=color;
         break;
      case 'V':
         c=D.m1;
         rs=D.m2;
         re=D.m3;
         color=D.dColor;
         if(rs>re) Swap(&rs, &re);
         for(r=rs; r<=re;r++)
            bitMap[r][c]=color;
         break;
      case 'H':
         cs=D.m1;
         ce=D.m2;
         r=D.m3;
         color=D.dColor;
         if(cs>ce) Swap(&cs, &ce);
         for(c=cs;c<=ce;c++)
            bitMap[r][c]=color;
         break;
      case 'K':
         cs=D.m1;
         rs=D.m2;
         ce=D.m3;
         re=D.m4;
         color=D.dColor;
         if(rs>re) Swap(&rs, &re);
         if(cs>ce) Swap(&cs, &ce);
         for(r=rs;r<=re;r++)
            for(c=cs;c<=ce;c++)
               bitMap[r][c]=color;
         break;
      case 'F':
         c=D.m1;
         r=D.m2;
         color=D.dColor;
         //채우기
         Fill(r,c,bitMap[r][c],color);
         break; 
      case 'S':
         strcpy(fileName,D.dName);
         puts(fileName);
         for(r=1;r<=N;r++)
         {
            for(c=1;c<=M;c++)
               putchar(bitMap[r][c]);
            putchar('\n');
         }
         break;
      }
      i++;
   }

   return 0;
}

 

참고풀이 결과]

 

 

 

 

 

대한민국의 아름다운 영토, 독도의 겨울

 

반응형

댓글