349 lines
11 KiB
Java
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();
|
|
}
|
|
}
|
|
}
|