1. /*
  2. * Copyright 2002,2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.apache.tools.ant.taskdefs.optional.image;
  18. import com.sun.media.jai.codec.FileSeekableStream;
  19. import org.apache.tools.ant.BuildException;
  20. import org.apache.tools.ant.DirectoryScanner;
  21. import org.apache.tools.ant.taskdefs.MatchingTask;
  22. import org.apache.tools.ant.types.FileSet;
  23. import org.apache.tools.ant.types.optional.image.Draw;
  24. import org.apache.tools.ant.types.optional.image.ImageOperation;
  25. import org.apache.tools.ant.types.optional.image.Rotate;
  26. import org.apache.tools.ant.types.optional.image.Scale;
  27. import org.apache.tools.ant.types.optional.image.TransformOperation;
  28. import javax.media.jai.JAI;
  29. import javax.media.jai.PlanarImage;
  30. import java.io.File;
  31. import java.io.FileOutputStream;
  32. import java.io.IOException;
  33. import java.util.ArrayList;
  34. import java.util.Iterator;
  35. import java.util.Vector;
  36. /**
  37. * A MatchingTask which relies on
  38. * <A HREF="http://java.sun.com/products/java-media/jai">JAI (Java Advanced Imaging)</A>
  39. * to perform image manipulation operations on existing images. The
  40. * operations are represented as ImageOperation DataType objects.
  41. * The operations are arranged to conform to the Chaining Model
  42. * of JAI.
  43. * Check out the
  44. * <A HREF="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/">
  45. * JAI Programming Guide</A>
  46. *
  47. * @see org.apache.tools.ant.types.optional.image.ImageOperation
  48. * @see org.apache.tools.ant.types.DataType
  49. */
  50. public class Image extends MatchingTask {
  51. protected Vector instructions = new Vector();
  52. protected String str_encoding = "JPEG";
  53. protected boolean overwrite = false;
  54. protected boolean garbage_collect = false;
  55. private boolean failonerror = true;
  56. protected Vector filesets = new Vector();
  57. protected File srcDir = null;
  58. protected File destDir = null;
  59. /**
  60. * Adds a set of files to be deleted.
  61. */
  62. public void addFileset(FileSet set) {
  63. filesets.addElement(set);
  64. }
  65. /**
  66. * If false, note errors to the output but keep going.
  67. * @param failonerror true or false
  68. */
  69. public void setFailOnError(boolean failonerror) {
  70. this.failonerror = failonerror;
  71. }
  72. /**
  73. * Set the source dir to find the image files.
  74. */
  75. public void setSrcdir(File srcDir) {
  76. this.srcDir = srcDir;
  77. }
  78. /**
  79. * Set the image encoding type.
  80. * <A HREF="http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/Encode.doc.html#56610">
  81. * See this table in the JAI Programming Guide</A>.
  82. */
  83. public void setEncoding(String encoding) {
  84. str_encoding = encoding;
  85. }
  86. /**
  87. * Sets whether or not to overwrite a file if there is a naming conflict.
  88. */
  89. public void setOverwrite(boolean overwrite) {
  90. this.overwrite = overwrite;
  91. }
  92. /**
  93. * Enables Garbage Collection after each image processed. Defaults to false.
  94. */
  95. public void setGc(boolean gc) {
  96. garbage_collect = gc;
  97. }
  98. /**
  99. * Sets the destination directory for manipulated images.
  100. * @param destDir The destination directory
  101. */
  102. public void setDestDir(File destDir) {
  103. this.destDir = destDir;
  104. }
  105. /**
  106. * Adds an ImageOperation to chain.
  107. * @param instr The ImageOperation to append to the chain
  108. */
  109. public void addImageOperation(ImageOperation instr) {
  110. instructions.add(instr);
  111. }
  112. /**
  113. * Adds a Rotate ImageOperation to the chain
  114. * @param instr The Rotate operation to add to the chain
  115. * @see org.apache.tools.ant.types.optional.image.Rotate
  116. */
  117. public void addRotate(Rotate instr) {
  118. instructions.add(instr);
  119. }
  120. /**
  121. * Adds a Scale ImageOperation to the chain
  122. * @param instr The Scale operation to add to the chain
  123. * @see org.apache.tools.ant.types.optional.image.Scale
  124. */
  125. public void addScale(Scale instr) {
  126. instructions.add(instr);
  127. }
  128. /**
  129. * Adds a Draw ImageOperation to the chain. DrawOperation
  130. * DataType objects can be nested inside the Draw object
  131. * @param instr The Draw operation to add to the chain
  132. * @see org.apache.tools.ant.types.optional.image.Draw
  133. * @see org.apache.tools.ant.types.optional.image.DrawOperation
  134. */
  135. public void addDraw(Draw instr) {
  136. instructions.add(instr);
  137. }
  138. /**
  139. * Executes all the chained ImageOperations on the file
  140. * specified.
  141. * @param file The file to be processed
  142. */
  143. public void processFile(File file) {
  144. try {
  145. log("Processing File: " + file.getAbsolutePath());
  146. FileSeekableStream input = new FileSeekableStream(file);
  147. PlanarImage image = JAI.create("stream", input);
  148. for (int i = 0; i < instructions.size(); i++) {
  149. Object instr = instructions.elementAt(i);
  150. if (instr instanceof TransformOperation) {
  151. image = ((TransformOperation) instr).executeTransformOperation(image);
  152. } else {
  153. log("Not a TransformOperation: " + instr);
  154. }
  155. }
  156. input.close();
  157. if (str_encoding.toLowerCase().equals("jpg")) {
  158. str_encoding = "JPEG";
  159. } else if (str_encoding.toLowerCase().equals("tif")) {
  160. str_encoding = "TIFF";
  161. }
  162. if (destDir == null) {
  163. destDir = srcDir;
  164. }
  165. File new_file = new File(destDir.getAbsolutePath() + File.separator + file.getName());
  166. if ((overwrite && new_file.exists()) && (!new_file.equals(file))) {
  167. new_file.delete();
  168. }
  169. FileOutputStream stream = new FileOutputStream(new_file);
  170. JAI.create("encode", image, stream, str_encoding.toUpperCase(), null);
  171. stream.flush();
  172. stream.close();
  173. } catch (IOException err) {
  174. if (!failonerror) {
  175. log("Error processing file: " + err);
  176. } else {
  177. throw new BuildException(err);
  178. }
  179. } catch (java.lang.RuntimeException rerr) {
  180. if (!failonerror) {
  181. log("Error processing file: " + rerr);
  182. } else {
  183. throw new BuildException(rerr);
  184. }
  185. }
  186. }
  187. /**
  188. * Executes the Task
  189. */
  190. public void execute() throws BuildException {
  191. validateAttributes();
  192. try {
  193. DirectoryScanner ds = null;
  194. String[] files = null;
  195. ArrayList filesList = new ArrayList();
  196. // deal with specified srcDir
  197. if (srcDir != null) {
  198. ds = super.getDirectoryScanner(srcDir);
  199. files = ds.getIncludedFiles();
  200. for (int i = 0; i < files.length; i++) {
  201. filesList.add(new File(srcDir.getAbsolutePath() + File.separator + files[i]));
  202. }
  203. }
  204. // deal with the filesets
  205. for (int i = 0; i < filesets.size(); i++) {
  206. FileSet fs = (FileSet) filesets.elementAt(i);
  207. ds = fs.getDirectoryScanner(getProject());
  208. files = ds.getIncludedFiles();
  209. File fromDir = fs.getDir(getProject());
  210. for (int j = 0; j < files.length; j++) {
  211. filesList.add(new File(fromDir.getAbsolutePath() + File.separator + files[j]));
  212. }
  213. }
  214. if (!overwrite) {
  215. // remove any files that shouldn't be overwritten.
  216. ArrayList filesToRemove = new ArrayList();
  217. for (Iterator i = filesList.iterator(); i.hasNext();) {
  218. File f = (File) i.next();
  219. File new_file = new File(destDir.getAbsolutePath()
  220. + File.separator + f.getName());
  221. if (new_file.exists()) {
  222. filesToRemove.add(f);
  223. }
  224. }
  225. filesList.removeAll(filesToRemove);
  226. }
  227. // iterator through all the files and process them.
  228. for (Iterator i = filesList.iterator(); i.hasNext();) {
  229. File file = (File) i.next();
  230. processFile(file);
  231. if (garbage_collect) {
  232. System.gc();
  233. }
  234. }
  235. } catch (Exception err) {
  236. err.printStackTrace();
  237. throw new BuildException(err.getMessage());
  238. }
  239. }
  240. /**
  241. * Ensure we have a consistent and legal set of attributes, and set
  242. * any internal flags necessary based on different combinations
  243. * of attributes.
  244. */
  245. protected void validateAttributes() throws BuildException {
  246. if (srcDir == null && filesets.size() == 0) {
  247. throw new BuildException("Specify at least one source "
  248. + "- a srcDir or a fileset.");
  249. }
  250. if (srcDir == null && destDir == null) {
  251. throw new BuildException("Specify the destDir, or the srcDir.");
  252. }
  253. }
  254. }