273 lines
10 KiB
Java
273 lines
10 KiB
Java
package org.expkgzone58.image;
|
|
|
|
import static org.basex.query.QueryError.IOERR_X;
|
|
|
|
import java.awt.Dimension;
|
|
import java.awt.Font;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import org.basex.io.IOContent;
|
|
import org.basex.query.QueryException;
|
|
import org.basex.query.QueryModule;
|
|
//import org.basex.query.func.fn.FnTrace;
|
|
import org.basex.query.value.item.B64Stream;
|
|
import org.basex.query.value.item.Dbl;
|
|
import org.basex.query.value.item.Int;
|
|
import org.basex.query.value.node.ANode;
|
|
import org.basex.util.Token;
|
|
import org.basex.data.Data;
|
|
|
|
import net.coobird.thumbnailator.ThumbnailParameter;
|
|
import net.coobird.thumbnailator.Thumbnailator;
|
|
import net.coobird.thumbnailator.builders.ThumbnailParameterBuilder;
|
|
import net.coobird.thumbnailator.filters.Pipeline;
|
|
import net.coobird.thumbnailator.filters.Rotation;
|
|
import net.coobird.thumbnailator.filters.Watermark;
|
|
import net.coobird.thumbnailator.geometry.AbsoluteSize;
|
|
import net.coobird.thumbnailator.geometry.Position;
|
|
import net.coobird.thumbnailator.geometry.Positions;
|
|
import net.coobird.thumbnailator.geometry.Region;
|
|
import net.coobird.thumbnailator.tasks.StreamThumbnailTask;
|
|
import net.coobird.thumbnailator.filters.Canvas;
|
|
import net.coobird.thumbnailator.filters.Caption;
|
|
import net.coobird.thumbnailator.filters.Colorize;
|
|
import net.coobird.thumbnailator.filters.Flip;
|
|
import net.coobird.thumbnailator.filters.ImageFilter;
|
|
|
|
/*
|
|
* BaseX Thumbnailator interface
|
|
* @author andy bunce
|
|
* @copyright Quodatum Ltd
|
|
* @date 2017
|
|
* @licence Apache 2
|
|
*/
|
|
public class Thumbs extends QueryModule{
|
|
|
|
public B64Stream size(final B64Stream inputStream, final int width, final int height)
|
|
throws IOException, QueryException {
|
|
ByteArrayInputStream is = new ByteArrayInputStream(inputStream.binary(null));
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
ThumbnailParameterBuilder builder = new ThumbnailParameterBuilder();
|
|
builder.size(width, height);
|
|
StreamThumbnailTask task = new StreamThumbnailTask(builder.build(), is, os);
|
|
Thumbnailator.createThumbnail(task);
|
|
return new B64Stream(new IOContent(os.toByteArray()), IOERR_X);
|
|
}
|
|
|
|
public B64Stream scale(final B64Stream inputStream,
|
|
final double xscale, final double yscale)
|
|
throws IOException, QueryException {
|
|
ByteArrayInputStream is = new ByteArrayInputStream(inputStream.binary(null));
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
ThumbnailParameterBuilder builder = new ThumbnailParameterBuilder();
|
|
builder.scale(xscale, yscale);
|
|
StreamThumbnailTask task = new StreamThumbnailTask(builder.build(), is, os);
|
|
Thumbnailator.createThumbnail(task);
|
|
return new B64Stream(new IOContent(os.toByteArray()), IOERR_X);
|
|
}
|
|
|
|
public B64Stream task(final B64Stream inputStream, final ANode thumbnail)
|
|
throws IOException, QueryException {
|
|
ByteArrayInputStream is = new ByteArrayInputStream(inputStream.binary(null));
|
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
ThumbnailParameter param = fromNode(thumbnail);
|
|
StreamThumbnailTask task = new StreamThumbnailTask(param, is, os);
|
|
Thumbnailator.createThumbnail(task);
|
|
return new B64Stream(new IOContent(os.toByteArray()), IOERR_X);
|
|
}
|
|
|
|
// build parameters from XML
|
|
ThumbnailParameter fromNode(final ANode node) throws QueryException, IOException {
|
|
ThumbnailParameterBuilder builder = new ThumbnailParameterBuilder();
|
|
|
|
Iterator<ANode> itr = node.children().iterator();
|
|
while (itr.hasNext()) {
|
|
ANode element = itr.next();
|
|
if (element.kind() == Data.ELEM) {
|
|
String name = Token.string(element.name());
|
|
// FnTrace.trace(name.getBytes(), "element: ".getBytes(), queryContext);
|
|
switch (name) {
|
|
|
|
case "size":
|
|
size(builder, element);
|
|
break;
|
|
|
|
case "scale":
|
|
scale(builder, element);
|
|
break;
|
|
|
|
case "region":
|
|
region(builder, element);
|
|
break;
|
|
|
|
case "constrain":
|
|
constrain(builder, element);
|
|
break;
|
|
|
|
case "filters":
|
|
List<ImageFilter> filters = filters(element);
|
|
builder.filters(filters);
|
|
break;
|
|
|
|
case "output":
|
|
String format = Utils.attrib(element, "format",
|
|
ThumbnailParameter.ORIGINAL_FORMAT);
|
|
builder.format(format);
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return builder.build();
|
|
}
|
|
|
|
void region(final ThumbnailParameterBuilder builder, final ANode node)
|
|
throws QueryException {
|
|
|
|
int width = (int) Int.parse(node.attribute("width"), null);
|
|
int height = (int) Int.parse(node.attribute("height"), null);
|
|
Dimension d = new Dimension(width, height);
|
|
Position pos = Utils.position(node, "position", Positions.CENTER);
|
|
Region r = new Region(pos, new AbsoluteSize(d));
|
|
builder.region(r);
|
|
}
|
|
|
|
void constrain(final ThumbnailParameterBuilder builder, final ANode node)
|
|
throws QueryException {
|
|
|
|
boolean aspect = Utils.attrib(node, "aspect", true);
|
|
builder.keepAspectRatio(aspect);
|
|
// FnTrace.trace(Boolean.toString(aspect).getBytes(), "constrain: ".getBytes(), queryContext);
|
|
boolean exif = Utils.attrib(node, "exif", true);
|
|
builder.useExifOrientation(exif);
|
|
|
|
boolean fit = Utils.attrib(node, "fit", true);
|
|
builder.fitWithinDimensions(fit);
|
|
}
|
|
|
|
void size(final ThumbnailParameterBuilder builder, final ANode node)
|
|
throws QueryException {
|
|
int width = (int) Int.parse(node.attribute("width"), null);
|
|
int height = (int) Int.parse(node.attribute("height"), null);
|
|
builder.size(width, height);
|
|
}
|
|
|
|
void scale(final ThumbnailParameterBuilder builder, final ANode node)
|
|
throws QueryException {
|
|
double x = Utils.attrib(node, "x", 0.5f);
|
|
double y = Utils.attrib(node, "y", 0.5f);
|
|
builder.scale(x, y);
|
|
}
|
|
|
|
List<ImageFilter> filters(final ANode filters) throws QueryException, IOException {
|
|
Pipeline pipeline = new Pipeline();
|
|
Iterator<ANode> itr = filters.children().iterator();
|
|
while (itr.hasNext()) {
|
|
ANode node = itr.next();
|
|
if (node.kind() == Data.ELEM) {
|
|
switch (Token.string(node.name())) {
|
|
|
|
case "canvas": // @width @height @color @position
|
|
canvas(pipeline, node);
|
|
break;
|
|
|
|
case "caption": //@color @position text()
|
|
caption(pipeline, node);
|
|
break;
|
|
|
|
case "colorize": //@color @alpha
|
|
colorize(pipeline, node);
|
|
break;
|
|
|
|
case "flip": //@axis
|
|
flip(pipeline, node);
|
|
break;
|
|
|
|
case "rotate": //@angle
|
|
rotate(pipeline, node);
|
|
break;
|
|
|
|
case "watermark": //@src @alpha @position
|
|
watermark(pipeline, node);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return pipeline.getFilters();
|
|
}
|
|
|
|
private void watermark(final Pipeline pipeline, final ANode node)
|
|
throws IOException, QueryException {
|
|
ImageFilter filter;
|
|
Position pos;
|
|
String src = Token.string(node.attribute("src"));
|
|
pos = Utils.position(node, "position", Positions.BOTTOM_RIGHT);
|
|
BufferedImage watermarkImg = ImageIO.read(new File(src));
|
|
filter = new Watermark(pos, watermarkImg, Utils.attrib(node, "alpha", 0.5f));
|
|
pipeline.add(filter);
|
|
}
|
|
|
|
private void rotate(final Pipeline pipeline, final ANode node)
|
|
throws QueryException {
|
|
double angle = (double) Dbl.parse(node.attribute("angle"), null);
|
|
pipeline.add(Rotation.newRotator(angle));
|
|
}
|
|
|
|
private void flip(final Pipeline pipeline, final ANode node) {
|
|
ImageFilter filter;
|
|
String axis = Token.string(node.attribute("axis"));
|
|
// FnTrace.trace(axis.getBytes(), "FLIP: ".getBytes(), queryContext);
|
|
filter = axis.equalsIgnoreCase("vertical") ? Flip.VERTICAL : Flip.HORIZONTAL;
|
|
pipeline.add(filter);
|
|
}
|
|
|
|
private void colorize(final Pipeline pipeline, final ANode node) throws QueryException {
|
|
ImageFilter filter;
|
|
String color;
|
|
color = Utils.attrib(node, "color", "black");
|
|
filter = new Colorize(Utils.stringToColor(color),
|
|
Utils.attrib(node, "alpha", 0.0f));
|
|
pipeline.add(filter);
|
|
}
|
|
|
|
private void canvas(final Pipeline pipeline, final ANode node) throws QueryException {
|
|
ImageFilter filter;
|
|
String color;
|
|
Position pos;
|
|
int width = (int) Int.parse(node.attribute("width"), null);
|
|
int height = (int) Int.parse(node.attribute("height"), null);
|
|
color = Utils.attrib(node, "color", "black");
|
|
pos = Utils.position(node, "position", Positions.CENTER);
|
|
filter = new Canvas(width, height, pos, false, Utils.stringToColor(color));
|
|
pipeline.add(filter);
|
|
}
|
|
|
|
private void caption(final Pipeline pipeline, final ANode node) throws QueryException {
|
|
ImageFilter filter;
|
|
String color;
|
|
Position pos;
|
|
String text = Token.string(node.string());
|
|
color = Utils.attrib(node, "color", "black");
|
|
pos = Utils.position(node, "position", Positions.TOP_CENTER);
|
|
String fontName = Utils.attrib(node, "font", "SansSerif");
|
|
int size = Utils.attrib(node, "size", 14);
|
|
int insets = Utils.attrib(node, "insets", 0);
|
|
Font font = new Font(fontName, Font.PLAIN, size);
|
|
filter = new Caption(text, font , Utils.stringToColor(color),
|
|
pos, insets);
|
|
pipeline.add(filter);
|
|
}
|
|
}
|