코드 정리하다가 블로그에 정리되지 않은 코드가 있어 정리해 봅니다. 일반적인 이미지를 작은 이미지, 즉 썸네일 이미지로 만들어 주는 코드입니다. 이미지의 종횡비 크기를 유지하며 썸네일 이미지를 만들어 줍니다. 썸네일 이미지 만드는 코드를 실제 프로젝트에 붙이기 위해 만들다 보니, 부가적인 내용이 덧붙여 있으니 참고하시기 바랍니다.
사용은 아래처럼 하면 됩니다. 즉, d:/a.jpg 파일을 썸네일 이미지를 만드는데, 가로 또는 세로 크기 중 하나를 256을 만듭니다.
reateThumbnail("d:/a.jpg", 256);
아래는 d:/a.jpg의 실제 이미지입니다. 이미지 크기는 920×600입니다.
위의 이미지가 위의 코드를 통해 아래와 같이 d:/a.thumbnail.jpg 파일로 만들어지고 크기는 256×166이 됩니다. 원본 이미지의 가로 크기가 세로보다 길다보니 가로를 256으로 만들어지게 되는 것입니다.
createThumbnail 함수는 아래와 같습니다.
private static boolean createThumbnail(String fileName, int maxSize) { try { int thumbnail_width = maxSize; int thumbnail_height = maxSize; File origin_file_name = new File(fileName); String ext = getFileExt(fileName); String newFileName = fileName.replace("." + ext, ".thumbnail." + ext); BufferedImage buffer_original_image = ImageIO.read(origin_file_name); double imgWidth = buffer_original_image.getWidth(); double imgHeight = buffer_original_image.getHeight(); if(imgWidth < imgHeight) { thumbnail_width = (int)((imgWidth / imgHeight) * maxSize); } else { thumbnail_height = (int)((imgHeight / imgWidth) * maxSize); } int imgType = (buffer_original_image.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; BufferedImage buffer_thumbnail_image = new BufferedImage(thumbnail_width, thumbnail_height, imgType); Graphics2D graphic = buffer_thumbnail_image.createGraphics(); graphic.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); graphic.drawImage(buffer_original_image, 0, 0, thumbnail_width, thumbnail_height, null); if(ext.equalsIgnoreCase("jpg")) { writeJpeg(buffer_thumbnail_image, newFileName, 1.0f); } else { File thumb_file_name = new File(newFileName); ImageIO.write(buffer_thumbnail_image, ext.toLowerCase(), thumb_file_name); } graphic.dispose(); } catch (Exception e) { e.printStackTrace(System.err); return false; } return true; }
위의 함수는 2개의 내부 함수를 호출하고 있는데, 해당되는 함수들은 아래와 같습니다.
private static String getFileExt(String fileName) { // "abc.txt" -> "txt", not ".txt" int i = fileName.lastIndexOf('.'); int p = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\')); if (i > p) { return fileName.substring(i+1); } return null; } private static void writeJpeg(BufferedImage image, String destFile, float quality) throws IOException { ImageWriter writer = null; FileImageOutputStream output = null; try { writer = ImageIO.getImageWritersByFormatName("jpeg").next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); output = new FileImageOutputStream(new File(destFile)); writer.setOutput(output); IIOImage iioImage = new IIOImage(image, null, null); writer.write(null, iioImage, param); } catch (IOException ex) { throw ex; } finally { if (writer != null) { writer.dispose(); } if (output != null) { output.close(); } } }
단위 테스트로 만들어 놓은 코드인지라 최적화가 되어 있지 않으니, 살펴보시고 최적화 해 사용하시기 바랍니다.