All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.docbook.xsltng.extensions.ImageProperties Maven / Gradle / Ivy

package org.docbook.xsltng.extensions;

import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.ExtensionFunctionCall;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.s9api.XdmAtomicValue;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;

import java.awt.*;
import java.awt.image.ImageObserver;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;

import static java.lang.Thread.sleep;

/**
 * Saxon extension to obtain the intrinsic size of images.
 *
 * This class provides a
 * Saxon
 * extension to find the intrinsic size of images.
 *
 * 

The function attempts to load the image with the AWT Image toolkit. If that fails, * it searches for a bounding box (present in, e.g., EPS and PDF images). * *

If the image can be loaded or a bounding box is found, the width and height * of the image are returned. * *

Copyright © 2002-2020 Norman Walsh.

* * @author Norman Walsh * [email protected] */ public class ImageProperties extends ExtensionFunctionDefinition { private static final StructuredQName qName = new StructuredQName("", "http://docbook.org/extensions/xslt", "image-properties"); private static final Pattern dimPatn = Pattern.compile("^(\\d+(\\.\\d*)?)(.*)$"); @Override public StructuredQName getFunctionQName() { return qName; } @Override public int getMinimumNumberOfArguments() { return 1; } @Override public int getMaximumNumberOfArguments() { return 1; } @Override public SequenceType[] getArgumentTypes() { return new SequenceType[]{SequenceType.SINGLE_STRING}; } @Override public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) { return SequenceType.SINGLE_ITEM; } public ExtensionFunctionCall makeCallExpression() { return new PropertiesCall(); } private class PropertiesCall extends ImageCall implements ImageObserver { boolean imageLoaded = false; boolean imageFailed = false; Image image = null; int width = -1; int depth = -1; public Sequence call(XPathContext xpathContext, Sequence[] sequences) throws XPathException { context = xpathContext; logger = new DebuggingLogger(xpathContext.getConfiguration().getLogger()); String imageFn = sequences[0].head().getStringValue(); imageLoaded = false; imageFailed = false; image = null; System.setProperty("java.awt.headless", "true"); try { URL url = new URL(imageFn); image = Toolkit.getDefaultToolkit().getImage (url); } catch (MalformedURLException mue) { image = Toolkit.getDefaultToolkit().getImage (imageFn); } width = image.getWidth(this); depth = image.getHeight(this); while (!imageFailed && (width == -1 || depth == -1)) { try { sleep(50); } catch (Exception e) { // nop; } width = image.getWidth(this); depth = image.getHeight(this); } image.flush(); if (width >= 0 && depth >= 0) { map = map.put(new XdmAtomicValue("width"), new XdmAtomicValue(width)); map = map.put(new XdmAtomicValue("height"), new XdmAtomicValue(depth)); } if ((width == -1 || depth == -1) && imageFailed) { parseImage(imageFn); } return map.getUnderlyingValue(); } public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { if (((infoflags & ImageObserver.ERROR) == ImageObserver.ERROR) || ((infoflags & ImageObserver.ABORT) == ImageObserver.ABORT)) { imageFailed = true; return false; } // I really only care about the width and height, but if I return false as // soon as those are available, the BufferedInputStream behind the loader // gets closed too early. return (infoflags & ImageObserver.ALLBITS) != ImageObserver.ALLBITS; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy