001: //$HeadURL: https://sushibar/svn/deegree/base/trunk/resources/eclipse/svn_classfile_header_template.xml $
002: /*---------------- FILE HEADER ------------------------------------------
003: This file is part of deegree.
004: Copyright (C) 2001-2008 by:
005: Department of Geography, University of Bonn
006: http://www.giub.uni-bonn.de/deegree/
007: lat/lon GmbH
008: http://www.lat-lon.de
009:
010: This library is free software; you can redistribute it and/or
011: modify it under the terms of the GNU Lesser General Public
012: License as published by the Free Software Foundation; either
013: version 2.1 of the License, or (at your option) any later version.
014: This library is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: Lesser General Public License for more details.
018: You should have received a copy of the GNU Lesser General Public
019: License along with this library; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: Contact:
022:
023: Andreas Poth
024: lat/lon GmbH
025: Aennchenstr. 19
026: 53177 Bonn
027: Germany
028: E-Mail: poth@lat-lon.de
029:
030: Prof. Dr. Klaus Greve
031: Department of Geography
032: University of Bonn
033: Meckenheimer Allee 166
034: 53115 Bonn
035: Germany
036: E-Mail: greve@giub.uni-bonn.de
037: ---------------------------------------------------------------------------*/
038:
039: package org.deegree.tools.raster;
040:
041: import java.awt.geom.AffineTransform;
042: import java.awt.geom.NoninvertibleTransformException;
043: import java.awt.image.BufferedImage;
044: import java.awt.image.ColorModel;
045: import java.awt.image.SampleModel;
046: import java.io.File;
047: import java.io.IOException;
048: import java.util.LinkedList;
049:
050: import javax.imageio.ImageIO;
051:
052: import org.deegree.framework.log.ILogger;
053: import org.deegree.framework.log.LoggerFactory;
054: import org.deegree.model.coverage.grid.WorldFile;
055: import org.deegree.model.spatialschema.Envelope;
056: import org.deegree.model.spatialschema.GeometryFactory;
057: import org.deegree.processing.raster.converter.Image2RawData;
058: import org.deegree.processing.raster.converter.RawData2Image;
059:
060: /**
061: * <code>WorldfileNormalizer</code>
062: *
063: * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a>
064: * @author last edited by: $Author:$
065: *
066: * @version $Revision:$, $Date:$
067: */
068: public class WorldfileNormalizer {
069:
070: private static ILogger LOG = LoggerFactory
071: .getLogger(WorldfileNormalizer.class);
072:
073: private Config config;
074:
075: private double resx, resy, rotx, roty, minx, miny;
076:
077: // int xmin = Integer.MAX_VALUE;
078: //
079: // int ymin = Integer.MAX_VALUE;
080: //
081: // int xmax = Integer.MIN_VALUE;
082: //
083: // int ymax = Integer.MIN_VALUE;
084:
085: private int width, height;
086:
087: private AffineTransform transform = new AffineTransform();
088:
089: /**
090: * @param config
091: */
092: public WorldfileNormalizer(Config config) {
093: this .config = config;
094: }
095:
096: // x -> y -> interpolation -> wert
097: private float getValue(Image2RawData data, double x, double y) {
098: // transform = new AffineTransform(resx, roty, minx + x*resx, rotx, resy, miny + y*resy);
099:
100: // System.out.println( transform );
101: // try {
102: // transform = transform.createInverse();
103: // } catch ( NoninvertibleTransformException e ) {
104: // // TODO Auto-generated catch block
105: // e.printStackTrace();
106: // }
107: // int srcy = (int)( ( resx * ( y - miny ) - rotx * ( x - minx ) ) / denominator );
108: // int srcx = (int)( ( x - roty * srcy - minx ) / resx );
109: // int srcy = (int)( ( ( y ) - rotx * ( x ) ) / denominator );
110: // int srcx = (int)( ( x - roty * srcy ) );
111:
112: // double tmpx = (int) ( x * cos1 - y * sin1 );
113: // double tmpy = (int) ( x * sin1 + y * cos1 );
114: double[] dest = new double[2];
115: transform.transform(new double[] { x, y }, 0, dest, 0, 1);
116: int srcx = (int) (dest[0]);
117: int srcy = (int) (dest[1]);
118: if (srcx < width && srcx >= 0 && srcy >= 0 && srcy < height) {
119: return data.get(srcx, srcy);
120: }
121:
122: // System.out.println( srcx + "/" + srcy );
123: return 0;
124: }
125:
126: // private int getTargetWidth() {
127: // double hyp = width / Math.cos( rotx );
128: // hyp *= hyp;
129: // double res = Math.sqrt( hyp - width * width );
130: // return (int) ( width + res );
131: // }
132: //
133: // private int getTargetHeight() {
134: // double hyp = height / Math.cos( rotx );
135: // hyp *= hyp;
136: // double res = Math.sqrt( hyp - height * height );
137: // return (int) ( height + res );
138: // }
139:
140: private void normalize(String file) throws IOException {
141: // avoid trying to read world files as images
142: if (WorldFile.hasWorldfileSuffix(file)) {
143: return;
144: }
145: BufferedImage src = null;
146: try {
147: LOG.logInfo("Reading " + file);
148: src = ImageIO.read(new File(file)); // ImageUtils.loadImage( file );
149: // src = ImageUtils.loadImage( file );
150: } catch (Exception e) {
151: LOG.logError(e.getMessage(), e);
152: LOG.logInfo("Ignoring " + file);
153: // ignore faulty images/files that are no images
154: return;
155: }
156:
157: LOG.logInfo("Read " + file);
158:
159: WorldFile wf = WorldFile.readWorldFile(file, config.type, src);
160:
161: Envelope env = wf.getEnvelope();
162:
163: file = file.substring(0, file.length() - 4);
164: resx = wf.getResx();
165: resy = -wf.getResy();
166: rotx = wf.getRotation1();
167: roty = wf.getRotation2();
168: minx = env.getMin().getX();
169: miny = env.getMax().getY();
170: double maxx = Double.MIN_VALUE, maxy = Double.MIN_VALUE;
171: minx = Double.MIN_VALUE;
172: miny = Double.MIN_VALUE;
173: width = Math.abs((int) (wf.getEnvelope().getWidth() / resx)) + 1;
174: height = Math.abs((int) (wf.getEnvelope().getHeight() / resy)) + 1;
175:
176: transform = new AffineTransform(resx, rotx, roty, resy, minx,
177: miny);
178: try {
179:
180: double[] d = new double[2];
181: for (int x = 0; x < width; ++x)
182: for (int y = 0; y < height; ++y) {
183:
184: transform.transform(new double[] { x, y }, 0, d, 0,
185: 1);
186: if (d[0] > maxx)
187: maxx = d[0];
188:
189: if (d[1] > maxy)
190: maxy = d[1];
191:
192: if (d[0] < minx)
193: minx = d[0];
194:
195: if (d[1] < miny)
196: miny = d[1];
197: }
198:
199: transform = transform.createInverse();
200: } catch (NoninvertibleTransformException e) {
201: LOG.logError(
202: "Worldfile was filled with invalid parameters.", e);
203: }
204:
205: int twidth = (int) ((maxx - minx) / resx);
206: int theight = (int) -((maxy - miny) / resy);
207:
208: LOG.logInfo("Target image size is " + twidth + "x" + theight);
209:
210: LOG.logInfo("Image size is " + width + "x" + height);
211: Image2RawData srcData = new Image2RawData(src);
212:
213: ColorModel model = src.getColorModel();
214: SampleModel sampleModel = src.getSampleModel();
215:
216: float[][] destData = new float[theight][twidth];
217: for (int i = 0; i < theight; ++i) {
218: destData[i] = new float[twidth];
219: }
220:
221: LOG.logInfo("Transforming image.");
222: for (int x = 0; x < twidth; ++x) {
223: if (x % 1000 == 0) {
224: System.out.print("\r" + x);
225: }
226: for (int y = 0; y < theight; ++y) {
227: destData[destData.length - y - 1][x] = getValue(
228: srcData, x * resx + minx, miny - y * resy);
229: }
230: }
231:
232: System.out.println("\r ");
233: LOG.logInfo("Finished transforming image.");
234: srcData = null;
235: src = null;
236: System.gc();
237: System.gc();
238: // LOG.logInfo( "Target image size is " + twidth + "x" + theight );
239:
240: LOG.logInfo("Creating target image...");
241: BufferedImage dest = RawData2Image.rawData2Image(destData,
242: true, model, sampleModel);
243: destData = null;
244: System.gc();
245: System.gc();
246:
247: LOG.logInfo("Writing target image...");
248: ImageIO.write(dest, "jpeg", new File(file + "_converted.jpg"));
249: LOG.logInfo("Finished writing image.");
250:
251: double minx = env.getMin().getX();
252: double miny = env.getMin().getY();
253: Envelope env2 = GeometryFactory.createEnvelope(minx, miny,
254: maxx, maxy, env.getCoordinateSystem());
255:
256: WorldFile outWF = new WorldFile(resx, resy, 0, 0, env2);
257: WorldFile.writeWorldFile(outWF, file + "_converted");
258: }
259:
260: private void normalize() {
261: while (config.files.size() > 0) {
262: String file = config.files.poll();
263: try {
264: normalize(file);
265: } catch (IOException e) {
266: LOG.logWarning("No world file named '" + file
267: + "' could be found/read.");
268: e.printStackTrace();
269: }
270: }
271: }
272:
273: /**
274: * @param args
275: */
276: public static void main(String[] args) {
277: if (args.length == 0) {
278: printUsage(null);
279: }
280:
281: WorldfileNormalizer wfn = new WorldfileNormalizer(new Config(
282: args));
283: wfn.normalize();
284: }
285:
286: /**
287: * Prints usage information and exits.
288: *
289: * @param msg
290: */
291: public static void printUsage(String msg) {
292: if (msg != null) {
293: System.out.println(msg);
294: System.out.println();
295: }
296:
297: System.out.println("Usage:");
298: System.out.println("java -cp ... "
299: + WorldfileNormalizer.class.getCanonicalName()
300: + " <options> <files>");
301: System.out.println();
302: System.out.println(" --help, -h:");
303: System.out
304: .println(" Print out this message and exit.");
305: System.out.println(" --directory, -d <dir>:");
306: System.out
307: .println(" Adds all worldfiles in a directory to the list of files.");
308: System.out.println(" --type, -t <type>:");
309: System.out
310: .println(" Set the INPUT world file type, either to 'center' or to 'outer'.");
311: System.out
312: .println(" Note that the output world file type will always be 'center'.");
313: System.out
314: .println(" For details on the world file types see the documentation");
315: System.out.println(" of the RasterTreeBuilder.");
316: System.out.println(" --interpolation, -i <method>:");
317: System.out
318: .println(" Set the interpolation method. Can be one of 'bicubic', 'bilinear' or");
319: System.out
320: .println(" 'nearest'. Default is nearest neighbor.");
321:
322: System.exit(0);
323: }
324:
325: private static class Config {
326:
327: /**
328: * List of files to convert.
329: */
330: public LinkedList<String> files = new LinkedList<String>();
331:
332: /**
333: * The type of the world files.
334: */
335: public WorldFile.TYPE type = WorldFile.TYPE.CENTER;
336:
337: /**
338: * Interpolation method, default is 'nearest'.
339: */
340: public String interpolation = "nearest";
341:
342: /**
343: * Parses the commandline arguments. If -h or --help is contained in the array, the
344: * application will exit.
345: *
346: * @param args
347: * cmdline arguments
348: */
349: public Config(String[] args) {
350: int i = 0;
351:
352: while (i < args.length) {
353: if (args[i].equals("-h") || args[i].equals("--help")) {
354: printUsage(null);
355: } else if (args[i].equals("--type")
356: || args[i].equals("-t")) {
357: if (args[i + 1].equalsIgnoreCase("outer")) {
358: type = WorldFile.TYPE.OUTER;
359: }
360: if (args[i + 1].equalsIgnoreCase("center")) {
361: type = WorldFile.TYPE.CENTER;
362: }
363: i += 2;
364: } else if (args[i].equals("--interpolation")
365: || args[i].equals("-i")) {
366: String m = args[i + 1].toLowerCase();
367: if (m.equals("nearest") || m.equals("bilinear")
368: || m.equals("biqubic")) {
369: interpolation = m;
370: } else {
371: printUsage("Unknown interpolation method: '"
372: + m + "'");
373: }
374: i += 2;
375: } else if (args[i].equals("-d")
376: || args[i].equals("--directory")) {
377: File dir = new File(args[i + 1]);
378: File[] fs = dir.listFiles();
379: for (File f : fs) {
380: String s = f.getAbsolutePath();
381: if (s.toLowerCase().endsWith("jpg")
382: || s.toLowerCase().endsWith("jpeg")
383: || s.toLowerCase().endsWith("gif")
384: || s.toLowerCase().endsWith("png")
385: || s.toLowerCase().endsWith("tif")
386: || s.toLowerCase().endsWith("tiff")
387: || s.toLowerCase().endsWith("bmp")) {
388: files.add(s);
389: }
390: }
391: i += 2;
392: } else {
393: files.add(args[i]);
394: ++i;
395: }
396: }
397: }
398:
399: }
400:
401: }
|