티스토리 뷰
client.jsp에서는 사용자가 파일 선택, 파일명 지정, 알고리즘 선택하여 개인 컴퓨터에 저장될 수 있게 함.
client.jsp 에 들어갈 코드
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<form name='fileForm' enctype='multipart/form-data' action="02-03_photo_server.jsp" method="post">
<p> 이름 : <input type='text' name='name'>
<p> 파일 : <input type='file' name='filename'>
<p> 파라미터(숫자만 입력) : <input type="text" value="45" name="parameter">
<p> <select name="algo">
<option value=""> --선택--</option>
<option value="1">반전처리</option>
<option value="2">밝게하기</option>
<option value="3">블러처리</option>
<option value="4">엠보싱</option>
<option value="5">회전</option>
<option value="6">좌우반전</option>
<option value="7">상하반전</option>
<option value="8">그래프</option>
</select>
<p> <input type="submit" value="처리하기">
</form>
</body>
</html>
server.jsp에서는 사용자에게서 넘겨받은 파일을 지정된 알고리즘에 따라 출력 및 저장될 수 있게 함.
알고리즘은 switch/case문을 활용함.
MultipartRequest
웹 페이지에서 서버로 업로드되는 파일 자체만 다루는 클래스로 cos(com.oreilly.servlet) 패키지에 포함되어 있음.
패키지 파일을 받았다면
1) C:\프로젝트폴더\WebContent\WEB-INF\lib
2) C:\apache-tomcat-9.0.2\lib
3)이클립스 내 프로젝트명 우클릭 후 Java Build Path >> [Libraries] >> Classpath >> <Add External JARs>로 추가해야 함.
server.jsp 에 들어갈 코드
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ page import="com.oreilly.servlet.*"%>
<%@ page import="com.oreilly.servlet.multipart.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
<title>Insert title here</title>
</head>
<body>
<%
MultipartRequest multi = new MultipartRequest(request, "C:\\upload",
5*1024*1024, "utf-8", new DefaultFileRenamePolicy());
String tmp;
Enumeration params = multi.getParameterNames();
tmp = (String) params.nextElement();
String name = multi.getParameter(tmp);
tmp = (String) params.nextElement();
String filename = multi.getParameter(tmp);
Enumeration files = multi.getFileNames();
tmp = (String) files.nextElement();
filename = multi.getFilesystemName(tmp);
filename = multi.getOriginalFileName("filename");
String algo = multi.getParameter("algo");
String parameter = multi.getParameter("parameter");
//int parameter = Integer.parseInt(multi.getParameter("parameter"));
int inW=0, inH=0,outW=0, outH=0;
File inFp;
FileInputStream inFs;
inFp = new File("C:/Images/RAW/"+filename);
long fLen = inFp.length();
inH = inW = (int)Math.sqrt(fLen);
inFs = new FileInputStream(inFp.getPath());
// (2) JSP에서 배열 처리
int[][] inImage = new int[inH][inW]; // 메모리 할당
// 파일 --> 메모리
for (int i=0; i<inH; i++) {
for (int k=0; k<inW; k++) {
inImage[i][k] = inFs.read();
}
}
inFs.close();
int[][] outImage = null;
switch (algo) {
case "1" : // 반전하기
// 반전 알고리즘 : out = 255 - in
// (중요!) 출력영상의 크기 결정 --> 알고리즘에 의존
outH = inH;
outW = inW;
// 메모리 할당
outImage = new int[outH][outW];
// 진짜 영상처리 알고리즘
for(int i=0; i<inH; i++)
for (int k=0; k<inW; k++) {
outImage[i][k] = 255 - inImage[i][k];
}
break;
case "2" : // 밝게하기
// 더하기 알고리즘 : out = in + 값 (주의!오버플로)
// (중요!) 출력영상의 크기 결정 --> 알고리즘에 의존
outH = inH;
outW = inW;
// 메모리 할당
outImage = new int[outH][outW];
// 진짜 영상처리 알고리즘
for(int i=0; i<inH; i++)
for (int k=0; k<inW; k++) {
int value = inImage[i][k] + Integer.parseInt(parameter);
if (value > 255)
value = 255;
if (value < 0)
value = 0;
outImage[i][k] = value;
}
break;
case "3" : // 블러처리
outH = inH;
outW = inW;
// (3) 알고리즘 적용하기
// (중요!) 출력 영상의 크기 결정 --> 알고리즘에 의존
//메모리 할당
outImage = new int[outH][outW];
// mask
double[][] mask = {{1.0/9.0,1.0/9.0,1.0/9.0},{1.0/9.0,1.0/9.0,1.0/9.0},{1.0/9.0,1.0/9.0,1.0/9.0}};
// 임시 입력 배열
int tempInput[][] = new int[inH+2][inW+2];
// 임시 입력 배열 초기화
for(int i=0; i<inH+2; i++){
for(int k=0; k<inW+2; k++){
tempInput[i][k] = 127;
}
}
// 입력 배열 --> 임시 입력
for(int i=0; i<inH; i++){
for(int k=0; k<inW; k++){
tempInput[i+1][k+1] = inImage[i][k];
}
}
//회전 연산 알고리즘
for(int i=0; i<inH;i++){
for(int k=0; k<inW;k++){
double s=0;
for(int m=0; m<3; m++){
for(int n=0;n<3;n++){
s += mask[m][n] * tempInput[i+m][k+n];
}
}
outImage[i][k] = (int)s;
}
}
for(int i=0; i<outH; i++){
for(int k=0; k<outH; k++){
if(outImage[i][k] > 255){
outImage[i][k] = 255;
}
if(outImage[i][k] < 0){
outImage[i][k] = 0;
}
}
}
break;
case "4" : //엠보싱
outH = inH;
outW = inW;
// (3) 알고리즘 적용하기
// (중요!) 출력 영상의 크기 결정 --> 알고리즘에 의존
//메모리 할당
outImage = new int[outH][outW];
// mask
double[][] mask2 = {{-1.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 1.0}};
// 임시 입력 배열
int temp[][] = new int[inH+2][inW+2];
// 임시 입력 배열 초기화
for(int i=0; i<inH+2; i++){
for(int k=0; k<inW+2; k++){
temp[i][k] = 127;
}
}
// 입력 배열 --> 임시 입력
for(int i=0; i<inH; i++){
for(int k=0; k<inW; k++){
temp[i+1][k+1] = inImage[i][k];
}
}
//회전 연산 알고리즘
for(int i=0; i<inH;i++){
for(int k=0; k<inW;k++){
double s=0;
for(int m=0; m<3; m++){
for(int n=0;n<3;n++){
s += mask2[m][n] * temp[i+m][k+n];
}
}
outImage[i][k] = (int)s;
}
}
for(int i=0; i<outH; i++){
for(int k=0; k<outH; k++){
if(outImage[i][k] > 255){
outImage[i][k] = 255;
}
if(outImage[i][k] < 0){
outImage[i][k] = 0;
}
}
}
break;
case "5" : //회전 백워딩
int degree = Integer.parseInt(parameter);
double radian = degree*Math.PI/180.0;
double value = Math.sin(radian) + Math.cos(radian);
//outW = (int)(inH*value);
//outH = (int)(inH*value);
outW = inW;
outH = inH;
outImage = new int[outH][outW];
// ***** 진짜 영상처리 알고리즘 ****
radian = -radian;
// 수식
// xd = cos * xs - sin * ys;
// yd = sin * xs + cos * ys;
int xd, yd, xs, ys;
//중앙값 구하기
int cx = inH / 2;
int cy = inW / 2;
for(int i=0; i<outH; i++) {
for (int k=0; k<outW; k++) {
xs = i;
ys = k;
xd = (int)(Math.cos(radian)*(xs-cy) - Math.sin(radian)*(ys-cy) + cx);
yd = (int)(Math.sin(radian)*(xs-cy) + Math.cos(radian)*(ys-cy) + cx);
// 회전 이후의 위치가 출력영상의 범위 안에 있니?
if ((0<=xd && xd<inH ) && (0<=yd && yd<inW)){
outImage[xs][ys] = inImage[xd][yd];
}
else{
outImage[xs][ys] = 255;
}
}
}
break;
case "6" : // 좌우반전
outH = inH;
outW = inW;
//메모리 할당
outImage = new int[outH][outW];
for (int i=0; i<inH; i++){
for(int k=0; k<inW; k++){
outImage[i][k] = inImage[i][inW-1-k];
}
}
break;
case "7" : // 상하반전
outH = inH;
outW = inW;
//메모리 할당
outImage = new int[outH][outW];
for (int i=0; i<inH; i++){
for(int k=0; k<inW; k++){
outImage[i][k] = inImage[inH-1-i][k];
}
}
break;
case "8" : // 회전백워딩
// *** 히스토그램 생성
// 히스토그램 배열 생성
int[] histo = new int[256]; // 화소값 0 ~ 255
for(int i=0; i<256; i++) // 히스토그램 배열 0(개수)으로 초기화
histo[i] = 0;
for(int i=0; i<inH; i++) {
for(int k=0; k<inW; k++) {
int value1 = inImage[i][k];
histo[value1]++; // inImage배열에서 화소값마다 개수 알아내서 histo배열에 저장
}
}
// *** 히스토그램 정규화
int max = 0; // 최대값: 가장 작은 개수부터 시작
int min = inW*inH; // 최소값: 가장 큰 개수부터 시작
for(int i=0; i<256; i++) {
if(histo[i] < min)
min = histo[i];
if(histo[i] > max)
max = histo[i];
}
int dif = max - min;
// 히스토그램(정규화) 배열 생성
int[] normalHisto = new int[256];
for(int i=0; i<256; i++)
normalHisto[i] = (histo[i] - min)*255/dif; // 정규화식 적용
// *** 히스토그램 이미지로 출력
// 출력 배열 준비
outW = 256;
outH = 256;
outImage = new int[outH][outW];
for (int i = 0; i < outH; i++) {
for (int k = 0; k < outW; k++) {
outImage[i][k] = 255; // 출력 배열 255(흰색)으로 초기화
}
}
// 히스토그램 개수만큼 0(검정색)으로 값 넣기
for (int i = 0; i < outH; i++) {
for (int k = 0; k < normalHisto[i]; k++) {
outImage[255 - k][i] = 0;
}
}
break;
}
// (4) 결과를 파일로 쓰기
File outFp;
FileOutputStream outFs;
outFp = new File("c:/images/Out/" + name+".raw");
outFs = new FileOutputStream(outFp.getPath());
// 메모리 --> 파일
for (int i = 0; i < outH; i++) {
for (int k = 0; k < outW; k++) {
outFs.write(outImage[i][k]);
}
}
outFs.close();
out.println("c:/images/Out/" + name + " 처리됨~");
%>
</body>
</html>
반응형
LIST
'공부합시다 > 찍먹' 카테고리의 다른 글
[JSP - DB 연동하기] (2) DB 연동 (0) | 2021.05.03 |
---|---|
[JSP - DB 연동하기] (1) DB 설치 및 만들기 (0) | 2021.05.03 |
[JSP]영상처리 알고리즘 - 엠보싱 (0) | 2021.04.26 |
[JSP]영상처리 알고리즘 - 블러링 (0) | 2021.04.26 |
[Oracle DBMS] 데이터 활용하기 (0) | 2021.04.22 |
댓글