Package ch.entwine.weblounge.common.impl.content.image

Source Code of ch.entwine.weblounge.common.impl.content.image.ImageStyleUtils

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.common.impl.content.image;

import ch.entwine.weblounge.common.content.Resource;
import ch.entwine.weblounge.common.content.image.ImageContent;
import ch.entwine.weblounge.common.content.image.ImageStyle;
import ch.entwine.weblounge.common.language.Language;
import ch.entwine.weblounge.common.site.ImageScalingMode;
import ch.entwine.weblounge.common.site.Module;
import ch.entwine.weblounge.common.site.Site;
import ch.entwine.weblounge.common.url.PathUtils;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* Utility class used for dealing with images and image styles.
*/
public final class ImageStyleUtils {

  public static final String DEFAULT_PREVIEW_FORMAT = "png";

  /**
   * This class is not meant to be instantiated.
   */
  private ImageStyleUtils() {
    // Utility classes should not have a public or default constructor
  }

  /**
   * Returns the calculated width in pixels for the image with the given image
   * style applied to it.
   *
   * @param image
   *          the image
   * @param style
   *          the image style
   * @return the width
   */
  public static int getStyledWidth(ImageContent image, ImageStyle style) {
    return getStyledWidth(image.getWidth(), image.getHeight(), style);
  }

  /**
   * Returns the calculated height in pixels for the image with the given image
   * style applied to it.
   *
   * @param image
   *          the image
   * @param style
   *          the image style
   * @return the height
   */
  public static int getStyledHeight(ImageContent image, ImageStyle style) {
    return getStyledHeight(image.getWidth(), image.getHeight(), style);
  }

  /**
   * Returns the scaling factor needed for the image in order to comply with the
   * image style.
   *
   * @param imageWidth
   *          width of the original image
   * @param imageHeight
   *          height of the original image
   * @param style
   *          the image style
   * @return the scaling factor
   */
  public static float getScale(float imageWidth, float imageHeight,
      ImageStyle style) {
    float scale = 1.0f;
    float scaleX = style.getWidth() / imageWidth;
    float scaleY = style.getHeight() / imageHeight;

    switch (style.getScalingMode()) {
      case Box:
        scale = Math.min(scaleX, scaleY);
        if (imageWidth <= style.getWidth() && imageHeight <= style.getHeight())
          scale = 1.0f;
        break;
      case Cover:
        if (scaleX >= 1f || scaleY >= 1f)
          scale = Math.max(scaleX, scaleY);
        else if (scaleX < 0f || scaleY < 1f)
          scale = Math.max(scaleX, scaleY);
        else
          scale = Math.min(scaleX, scaleY);
        break;
      case Fill:
        scale = Math.max(scaleX, scaleY);
        break;
      case Height:
        scale = scaleY;
        break;
      case None:
        scale = 1.0f;
        break;
      case Width:
        scale = scaleX;
        break;
      default:
        throw new IllegalStateException("Image style " + style + " contains an unknown scaling mode '" + style.getScalingMode() + "'");
    }

    return scale;
  }

  /**
   * Returns the cropping value in horizontal direction needed for the image in
   * order to comply with the image style.
   *
   * @param imageWidth
   *          width of the original image
   * @param imageHeight
   *          height of the original image
   * @param style
   *          the image style
   * @return the horizontal cropping amount
   */
  public static int getCropX(int imageWidth, int imageHeight, ImageStyle style) {
    int cropX = 0;
    int styledWidth = getStyledWidth(imageWidth, imageHeight, style);
    float scale = getScale(imageWidth, imageHeight, style);
    switch (style.getScalingMode()) {
      case Fill:
      case Box:
      case Cover:
      case Width:
      case Height:
        if (styledWidth > -1 && styledWidth < scale * imageWidth)
          cropX = Math.round(scale * imageWidth) - styledWidth;
        break;
      case None:
        break;
      default:
        throw new IllegalStateException("Image style " + style + " contains an unknown scaling mode '" + style.getScalingMode() + "'");
    }

    return cropX;
  }

  /**
   * Returns the cropping value in vertical direction needed for the image in
   * order to comply with the image style.
   *
   * @param imageWidth
   *          width of the original image
   * @param imageHeight
   *          height of the original image
   * @param style
   *          the image style
   * @return the vertical cropping amount
   */
  public static int getCropY(int imageWidth, int imageHeight, ImageStyle style) {
    int cropY = 0;
    int styledHeight = getStyledHeight(imageWidth, imageHeight, style);
    float scale = getScale(imageWidth, imageHeight, style);
    switch (style.getScalingMode()) {
      case Fill:
      case Box:
      case Cover:
      case Height:
      case Width:
        if (styledHeight > -1 && styledHeight < scale * imageHeight)
          cropY = Math.round(scale * imageHeight) - styledHeight;
        break;
      case None:
        break;
      default:
        throw new IllegalStateException("Image style " + style + " contains an unknown scaling mode '" + style.getScalingMode() + "'");
    }

    return cropY;
  }

  /**
   * Returns the width of the image after scaling with the given style.
   *
   * @param imageWidth
   *          width of the original image
   * @param imageHeight
   *          height of the original image
   * @param style
   *          the image style
   * @return the width of the scaled image
   */
  public static int getStyledWidth(int imageWidth, int imageHeight,
      ImageStyle style) {
    int width = imageWidth;
    float scale = getScale(imageWidth, imageHeight, style);
    switch (style.getScalingMode()) {
      case Fill:
      case Width:
        width = style.getWidth();
        break;
      case Box:
        if (scale < 1)
          width = Math.round(scale * imageWidth);
        break;
      case Cover:
        width = Math.round(scale * imageWidth);
        break;
      case Height:
        width = Math.round(scale * imageWidth);
        if (width > style.getWidth())
          width = style.getWidth();
        break;
      case None:
        break;
      default:
        throw new IllegalStateException("Image style " + style + " contains an unknown scaling mode '" + style.getScalingMode() + "'");
    }
    return width;
  }

  /**
   * Returns the height of the image after scaling with the given style.
   *
   * @param imageWidth
   *          width of the original image
   * @param imageHeight
   *          height of the original image
   * @param style
   *          the image style
   * @return the width of the scaled image
   */
  public static int getStyledHeight(int imageWidth, int imageHeight,
      ImageStyle style) {
    int height = imageHeight;
    float scale = getScale(imageWidth, imageHeight, style);
    switch (style.getScalingMode()) {
      case Fill:
      case Height:
        height = style.getHeight();
        break;
      case Box:
        if (scale < 1)
          height = Math.round(scale * imageHeight);
        break;
      case Cover:
        height = Math.round(scale * imageHeight);
        break;
      case Width:
        height = Math.round(scale * imageHeight);
        if (height > style.getHeight())
          height = style.getHeight();
        break;
      case None:
        height = imageHeight;
        break;
      default:
        throw new IllegalStateException("Image style " + style + " contains an unknown scaling mode '" + style.getScalingMode() + "'");
    }
    return height;
  }

  /**
   * Searches all modules of the given site for the image style identified by
   * <code>styleId</code> and returns it. If no such style was found,
   * <code>null</code> is returned.
   *
   * @param styleId
   *          the image style identifier
   * @param site
   *          the site
   * @return the image style or <code>null</code> if the style was not found
   */
  public static ImageStyle findStyle(String styleId, Site site) {
    if (styleId == null)
      throw new IllegalArgumentException("Style identifier cannot be null");
    if (site == null)
      throw new IllegalArgumentException("Site cannot be null");
    for (Module m : site.getModules()) {
      ImageStyle style = m.getImageStyle(styleId);
      if (style != null)
        return style;
    }
    return null;
  }

  /**
   * Searches all modules of the given site for the image styles whose
   * identifier matches <code>regex</code>. If no such style was found, an empty
   * array is returned.
   *
   * @param regex
   *          the image style identifier
   * @param composeableOnly
   *          if <code>true</code>, return composeable styles only
   * @param site
   *          the site
   * @return the image styles
   */
  public static ImageStyle[] findStyles(String regex, boolean composeableOnly,
      Site site) {
    if (regex == null)
      throw new IllegalArgumentException("Regular expression cannot be null");
    if (site == null)
      throw new IllegalArgumentException("Site cannot be null");
    List<ImageStyle> styles = new ArrayList<ImageStyle>();
    for (Module m : site.getModules()) {
      for (ImageStyle style : m.getImageStyles()) {
        if (composeableOnly && !style.isComposeable())
          continue;
        if (!style.getIdentifier().matches(regex))
          continue;
        styles.add(style);
      }
    }
    return styles.toArray(new ImageStyle[styles.size()]);
  }

  /**
   * Creates a file and its parent directories for the scaled image that is
   * identified by <code>filename</code>, <code>language</code> and
   * <code>style</code>.
   * <p>
   * If no filename is specified, the resource's identifier is used.
   *
   * @param resource
   *          the resource
   * @param language
   *          the language
   * @param style
   *          the image style
   * @throws IOException
   *           if creating the file fails
   * @throws IllegalStateException
   *           if a file is found at the parent directory location
   * @return the file
   */
  public static File createScaledFile(Resource<?> resource, Language language,
      ImageStyle style) throws IOException, IllegalStateException {
    return createScaledFile(resource, null, language, style);
  }

  /**
   * Creates a file and its parent directories for the scaled image that is
   * identified by <code>filename</code>, <code>language</code> and
   * <code>style</code>.
   * <p>
   * If no filename is specified, the resource's identifier is used.
   *
   * @param resource
   *          the resource
   * @param filename
   *          the file name
   * @param language
   *          the language
   * @param style
   *          the image style
   * @throws IOException
   *           if creating the file fails
   * @throws IllegalStateException
   *           if a file is found at the parent directory location
   * @return the file
   */
  public static File createScaledFile(Resource<?> resource, String filename,
      Language language, ImageStyle style) throws IOException,
      IllegalStateException {

    File scaledFile = getScaledFile(resource, language, style);
    File dir = scaledFile.getParentFile();

    if (dir.exists() && !dir.isDirectory())
      throw new IllegalStateException("Found a file at " + dir + " instead of a directory");
    if (!dir.isDirectory())
      FileUtils.forceMkdir(dir);

    return scaledFile;
  }

  /**
   * Returns the file for the scaled image that is identified by
   * <code>filename</code>, <code>language</code> and <code>style</code>.
   * <p>
   * If no filename is specified, the resource's identifier is used.
   *
   * @param resource
   *          the resource
   * @param language
   *          the language
   * @param style
   *          the image style
   * @return the file on the filesystem
   */
  public static File getScaledFile(Resource<?> resource, Language language,
      ImageStyle style) {
    return getScaledFile(resource, null, language, style);
  }

  /**
   * Returns the original file for the scaled image that is identified by
   * <code>filename</code> and <code>language</code>.
   * <p>
   * If no filename is specified, the resource's identifier is used.
   *
   * @param resource
   *          the resource
   * @param language
   *          the language
   * @return the file on the filesystem
   */
  public static File getUnscaledFile(Resource<?> resource, Language language) {
    return getScaledFile(resource, null, language, null);
  }

  /**
   * Returns the file for the scaled image that is identified by
   * <code>filename</code>, <code>language</code> and <code>style</code>.
   * <p>
   * If no filename is specified, the resource's identifier is used.
   * <p>
   * If <code>null</code> is provided as the image style, the
   * <code>original</code> style will be used.
   *
   * @param resource
   *          the resource
   * @param filename
   *          the file name
   * @param language
   *          the language
   * @param style
   *          the image style
   * @return the path to the scaled image
   */
  public static File getScaledFile(Resource<?> resource, String filename,
      Language language, ImageStyle style) {

    if (StringUtils.isBlank(filename) && resource.getContent(language) != null)
      filename = resource.getContent(language).getFilename();
    if (StringUtils.isBlank(filename))
      filename = resource.getURI().getIdentifier();

    if (style == null) {
      style = new ImageStyleImpl("original", ImageScalingMode.None);
    }

    String suffix = FilenameUtils.getExtension(filename);
    if (StringUtils.isBlank(suffix))
      suffix = DEFAULT_PREVIEW_FORMAT;

    // If needed, create the scaled file's parent directory
    Site site = resource.getURI().getSite();
    File dir = new File(PathUtils.concat(System.getProperty("java.io.tmpdir"), "sites", site.getIdentifier(), "images", style.getIdentifier(), resource.getIdentifier(), Long.toString(resource.getVersion()), language.getIdentifier()));

    // Create the filename
    StringBuffer scaledFilename = new StringBuffer(FilenameUtils.getBaseName(filename));
    scaledFilename.append("-").append(style.getIdentifier());

    if (StringUtils.isNotBlank(suffix))
      scaledFilename.append(".").append(suffix);

    return new File(dir, scaledFilename.toString());
  }

  /**
   * Returns the file for the original image that is identified by
   * <code>filename</code> and <code>language</code>.
   *
   * @param resource
   *          the resource
   * @param filename
   *          the file name
   * @param language
   *          the language
   * @return the path to the preview image
   */
  public static File getUnscaledFile(Resource<?> resource, String filename,
      Language language) {
    return getScaledFile(resource, filename, language, null);
  }

  /**
   * Returns the base directory for the site's preview images.
   *
   * @param site
   *          the site
   * @return the directory holding the site's preview images
   * @throws IllegalArgumentException
   *           if <code>site</code> is null
   */
  public static File getDirectory(Site site) {
    if (site == null)
      throw new IllegalArgumentException("site must not be null");
    return new File(PathUtils.concat(System.getProperty("java.io.tmpdir"), "sites", site.getIdentifier(), "images"));
  }

  /**
   * Returns the base directory for the site's preview images.
   *
   * @param site
   *          the site
   * @param style
   *          the image style
   * @return the directory holding the site's preview images
   * @throws IllegalArgumentException
   *           if either one of <code>site</code>, <code>style</code> is null
   */
  public static File getDirectory(Site site, ImageStyle style) {
    if (site == null)
      throw new IllegalArgumentException("site must not be null");
    if (style == null)
      throw new IllegalArgumentException("style must not be null");
    return new File(PathUtils.concat(System.getProperty("java.io.tmpdir"), "sites", site.getIdentifier(), "images", style.getIdentifier()));
  }

}
TOP

Related Classes of ch.entwine.weblounge.common.impl.content.image.ImageStyleUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.