task interface and java helper

This commit is contained in:
Andy Bunce 2017-04-21 14:48:37 +01:00
parent 20dd832c82
commit 57f3c1eee7
35 changed files with 793 additions and 251 deletions

12
.classpath Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="C:/Program Files (x86)/BaseX/BaseX.jar" sourcepath="/basex-core/src"/>
<classpathentry kind="lib" path="src/main/content/thumbnailator-0.4.8.jar"/>
<classpathentry kind="output" path="build/classes"/>
</classpath>

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build/

View File

@ -5,7 +5,25 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>net.sf.eclipsecs.core.CheckstyleBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>net.sf.eclipsecs.core.CheckstyleNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="java" version="1.7"/>
</faceted-project>

10
catalog.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog PUBLIC "-//OASIS//DTD XML Catalogs V1.1//EN" "http://www.oasis-open.org/committees/entity/release/1.1/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<!-- catalog entry for all notes -->
<rewriteURI
uriStartString="expkg-zone58:image.thumbnailator/schema/"
rewritePrefix="./src/content/"/>
</catalog>

View File

@ -1,37 +1,36 @@
<xqdoc:xqdoc xmlns:xqdoc="http://www.xqdoc.org/1.0">
<xqdoc:control>
<xqdoc:date>2016-04-16T22:19:53.356+01:00</xqdoc:date>
<xqdoc:date>2017-04-21T14:41:43.648+01:00</xqdoc:date>
<xqdoc:version>1.1</xqdoc:version>
</xqdoc:control>
<xqdoc:module type="library">
<xqdoc:uri>expkg-zone58.image.thumbnailator</xqdoc:uri>
<xqdoc:uri>expkg-zone58:image.thumbnailator</xqdoc:uri>
<xqdoc:name>thumbnailator.xqm</xqdoc:name>
<xqdoc:comment>
<xqdoc:description>Generate thumbnails using http://code.google.com/p/thumbnailator/</xqdoc:description>
<xqdoc:description>Generate image thumbnails using the thumbnailator library.</xqdoc:description>
<xqdoc:see>https://github.com/coobird/thumbnailator</xqdoc:see>
<xqdoc:author>andy bunce</xqdoc:author>
<xqdoc:version>4.4.1</xqdoc:version>
</xqdoc:comment>
</xqdoc:module>
<xqdoc:namespaces>
<xqdoc:namespace prefix="thumbnails" uri="expkg-zone58.image.thumbnailator"/>
<xqdoc:namespace prefix="File" uri="java:java.io.File"/>
<xqdoc:namespace prefix="Thumbnailator" uri="java:net.coobird.thumbnailator.Thumbnailator"/>
<xqdoc:namespace prefix="BufferedImageBuilder" uri="java:net.coobird.thumbnailator.builders.BufferedImageBuilder"/>
<xqdoc:namespace prefix="Builder" uri="java:net.coobird.thumbnailator.Thumbnails$Builder"/>
<xqdoc:namespace prefix="thumbnails" uri="expkg-zone58:image.thumbnailator"/>
</xqdoc:namespaces>
<xqdoc:imports/>
<xqdoc:variables/>
<xqdoc:functions>
<xqdoc:function arity="4">
<xqdoc:name>sourceRegion</xqdoc:name>
<xqdoc:signature>declare function sourceRegion($x as xs:integer, $y as xs:integer, $width as xs:integer, $height as xs:integer) as item()*</xqdoc:signature>
<xqdoc:function arity="3">
<xqdoc:comment>
<xqdoc:description>generate scaled version of source image with maximum dimension of size</xqdoc:description>
<xqdoc:param>$source base64Binary (streamed?) e.g from `fetch:binary`</xqdoc:param>
<xqdoc:custom tag="result">base64Binary for thumbnail</xqdoc:custom>
</xqdoc:comment>
<xqdoc:name>thumbnails:size</xqdoc:name>
<xqdoc:signature>declare function thumbnails:size($source as xs:base64Binary, $width as xs:integer, $height as xs:integer) as xs:base64Binary</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>x</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>y</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
<xqdoc:name>source</xqdoc:name>
<xqdoc:type>xs:base64Binary</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>width</xqdoc:name>
@ -43,53 +42,74 @@
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
<xqdoc:type>xs:base64Binary</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
<xqdoc:function arity="3">
<xqdoc:name>size</xqdoc:name>
<xqdoc:signature>declare function size($builder as item()*, $width as xs:int, $height as xs:int) as item()*</xqdoc:signature>
<xqdoc:comment>
<xqdoc:description>generate scaled version of source image at given factors 0-1</xqdoc:description>
<xqdoc:param>$source base64Binary (streamed?) e.g from `fetch:binary`</xqdoc:param>
<xqdoc:custom tag="result">base64Binary for thumbnail</xqdoc:custom>
</xqdoc:comment>
<xqdoc:name>thumbnails:scale</xqdoc:name>
<xqdoc:signature>declare function thumbnails:scale($source as xs:base64Binary, $xscale as xs:float, $yscale as xs:float) as xs:base64Binary</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>builder</xqdoc:name>
<xqdoc:type occurrence="*">item()</xqdoc:type>
<xqdoc:name>source</xqdoc:name>
<xqdoc:type>xs:base64Binary</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>width</xqdoc:name>
<xqdoc:type>xs:int</xqdoc:type>
<xqdoc:name>xscale</xqdoc:name>
<xqdoc:type>xs:float</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>height</xqdoc:name>
<xqdoc:type>xs:int</xqdoc:type>
<xqdoc:name>yscale</xqdoc:name>
<xqdoc:type>xs:float</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
<xqdoc:type>xs:base64Binary</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
<xqdoc:function arity="4">
<xqdoc:name>create-thumbnail</xqdoc:name>
<xqdoc:signature>declare function create-thumbnail($src as xs:string, $dest as xs:string, $width as xs:integer, $height as xs:integer) as item()*</xqdoc:signature>
<xqdoc:function arity="2">
<xqdoc:comment>
<xqdoc:description>generate thumbnail using parameters specified via XML</xqdoc:description>
<xqdoc:param>$source base64Binary (streamed?) e.g from `fetch:binary`</xqdoc:param>
<xqdoc:param>$task XML parameters &lt;task&gt;&lt;size width="100" ..</xqdoc:param>
<xqdoc:custom tag="result">base64Binary for thumbnail</xqdoc:custom>
</xqdoc:comment>
<xqdoc:name>thumbnails:task</xqdoc:name>
<xqdoc:signature>declare function thumbnails:task($source as xs:base64Binary, $task as element(task)) as xs:base64Binary</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>source</xqdoc:name>
<xqdoc:type>xs:base64Binary</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>task</xqdoc:name>
<xqdoc:type>element(task)</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type>xs:base64Binary</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
<xqdoc:function arity="1">
<xqdoc:comment>
<xqdoc:description>validate task XML against schema</xqdoc:description>
<xqdoc:param>$src XML parameters &lt;task&gt;&lt;size width="100" ..</xqdoc:param>
<xqdoc:custom tag="result">validation report</xqdoc:custom>
</xqdoc:comment>
<xqdoc:name>thumbnails:validation-report</xqdoc:name>
<xqdoc:signature>declare function thumbnails:validation-report($src as item()*) as element(report)</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>src</xqdoc:name>
<xqdoc:type>xs:string</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>dest</xqdoc:name>
<xqdoc:type>xs:string</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>width</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>height</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
<xqdoc:type occurrence="*">item()</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
<xqdoc:type>element(report)</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
</xqdoc:functions>

108
dist/xqdoc.xml vendored
View File

@ -1,108 +0,0 @@
<xqdoc:xqdoc xmlns:xqdoc="http://www.xqdoc.org/1.0">
<xqdoc:control>
<xqdoc:date>2013-08-04T23:31:57.796+01:00</xqdoc:date>
<xqdoc:version>1.1</xqdoc:version>
</xqdoc:control>
<xqdoc:module type="library">
<xqdoc:uri>apb.image.thumbnailator</xqdoc:uri>
<xqdoc:name>thumbnailator.xqm</xqdoc:name>
<xqdoc:comment>
<xqdoc:description>Generate thumbnails using http://code.google.com/p/thumbnailator/</xqdoc:description>
<xqdoc:author>andy bunce</xqdoc:author>
</xqdoc:comment>
</xqdoc:module>
<xqdoc:namespaces>
<xqdoc:namespace prefix="thumbnails" uri="apb.image.thumbnailator"/>
<xqdoc:namespace prefix="File" uri="java:java.io.File"/>
<xqdoc:namespace prefix="Thumbnailator" uri="java:net.coobird.thumbnailator.Thumbnailator"/>
<xqdoc:namespace prefix="BufferedImageBuilder" uri="java:net.coobird.thumbnailator.builders.BufferedImageBuilder"/>
<xqdoc:namespace prefix="Builder" uri="java:net.coobird.thumbnailator.Thumbnails$Builder"/>
</xqdoc:namespaces>
<xqdoc:imports/>
<xqdoc:variables/>
<xqdoc:functions>
<xqdoc:function arity="1">
<xqdoc:name>fromFilenames</xqdoc:name>
<xqdoc:signature>declare function fromFilenames($file as xs:string)</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>file</xqdoc:name>
<xqdoc:type>xs:string</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
<xqdoc:function arity="4">
<xqdoc:name>sourceRegion</xqdoc:name>
<xqdoc:signature>declare function sourceRegion($x as xs:integer, $y as xs:integer, $width as xs:integer, $height as xs:integer)</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>x</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>y</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>width</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>height</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
<xqdoc:function arity="3">
<xqdoc:name>size</xqdoc:name>
<xqdoc:signature>declare function size($builder, $width as xs:int, $height as xs:int)</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>builder</xqdoc:name>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>width</xqdoc:name>
<xqdoc:type>xs:int</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>height</xqdoc:name>
<xqdoc:type>xs:int</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
<xqdoc:function arity="4">
<xqdoc:name>make</xqdoc:name>
<xqdoc:signature>declare function make($src as xs:string, $dest as xs:string, $width as xs:integer, $height as xs:integer)</xqdoc:signature>
<xqdoc:parameters>
<xqdoc:parameter>
<xqdoc:name>src</xqdoc:name>
<xqdoc:type>xs:string</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>dest</xqdoc:name>
<xqdoc:type>xs:string</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>width</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
<xqdoc:parameter>
<xqdoc:name>height</xqdoc:name>
<xqdoc:type>xs:integer</xqdoc:type>
</xqdoc:parameter>
</xqdoc:parameters>
<xqdoc:return>
<xqdoc:type occurrence="*">item()</xqdoc:type>
</xqdoc:return>
</xqdoc:function>
</xqdoc:functions>
</xqdoc:xqdoc>

16
makejar.jardesc Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
<jardesc>
<jar path="ex-thumbnailator/src/main/content/thumbhelper-0.4.17.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ex-thumbnailator/makejar.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="true" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/>
<manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
<sealing sealJar="false">
<packagesToSeal/>
<packagesToUnSeal/>
</sealing>
</manifest>
<selectedElements exportClassFiles="true" exportJavaFiles="true" exportOutputFolder="false">
<javaElement handleIdentifier="=ex-thumbnailator/src\/java"/>
</selectedElements>
</jardesc>

View File

@ -1,7 +1,7 @@
<!-- @see http://cxan.org/faq#add-pkg -->
<repo abbrev="ex-thumbnailator">
<pkg abbrev="ex-thumbnailator" id="expkg-zone58.image.thumbnailator">
<name>expkg-zone58.image.thumbnailator</name>
<pkg abbrev="ex-thumbnailator" id="https://github.com/expkg-zone58/ex-thumbnailator">
<name>https://github.com/expkg-zone58/ex-thumbnailator</name>
<abstract>Create a thumbnail from a file path.</abstract>
<author id="coobird">coobird</author>
<maintainer id="abunce">Andy Bunce</maintainer>
@ -10,11 +10,7 @@
<tag>image</tag>
<tag>resize</tag>
<tag>graphic</tag>
<version num="2.0.0">
<dependency processor="basex"/>
<file name="ex-dotml-0.0.5.xar" role="pkg"/>
</version>
<version num="2.0.1">
<version num="4.1.4">
<!-- generated: {fn:current-dateTime()} -->
</version>
</pkg>

View File

@ -1,25 +1,51 @@
# expkg-zone58.image.thumbnailator
An XQuery interface to the thumbnail generator library
[thumbnailator](https://github.com/coobird/thumbnailator)
[thumbnailator](https://github.com/coobird/thumbnailator).
Tested against BaseX 8.4.3.
Tested against BaseX 8.6.2
# Installation
## Usage
### Simple
```xquery
import module namespace t="expkg-zone58:image.thumbnailator";
fetch:binary("http://images.metmuseum.org/CRDImages/ep/original/DT46.jpg")
=>t:scale(80,60)
```
### Tasks
This function takes an XML description of the operations to apply to generate the thumbnail.
```xml
<thumbnail>
<size width="500" height="500"/>
<filters>
<colorize color="green" alpha=".5"/>
<caption position="CENTER">Some Text here</caption>
<rotate angle="15"/>
<canvas height="500" width="500" position="TOP_LEFT" color="black"/>
<watermark src="{$watermark}" alpha=".5" position="TOP_LEFT"/>
</filters>
</thumbnail>
```
A schema is provided.
## Installation
The library is packaged in the [EXpath](http://expath.org/spec/pkg) xar format with
the thumbnailator jar included. It can be installed into the BaseX repository by
executing the command:
````
repo:install('https://github.com/expkg-zone58/ex-thumbnailator/dist/thumbnailator.zar')
````
# Usage
````
import module namespace t="expkg-zone58.image.thumbnailator";
t:create-thumbnail("/tmp/pic.jpg","/tmp/small.jpg",120,120)
````
the thumbnailator jar included. See releases for installation instructions.
# Tests
`test.xqm` script uses the BaseX [Unit module](http://docs.basex.org/wiki/Unit_Module)
## License
* ex-thumbnailator Copyright (c) 2017, Andy Bunce. (Apache 2 License).
* thumbnailator Copyright (c) Chris Kroells (MIT License).
# todo
explore java binding limits and fluent interface
scale sourceregion

View File

@ -0,0 +1,256 @@
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.Position;
import net.coobird.thumbnailator.geometry.Positions;
import net.coobird.thumbnailator.geometry.Region;
import net.coobird.thumbnailator.geometry.Size;
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 static 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(new Dimension(width, height));
StreamThumbnailTask task = new StreamThumbnailTask(builder.build(), is, os);
Thumbnailator.createThumbnail(task);
return new B64Stream(new IOContent(os.toByteArray()), IOERR_X);
}
public static 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 static 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
static 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());
switch (name) {
case "size":
size(builder, element);
break;
case "scale":
scale(builder, element);
break;
case "region":
region(builder, element);
break;
case "exif-orientation":
exif(builder, element);
break;
case "filters":
List<ImageFilter> filters = filters(element);
builder.filters(filters);
break;
default:
break;
}
}
}
return builder.build();
}
static 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, (Size) d);
builder.region(r);
}
static void exif(final ThumbnailParameterBuilder builder, final ANode node)
throws QueryException {
boolean use = Utils.attrib(node, "use", true);
builder.useExifOrientation(use);
}
static 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);
}
static 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);
}
static 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 static 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 static 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 static 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 static 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 static 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 static 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);
Font font = new Font(fontName, Font.PLAIN, size);
filter = new Caption(text, font , Utils.stringToColor(color),
pos, 0);
pipeline.add(filter);
}
}

View File

@ -0,0 +1,71 @@
package org.expkgzone58.image;
import java.awt.Color;
import java.lang.reflect.Field;
import org.basex.query.QueryException;
import org.basex.query.value.item.Bln;
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 net.coobird.thumbnailator.geometry.Position;
import net.coobird.thumbnailator.geometry.Positions;
public final class Utils {
private Utils() {
};
// get value from attribute with default
public static String attrib(final ANode element, final String name, final String def)
throws QueryException {
byte[] at = element.attribute(name);
return (at == null) ? def : Token.string(at);
}
public static float attrib(final ANode element, final String name, final float def)
throws QueryException {
byte[] at = element.attribute(name);
return (at == null) ? def : (float) Dbl.parse(at, null);
}
public static int attrib(final ANode element, final String name, final int def)
throws QueryException {
byte[] at = element.attribute(name);
return (at == null) ? def : (int) Int.parse(at, null);
}
public static boolean attrib(final ANode element, final String name, final boolean def)
throws QueryException {
byte[] at = element.attribute(name);
return (at == null) ? def : (boolean) Bln.parse(at, null);
}
// e.g. TOP_LEFT
public static Position position(final ANode element, final String name, final Position def) {
byte[] at = element.attribute(name);
return (at == null) ? def : Positions.valueOf(Token.string(at));
}
public static Color stringToColor(final String value) {
if (value == null) {
return Color.black;
}
try {
// get color by hex or octal value
return Color.decode(value);
} catch (NumberFormatException nfe) {
// if we can't decode lets try to get it by name
try {
// try to get a color by name using reflection
final Field f = Color.class.getField(value);
return (Color) f.get(null);
} catch (Exception ce) {
// if we can't get any color return black
return Color.black;
}
}
}
}

View File

@ -1,4 +1,5 @@
<package xmlns="http://www.basex.org/modules/pkg">
<jar>thumbhelper-0.4.17.jar</jar>
<jar>thumbnailator-0.4.8.jar</jar>
<class>net.coobird.thumbnailator.Thumbnails</class>
<class>org.expkgzone58.image.Thumbs</class>
</package>

133
src/main/content/task.xsd Normal file
View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- thumbnail schema apb apr 2017 -->
<xs:element name="thumbnail">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element ref="size" />
<xs:element ref="scale" />
</xs:choice>
<xs:element ref="region" minOccurs="0" />
<xs:element ref="exif-orientation" minOccurs="0" />
<xs:element ref="filters" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="size">
<xs:complexType>
<xs:attribute name="width" type="xs:int" />
<xs:attribute name="height" type="xs:int" />
</xs:complexType>
</xs:element>
<xs:element name="scale">
<xs:complexType>
<xs:attribute name="x" type="xs:double" />
<xs:attribute name="y" type="xs:double" />
</xs:complexType>
</xs:element>
<xs:element name="region">
<xs:complexType>
<xs:attribute name="height" type="xs:int" />
<xs:attribute name="width" type="xs:int" />
<xs:attribute name="position" type="PositionType" />
</xs:complexType>
</xs:element>
<xs:element name="exif-orientation">
<xs:complexType>
<xs:attribute name="use" type="xs:boolean" />
</xs:complexType>
</xs:element>
<xs:element name="filters">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element ref="canvas" minOccurs="0" />
<xs:element ref="caption" minOccurs="0" />
<xs:element ref="colorize" minOccurs="0" />
<xs:element ref="flip" minOccurs="0" />
<xs:element ref="rotate" minOccurs="0" />
<xs:element ref="watermark" minOccurs="0" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="canvas">
<xs:complexType>
<xs:attribute name="height" type="xs:int" />
<xs:attribute name="width" type="xs:int" />
<xs:attribute name="color" type="xs:string" />
<xs:attribute name="position" type="PositionType" />
</xs:complexType>
</xs:element>
<xs:element name="colorize">
<xs:complexType>
<xs:attribute name="color" type="xs:string" />
<xs:attribute name="alpha" type="xs:float" />
</xs:complexType>
</xs:element>
<xs:element name="caption">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="size" type="xs:int" />
<xs:attribute name="font" type="xs:string" />
<xs:attribute name="color" type="xs:string" />
<xs:attribute name="position" type="PositionType" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="flip">
<xs:complexType>
<xs:attribute name="axis" type="AxisType" />
</xs:complexType>
</xs:element>
<xs:element name="rotate">
<xs:complexType>
<xs:attribute name="angle" type="xs:float" />
</xs:complexType>
</xs:element>
<xs:element name="watermark">
<xs:complexType>
<xs:attribute name="src" type="xs:string" />
<xs:attribute name="position" type="PositionType" />
<xs:attribute name="alpha" type="xs:float" />
</xs:complexType>
</xs:element>
<xs:simpleType name="AxisType">
<xs:restriction base="xs:string">
<xs:enumeration value="horizontal" />
<xs:enumeration value="vertical" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PositionType">
<xs:restriction base="xs:string">
<xs:enumeration value="TOP_LEFT" />
<xs:enumeration value="TOP_CENTER" />
<xs:enumeration value="TOP_RIGHT" />
<xs:enumeration value="MIDDLE_LEFT" />
<xs:enumeration value="CENTER" />
<xs:enumeration value="MIDDLE_RIGHT" />
<xs:enumeration value="BOTTOM_LEFT" />
<xs:enumeration value="BOTTOM_CENTER" />
<xs:enumeration value="BOTTOM_RIGHT" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

Binary file not shown.

View File

@ -1,40 +1,52 @@
xquery version "3.0" encoding "UTF-8";
(:~ Generate thumbnails using http://code.google.com/p/thumbnailator/
xquery version "3.1" encoding "UTF-8";
(:~ Generate image thumbnails using the thumbnailator library.
: @see https://github.com/coobird/thumbnailator
: @author andy bunce
: @version 4.4.1
:)
module namespace thumbnails = 'expkg-zone58.image.thumbnailator';
declare default function namespace 'expkg-zone58.image.thumbnailator';
module namespace thumbnails = 'expkg-zone58:image.thumbnailator';
declare namespace File="java:java.io.File";
declare namespace Thumbnailator="java:net.coobird.thumbnailator.Thumbnailator";
declare namespace BufferedImageBuilder="java:net.coobird.thumbnailator.builders.BufferedImageBuilder";
declare namespace Builder="java:net.coobird.thumbnailator.Thumbnails$Builder";
(:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(640, 480)
.outputFormat("jpg")
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
:)
(: declare function fromFilenames($file as xs:string){
let $a:=File:new(file:path-to-native($file))
return Builder:of(($a,$a))
}; :)
declare function sourceRegion($x as xs:integer,$y as xs:integer,
$width as xs:integer,$height as xs:integer){
Builder:sourceRegion(xs:int($x),xs:int($y),xs:int($width),xs:int($height))
};
declare function size($builder,$width as xs:int,$height as xs:int){
BufferedImageBuilder:size($builder,$width,$height)
};
declare function create-thumbnail($src as xs:string,
$dest as xs:string,
$width as xs:integer,
$height as xs:integer){
let $src:=File:new(file:resolve-path($src))
let $dest:=File:new(file:resolve-path($dest))
return Thumbnailator:createThumbnail($src,$dest,xs:int($width),xs:int($height))
(:~
: generate scaled version of source image with maximum dimension of size
: @param $source base64Binary (streamed?) e.g from `fetch:binary`
: @result base64Binary for thumbnail
:)
declare function thumbnails:size($source as xs:base64Binary,$width as xs:integer,$height as xs:integer)
as xs:base64Binary
{
Q{java:org.expkgzone58.image.Thumbs}size($source,xs:int($width),xs:int($height))
};
(:~
: generate scaled version of source image at given factors 0-1
: @param $source base64Binary (streamed?) e.g from `fetch:binary`
: @result base64Binary for thumbnail
:)
declare function thumbnails:scale($source as xs:base64Binary,$xscale as xs:float,$yscale as xs:float)
as xs:base64Binary
{
Q{java:org.expkgzone58.image.Thumbs}scale($source,$xscale,$yscale)
};
(:~
: generate thumbnail using parameters specified via XML
: @param $source base64Binary (streamed?) e.g from `fetch:binary`
: @param $task XML parameters <task><size width="100" ..
: @result base64Binary for thumbnail
:)
declare function thumbnails:task($source as xs:base64Binary,
$task as element(task))
as xs:base64Binary
{
Q{java:org.expkgzone58.image.Thumbs}task($source,$task)
};
(:~
: validate task XML against schema
: @param $src XML parameters <task><size width="100" ..
: @result validation report
:)
declare function thumbnails:validation-report($src)
as element(report)
{
validate:xsd-report($src,"task.xsd")
};

View File

@ -1,5 +1,5 @@
<package xmlns="http://cxan.org/ns/package" id="thumbnailator">
<abstract>Create a thumbnail from a file path. </abstract>
<abstract>XQuery interface to the thumbnail generator library: thumbnailator</abstract>
<author id="coobird">coobird</author>
<maintainer id="abunce">Andy Bunce</maintainer>
<home>https://github.com/coobird/thumbnailator</home>

View File

@ -1,14 +1,14 @@
<package xmlns="http://expath.org/ns/pkg"
name="expkg-zone58.image.thumbnailator"
abbrev="thumbnailator"
version="2.0.1"
spec="1.0">
<title>Generate thumbnails using http://code.google.com/p/thumbnailator/</title>
<dependency processor="basex" />
<xquery>
<namespace>expkg-zone58.image.thumbnailator</namespace>
<file>thumbnailator.xqm</file>
</xquery>
<package xmlns="http://expath.org/ns/pkg" name="https://github.com/expkg-zone58/ex-thumbnailator"
abbrev="thumbnailator" version="4.1.4" spec="1.0">
<title>An XQuery interface to thumbnailator the thumbnail generator library.</title>
<dependency processor="basex" />
<xquery>
<namespace>expkg-zone58:image.thumbnailator</namespace>
<file>thumbnailator.xqm</file>
</xquery>
<xsd>
<import-uri>expkg-zone58:image.thumbnailator/schema/task.xsd</import-uri>
<file>task.xsd</file>
</xsd>
</package>

18
src/test/builder.xml Normal file
View File

@ -0,0 +1,18 @@
<thumbnail>
<!-- http://programtalk.com/java-api-usage-examples/net.coobird.thumbnailator.tasks.io.InputStreamImageSource/
ThumbnailParameterBuilder p=new ThumbnailParameterBuilder(); switch (element)
{ case "size": p.size(); break; .... ThumbnailParameter tp=p.build() } -->
<size x="200" y="89" />
<scale x="1" y="1" />
<sourceRegion x="0" y="0" width="100" height="100" />
<filters>
<canvas width="300" height="400" position=">?" crop="true"
fillColor="red" />
<caption >some text</caption>
<flip axis="vertical"/>
<colorize/>
<rotate angle="45" />
<watermark src="aa"/>
</filters>
</thumbnail>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
src/test/resources/icon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

8
src/test/rotate.xml Normal file
View File

@ -0,0 +1,8 @@
<thumbnail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="expkg-zone58:image.thumbnailator/schema/task.xsd">
<size width="200" height="200" />
<filters>
<rotate angle="251" />
<rotate angle="1" />
</filters>
</thumbnail>

12
src/test/sample-task.xml Normal file
View File

@ -0,0 +1,12 @@
<thumbnail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="expkg-zone58:image.thumbnailator/schema/task.xsd">
<size width="500" height="500" />
<filters>
<colorize color="#FF0096" alpha=".4" />
<caption position="CENTER" color="white" size="30" font="SansSerif">Some Text here</caption>
<rotate angle="15" />
<canvas height="500" width="500" position="TOP_LEFT" color="black" />
<watermark src="{$watermark}" alpha=".8" position="TOP_LEFT" />
</filters>
</thumbnail>

22
src/test/sample.xq Normal file
View File

@ -0,0 +1,22 @@
import module namespace t="expkg-zone58:image.thumbnailator";
declare variable $pic1:=resolve-uri("resources/simple.jpg");
declare variable $picr:=resolve-uri("resources/result2.jpg");
declare variable $remote:="http://images.metmuseum.org/CRDImages/ep/original/DT46.jpg";
declare variable $watermark:="C:\Users\andy\git\ex-thumbnailator\src\test\resources\icon.jpg";
let $task:=<thumbnail>
<size width="500" height="500"/>
<filters>
<colorize color="#FF0096" alpha=".4"/>
<caption position="CENTER" color="white" size="30" font="SansSerif">Some Text here</caption>
<rotate angle="15"/>
<canvas height="500" width="500" position="TOP_LEFT" color="black"/>
<watermark src="{$watermark}" alpha=".8" position="TOP_LEFT"/>
</filters>
</thumbnail>
(: let $task:=doc("rotate.xml")/task :)
let $x:=fetch:binary($remote)
(: let $r:=Q{java:org.expkgzone58.image.Thumbs}size($x,xs:int(40),xs:int(40)) :)
let $r:=Q{java:org.expkgzone58.image.Thumbs}task($x,$task)
return file:write-binary($picr,$r)

View File

@ -2,20 +2,39 @@ module namespace test = 'http://basex.org/modules/xqunit-tests';
(:~
: unit tests for thumbnail module
:)
import module namespace t="expkg-zone58.image.thumbnailator" at "../main/content/thumbnailator.xqm";
declare namespace File="java:java.io.File";
import module namespace t="expkg-zone58:image.thumbnailator" (: at "../main/content/thumbnailator.xqm" :);
declare variable $test:pic1:=resolve-uri("simple.jpg");
declare variable $test:picr:=resolve-uri("out.jpg");
declare variable $test:pic1:=resolve-uri( "resources/simple.jpg");
declare variable $test:picr:=resolve-uri( "resources/out.jpg");
declare variable $test:met:=<images>
<image src="http://images.metmuseum.org/CRDImages/rl/web-large/DT3136.jpg">
http://www.metmuseum.org/art/collection/search/459117
</image>
</images>;
(:~ make a thumbnail :)
declare
%unit:test
function test:create-thumbnail() {
let $r:=t:create-thumbnail($test:pic1,$test:picr,60,60)
return unit:assert(fn:empty($r))
function test:size() {
let $r:=t:size(
fetch:binary(
$test:pic1
),60,60
)
return unit:assert(
$r instance of xs:base64Binary
)
};
(:~ make a thumbnail :)
declare
%unit:test
function test:validate() {
let $r:=t:validation-report(doc("rotate.xml"))
return unit:assert( $r )
};

2
src/test/validate.xq Normal file
View File

@ -0,0 +1,2 @@
import module namespace t="expkg-zone58:image.thumbnailator";
t:validate("C:/Users/andy/git/ex-thumbnailator/src/test/sample-task.xml")

View File

@ -16,7 +16,7 @@ declare namespace pkg="http://expath.org/ns/pkg";
declare function files($src as xs:string) as xs:string*
{
fn:filter(file:list($src,fn:true()),
function ($f){file:is-file($src || $f)}
function ($f){($src || $f)=>fn:translate("\","/")=>file:is-file()}
)
!fn:translate(.,"\","/")
};
@ -25,7 +25,7 @@ declare namespace pkg="http://expath.org/ns/pkg";
: write xqdoc for $src/$path to $dest
:)
declare %updating function write-xqdoc($path,$src,$dest){
let $url:=fn:resolve-uri( $path,$src)
let $url:=fn:resolve-uri( $path,$src)=>fn:trace()
let $type:=fetch:content-type($url)
return switch($type)

View File

@ -1,19 +0,0 @@
(: create o/ps
: xar package and xqdoc
:)
declare namespace pkg="http://expath.org/ns/pkg";
import module namespace build = "quodatum.utils.build" at "buildx.xqm";
declare variable $base:=resolve-uri("../");
declare variable $src:=resolve-uri("../src/main/");
declare variable $dest:=resolve-uri("../dist/");
(:~
: the package definition as a pkg:package
:)
declare variable $package as element(pkg:package) :=doc(resolve-uri("expath-pkg.xml",$src))/pkg:package;
declare variable $content:=resolve-uri("content/",$src);
declare variable $dest-doc:=resolve-uri("doc/",$dest);
build:files($src)