001: package com.nwalsh.saxon;
002:
003: import java.io.File;
004: import java.io.BufferedReader;
005: import java.io.FileReader;
006: import java.io.IOException;
007: import java.net.URL;
008: import java.net.MalformedURLException;
009: import java.awt.Toolkit;
010: import java.awt.Image;
011: import java.awt.image.ImageObserver;
012: import java.lang.Thread;
013: import java.util.StringTokenizer;
014:
015: /**
016: * <p>Saxon extension to examine intrinsic size of images</p>
017: *
018: * <p>$Id: ImageIntrinsics.java,v 1.1 2007-05-18 15:03:13 sinisa Exp $</p>
019: *
020: * <p>Copyright (C) 2002 Norman Walsh.</p>
021: *
022: * <p>This class provides a
023: * <a href="http://saxon.sourceforge.net/">Saxon</a>
024: * extension to find the intrinsic size of images.</p>
025: *
026: * <p><b>Change Log:</b></p>
027: * <dl>
028: * <dt>1.0</dt>
029: * <dd><p>Initial release.</p></dd>
030: * </dl>
031: *
032: * @author Norman Walsh
033: * <a href="mailto:ndw@nwalsh.com">ndw@nwalsh.com</a>
034: *
035: * @version $Id: ImageIntrinsics.java,v 1.1 2007-05-18 15:03:13 sinisa Exp $
036: *
037: */
038: public class ImageIntrinsics implements ImageObserver {
039: boolean imageLoaded = false;
040: boolean imageFailed = false;
041: Image image = null;
042: int width = -1;
043: int depth = -1;
044:
045: /**
046: * <p>Constructor for ImageIntrinsics</p>
047: */
048: public ImageIntrinsics(String imageFn) {
049: System.setProperty("java.awt.headless", "true");
050:
051: // Hack. I expect the right way to do this is to always use a URL.
052: // However, that means getting the base URI correct and dealing
053: // with the various permutations of the file: URI scheme on different
054: // platforms. So instead, what we're going to do is cheat. If it
055: // starts with http: or ftp:, call it a URI. Otherwise, call it
056: // a file. Also call it a file if the URI is malformed.
057:
058: URL imageUrl = null;
059:
060: if (imageFn.startsWith("http:") || imageFn.startsWith("ftp:")
061: || imageFn.startsWith("file:")) {
062: try {
063: imageUrl = new URL(imageFn);
064: } catch (MalformedURLException mue) {
065: imageUrl = null;
066: }
067: }
068:
069: if (imageUrl != null) {
070: image = Toolkit.getDefaultToolkit().getImage(imageUrl);
071: } else {
072: image = Toolkit.getDefaultToolkit().getImage(imageFn);
073: }
074:
075: width = image.getWidth(this );
076:
077: while (!imageFailed && (width == -1 || depth == -1)) {
078: try {
079: java.lang.Thread.currentThread().sleep(50);
080: } catch (Exception e) {
081: // nop;
082: }
083: width = image.getWidth(this );
084: depth = image.getHeight(this );
085: }
086:
087: if (imageFailed) {
088: // Maybe it's an EPS or PDF?
089: // FIXME: this code is crude (and doesn't handle the URL case!!!)
090: BufferedReader ir = null;
091: String line = null;
092: int lineLimit = 100;
093:
094: try {
095: ir = new BufferedReader(new FileReader(
096: new File(imageFn)));
097: line = ir.readLine();
098:
099: if (line != null && line.startsWith("%PDF-")) {
100: // We've got a PDF!
101: while (lineLimit > 0 && line != null) {
102: lineLimit--;
103: if (line.startsWith("/CropBox [")) {
104: line = line.substring(10);
105: if (line.indexOf("]") >= 0) {
106: line = line.substring(0, line
107: .indexOf("]"));
108: }
109: parseBox(line);
110: lineLimit = 0;
111: }
112: line = ir.readLine();
113: }
114: } else if (line != null && line.startsWith("%!")
115: && line.indexOf(" EPSF-") > 0) {
116: // We've got an EPS!
117: while (lineLimit > 0 && line != null) {
118: lineLimit--;
119: if (line.startsWith("%%BoundingBox: ")) {
120: line = line.substring(15);
121: parseBox(line);
122: lineLimit = 0;
123: }
124: line = ir.readLine();
125: }
126: } else {
127: System.err.println("Failed to interpret image: "
128: + imageFn);
129: }
130: } catch (Exception e) {
131: System.err.println("Failed to load image: " + imageFn);
132: }
133:
134: if (ir != null) {
135: try {
136: ir.close();
137: } catch (Exception e) {
138: // nop;
139: }
140: }
141: }
142: }
143:
144: public int getWidth(int defaultWidth) {
145: if (width >= 0) {
146: return width;
147: } else {
148: return defaultWidth;
149: }
150: }
151:
152: public int getDepth(int defaultDepth) {
153: if (depth >= 0) {
154: return depth;
155: } else {
156: return defaultDepth;
157: }
158: }
159:
160: private void parseBox(String line) {
161: int[] corners = new int[4];
162: int count = 0;
163:
164: StringTokenizer st = new StringTokenizer(line);
165: while (count < 4 && st.hasMoreTokens()) {
166: try {
167: corners[count++] = Integer.parseInt(st.nextToken());
168: } catch (Exception e) {
169: // nop;
170: }
171: }
172:
173: width = corners[2] - corners[0];
174: depth = corners[3] - corners[1];
175: }
176:
177: public boolean imageUpdate(Image img, int infoflags, int x, int y,
178: int width, int height) {
179: if ((infoflags & ImageObserver.ERROR) == ImageObserver.ERROR) {
180: imageFailed = true;
181: return false;
182: }
183:
184: // I really only care about the width and height, but if I return false as
185: // soon as those are available, the BufferedInputStream behind the loader
186: // gets closed too early.
187: int flags = ImageObserver.ALLBITS;
188: if ((infoflags & flags) == flags) {
189: return false;
190: } else {
191: return true;
192: }
193: }
194: }
|