Java ImageWriter사용하기
필자는 마우스입력기의 보안솔루션을 개발하면서 일부 고객사에서 이미지IO와 관련하여 응답시간이 오래 걸린다는 보고가 되었습니다. 딱히 오류 결과만 보면 문제될 만한 부분이 없는데 문제가 발생하니 방안도 적절하지 못하였습니다. Java를 이용하여 이미지 결과물을 만들어 낼 때 ImageIO.write()를 사용하면 속도가 저하되는 문제가 발생하였습니다. 또한 ImageIO.write()는 Thread Safe하지 않다고 검색된 내용도 있었습니다.
// 이미지 합성
OutputStream os = null;
try {
BufferedImage bi = keypad.getImage();
out.clear(); // Response값을 초기화합니다.
response.setContentType("image/png"); // 마임타입을 지정합니다.
os = response.getOutputStream(); // HttpServletResponse의 Stream객체를 얻습니다.
ImageIO.write( bi , "png" , os ); // PNG 이미지를 생성합니다.
os.flush(); // Stream에 값을 모두 내보냅니다.
} catch (Exception e) {
e.printStackTrace();
} finally {
if(os != null) try{os.close();}catch(Exception e){}
}
이에 아래와 같이 이미지 IO를 ImageWriter를 사용하는 방법으로 변경하였습니다. 얼마 되지는 않았지만 아직 같은 오류보고가 되지는 않고 있습니다. 이번 오류를 수정하면서 HttpServletResponse에 직접 write하지 않고 byte배열을 통해 이미지 바이어리를 생성하고 그 byte 배열을 Response에 쓰는 방식으로 변경하였습니다.
// 이미지 합성
OutputStream os = null;
try {
BufferedImage bi = keypad.getImage();
out.clear(); // Response값을 초기화합니다.
response.setContentType("image/png"); // 마임타입을 지정합니다.
// Byte Array Stream 을 생성합니다.
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
MemoryCacheImageOutputStream outputStream = new MemoryCacheImageOutputStream(byteArrayOutputStream);
// ImageWriter를 png포맷으로 생성합니다.
Iterator iter = ImageIO.getImageWritersByFormatName("png");
ImageWriter writer = (ImageWriter) iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
//iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
//iwp.setCompressionQuality(IMAGE_QUALITY);
// 출력될 Stream을 지정합니다.
writer.setOutput(outputStream);
// ImageWriter를 통해 이미지를 생성합니다.
IIOImage image = new IIOImage(bi, null, null);
writer.write(null, image, iwp);
writer.dispose();
// byte[] 배열로 변환합니다.
byte[] result = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
outputStream.close();
os = response.getOutputStream(); // HttpServletResponse의 Stream객체를 얻습니다.
os.write(result); // byte[]을 Stream에 write합니다.
os.flush(); // Stream에 값을 모두 내보냅니다.
} catch (Exception e) {
e.printStackTrace();
} finally {
if(os != null) try{os.close();}catch(Exception e){}
}
붙임글
개발하고 있는 솔루션에서 이미지합성 라이브러리를 추가적으로 고민하였습니다. 하지만 단일한 jar을 제공하기 위해서 일단 이미지 합성을 위한 다른 라이브러리는 고려하지 않았습니다. Apache Imaging 라이브러리나 JDeli Image 라이브러리를 사용하는 것도 다른 방법 중 하나로 생각됩니다.
참고자료
www.programcreek.com/java-api-examples/?api=javax.imageio.ImageWriter
www.programcreek.com/java-api-examples/?api=javax.imageio.stream.MemoryCacheImageOutputStream
blog.idrsolutions.com/2014/10/imageio-write-executorservice-io-bound-applications-java/
'Tips, Tricks > Java, Spring Framework' 카테고리의 다른 글
Find links from a web page(웹페이지에서 링크 찾기) (0) | 2020.12.10 |
---|---|
Create a File Hash in Java(자바로 파일 해쉬 만들기) (0) | 2020.11.13 |
Spring Boot 프로젝트에 외부 jar 추가 방법(method of including external jar on spring boot maven project) (2) | 2020.04.23 |
TCP Socket Forwarding(Tunneling) by Java Socket (0) | 2020.02.18 |
Spring Boot - MyBatis, 다중 Database 연결 (0) | 2020.02.13 |