Yes, I thought about that too. Where do you think we should put it ? framework/images is mostly for static content, rather common I guess ?
BTW, I have refactored the code below since...

Jacques

From: "Adam Heath" <doo...@brainfood.com>
jler...@apache.org wrote:

Added: ofbiz/trunk/applications/product/src/org/ofbiz/image/ImageTransform.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/image/ImageTransform.java?rev=739042&view=auto
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/image/ImageTransform.java 
(added)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/image/ImageTransform.java 
Thu Jan 29 22:06:32 2009

I don't think this file should be in product.  It's too generic.


@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * 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.
+ 
*******************************************************************************/
+package org.ofbiz.image;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.ImagingOpException;
+import java.awt.RenderingHints;
+import java.awt.RenderingHints.Key;
+import java.io.File;
+import java.io.IOException;
+import java.lang.IllegalArgumentException;
+import java.lang.Double;
+import java.lang.Object;
+import java.lang.String;
+import java.lang.System;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.imageio.ImageIO;
+
+import javolution.util.FastList;
+import javolution.util.FastMap;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.jdom.filter.Filter;
+import org.jdom.JDOMException;

Please do not use jdom, there's no need to.  UtilXml does everything that
you need in this file(which is just parsing xml from java.io.File).  The
looping over the elements is standard dom.

+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.service.ServiceUtil;
+
+
+/**
+ * ImageTransform Class
+ * <p>
+ * Services to apply tranformation for images
+ */
+public class ImageTransform {
+
+    public static final String module = ImageTransform.class.getName();
+//    public static final String err_resource = "ContentErrorUiLabels";
+
+    public ImageTransform() {}
+
+
+    /**
+     * getBufferedImage
+     * <p>
+     * Set a buffered image
+     *
+     * @param   context
+     * @param   fileLocation    Full file Path or Url
+     * @return                  Url images for all different size types
+     * @throws  IOException Error prevents the document from being fully parsed
+     * @throws  JDOMException Errors occur in parsing
+     */
+    public Map getBufferedImage(String fileLocation)
+        throws IllegalArgumentException, IOException {
+
+        /* VARIABLES */
+        BufferedImage bufImg;
+        FastMap result = new FastMap();
+
+        /* BUFFERED IMAGE */
+        try{
+            bufImg = ImageIO.read(new File(fileLocation));
+        }catch(IllegalArgumentException e){
+            String errMsg = "Input is null : " + fileLocation + " ; " + 
e.toString();
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", errMsg);
+            return result;
+        }catch(IOException e){
+            String errMsg = "Error occurs during reading : " + fileLocation + " ; 
" + e.toString();
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", errMsg);
+            return result;
+        }
+
+        result.put("responseMessage", "success");
+        result.put("bufferedImage", bufImg);
+        return result;
+
+    } // getBufferedImage
+
+
+    /**
+     * scaleImageInAllSize
+     * <p>
+     * Scale the original image into all different size Types (small, medium, 
large, detail)
+     *
+     * @param   context                     Context
+     * @param   filenameToUse               Filename of future image files
+     * @param   viewType                    "Main" view or "additional" view
+     * @param   viewNumber                  If it's the main view, viewNumber = 
"0"
+     * @return                              Url images for all different size 
types
+     * @throws  IllegalArgumentException    Any parameter is null
+     * @throws  ImagingOpException          The transform is non-invertible
+     * @throws  IOException                 Error prevents the document from 
being fully parsed
+     * @throws  JDOMException               Errors occur in parsing
+     */
+ public Map scaleImageInAllSize(Map<String, ? extends Object> context, String filenameToUse, String viewType, String viewNumber)
+        throws IllegalArgumentException, ImagingOpException, IOException, 
JDOMException {
+
+        /* VARIABLES */
+        List<String> sizeTypeList = UtilMisc.toList("small", "medium", "large", 
"detail");
+        List<String> extensionList = UtilMisc.toList("jpeg", "jpg", "png");
+        int index;
+ LinkedHashMap<String, LinkedHashMap<String, String>> imgPropertyMap = new LinkedHashMap<String, LinkedHashMap<String, String>>();
+        BufferedImage bufImg, bufNewImg;
+        double imgHeight, imgWidth, defaultHeight, defaultWidth, scaleFactor;
+        AffineTransformOp op;
+        LinkedHashMap<String, String> imgUrlMap = new LinkedHashMap<String, 
String>();
+        LinkedHashMap resultXMLMap = new LinkedHashMap();
+        LinkedHashMap resultBufImgMap = new LinkedHashMap();
+        LinkedHashMap resultScaleImgMap = new LinkedHashMap();
+        FastMap result = new FastMap();
+
+        /* ImageProperties.xml */
+        String imgPropertyFullPath = System.getProperty("ofbiz.home") + 
"/applications/product/config/ImageProperties.xml";
+        resultXMLMap.putAll(getXMLValue(imgPropertyFullPath));
+        if(resultXMLMap.containsKey("responseMessage") && 
resultXMLMap.get("responseMessage").equals("success")){
+            imgPropertyMap.putAll((LinkedHashMap) resultXMLMap.get("xml"));
+        }else{
+            String errMsg = "Impossible to parse ImageProperties.xml ";
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", errMsg);
+            return result;
+        }
+
+        /* IMAGE */
+        // get Name and Extension
+        index = filenameToUse.lastIndexOf(".");
+        String imgName = filenameToUse.substring(0, index - 1);
+        String imgExtension = filenameToUse.substring(index + 1);
+        // paths
+        String mainFilenameFormat = UtilProperties.getPropertyValue("catalog", 
"image.filename.format");
+ String imageServerPath = FlexibleStringExpander.expandString(UtilProperties.getPropertyValue("catalog", "image.server.path"), context);
+        String imageUrlPrefix = UtilProperties.getPropertyValue("catalog", 
"image.url.prefix");
+
+        String id = new String();
+        String type = new String();
+        if(viewType.toLowerCase().contains("main")){
+            type = "original";
+            id = imgName;
+        }else if(viewType.toLowerCase().contains("additional") && viewNumber != null && 
!viewNumber.equals("0")){
+            type = "additional";
+            id = imgName + "_View_" + viewNumber;
+        }else{
+            return ServiceUtil.returnError("View Type : " + type + " is 
wrong");
+        }
+        FlexibleStringExpander mainFilenameExpander = 
FlexibleStringExpander.getInstance(mainFilenameFormat);
+ String fileLocation = mainFilenameExpander.expandString(UtilMisc.toMap("location", "products", "type", type, "id", filenameToUse));
+        String filePathPrefix = "";
+        if (fileLocation.lastIndexOf("/") != -1) {
+ filePathPrefix = fileLocation.substring(0, fileLocation.lastIndexOf("/") + 1); // adding 1 to include the trailing slash
+        }
+
+
+
+        /* get original BUFFERED IMAGE */
+        resultBufImgMap.putAll(this.getBufferedImage(imageServerPath + "/" + 
filePathPrefix + filenameToUse));
+
+        if(resultBufImgMap.containsKey("responseMessage") && 
resultBufImgMap.get("responseMessage").equals("success")){
+            bufImg = (BufferedImage) resultBufImgMap.get("bufferedImage");
+
+            // get Dimensions
+            imgHeight = (double) bufImg.getHeight();
+            imgWidth = (double) bufImg.getWidth();
+            if(imgHeight == 0.0 || imgWidth == 0.0){
+ String errMsg = "Any current image dimension is null : imgHeight = " + imgHeight + " ; imgWidth = " + imgWidth + ";";
+                Debug.logError(errMsg, module);
+                result.put("errorMessage", errMsg);
+                return result;
+            }
+
+            // new Filename Format
+            FlexibleStringExpander addFilenameExpander = mainFilenameExpander;
+            if(viewType.toLowerCase().contains("additional")){
+ String addFilenameFormat = UtilProperties.getPropertyValue("catalog", "image.filename.additionalviewsize.format");
+                addFilenameExpander = 
FlexibleStringExpander.getInstance(addFilenameFormat);
+            }
+
+            /* scale Image for each Size Type */
+            Iterator<String> sizeIter = sizeTypeList.iterator();
+            while(sizeIter.hasNext()){
+                String sizeType = sizeIter.next();
+
+                resultScaleImgMap.putAll(this.scaleImage(bufImg, imgHeight, 
imgWidth, imgPropertyMap, sizeType));
+
+ if(resultScaleImgMap.containsKey("responseMessage") && resultScaleImgMap.get("responseMessage").equals("success")){
+                    bufNewImg = (BufferedImage) 
resultScaleImgMap.get("bufferedImage");
+                    Double scaleFactorDb = (Double) 
resultScaleImgMap.get("scaleFactor");
+                    scaleFactor = scaleFactorDb.doubleValue();
+
+                    // define Interpolation
+                    LinkedHashMap<RenderingHints.Key, Object> rhMap = new 
LinkedHashMap<RenderingHints.Key, Object>();
+                        rhMap.put(RenderingHints.KEY_ALPHA_INTERPOLATION, 
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
+                        rhMap.put(RenderingHints.KEY_ANTIALIASING, 
RenderingHints.VALUE_ANTIALIAS_ON);
+                        rhMap.put(RenderingHints.KEY_COLOR_RENDERING, 
RenderingHints.VALUE_COLOR_RENDER_QUALITY);
+                        rhMap.put(RenderingHints.KEY_DITHERING, 
RenderingHints.VALUE_DITHER_DISABLE);
+                        rhMap.put(RenderingHints.KEY_FRACTIONALMETRICS, 
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+                        rhMap.put(RenderingHints.KEY_INTERPOLATION, 
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+                        rhMap.put(RenderingHints.KEY_RENDERING, 
RenderingHints.VALUE_RENDER_QUALITY);
+                        //rhMap.put(RenderingHints.KEY_STROKE_CONTROL, 
RenderingHints.VALUE_STROKE_PURE);
+                        rhMap.put(RenderingHints.KEY_TEXT_ANTIALIASING, 
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+                    RenderingHints rh = new RenderingHints(rhMap);
+
+                    /* IMAGE TRANFORMATION */
+                    AffineTransform tx = new AffineTransform();
+                    tx.scale(scaleFactor, scaleFactor);
+
+
+                    try{
+                        op = new AffineTransformOp(tx, rh);
+                    }catch(ImagingOpException e){
+                        String errMsg = "The transform is non-invertible" + 
e.toString();
+                        Debug.logError(errMsg, module);
+                        result.put("errorMessage", errMsg);
+                        return result;
+                    }
+
+                    // write the New Scaled Image
+                    String newFileLocation = new String();
+                    if(viewType.toLowerCase().contains("main")){
+ newFileLocation = mainFilenameExpander.expandString(UtilMisc.toMap("location", "products", "type", sizeType, "id", id));
+                    }else if(viewType.toLowerCase().contains("additional")){
+ newFileLocation = addFilenameExpander.expandString(UtilMisc.toMap("location", "products", "viewtype", viewType, "sizetype", sizeType,"id", id));
+                    }
+                    String newFilePathPrefix = "";
+                    if (newFileLocation.lastIndexOf("/") != -1) {
+ newFilePathPrefix = newFileLocation.substring(0, newFileLocation.lastIndexOf("/") + 1); // adding 1 to include the trailing slash
+                    }
+
+                    // choose final extension
+                    String finalExtension = new String();
+                    if(!extensionList.contains(imgExtension.toLowerCase())){
+                        finalExtension = 
imgPropertyMap.get("format").get("extension");
+                    }else{
+                        finalExtension = imgExtension;
+                    }
+
+                    String targetDirectory = imageServerPath + "/" + 
newFilePathPrefix;
+                    File targetDir = new File(targetDirectory);
+                    if (!targetDir.exists()) {
+                        boolean created = targetDir.mkdirs();
+                        if (!created) {
+                            Debug.logFatal("Unable to create target directory - 
" + targetDirectory, module);
+                            return ServiceUtil.returnError("Unable to create target 
directory - " + targetDirectory);
+                        }
+                    }
+
+                    // write new image
+                    try{
+ ImageIO.write(op.filter(bufImg, bufNewImg), imgExtension, new File(imageServerPath + "/" + newFilePathPrefix + filenameToUse));
+                    }catch(IllegalArgumentException e){
+                        String errMsg = "Any parameter is null" + e.toString();
+                        Debug.logError(errMsg, module);
+                        result.put("errorMessage", errMsg);
+                        return result;
+                    }catch(IOException e){
+                        String errMsg = "An error occurs during writing" + 
e.toString();
+                        Debug.logError(errMsg, module);
+                        result.put("errorMessage", errMsg);
+                        return result;
+                    }
+
+                    /* write Return Result */
+                    String imageUrl = imageUrlPrefix + "/" + newFilePathPrefix 
+ filenameToUse;
+                    imgUrlMap.put(sizeType, imageUrl);
+
+                } // scaleImgMap
+            } // sizeIter
+        }
+
+        result.put("responseMessage", "success");
+        result.put("imageUrlMap", imgUrlMap);
+        result.put("original", resultBufImgMap);
+        return result;
+
+    } // scaleImageInAllSize
+
+
+    /**
+     * scaleImage
+     * <p>
+     * scale original image related to the ImageProperties.xml dimensions
+     *
+     * @param   bufImg          Buffered image to scale
+     * @param   imgHeight       Original image height
+     * @param   imgwidth        Original image width
+     * @param   dimensionMap    Image dimensions by size type
+     * @param   sizeType        Size type to scale
+     * @return                  New scaled buffered image
+     */
+ private Map scaleImage(BufferedImage bufImg, double imgHeight, double imgWidth, LinkedHashMap<String, LinkedHashMap<String, String>> dimensionMap, String sizeType){
+
+        /* VARIABLES */
+        BufferedImage bufNewImg;
+        double defaultHeight, defaultWidth, scaleFactor;
+        FastMap result = new FastMap();
+
+        /* DIMENSIONS from ImageProperties */
+        defaultHeight = 
Double.parseDouble(dimensionMap.get(sizeType).get("height").toString());
+        defaultWidth = 
Double.parseDouble(dimensionMap.get(sizeType).get("width").toString());
+        if(defaultHeight == 0.0 || defaultWidth == 0.0){
+ String errMsg = "Any default dimension is null : defaultHeight = " + defaultHeight + " ; defaultWidth = " + defaultWidth + ";";
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", errMsg);
+            return result;
+        }
+
+        /* SCALE FACTOR */
+        // find the right Scale Factor related to the Image Dimensions
+        if(imgHeight > imgWidth){
+            scaleFactor = defaultHeight / imgHeight;
+            if(scaleFactor == 0.0){
+ String errMsg = "Height scaleFactor is null (defaultHeight = " + defaultHeight + "; imgHeight = " + imgHeight + ";";
+                Debug.logError(errMsg, module);
+                result.put("errorMessage", errMsg);
+                return result;
+            }
+            // get scaleFactor from the smallest width
+            if(defaultWidth < (imgWidth * scaleFactor)){
+                scaleFactor = defaultWidth / imgWidth;
+            }
+        }else{
+            scaleFactor = defaultWidth / imgWidth;
+            if(scaleFactor == 0.0){
+                String errMsg = "Width scaleFactor is null (defaultWidth = " + defaultWidth + 
"; imgWidth = " + imgWidth + ";";
+                Debug.logError(errMsg, module);
+                result.put("errorMessage", errMsg);
+                return result;
+            }
+            // get scaleFactor from the smallest height
+            if(defaultHeight < (imgHeight * scaleFactor)){
+                scaleFactor = defaultHeight / imgHeight;
+            }
+        }
+
+        if(scaleFactor == 0.0){
+            String errMsg = "Final scaleFactor is null = " + scaleFactor + ";";
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", errMsg);
+            return result;
+        }
+
+        bufNewImg = new BufferedImage( (int) (imgWidth * scaleFactor), (int) 
(imgHeight * scaleFactor), bufImg.getType());
+
+        result.put("responseMessage", "success");
+        result.put("bufferedImage", bufNewImg);
+        result.put("scaleFactor", scaleFactor);
+        return result;
+
+    } // scaleImage
+
+
+    /**
+     * getXMLValue
+     * <p>
+     * From a XML element, get a values map
+     *
+     * @param fileFullPath      File path to parse
+     * @return Map contains asked attribute values by attribute name
+     */
+    private Map getXMLValue(String fileFullPath)
+        throws IllegalStateException, IOException, JDOMException {
+
+        /* VARIABLES */
+        Document document;
+        Element rootElt;
+        List<Element> eltList;
+        LinkedHashMap<String, LinkedHashMap> valueMap = new LinkedHashMap<String, 
LinkedHashMap>();
+        FastMap result = new FastMap();
+
+        /* PARSING */
+        SAXBuilder sxb = new SAXBuilder();
+        try{
+            // JDOM
+            document = sxb.build(new File(fileFullPath));
+        }catch(JDOMException e){
+            String errMsg = "Errors occur in parsing ImageProperties.xml" + 
e.toString();
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", "error");
+            return result;
+        }catch(IOException e){
+            String errMsg = "Error prevents the document from being fully 
parsed" + e.toString();
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", "error");
+            return result;
+        }
+        // set Root Element
+        try{
+            rootElt = document.getRootElement();
+        }catch(IllegalStateException e){
+            String errMsg = "Root element hasn't been set" + e.toString();
+            Debug.logError(errMsg, module);
+            result.put("errorMessage", "error");
+            return result;
+        }
+
+        /* get NAME and VALUE */
+        Iterator<Element> eltIter = rootElt.getChildren().iterator();
+        while(eltIter.hasNext()){
+            Element currentElt = eltIter.next();
+            LinkedHashMap<String, String> eltMap = new LinkedHashMap<String, 
String>();
+            if(currentElt.getContentSize() > 0){
+                LinkedHashMap<String, String> childMap = new 
LinkedHashMap<String, String>();
+                // loop over Children 1st level
+                Iterator<Element> childrenIter = 
currentElt.getChildren().iterator();
+                while(childrenIter.hasNext()){
+                    Element currentChild = childrenIter.next();
+                    childMap.put(currentChild.getAttributeValue("name"), 
currentChild.getAttributeValue("value"));
+                }
+                valueMap.put(currentElt.getAttributeValue("name"), childMap);
+            }else{
+                eltMap.put(currentElt.getAttributeValue("name"), 
currentElt.getAttributeValue("value"));
+                valueMap.put(currentElt.getName(), eltMap);
+            }
+        } // eltIter
+
+        result.put("responseMessage", "success");
+        result.put("xml", valueMap);
+        return result;
+
+    } // getXMLValue
+
+} // ImageTransform Class




Reply via email to