Graphical+Editor

= PC/UVa ID: 110105/10267 - 그래픽 편집기(Graphical Editor) = 포토샵 같은 그래픽 편집기를 이용하면 텍스트 편집기에서 문서를 수정하는 것처럼 비트맵 이미지를 수정할 수 있다. 이미지는 픽셀로 이루어진 M x N 배열로 표현되며 각 픽셀마다 색이 주어진다.

간단한 대화형 그래픽 편집기 흉내를 낼 수 있는 프로그램을 만들어보자.

입력
입력은 한 줄에 하나씩의 편집기 명령으로 구성된다. 각 명령은 줄 맨 앞에 있는 대문자 한 개로 표현된다. 매개변수가 필요한 경우에는 그 명령과 같은 줄에 스페이스로 분리되어 매개변수가 입력된다.

픽셀 좌표는 1 이상 M 이하의 열 번호와 1 이상 N 이하의 행 번호, 이렇게 두 개의 정수로 표현되며 이때 1 <= M, N <= 250 라는 조건이 만족된다. 표의 왼쪽 위 꼭지점을 원점으로 삼는다. 색은 대문자로 지정된다.

편집기에서 받아들이는 명령은 다음과 같다.

(X1, Y1)은 왼쪽 위 끝점, (X2, Y2)는 오른쪽 아래 끝 점을 의미한다. || (X, Y) 픽셀과 색이 같고 R에 포함된 픽셀과 맞닿은 부분이 하나라도 있다면 그 픽셀도 R 영역에 포함된다. ||
 * ~ I M N || 모든 픽셀이 흰색(O)으로 칠해진 M x 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 열과 X2 행(X1, X2 포함) 사이에 주어진 색(C)으로 수평 방향 직선을 긋는다. ||
 * ~ K X1 Y1 X2 Y2 C || 주어진 색(C)으로 채워진 직사각형을 그린다.
 * ~ F X Y C || R 영역을 주어진 색(C)으로 채우는데, 영역 R은 다음과 같이 정의된다. (X, Y) 픽셀은 R에 속한다.
 * ~ S Name || 파일명을 MSDOS 8.3 형식으로 출력하고 그 뒤에 현재 이미지의 내용을 출력한다. ||
 * ~ X || 세션을 종료한다. ||

출력
S NAME이라는 명령이 있을 때마다 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 two.bmp JJJJJ JJZZJ JWJJJ JWJJJ JJJJJ JJJJJ

참고자료
[]

Source Code code format="c"
 * 1) include 
 * 2) include 


 * 1) include "SSMAlg.h"

char ssmsolution[100];

char **image;   // 이미지

void fill(int x, int y, char c, int m, int n, char c2) {   // 경계 검사 if(x < 0 || x >= m || y < 0 || y >= n)   { return; }

// 이미 칠한 곳이면 if(image[y][x] == c)   { return; }

// 스케치 영역이면 if(image[y][x] != c2) {       return; }

// 점 찍고 image[y][x] = c;

// 네 방향으로 확산 fill(x - 1, y, c, m, n, c2); fill(x + 1, y, c, m, n, c2); fill(x, y - 1, c, m, n, c2); fill(x, y + 1, c, m, n, c2); }

void main {   SSMInitAlgorithmTest("우준혁", "4");

FILE* fp = fopen("InputProblem4.txt", "r");

char comm;   // 명령어

int i, j;

while(1) {       fscanf(fp, "%c", &comm);

switch(comm) {       int M, N;    // 이미지의 크기 int X, Y;   // 픽셀 좌표 int X1, Y1; int X2, Y2; char C;       // 색 char Name[100];   // 파일명

case 'I': fscanf(fp, "%d %d", &M, &N);

// 이미지를 생성한다. image = (char**) malloc(N * sizeof(char*)); for(i = 0; i < N; i++) {               image[i] = (char*) malloc(M * sizeof(char)); }

// 흰색으로 칠한다. for(i = 0; i < N; i++) {               for(j = 0; j < M; j++) {                   image[i][j] = 'O'; }           }

break;

case 'C': // 흰색으로 칠한다. for(i = 0; i < N; i++) {               for(j = 0; j < M; j++) {                   image[i][j] = 'O'; }           }            break;

case 'L': fscanf(fp, "%d %d %c", &X, &Y, &C);

image[Y - 1][X - 1] = C;

break;

// 수직 방향의 직선을 긋는다. case 'V': fscanf(fp, "%d %d %d %c", &X, &Y1, &Y2, &C);

for(i = Y1 - 1; i < Y2; i++) {               image[i][X - 1] = C;            }

break;

// 수평 방향의 직선을 긋는다. case 'H': fscanf(fp, "%d %d %d %c", &X1, &X2, &Y, &C);

for(i = X1 - 1; i < X2; i++) {               image[Y - 1][i] = C;            }

break;

// 채워진 직사각형을 그린다. case 'K': fscanf(fp, "%d %d %d %d %c", &X1, &X2, &Y1, &Y2, &C);

for(i = Y1 - 1; i < Y2; i++) {               for(j = X1 - 1; j < X2; j++) {                   image[i][j] = C;                } }           break;

// 영역 채우기 알고리즘 case 'F': fscanf(fp, "%d %d %c", &X, &Y, &C);

fill(X - 1, Y - 1, C, M, N, image[Y - 1][X - 1]);

break;

// 출력한다. case 'S': fscanf(fp, "%s", Name);

sprintf(ssmsolution, "%s\n", Name); SSMPrintSolution(ssmsolution);

for(i = 0; i < N; i++) {               for(j = 0; j < M; j++) {                   sprintf(ssmsolution, "%c", image[i][j]); SSMPrintSolution(ssmsolution); }               sprintf(ssmsolution, "\n"); SSMPrintSolution(ssmsolution); }           break;

// 종료한다. case 'X': SSMExitAlgorithmTest;

fclose(fp);

return; }   } } code code format="java5" import java.util.Scanner;

public class GraphicalEditor { private char[][] image; private int M, N;

public GraphicalEditor(int m, int n) { this.M = m;       this.N = n;

image = new char[N][M];

clear; }

public void clear { for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { image[i][j] = 'O'; }       }    }

public char getPixel(int x, int y) { return image[y - 1][x - 1]; }

public void setPixel(int x, int y, char color) { image[y - 1][x - 1] = color; }

public void fill(int x, int y, char oldColor, char newColor) { int r = y - 1; int c = x - 1;

if(r < 0 || r >= N || c < 0 || c >= M) { return; }

if(image[r][c] != oldColor) { return; }

image[r][c] = newColor;

fill(y - 1, x, oldColor, newColor); fill(y + 1, x, oldColor, newColor); fill(y, x - 1, oldColor, newColor); fill(y, x + 1, oldColor, newColor); }

public void draw { for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { System.out.print(image[i][j]); }           System.out.println; }   }

public int getM { return M;   }

public int getN { return N;   }

public void setM(int m) { this.M = m;   }

public void setN(int n) { this.M = n;   }

public static void main(String[] args) { Scanner scan = new Scanner(System.in);

GraphicalEditor ge = null;

while(true) { String line = scan.nextLine; String[] token = line.split(" "); String command = token[0];

if("I".equals(command)) { int M = Integer.parseInt(token[1]); int N = Integer.parseInt(token[2]);

ge = new GraphicalEditor(M, N); }           else if("C".equals(command)) { ge.clear; }           else if("L".equals(command)) { int X = Integer.parseInt(token[1]); int Y = Integer.parseInt(token[2]); char C = token[3].charAt(0);

ge.setPixel(X, Y, C); }           else if("V".equals(command)) { int X = Integer.parseInt(token[1]); int Y1 = Integer.parseInt(token[2]); int Y2 = Integer.parseInt(token[3]); char C = token[4].charAt(0);

for(int i = Y1; i <= Y2; i++) { ge.setPixel(X, i, C); }           }            else if("H".equals(command)) { int X1 = Integer.parseInt(token[1]); int X2 = Integer.parseInt(token[2]); int Y = Integer.parseInt(token[3]); char C = token[4].charAt(0);

for(int i = X1; i <= X2; i++) { ge.setPixel(i, Y, C); }           }            else if("K".equals(command)) { int X1 = Integer.parseInt(token[1]); int X2 = Integer.parseInt(token[2]); int Y1 = Integer.parseInt(token[3]); int Y2 = Integer.parseInt(token[4]); char C = token[5].charAt(0);

for(int i = Y1; i <= Y2; i++) { for(int j = X1; j <= X2; j++) { ge.setPixel(i, j, C); }               }            }            else if("F".equals(command)) { int X = Integer.parseInt(token[1]); int Y = Integer.parseInt(token[2]); char C = token[3].charAt(0);

ge.fill(X, Y, ge.getPixel(X, Y), C); }           else if("S".equals(command)) { String Name = token[1];

System.out.println(Name);

ge.draw; }           else if("X".equals(command)) { break; }       }    } } code

Comment 색상 채우기 알고리즘만 안다면 금방 푸는 문제이다.