You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlgraphics.apache.org by je...@apache.org on 2007/11/29 12:15:23 UTC

svn commit: r599383 - in /xmlgraphics/commons/trunk: ./ src/java/org/apache/xmlgraphics/ps/

Author: jeremias
Date: Thu Nov 29 03:15:22 2007
New Revision: 599383

URL: http://svn.apache.org/viewvc?rev=599383&view=rev
Log:
PostScript: Improved PSImageUtils by introducing the ImageEncoder interface and allowing for streams instead of byte arrays for data transfer which can lower memory consumption.
Backwards compatibility is preserved but I've deprecated the methods using byte[].
Copied over PSDictionary from FOP because it is useful in PSImageUtils.

Added:
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java   (with props)
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java   (contents, props changed)
      - copied, changed from r596288, xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionary.java
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java   (contents, props changed)
      - copied, changed from r596288, xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java
Modified:
    xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSImageUtils.java
    xmlgraphics/commons/trunk/status.xml

Added: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java?rev=599383&view=auto
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java (added)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java Thu Nov 29 03:15:22 2007
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+ 
+package org.apache.xmlgraphics.ps;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * The interface is implemented by classes that can generate the raw bitmap field for an image
+ * that might be further encoded/compressed by the image handler class.
+ */
+public interface ImageEncoder {
+
+    /**
+     * Writes the whole raw bitmap field to the given OutputStream. The implementation must not
+     * close the OutputStream when it is finished!
+     * @param out the OutputStream to write to
+     * @throws IOException if an I/O error occurs
+     */
+    void writeTo(OutputStream out) throws IOException;
+    
+    String getImplicitFilter();
+    
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/ImageEncoder.java
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java (from r596288, xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionary.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java?p2=xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java&p1=xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionary.java&r1=596288&r2=599383&rev=599383&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionary.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java Thu Nov 29 03:15:22 2007
@@ -1,312 +1,312 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id: $ */
-
-package org.apache.fop.render.ps;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.StringTokenizer;
-
-/**
- * This class is used to encapsulate postscript dictionary objects.
- */
-public class PSDictionary extends java.util.HashMap {
-    
-    private static final long serialVersionUID = 815367222496219197L;
-
-    /**
-     * This class is used to parse dictionary strings.
-     */
-    private static class Maker {
-        
-        /**
-         * Simple token holding class
-         */
-        private class Token {
-            /**
-             * start index in string
-             */
-            private int startIndex = -1;
-            
-            /**
-             * end index in string
-             */
-            private int endIndex = -1;
-            
-            /**
-             * token string value
-             */
-            private String value;        
-        }
-        
-        private static final String[][] BRACES = {
-            {"<<", ">>"},
-            {"[", "]"},
-            {"{", "}"}
-        };
-
-        private static final int OPENING = 0;
-        private static final int CLOSING = 1;
-        private static final int DICTIONARY = 0;
-        private static final int ARRAY = 1;
-        private static final int PROCEDURE = 2;
-
-        /**
-         * Returns a Token containing the start, end index and value of the next token
-         * found in a given string
-         * 
-         * @param str
-         *            string to search
-         * @param fromIndex
-         *            search from index
-         * @return Token containing the start, end index and value of the next token
-         */
-        protected Token nextToken(String str, int fromIndex) {
-            Token t = null;
-            for (int i = fromIndex; i < str.length(); i++) {
-                boolean isWhitespace = Character.isWhitespace(str.charAt(i));
-                // start index found
-                if (t == null && !isWhitespace) {
-                    t = new Token();
-                    t.startIndex = i;
-                // end index found
-                } else if (t != null && isWhitespace) {
-                    t.endIndex = i;
-                    break;
-                }
-            }
-            // start index found
-            if (t != null) {
-                // end index not found so take end of string
-                if (t.endIndex == -1) {
-                    t.endIndex = str.length();
-                }
-                t.value = str.substring(t.startIndex, t.endIndex);
-            }
-            return t;
-        }
-
-        /**
-         * Returns the closing brace index from a given string searches from a
-         * given index
-         * 
-         * @param str
-         *            string to search
-         * @param braces
-         *            string array of opening and closing brace
-         * @param fromIndex
-         *            searches from index
-         * @return matching brace index
-         * @throws org.apache.fop.render.ps.PSDictionaryFormatException
-         *            thrown in the event that a parsing error occurred
-         */
-        private int indexOfMatchingBrace(String str, String[] braces,
-                int fromIndex) throws PSDictionaryFormatException {
-            final int len = str.length();
-            if (braces.length != 2) {
-                throw new PSDictionaryFormatException("Wrong number of braces");
-            }
-            for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) {
-                if (str.startsWith(braces[OPENING], fromIndex)) {
-                    openCnt++;
-                } else if (str.startsWith(braces[CLOSING], fromIndex)) {
-                    closeCnt++;
-                    if (openCnt > 0 && openCnt == closeCnt) {
-                        return fromIndex; // found
-                    }
-                }
-            }
-            return -1; // not found
-        }
-
-        /**
-         * Strips braces from complex object string
-         * 
-         * @param str
-         *            String to parse
-         * @param braces
-         *            String array containing opening and closing braces
-         * @return String with braces stripped
-         * @throws
-         *      org.apache.fop.render.ps.PSDictionaryFormatException object format exception
-         */
-        private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException {
-            // find first opening brace
-            int firstIndex = str.indexOf(braces[OPENING]);
-            if (firstIndex == -1) {
-                throw new PSDictionaryFormatException(
-                        "Failed to find opening parameter '" + braces[OPENING]
-                                + "");
-            }
-
-            // find last matching brace
-            int lastIndex = indexOfMatchingBrace(str, braces, firstIndex);
-            if (lastIndex == -1) {
-                throw new PSDictionaryFormatException(
-                        "Failed to find matching closing parameter '"
-                                + braces[CLOSING] + "'");
-            }
-
-            // strip brace and trim
-            int braceLen = braces[OPENING].length();
-            str = str.substring(firstIndex + braceLen, lastIndex).trim();
-            return str;
-        }
-
-        /**
-         * Parses a dictionary string and provides a dictionary object
-         * 
-         * @param str a dictionary string
-         * @return A postscript dictionary object
-         * @throws
-         *      PSDictionaryFormatException thrown if a dictionary format exception occurs
-         */
-        public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException {
-            PSDictionary dictionary = new PSDictionary();
-            str = stripBraces(str.trim(), BRACES[DICTIONARY]);
-            // length of dictionary string
-            final int len = str.length();
-
-            Token keyToken;
-            for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null
-                    && currIndex <= len;) {
-                if (keyToken.value == null) {
-                    throw new PSDictionaryFormatException("Failed to parse object key");
-                }
-                Token valueToken = nextToken(str, keyToken.endIndex + 1);
-                String[] braces = null;
-                for (int i = 0; i < BRACES.length; i++) {
-                    if (valueToken.value.startsWith(BRACES[i][OPENING])) {
-                        braces = BRACES[i];
-                        break;
-                    }
-                }
-                Object obj = null;
-                if (braces != null) {
-                    // find closing brace
-                    valueToken.endIndex = indexOfMatchingBrace(str, braces,
-                        valueToken.startIndex)
-                        + braces[OPENING].length();
-                    if (valueToken.endIndex < 0) {
-                        throw new PSDictionaryFormatException("Closing value brace '"
-                            + braces[CLOSING] + "' not found for key '"
-                            + keyToken.value + "'");
-                    }
-                    valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex);
-                }
-                if (braces == null || braces == BRACES[PROCEDURE]) {
-                    obj = valueToken.value;                        
-                } else if (BRACES[ARRAY] == braces) {
-                    List objList = new java.util.ArrayList();
-                    String objString = stripBraces(valueToken.value, braces);
-                    StringTokenizer tokenizer = new StringTokenizer(objString, ",");
-                    while (tokenizer.hasMoreTokens()) {
-                        objList.add(tokenizer.nextToken());
-                    }
-                    obj = objList;                        
-                } else if (BRACES[DICTIONARY] == braces) {
-                    obj = parseDictionary(valueToken.value);
-                }
-                dictionary.put(keyToken.value, obj);
-                currIndex = valueToken.endIndex + 1;
-            }
-            return dictionary;
-        }    
-    }
-    
-    /**
-     * Parses a given a dictionary string and returns an object 
-     * 
-     * @param str dictionary string
-     * @return dictionary object
-     * @throws PSDictionaryFormatException object format exception
-     */
-    public static PSDictionary valueOf(String str) throws PSDictionaryFormatException {
-        return (new Maker()).parseDictionary(str);
-    }
-
-    /**
-     * @param obj object to test equality against
-     * @return whether a given object is equal to this dictionary object
-     * @see java.lang.Object#equals(Object)
-     */
-    public boolean equals(Object obj) {
-        if (!(obj instanceof PSPageDeviceDictionary)) {
-            return false;
-        }
-        PSDictionary dictionaryObj = (PSDictionary) obj;
-        if (dictionaryObj.size() != size()) {
-            return false;
-        }
-        for (Iterator it = keySet().iterator(); it.hasNext();) {
-            String key = (String) it.next();
-            if (!dictionaryObj.containsKey(key)) {
-                return false;
-            }
-            if (!dictionaryObj.get(key).equals(get(key))) {
-                return false;
-            }
-        }
-        return true;
-    }
-    
-    /**
-     * @return a hash code value for this object.
-     * @see java.lang.Object#hashCode()
-     */
-    public int hashCode() {
-        int hashCode = 7;
-        for (Iterator it = values().iterator(); it.hasNext();) {
-            Object value = it.next();
-            hashCode += value.hashCode();
-        }
-        return hashCode;
-    }
-
-    /**
-     * @return a string representation of this dictionary
-     * @see java.lang.String#toString()
-     */
-    public String toString() {
-        if (isEmpty()) {
-            return "";
-        }
-        StringBuffer sb = new StringBuffer("<<\n");
-        for (Iterator it = super.keySet().iterator(); it.hasNext();) {
-            String key = (String) it.next();
-            sb.append("  " + key + " ");
-            Object obj = super.get(key);
-            if (obj instanceof java.util.ArrayList) {
-                List array = (List)obj;
-                String str = "[";
-                for (int i = 0; i < array.size(); i++) {
-                    Object element = array.get(i);
-                    str += element + " ";
-                }
-                str = str.trim();
-                str += "]";
-                sb.append(str + "\n");                
-            } else {
-                sb.append(obj.toString() + "\n");
-            }
-        }
-        sb.append(">>");
-        return sb.toString();
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.xmlgraphics.ps;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * This class is used to encapsulate postscript dictionary objects.
+ */
+public class PSDictionary extends java.util.HashMap {
+    
+    private static final long serialVersionUID = 815367222496219197L;
+
+    /**
+     * This class is used to parse dictionary strings.
+     */
+    private static class Maker {
+        
+        /**
+         * Simple token holding class
+         */
+        private class Token {
+            /**
+             * start index in string
+             */
+            private int startIndex = -1;
+            
+            /**
+             * end index in string
+             */
+            private int endIndex = -1;
+            
+            /**
+             * token string value
+             */
+            private String value;        
+        }
+        
+        private static final String[][] BRACES = {
+            {"<<", ">>"},
+            {"[", "]"},
+            {"{", "}"}
+        };
+
+        private static final int OPENING = 0;
+        private static final int CLOSING = 1;
+        private static final int DICTIONARY = 0;
+        private static final int ARRAY = 1;
+        private static final int PROCEDURE = 2;
+
+        /**
+         * Returns a Token containing the start, end index and value of the next token
+         * found in a given string
+         * 
+         * @param str
+         *            string to search
+         * @param fromIndex
+         *            search from index
+         * @return Token containing the start, end index and value of the next token
+         */
+        protected Token nextToken(String str, int fromIndex) {
+            Token t = null;
+            for (int i = fromIndex; i < str.length(); i++) {
+                boolean isWhitespace = Character.isWhitespace(str.charAt(i));
+                // start index found
+                if (t == null && !isWhitespace) {
+                    t = new Token();
+                    t.startIndex = i;
+                // end index found
+                } else if (t != null && isWhitespace) {
+                    t.endIndex = i;
+                    break;
+                }
+            }
+            // start index found
+            if (t != null) {
+                // end index not found so take end of string
+                if (t.endIndex == -1) {
+                    t.endIndex = str.length();
+                }
+                t.value = str.substring(t.startIndex, t.endIndex);
+            }
+            return t;
+        }
+
+        /**
+         * Returns the closing brace index from a given string searches from a
+         * given index
+         * 
+         * @param str
+         *            string to search
+         * @param braces
+         *            string array of opening and closing brace
+         * @param fromIndex
+         *            searches from index
+         * @return matching brace index
+         * @throws org.apache.fop.render.ps.PSDictionaryFormatException
+         *            thrown in the event that a parsing error occurred
+         */
+        private int indexOfMatchingBrace(String str, String[] braces,
+                int fromIndex) throws PSDictionaryFormatException {
+            final int len = str.length();
+            if (braces.length != 2) {
+                throw new PSDictionaryFormatException("Wrong number of braces");
+            }
+            for (int openCnt = 0, closeCnt = 0; fromIndex < len; fromIndex++) {
+                if (str.startsWith(braces[OPENING], fromIndex)) {
+                    openCnt++;
+                } else if (str.startsWith(braces[CLOSING], fromIndex)) {
+                    closeCnt++;
+                    if (openCnt > 0 && openCnt == closeCnt) {
+                        return fromIndex; // found
+                    }
+                }
+            }
+            return -1; // not found
+        }
+
+        /**
+         * Strips braces from complex object string
+         * 
+         * @param str
+         *            String to parse
+         * @param braces
+         *            String array containing opening and closing braces
+         * @return String with braces stripped
+         * @throws
+         *      org.apache.fop.render.ps.PSDictionaryFormatException object format exception
+         */
+        private String stripBraces(String str, String[] braces) throws PSDictionaryFormatException {
+            // find first opening brace
+            int firstIndex = str.indexOf(braces[OPENING]);
+            if (firstIndex == -1) {
+                throw new PSDictionaryFormatException(
+                        "Failed to find opening parameter '" + braces[OPENING]
+                                + "");
+            }
+
+            // find last matching brace
+            int lastIndex = indexOfMatchingBrace(str, braces, firstIndex);
+            if (lastIndex == -1) {
+                throw new PSDictionaryFormatException(
+                        "Failed to find matching closing parameter '"
+                                + braces[CLOSING] + "'");
+            }
+
+            // strip brace and trim
+            int braceLen = braces[OPENING].length();
+            str = str.substring(firstIndex + braceLen, lastIndex).trim();
+            return str;
+        }
+
+        /**
+         * Parses a dictionary string and provides a dictionary object
+         * 
+         * @param str a dictionary string
+         * @return A postscript dictionary object
+         * @throws
+         *      PSDictionaryFormatException thrown if a dictionary format exception occurs
+         */
+        public PSDictionary parseDictionary(String str) throws PSDictionaryFormatException {
+            PSDictionary dictionary = new PSDictionary();
+            str = stripBraces(str.trim(), BRACES[DICTIONARY]);
+            // length of dictionary string
+            final int len = str.length();
+
+            Token keyToken;
+            for (int currIndex = 0; (keyToken = nextToken(str, currIndex)) != null
+                    && currIndex <= len;) {
+                if (keyToken.value == null) {
+                    throw new PSDictionaryFormatException("Failed to parse object key");
+                }
+                Token valueToken = nextToken(str, keyToken.endIndex + 1);
+                String[] braces = null;
+                for (int i = 0; i < BRACES.length; i++) {
+                    if (valueToken.value.startsWith(BRACES[i][OPENING])) {
+                        braces = BRACES[i];
+                        break;
+                    }
+                }
+                Object obj = null;
+                if (braces != null) {
+                    // find closing brace
+                    valueToken.endIndex = indexOfMatchingBrace(str, braces,
+                        valueToken.startIndex)
+                        + braces[OPENING].length();
+                    if (valueToken.endIndex < 0) {
+                        throw new PSDictionaryFormatException("Closing value brace '"
+                            + braces[CLOSING] + "' not found for key '"
+                            + keyToken.value + "'");
+                    }
+                    valueToken.value = str.substring(valueToken.startIndex, valueToken.endIndex);
+                }
+                if (braces == null || braces == BRACES[PROCEDURE]) {
+                    obj = valueToken.value;                        
+                } else if (BRACES[ARRAY] == braces) {
+                    List objList = new java.util.ArrayList();
+                    String objString = stripBraces(valueToken.value, braces);
+                    StringTokenizer tokenizer = new StringTokenizer(objString, ",");
+                    while (tokenizer.hasMoreTokens()) {
+                        objList.add(tokenizer.nextToken());
+                    }
+                    obj = objList;                        
+                } else if (BRACES[DICTIONARY] == braces) {
+                    obj = parseDictionary(valueToken.value);
+                }
+                dictionary.put(keyToken.value, obj);
+                currIndex = valueToken.endIndex + 1;
+            }
+            return dictionary;
+        }    
+    }
+    
+    /**
+     * Parses a given a dictionary string and returns an object 
+     * 
+     * @param str dictionary string
+     * @return dictionary object
+     * @throws PSDictionaryFormatException object format exception
+     */
+    public static PSDictionary valueOf(String str) throws PSDictionaryFormatException {
+        return (new Maker()).parseDictionary(str);
+    }
+
+    /**
+     * @param obj object to test equality against
+     * @return whether a given object is equal to this dictionary object
+     * @see java.lang.Object#equals(Object)
+     */
+    public boolean equals(Object obj) {
+        if (!(obj instanceof PSDictionary)) {
+            return false;
+        }
+        PSDictionary dictionaryObj = (PSDictionary) obj;
+        if (dictionaryObj.size() != size()) {
+            return false;
+        }
+        for (Iterator it = keySet().iterator(); it.hasNext();) {
+            String key = (String) it.next();
+            if (!dictionaryObj.containsKey(key)) {
+                return false;
+            }
+            if (!dictionaryObj.get(key).equals(get(key))) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * @return a hash code value for this object.
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode() {
+        int hashCode = 7;
+        for (Iterator it = values().iterator(); it.hasNext();) {
+            Object value = it.next();
+            hashCode += value.hashCode();
+        }
+        return hashCode;
+    }
+
+    /**
+     * @return a string representation of this dictionary
+     * @see java.lang.String#toString()
+     */
+    public String toString() {
+        if (isEmpty()) {
+            return "";
+        }
+        StringBuffer sb = new StringBuffer("<<\n");
+        for (Iterator it = super.keySet().iterator(); it.hasNext();) {
+            String key = (String) it.next();
+            sb.append("  " + key + " ");
+            Object obj = super.get(key);
+            if (obj instanceof java.util.ArrayList) {
+                List array = (List)obj;
+                String str = "[";
+                for (int i = 0; i < array.size(); i++) {
+                    Object element = array.get(i);
+                    str += element + " ";
+                }
+                str = str.trim();
+                str += "]";
+                sb.append(str + "\n");                
+            } else {
+                sb.append(obj.toString() + "\n");
+            }
+        }
+        sb.append(">>");
+        return sb.toString();
+    }
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionary.java
------------------------------------------------------------------------------
    svn:keywords = Id

Copied: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java (from r596288, xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java)
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java?p2=xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java&p1=xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java&r1=596288&r2=599383&rev=599383&view=diff
==============================================================================
--- xmlgraphics/fop/branches/Temp_ImagePackageRedesign/src/java/org/apache/fop/render/ps/PSDictionaryFormatException.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java Thu Nov 29 03:15:22 2007
@@ -1,37 +1,37 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- * 
- *      http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id: $ */
-
-package org.apache.fop.render.ps;
-
-/**
- * Thrown to indicate that a formatting error has occured when
- * trying to parse a postscript dictionary object
- */
-public class PSDictionaryFormatException extends Exception {
-
-    private static final long serialVersionUID = 6492321557297860931L;
-
-    /**
-     * Default constructor
-     * @param string error message
-     */
-    public PSDictionaryFormatException(String string) {
-        super(string);
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.xmlgraphics.ps;
+
+/**
+ * Thrown to indicate that a formatting error has occurred when
+ * trying to parse a PostScript dictionary object
+ */
+public class PSDictionaryFormatException extends Exception {
+
+    private static final long serialVersionUID = 6492321557297860931L;
+
+    /**
+     * Default constructor
+     * @param string error message
+     */
+    public PSDictionaryFormatException(String string) {
+        super(string);
+    }
+}

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSDictionaryFormatException.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSImageUtils.java
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSImageUtils.java?rev=599383&r1=599382&r2=599383&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSImageUtils.java (original)
+++ xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/ps/PSImageUtils.java Thu Nov 29 03:15:22 2007
@@ -24,11 +24,16 @@
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
 import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.IndexColorModel;
 import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.CountingOutputStream;
 import org.apache.xmlgraphics.util.io.ASCII85OutputStream;
 import org.apache.xmlgraphics.util.io.Finalizable;
 import org.apache.xmlgraphics.util.io.FlateEncodeOutputStream;
@@ -50,17 +55,97 @@
      * @param colorSpace the color space of the image
      * @param gen the PostScript generator
      * @throws IOException In case of an I/O exception
+     * @deprecated Please use the variant with the more versatile ImageEncoder as parameter
      */
-    public static void writeImage(byte[] img,
+    public static void writeImage(final byte[] img,
             Dimension imgDim, String imgDescription,
             Rectangle2D targetRect, 
-            boolean isJPEG, ColorSpace colorSpace,
+            final boolean isJPEG, ColorSpace colorSpace,
+            PSGenerator gen) throws IOException {
+        ImageEncoder encoder = new ImageEncoder() {
+            public void writeTo(OutputStream out) throws IOException {
+                out.write(img);
+            }
+
+            public String getImplicitFilter() {
+                if (isJPEG) {
+                    return "<< >> /DCTDecode";
+                } else {
+                    return null;
+                }
+            }
+        };
+        writeImage(encoder, imgDim, imgDescription, targetRect, colorSpace, false, gen);
+    }
+    
+    /**
+     * Writes a bitmap image to the PostScript stream.
+     * @param img the bitmap image as a byte array
+     * @param imgDim the dimensions of the image
+     * @param imgDescription the name of the image
+     * @param targetRect the target rectangle to place the image in
+     * @param colorSpace the color space of the image
+     * @param invertImage true if the image shall be inverted
+     * @param gen the PostScript generator
+     * @throws IOException In case of an I/O exception
+     */
+    public static void writeImage(ImageEncoder encoder,
+            Dimension imgDim, String imgDescription,
+            Rectangle2D targetRect, 
+            ColorSpace colorSpace, boolean invertImage,
             PSGenerator gen) throws IOException {
         gen.saveGraphicsState();
-        gen.writeln(gen.formatDouble(targetRect.getX()) + " " 
-                + gen.formatDouble(targetRect.getY()) + " translate");
-        gen.writeln(gen.formatDouble(targetRect.getWidth()) + " " 
-                + gen.formatDouble(targetRect.getHeight()) + " scale");
+        translateAndScale(gen, targetRect);
+
+        gen.commentln("%AXGBeginBitmap: " + imgDescription);
+
+        gen.writeln("{{");
+        // Template: (RawData is used for the EOF signal only)
+        // gen.write("/RawData currentfile <first filter> filter def");
+        // gen.write("/Data RawData <second filter> <third filter> [...] def");
+        String implicitFilter = encoder.getImplicitFilter(); 
+        if (implicitFilter != null) {
+            gen.writeln("/RawData currentfile /ASCII85Decode filter def");
+            gen.writeln("/Data RawData " + implicitFilter + " filter def");
+        } else {
+            if (gen.getPSLevel() >= 3) {
+                gen.writeln("/RawData currentfile /ASCII85Decode filter def");
+                gen.writeln("/Data RawData /FlateDecode filter def");
+            } else {
+                gen.writeln("/RawData currentfile /ASCII85Decode filter def");
+                gen.writeln("/Data RawData /RunLengthDecode filter def");
+            }
+        }
+        writeImageCommand(imgDim, colorSpace, invertImage, gen, "Data");
+        /* the following two lines could be enabled if something still goes wrong
+         * gen.write("Data closefile");
+         * gen.write("RawData flushfile");
+         */
+        gen.writeln("} stopped {handleerror} if");
+        gen.writeln("  RawData flushfile");
+        gen.writeln("} exec");
+
+        compressAndWriteBitmap(encoder, gen);
+
+        gen.writeln("");
+        gen.commentln("%AXGEndBitmap");
+        gen.restoreGraphicsState();
+    }
+
+    /**
+     * Writes a bitmap image to the PostScript stream.
+     * @param img the bitmap image as a byte array
+     * @param targetRect the target rectangle to place the image in
+     * @param gen the PostScript generator
+     * @throws IOException In case of an I/O exception
+     */
+    private static void writeImage(RenderedImage img,
+            Rectangle2D targetRect, PSGenerator gen) throws IOException {
+        ImageEncoder encoder = new RenderedImageEncoder(img);
+        String imgDescription = img.getClass().getName();
+        
+        gen.saveGraphicsState();
+        translateAndScale(gen, targetRect);
 
         gen.commentln("%AXGBeginBitmap: " + imgDescription);
 
@@ -68,9 +153,10 @@
         // Template: (RawData is used for the EOF signal only)
         // gen.write("/RawData currentfile <first filter> filter def");
         // gen.write("/Data RawData <second filter> <third filter> [...] def");
-        if (isJPEG) {
+        String implicitFilter = encoder.getImplicitFilter(); 
+        if (implicitFilter != null) {
             gen.writeln("/RawData currentfile /ASCII85Decode filter def");
-            gen.writeln("/Data RawData << >> /DCTDecode filter def");
+            gen.writeln("/Data RawData " + implicitFilter + " filter def");
         } else {
             if (gen.getPSLevel() >= 3) {
                 gen.writeln("/RawData currentfile /ASCII85Decode filter def");
@@ -80,7 +166,10 @@
                 gen.writeln("/Data RawData /RunLengthDecode filter def");
             }
         }
-        writeImageCommand(imgDim, colorSpace, gen, "Data");
+        PSDictionary imageDict = new PSDictionary();
+        imageDict.put("/DataSource", "Data");
+        writeImageCommand(img, imageDict, gen);
+
         /* the following two lines could be enabled if something still goes wrong
          * gen.write("Data closefile");
          * gen.write("RawData flushfile");
@@ -89,32 +178,136 @@
         gen.writeln("  RawData flushfile");
         gen.writeln("} exec");
 
-        encodeBitmap(img, isJPEG, gen);
+        compressAndWriteBitmap(encoder, gen);
 
         gen.writeln("");
         gen.commentln("%AXGEndBitmap");
         gen.restoreGraphicsState();
     }
 
+    private static void writeImageCommand(RenderedImage img,
+            PSDictionary imageDict, PSGenerator gen) throws IOException {
+        String w = Integer.toString(img.getWidth());
+        String h = Integer.toString(img.getHeight());
+        imageDict.put("/ImageType", "1");
+        imageDict.put("/Width", w);
+        imageDict.put("/Height", h);
+        
+        ColorModel cm = img.getColorModel();
+        ColorSpace cs = cm.getColorSpace();
+        int tilesX = img.getNumXTiles();
+        int tilesY = img.getNumYTiles();
+        boolean multiTile = (tilesX != 1 || tilesY != 1);
+        
+        boolean invertColors = false;
+        String decodeArray;
+        boolean monochrome1Bit = (cm.getPixelSize() == 1 && !multiTile);
+        if (cs.getType() == ColorSpace.TYPE_CMYK) {
+            if (invertColors) {
+                decodeArray = "[1 0 1 0 1 0 1 0]";
+            } else {
+                decodeArray = "[0 1 0 1 0 1 0 1]";
+            }
+        } else if (cs.getType() == ColorSpace.TYPE_GRAY || monochrome1Bit) {
+            decodeArray = "[0 1]";
+        } else {
+            decodeArray = "[0 1 0 1 0 1]";
+        }
+        
+        int bitsPerComp = 8;
+        
+        // Setup scanning for left-to-right and top-to-bottom
+        imageDict.put("/ImageMatrix", "[" + w + " 0 0 " + h + " 0 0]");
+        
+        //Prepare color space
+        boolean indexedColorSpace = (cm instanceof IndexColorModel);
+        if (indexedColorSpace) {
+            if (!multiTile) {
+                IndexColorModel im = (IndexColorModel)cm;
+                gen.write("[/Indexed " + getColorSpaceName(cs));
+                int c = im.getMapSize();
+                int hival = c - 1;
+                if (hival > 4095) {
+                    throw new UnsupportedOperationException("hival must not go beyond 4095");
+                }
+                gen.writeln(" " + Integer.toString(hival));
+                gen.write("  <");
+                int[] palette = new int[c];
+                im.getRGBs(palette);
+                for (int i = 0; i < c; i++) {
+                    if (i > 0) {
+                        if ((i % 8) == 0) {
+                            gen.newLine();
+                            gen.write("   ");
+                        } else {
+                            gen.write(" ");
+                        }
+                    }
+                    gen.write(rgb2Hex(palette[i]));
+                }
+                gen.writeln(">");
+                gen.writeln("] setcolorspace");
+                decodeArray = "[0 " + Integer.toString(hival) + "]";
+                bitsPerComp = im.getPixelSize();
+            } else {
+                cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+                gen.writeln(getColorSpaceName(cs) + " setcolorspace");
+            }
+        } else {
+            gen.writeln(getColorSpaceName(cs) + " setcolorspace");
+        }
+        imageDict.put("/BitsPerComponent", Integer.toString(bitsPerComp));
+        imageDict.put("/Decode", decodeArray);
+        gen.write(imageDict.toString());
+        gen.writeln(" image");
+    }
+
+    private static final char[] HEX = {
+            '0', '1', '2', '3', '4', '5', '6', '7',
+            '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+        };
+    
+    private static String rgb2Hex(int rgb) {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 5; i >= 0; i--) {
+            int shift = i * 4;
+            int n = (rgb & (15 << shift)) >> shift;
+            sb.append(HEX[n % 16]);
+        }
+        return sb.toString();
+    }
+    
+    /**
+     * Renders a bitmap image to PostScript.
+     * @param img image to render
+     * @param x x position
+     * @param y y position
+     * @param w width
+     * @param h height
+     * @param gen PS generator
+     * @throws IOException In case of an I/O problem while rendering the image
+     */
+    public static void renderBitmapImage(RenderedImage img, 
+                float x, float y, float w, float h, PSGenerator gen)
+                    throws IOException {
+        Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
+        writeImage(img, targetRect, gen);
+    }
+
     private static void writeImageCommand(Dimension imgDim, ColorSpace colorSpace, 
-            PSGenerator gen, String dataSource) throws IOException {
-        boolean iscolor = colorSpace.getType() != ColorSpace.TYPE_GRAY;
+            boolean invertImage, PSGenerator gen, String dataSource) throws IOException {
         prepareColorspace(colorSpace, gen);
         gen.writeln("<< /ImageType 1");
         gen.writeln("  /Width " + imgDim.width);
         gen.writeln("  /Height " + imgDim.height);
         gen.writeln("  /BitsPerComponent 8");
-        if (colorSpace.getType() == ColorSpace.TYPE_CMYK) {
-            if (false /*TODO img.invertImage()*/) {
-                gen.writeln("  /Decode [1 0 1 0 1 0 1 0]");
-            } else {
-                gen.writeln("  /Decode [0 1 0 1 0 1 0 1]");
-            }
-        } else if (iscolor) {
-            gen.writeln("  /Decode [0 1 0 1 0 1]");
-        } else {
-            gen.writeln("  /Decode [0 1]");
+        StringBuffer sb = new StringBuffer();
+        sb.append("  /Decode [");
+        for (int i = 0; i < colorSpace.getNumComponents(); i++) {
+            sb.append(invertImage ? "1 0 " : "0 1 ");
         }
+        sb.append("]");
+        gen.writeln(sb.toString());
         // Setup scanning for left-to-right and top-to-bottom
         gen.writeln("  /ImageMatrix [" + imgDim.width + " 0 0 "
               + imgDim.height + " 0 0]");
@@ -136,10 +329,44 @@
      * @param gen the PostScript generator
      * @return a PSResource representing the form for resource tracking
      * @throws IOException In case of an I/O exception
+     * @deprecated Please use the variant with the more versatile ImageEncoder as parameter
      */
-    public static PSResource writeReusableImage(byte[] img,
+    public static PSResource writeReusableImage(final byte[] img,
             Dimension imgDim, String formName, String imageDescription,
-            boolean isJPEG, ColorSpace colorSpace,
+            final boolean isJPEG, ColorSpace colorSpace,
+            PSGenerator gen) throws IOException {
+        ImageEncoder encoder = new ImageEncoder() {
+            public void writeTo(OutputStream out) throws IOException {
+                out.write(img);
+            }
+            public String getImplicitFilter() {
+                if (isJPEG) {
+                    return "<< >> /DCTDecode";
+                } else {
+                    return null;
+                }
+            }
+        };
+        return writeReusableImage(encoder, imgDim, formName,
+                imageDescription, colorSpace, false, gen);
+    }
+    
+    /**
+     * Writes a bitmap image as a PostScript form enclosed by DSC resource wrappers to the
+     * PostScript file.
+     * @param encoder the ImageEncoder that will provide the raw bitmap data
+     * @param imgDim the dimensions of the image
+     * @param formName the name of the PostScript form to use
+     * @param imageDescription a description of the image added as a DSC Title comment
+     * @param colorSpace the color space of the image
+     * @param invertImage true if the image shall be inverted
+     * @param gen the PostScript generator
+     * @return a PSResource representing the form for resource tracking
+     * @throws IOException In case of an I/O exception
+     */
+    public static PSResource writeReusableImage(ImageEncoder encoder,
+            Dimension imgDim, String formName, String imageDescription,
+            ColorSpace colorSpace, boolean invertImage,
             PSGenerator gen) throws IOException {
         if (gen.getPSLevel() < 2) {
             throw new UnsupportedOperationException(
@@ -152,8 +379,9 @@
         }
         
         String additionalFilters;
-        if (isJPEG) {
-            additionalFilters = "/ASCII85Decode filter /DCTDecode filter";
+        String implicitFilter = encoder.getImplicitFilter(); 
+        if (implicitFilter != null) {
+            additionalFilters = "/ASCII85Decode filter " + implicitFilter + " filter";
         } else {
             if (gen.getPSLevel() >= 3) {
                 additionalFilters = "/ASCII85Decode filter /FlateDecode filter";
@@ -180,7 +408,7 @@
         } else {
             dataSource = dataName;
         }
-        writeImageCommand(imgDim, colorSpace, gen, dataSource); 
+        writeImageCommand(imgDim, colorSpace, invertImage, gen, dataSource); 
         gen.writeln("    grestore");
         gen.writeln("  } bind");
         gen.writeln(">> def");
@@ -193,7 +421,7 @@
         } else {
             gen.writeln("/ReusableStreamDecode filter");
         }
-        encodeBitmap(img, isJPEG, gen);
+        compressAndWriteBitmap(encoder, gen);
         gen.writeln("def");
         gen.writeDSCComment(DSCConstants.END_RESOURCE);
         PSResource res = new PSResource(PSResource.TYPE_FORM, formName); 
@@ -228,10 +456,7 @@
             Rectangle2D targetRect, 
             PSGenerator gen) throws IOException {
         gen.saveGraphicsState();
-        gen.writeln(gen.formatDouble(targetRect.getX()) + " " 
-                + gen.formatDouble(targetRect.getY()) + " translate");
-        gen.writeln(gen.formatDouble(targetRect.getWidth()) + " " 
-                + gen.formatDouble(targetRect.getHeight()) + " scale");
+        translateAndScale(gen, targetRect);
         gen.writeln(form.getName() + " execform");
         
         gen.getResourceTracker().notifyResourceUsageOnPage(form);
@@ -240,20 +465,25 @@
     
     private static void prepareColorspace(ColorSpace colorSpace, PSGenerator gen)
                 throws IOException {
+        gen.writeln(getColorSpaceName(colorSpace) + " setcolorspace");
+    }
+
+    private static String getColorSpaceName(ColorSpace colorSpace) {
         if (colorSpace.getType() == ColorSpace.TYPE_CMYK) {
-            gen.writeln("/DeviceCMYK setcolorspace");
+            return("/DeviceCMYK");
         } else if (colorSpace.getType() == ColorSpace.TYPE_GRAY) {
-            gen.writeln("/DeviceGray setcolorspace");
+            return("/DeviceGray");
         } else {
-            gen.writeln("/DeviceRGB setcolorspace");
+            return("/DeviceRGB");
         }
     }
 
-    private static void encodeBitmap(byte[] img, boolean isJPEG, PSGenerator gen)
+    private static void compressAndWriteBitmap(ImageEncoder encoder, PSGenerator gen)
                 throws IOException {
         OutputStream out = gen.getOutputStream();
         out = new ASCII85OutputStream(out);
-        if (isJPEG) {
+        String implicitFilter = encoder.getImplicitFilter();
+        if (implicitFilter != null) {
             //nop
         } else {
             if (gen.getPSLevel() >= 3) {
@@ -262,7 +492,9 @@
                 out = new RunLengthEncodeOutputStream(out);
             }
         }
-        out.write(img);
+        CountingOutputStream cout = new CountingOutputStream(out);
+        encoder.writeTo(cout);
+        System.out.println("Bitmap size in bytes: " + cout.getByteCount());
         if (out instanceof Finalizable) {
             ((Finalizable)out).finalizeStream();
         } else {
@@ -271,29 +503,81 @@
         gen.newLine();
     }
 
-    /**
-     * Renders a bitmap image to PostScript.
-     * @param img image to render
-     * @param x x position
-     * @param y y position
-     * @param w width
-     * @param h height
-     * @param gen PS generator
-     * @throws IOException In case of an I/O problem while rendering the image
-     */
-    public static void renderBitmapImage(RenderedImage img, 
-                float x, float y, float w, float h, PSGenerator gen)
-                    throws IOException {
-        byte[] imgmap = getBitmapBytes(img);
-
-        String imgName = img.getClass().getName();
-        Dimension imgDim = new Dimension(img.getWidth(), img.getHeight());
-        Rectangle2D targetRect = new Rectangle2D.Double(x, y, w, h);
-        boolean isJPEG = false;
-        writeImage(imgmap, imgDim, imgName, targetRect, isJPEG, 
-                img.getColorModel().getColorSpace(), gen);
+    private static void translateAndScale(PSGenerator gen, Rectangle2D targetRect)
+            throws IOException {
+        gen.writeln(gen.formatDouble(targetRect.getX()) + " " 
+                + gen.formatDouble(targetRect.getY()) + " translate");
+        gen.writeln(gen.formatDouble(targetRect.getWidth()) + " " 
+                + gen.formatDouble(targetRect.getHeight()) + " scale");
     }
 
+    private static class RenderedImageEncoder implements ImageEncoder {
+
+        private RenderedImage img;
+        
+        public RenderedImageEncoder(RenderedImage img) {
+            this.img = img;
+        }
+        
+        private void writeRGBTo(OutputStream out) throws IOException {
+            int[] tmpMap = getRGB(img, 0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth());
+            // Should take care of the ColorSpace and bitsPerPixel
+            for (int y = 0, my = img.getHeight(); y < my; y++) {
+                for (int x = 0, mx = img.getWidth(); x < mx; x++) {
+                    int p = tmpMap[y * mx + x];
+                    int r = (p >> 16) & 0xFF;
+                    int g = (p >> 8) & 0xFF;
+                    int b = (p) & 0xFF;
+                    out.write(r);
+                    out.write(g);
+                    out.write(b);
+                }
+            }
+        }
+        
+        private boolean optimizedWriteTo(OutputStream out) throws IOException {
+            ColorModel cm = img.getColorModel();
+            ColorSpace cs = cm.getColorSpace();
+            int tilesX = img.getNumXTiles();
+            int tilesY = img.getNumYTiles();
+            boolean multiTile = (tilesX != 1 || tilesY != 1); 
+            if (cm.getNumComponents() == 1 && cs.getType() == ColorSpace.TYPE_GRAY && !multiTile) {
+                System.out.println("gray");
+                Raster raster = img.getTile(0, 0);
+                DataBuffer buffer = raster.getDataBuffer();
+                if (buffer instanceof DataBufferByte) {
+                    out.write(((DataBufferByte)buffer).getData());
+                    return true;
+                }
+            }
+            if (!multiTile && cm instanceof IndexColorModel) {
+                IndexColorModel im = (IndexColorModel)cm;
+                //int pixelSize = im.getPixelSize(); 
+                Raster raster = img.getTile(0, 0);
+                DataBuffer buffer = raster.getDataBuffer();
+                if (buffer instanceof DataBufferByte) {
+                    DataBufferByte byteBuffer = (DataBufferByte)buffer;
+                    out.write(byteBuffer.getData());
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        public void writeTo(OutputStream out) throws IOException {
+            boolean optimized = optimizedWriteTo(out);
+            if (!optimized) {
+                //fallback
+                writeRGBTo(out);
+            }
+        }
+
+        public String getImplicitFilter() {
+            return null; //No implicit filters with RenderedImage instances
+        }
+        
+    }
+    
     private static byte[] getBitmapBytes(RenderedImage img) {
         int[] tmpMap = getRGB(img, 0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth());
         // Should take care of the ColorSpace and bitsPerPixel
@@ -374,21 +658,47 @@
      * Places an EPS file in the PostScript stream.
      * @param rawEPS byte array containing the raw EPS data
      * @param name name for the EPS document
-     * @param x x-coordinate of viewport in millipoints
-     * @param y y-coordinate of viewport in millipoints
-     * @param w width of viewport in millipoints
-     * @param h height of viewport in millipoints
+     * @param x x-coordinate of viewport in points
+     * @param y y-coordinate of viewport in points
+     * @param w width of viewport in points
+     * @param h height of viewport in points
      * @param bboxx x-coordinate of EPS bounding box in points
      * @param bboxy y-coordinate of EPS bounding box in points
      * @param bboxw width of EPS bounding box in points
      * @param bboxh height of EPS bounding box in points
      * @param gen the PS generator
      * @throws IOException in case an I/O error happens during output
+     * @deprecated Please use the variant with the InputStream as parameter
      */
     public static void renderEPS(byte[] rawEPS, String name,
                     float x, float y, float w, float h,
                     float bboxx, float bboxy, float bboxw, float bboxh,
                     PSGenerator gen) throws IOException {
+       renderEPS(new java.io.ByteArrayInputStream(rawEPS), name,
+               x, y, w, h,
+               bboxx, bboxy, bboxw, bboxh,
+               gen);
+    }
+    
+    /**
+     * Places an EPS file in the PostScript stream.
+     * @param in the InputStream that contains the EPS stream
+     * @param name name for the EPS document
+     * @param x x-coordinate of viewport in points
+     * @param y y-coordinate of viewport in points
+     * @param w width of viewport in points
+     * @param h height of viewport in points
+     * @param bboxx x-coordinate of EPS bounding box in points
+     * @param bboxy y-coordinate of EPS bounding box in points
+     * @param bboxw width of EPS bounding box in points
+     * @param bboxh height of EPS bounding box in points
+     * @param gen the PS generator
+     * @throws IOException in case an I/O error happens during output
+     */
+    public static void renderEPS(InputStream in, String name,
+                    float x, float y, float w, float h,
+                    float bboxx, float bboxy, float bboxw, float bboxh,
+                    PSGenerator gen) throws IOException {
         gen.getResourceTracker().notifyResourceUsageOnPage(PSProcSets.EPS_PROCSET);
         gen.writeln("%AXGBeginEPS: " + name);
         gen.writeln("BeginEPSF");
@@ -404,14 +714,15 @@
         if (bboxx != 0 || bboxy != 0) {
             gen.writeln(gen.formatDouble(-bboxx) + " " + gen.formatDouble(-bboxy) + " translate");
         }
-        gen.writeln(gen.formatDouble(bboxy) + " " + gen.formatDouble(bboxy) 
+        gen.writeln(gen.formatDouble(bboxx) + " " + gen.formatDouble(bboxy) 
                 + " " + gen.formatDouble(bboxw) + " " + gen.formatDouble(bboxh) + " re clip");
         gen.writeln("newpath");
         
         PSResource res = new PSResource(PSResource.TYPE_FILE, name);
         gen.getResourceTracker().notifyResourceUsageOnPage(res);
         gen.writeDSCComment(DSCConstants.BEGIN_DOCUMENT, res.getName());
-        gen.writeByteArr(rawEPS);
+        IOUtils.copy(in, gen.getOutputStream());
+        gen.newLine();
         gen.writeDSCComment(DSCConstants.END_DOCUMENT);
         gen.writeln("EndEPSF");
         gen.writeln("%AXGEndEPS");

Modified: xmlgraphics/commons/trunk/status.xml
URL: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/status.xml?rev=599383&r1=599382&r2=599383&view=diff
==============================================================================
--- xmlgraphics/commons/trunk/status.xml (original)
+++ xmlgraphics/commons/trunk/status.xml Thu Nov 29 03:15:22 2007
@@ -25,6 +25,11 @@
 	</todo>
 	<changes>
 		<release version="Trunk" date="n/a">
+		  <action context="Code" dev="JM" type="update">
+		    PostScript: Improved PSImageUtils by introducing the ImageEncoder interface and
+		    allowing for streams instead of byte arrays for data transfer which can lower
+		    memory consumption.
+		  </action>
 		  <action context="Code" dev="JM" type="fix">
 		    PostScript: Fixed %%EOF checking for nested documents.
 		  </action>



---------------------------------------------------------------------
Apache XML Graphics Project URL: http://xmlgraphics.apache.org/
To unsubscribe, e-mail: commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: commits-help@xmlgraphics.apache.org