Files
Application/src/main/java/workers/ScaleWorker.java
T
2017-01-17 13:57:53 +01:00

349 lines
11 KiB
Java

package workers;
import javafx.concurrent.Task;
import javafx.embed.swing.SwingFXUtils;
import model.SOMConfig;
import model.SOMImage;
import model.SOMLayout;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.io.File;
import java.io.IOException;
public class ScaleWorker extends Thread {
public static final int SOURCE = 0;
public static final int PREVIEW = 1;
public static final int THUMBNAIL = 2;
SOMConfig config = SOMConfig.getInstance();
public static SOMImage scale(SOMImage somImage1, final int type) {
final SOMImage somImage = somImage1;
Task task = new Task() {
@Override
protected SOMImage call() throws Exception {
// Do the scale work
return prepareandStart(somImage, type);
}
};
// open Thread
Thread thread = new Thread(task);
// start Thread
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//return the somImage1
return somImage1;
}
// Overload of scale() that lets you enter Arrays of Pictures
public static SOMImage[] scale(SOMImage[] somImages, int type) {
// loop through Array of SOMImages
for (SOMImage image : somImages) {
//update the image
image = scale(image, type);
}
// return the imagearray
return somImages;
}
private static SOMImage prepareandStart(SOMImage somImage, int type) {
// the image before scaling
// Image sourceImage;
// the image after scaling
// Image resultImage;
// type of image to be used to scale down
int source = SOURCE;
// check for scaled versions of the image
somImage.updateImageState();
// preview
if (type == PREVIEW) {
// check if the requested image already exists
if (somImage.isPrvthere())
// exit the scaler
return somImage;
// The requested image does not exist,
}
// thumbnail
if (type == THUMBNAIL) {
// check if the requested image already exists
if (somImage.isTmbthere()) {
return somImage;
}
// The requested image does not exist,
// check for Preview to scale faster
if (somImage.isPrvthere()) {
source = PREVIEW;
}
}
// In any other case we need to scale the
// full sized image, which is default
somImage = generateScaledImage(somImage, type, source);
return somImage;
}
private static SOMImage generateScaledImage(SOMImage somImage, int target, int source) {
// the source image size
double sourceWidth = 0;
double sourceHeight = 0;
// the scaled sources width and height
// before cropping
int scaledSourceHeight;
int scaledSourceWidth;
// the later image size
int targetWidth = 0;
int targetHeight = 0;
// Aspect ratio before cropping
double sourceAspect;
// The ImageViews' cropped aspect ratio
double targetAspect;
// Source File
File sourceFile = somImage.getSrc();
// Target File
File targetFile = null;
// ImageIcons
ImageIcon sourceImageIcon;
ImageIcon targetImageIcon;
// JAVAFX Images
javafx.scene.image.Image targetImage;
// Buffered Images
BufferedImage scaledSourceBufferedImage;
BufferedImage croppedBufferedImage;
// Graphics for Buffered Images
Graphics2D scaledSourceGraphics;
Graphics croppedGraphics;
// get the target IMAGE SIZES
// and the target FILE
switch (target) {
// for the preview
case PREVIEW:
targetWidth = SOMLayout.screenWidth;
targetHeight = SOMLayout.screenHeight;
targetFile = somImage.getPrv();
// for the Thumbnail
break;
case THUMBNAIL:
targetWidth = SOMLayout.getColumn(1);
targetHeight = SOMLayout.getRow(1);
targetFile = somImage.getTmb();
break;
}
// get the SOURCE FILE
switch (source) {
case SOURCE:
sourceFile = somImage.getSrc();
break;
case PREVIEW:
sourceFile = somImage.getPrv();
break;
}
switch (SOMConfig.SCALING_ALGORITHM) {
// GRAPHICS 2D ----------------------------------------------------------
case SOMConfig.SCALING_GRAPHICS_2D: {
// Generate an ImageIcon from the Source File
sourceImageIcon = new ImageIcon(sourceFile.getPath());
// the sources original width and height
sourceWidth = sourceImageIcon.getIconWidth();
sourceHeight = sourceImageIcon.getIconHeight();
// Calculate the aspect ratio before cropping
sourceAspect = (sourceWidth) / (sourceHeight);
// Calculate the ImageViews' cropped aspect ratio
targetAspect = ((double) targetWidth) / ((double) targetHeight);
// if picture is higher than frame
if (sourceAspect < targetAspect) {
scaledSourceHeight = (int) Math.ceil(targetWidth / sourceAspect);
scaledSourceWidth = targetWidth;
}
// if Picture is narrower (or equal)
else {
scaledSourceWidth = (int) Math.ceil(targetHeight * sourceAspect);
scaledSourceHeight = targetHeight;
}
// Probably way faster than ImageIcon
System.out.println("Scale with Graphics2D:");
// Print the File Path
System.out.println(sourceFile.toString());
// SCALE -----------------------------------------------------------
// THE -------------------------------------------------------------
// SOURCE ----------------------------------------------------------
// Get the ImageIcon
Image sourceImageIconImage = sourceImageIcon.getImage();
// Open a buffered Image in the specified size
// (with no data at this point --> black image)
scaledSourceBufferedImage = new BufferedImage(
scaledSourceWidth,
scaledSourceHeight,
BufferedImage.TYPE_INT_RGB
);
// Get the Graphics2D
scaledSourceGraphics = scaledSourceBufferedImage.createGraphics();
// Set the Rendering hints
scaledSourceGraphics.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR
);
// Actually Scale the Image
scaledSourceGraphics.drawImage(sourceImageIconImage, 0, 0, scaledSourceWidth, scaledSourceHeight, null);
scaledSourceGraphics.dispose();
// System Resources Released
// Calculate the Offsets
int wOffset;
int hOffset;
// CROP ------------------------------------------------------------
// THE -------------------------------------------------------------
// IMAGE -----------------------------------------------------------
if (sourceAspect > targetAspect) {
hOffset = 0;
wOffset = (scaledSourceWidth - targetWidth) / 2;
} else {
hOffset = (scaledSourceHeight - targetHeight) / 2;
wOffset = 0;
}
CropImageFilter cropimgf = new CropImageFilter(
// Crop by moving the image half the way
// it is wider to the left
wOffset,
// Crop by moving the image half the way
// it is higher to the top
hOffset,
targetWidth,
targetHeight
);
FilteredImageSource producer = new FilteredImageSource(
scaledSourceBufferedImage.getSource(),
cropimgf
);
Image image = Toolkit.getDefaultToolkit().createImage(
producer
);
targetImageIcon = new ImageIcon(
image
);
// save the smaller image
croppedBufferedImage = new BufferedImage(
targetWidth,
targetHeight,
BufferedImage.TYPE_INT_RGB
);
croppedGraphics = croppedBufferedImage.getGraphics();
croppedGraphics.drawImage(targetImageIcon.getImage(), 0, 0, null);
// WRITE ---------------------------------------------------------------
// THE -----------------------------------------------------------------
// IMAGE ---------------------------------------------------------------
writeJPEG(targetFile, croppedBufferedImage);
// UPDATE ---------------------------------------------------------------
// IMAGE ----------------------------------------------------------------
// STATE ----------------------------------------------------------------
somImage.updateImageState();
System.out.println("Image State Updated: Scaled");
// Clean up
croppedGraphics.dispose();
scaledSourceGraphics.dispose();
image.flush();
sourceImageIconImage.flush();
System.gc();
break;
}
// JAVAFX ----------------------------------------------------------
case SOMConfig.SCALING_JAVAFX: {
// Scale with javafx
// FIXME breaks up
targetImage = new javafx.scene.image.Image(sourceFile.toString(), targetWidth, targetHeight, true, false, true);
BufferedImage bi = SwingFXUtils.fromFXImage(targetImage, null);
writeJPEG(targetFile, bi);
somImage.updateImageState();
System.out.println("Image State Updated: Scaled");
somImage.updateImageState();
break;
}
}
return somImage;
}
private static void writeJPEG(File targetFile, BufferedImage bi) {
try {
boolean iw = ImageIO.write(bi, "JPEG", targetFile);
} catch (IOException e) {
e.printStackTrace();
}
}
}