How to Build a Java Thumbnailer: Step-by-Step Guide with Code
Overview
A Java thumbnailer reads images, resizes them to a target size while preserving aspect ratio (optionally cropping), and writes the result in a chosen format. This guide builds a simple, efficient thumbnailer with a command-line interface, batch processing, and optional caching.
Features
- Preserve aspect ratio or center-crop to exact dimensions
- Choose output format (JPEG/PNG/WebP)
- Batch processing of a directory
- Multithreaded processing for speed
- Optional in-memory/LRU cache for repeated requests
Tools & libraries
- Java 17+ (recommended)
- Image I/O (javax.imageio)
- Thumbnail scaling: use imgscalr (simple) or TwelveMonkeys plugins for better format support
- Optional: webp-imageio or libwebp wrapper for WebP
- Build: Maven or Gradle
Project structure
- src/main/java/
- com.example.thumbnailer
- App.java (CLI entry)
- Thumbnailer.java (core logic)
- ImageUtils.java (helpers: read/write, format detection)
- WorkerPool.java (thread management)
- Cache.java (optional LRU cache)
- com.example.thumbnailer
- src/test/java/… (unit tests)
Key design choices
- Use BufferedImage and Graphics2D with high-quality rendering hints for quality resizing.
- For large images, read with subsampling to reduce memory use.
- Limit concurrent threads to number of CPU cores.
- Expose options: width, height, mode (fit/crop), output format, quality.
Step-by-step implementation
1) Maven dependencies (pom.xml)
xml
<dependencies> <dependency> <groupId>org.imgscalr</groupId> <artifactId>imgscalr-lib</artifactId> <version>4.2</version> </dependency> <dependency> <groupId>com.twelvemonkeys.imageio</groupId> <artifactId>imageio-jpeg</artifactId> <version>3.8.1</version> </dependency> </dependencies>
2) Core: Thumbnailer.java
java
package com.example.thumbnailer; import org.imgscalr.Scalr; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.; public class Thumbnailer { public enum Mode { FIT, CROP } public static void createThumbnail(File input, File output, int targetW, int targetH, Mode mode, String format, float quality) throws IOException { BufferedImage src = ImageIO.read(input); if (src == null) throw new IOException(“Unsupported image: “ + input); BufferedImage dst; if (mode == Mode.FIT) { dst = Scalr.resize(src, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.AUTOMATIC, targetW, targetH, Scalr.OP_ANTIALIAS); } else { BufferedImage resized = Scalr.resize(src, Scalr.Method.ULTRAQUALITY, Math.max(targetW, targetH)); int x = (resized.getWidth() - targetW) / 2; int y = (resized.getHeight() - targetH) / 2; dst = Scalr.crop(resized, x, y, targetW, targetH); } try (OutputStream os = new FileOutputStream(output)) { if (“jpg”.equalsIgnoreCase(format) || “jpeg”.equalsIgnoreCase(format)) { ImageUtils.writeJpeg(dst, os, quality); } else { ImageIO.write(dst, format, os); } } } }
3) Helper: ImageUtils.java (JPEG quality)
java
package com.example.thumbnailer; import javax.imageio.; import javax.imageio.stream.ImageOutputStream; import java.awt.image.BufferedImage; import java.io.; import java.util.Iterator; public class ImageUtils { public static void writeJpeg(BufferedImage image, OutputStream os, float quality) throws IOException { Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(“jpeg”); if (!writers.hasNext()) throw new IllegalStateException(“No JPEG writer”); ImageWriter writer = writers.next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(Math.max(0f, Math.min(1f, quality))); try (ImageOutputStream ios = ImageIO.createImageOutputStream(os)) { writer.setOutput(ios); writer.write(null, new IIOImage(image, null, null), param); writer.dispose(); } } }
4) CLI: App.java
”`java package com.example.thumbnailer;
import java.io.File; import java.util.concurrent.;
public class App { public static void main(String[] args) { // reasonable defaults int width = 200, height = 200; Thumbnailer.Mode mode = Thumbnailer.Mode.FIT; String
Leave a Reply
You must be logged in to post a comment.