/** * We compute a sampling ratio but we keep roughly samplingFactor^2 times more pixels so that after * rescaling quality is better than with sampling using maximal possible ratio. * We compute ratio for both width and height and than discard the one that could result in exceeding * memory expectations defined by samplingFactor. */ static public int computeSubsamplingRatio(final ThumbnailDimension original, final ThumbnailDimension scaled, final int samplingFactor) { final double widthRatio = (double) original.getWidth() / (double) scaled.getWidth(); final double heightRatio = (double) original.getHeight() / (double) scaled.getHeight(); final double maxRatio = Math.max(widthRatio, heightRatio); final double ratio = maxRatio / (double) samplingFactor; return Math.max(1, (int) Math.floor(ratio)); } }
private Thumbnail readThumbnail(@Nonnull final Attachment attachment, @Nonnull final File thumbnailFile) { if (thumbnailFile.exists()) { log.debug("Thumbnail file '{}' already exists. Returning existing thumbnail.", thumbnailFile); InputStream inputStream = null; try { inputStream = new FileInputStream(thumbnailFile); final ThumbnailDimension thumbnailDimension = ThumbnailUtil.dimensionsForImage(inputStream); return new Thumbnail(thumbnailDimension.getHeight(), thumbnailDimension.getWidth(), thumbnailFile.getName(), attachment.getId(), MIME_TYPE); } catch (IOException asd) { log.debug("Unable to read image data from existing thumbnail file '{}'. Deleting this thumbnail.", thumbnailFile); deleteQuietly(thumbnailFile); } finally { closeQuietly(inputStream); } } return null; }
public UploadedAvatar scaleImageToTempFile(final Image sourceImage, final File targetFile, final int edgeSize) throws IOException { ThumbnailDimension targetDimension = thumber.determineScaleSize(edgeSize, edgeSize, sourceImage.getWidth(null), sourceImage.getHeight(null)); BufferedImage scaledImage = thumber.scaleImage(sourceImage, targetDimension); ImageIO.write(scaledImage, AVATAR_IMAGE_FORMAT, targetFile); return new UploadedAvatar(targetFile, AVATAR_IMAGE_FORMAT_FULL.getContentType(), targetDimension.getWidth(), targetDimension.getHeight()); } }
/** * This method should take BufferedImage argument, but takes just Image for backward compatibility (so that the * client code can stay intact). Normally anyway a BufferedImage instance will be provided and the image will be * directly processed without transforming it to BufferedImage first. * * @param imageToScale image to scale (BufferedImage is welcome, other image types will be transformed to * BufferedImage first) * @param newDimensions desired max. dimensions * @return scaled image */ public BufferedImage scaleImage(Image imageToScale, ThumbnailDimension newDimensions) { final BufferedImage sourceImage = Pictures.toBufferedImage(imageToScale); final Image scaledInstance = sourceImage.getScaledInstance(newDimensions.getWidth(), newDimensions.getHeight(), Image.SCALE_SMOOTH); final BufferedImage bufferedScaledImage = new BufferedImage(newDimensions.getWidth(), newDimensions.getHeight(), Pictures.hasAlpha(imageToScale) ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); final Graphics graphics = bufferedScaledImage.getGraphics(); try { graphics.drawImage(scaledInstance, 0, 0, null); } finally { graphics.dispose(); } return bufferedScaledImage; }
private BufferedImage scaleImage(int maxWidth, int maxHeight, ImageInputStream imageInputStream) throws IOException { final Optional<ImageReader> imageReader = ThumbnailUtil.getFirstImageReader(imageInputStream); if (!imageReader.isPresent()) { throw new IOException("Cannot read the image"); } final ImageReader reader = imageReader.get(); try { reader.setInput(imageInputStream); final ThumbnailDimension originalImageDimensions = new ThumbnailDimension(reader.getWidth(0), reader.getHeight(0)); final ThumbnailDimension scaledImageDimension = ThumbnailUtil.determineScaledDimensions(maxWidth, maxHeight, originalImageDimensions.getWidth(), originalImageDimensions.getHeight()); final int ratio = ThumbnailUtil.computeSubsamplingRatio(originalImageDimensions, scaledImageDimension, samplingFactor); final ImageReadParam param = reader.getDefaultReadParam(); param.setSourceSubsampling(ratio, ratio, 0, 0); final BufferedImage scaledImage = reader.read(0, param); //Subsampling does not return an exact size of an image - we need to resize it return scaleImage(scaledImage, scaledImageDimension); } finally { reader.dispose(); } }