Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

LPS-13051 Colors on Thumbnail of CMYK image are distorted #5050

Closed
wants to merge 2 commits into from

3 participants

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 20, 2012
  1. @caorongjin @juliocamarero
  2. @caorongjin @juliocamarero

    LPS-13051 Update Javadocs

    caorongjin authored juliocamarero committed
This page is out of date. Refresh to see the latest.
Showing with 712 additions and 201 deletions.
  1. +5 −0 portal-impl/src/META-INF/util-spring.xml
  2. +253 −0 portal-impl/src/com/liferay/portal/image/ImageMagickImpl.java
  3. +93 −14 portal-impl/src/com/liferay/portal/image/ImageToolImpl.java
  4. +3 −17 portal-impl/src/com/liferay/{portlet/documentlibrary/util → portal/image}/LiferayConvertCmd.java
  5. +77 −0 portal-impl/src/com/liferay/portal/image/LiferayIdentifyCmd.java
  6. +2 −2 portal-impl/src/com/liferay/portlet/admin/action/EditServerAction.java
  7. +11 −0 portal-impl/src/com/liferay/portlet/documentlibrary/util/ImageProcessorImpl.java
  8. +6 −116 portal-impl/src/com/liferay/portlet/documentlibrary/util/PDFProcessorImpl.java
  9. +39 −0 portal-service/src/com/liferay/portal/kernel/image/ImageMagick.java
  10. +107 −0 portal-service/src/com/liferay/portal/kernel/image/ImageMagickUtil.java
  11. +5 −19 portal-service/src/com/liferay/portal/kernel/image/ImageTool.java
  12. +107 −1 portal-service/src/com/liferay/portal/kernel/image/ImageToolUtil.java
  13. +0 −10 portal-service/src/com/liferay/portlet/documentlibrary/util/PDFProcessor.java
  14. +0 −18 portal-service/src/com/liferay/portlet/documentlibrary/util/PDFProcessorUtil.java
  15. +1 −1  portal-web/docroot/html/portlet/admin/init.jsp
  16. +3 −3 portal-web/docroot/html/portlet/admin/server.jspf
View
5 portal-impl/src/META-INF/util-spring.xml
@@ -156,6 +156,11 @@
<bean class="com.liferay.portal.googleapps.GoogleAppsFactoryImpl" />
</property>
</bean>
+ <bean id="com.liferay.portal.kernel.image.ImageMagickUtil" class="com.liferay.portal.kernel.image.ImageMagickUtil">
+ <property name="imageMagick">
+ <bean class="com.liferay.portal.image.ImageMagickImpl" />
+ </property>
+ </bean>
<bean id="com.liferay.portal.kernel.image.ImageToolUtil" class="com.liferay.portal.kernel.image.ImageToolUtil">
<property name="imageTool">
<bean class="com.liferay.portal.image.ImageToolImpl" />
View
253 portal-impl/src/com/liferay/portal/image/ImageMagickImpl.java
@@ -0,0 +1,253 @@
+/**
+ * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
+ *
+ * This library 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.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library 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.
+ */
+
+package com.liferay.portal.image;
+
+import com.liferay.portal.kernel.configuration.Filter;
+import com.liferay.portal.kernel.image.ImageMagick;
+import com.liferay.portal.kernel.log.Log;
+import com.liferay.portal.kernel.log.LogFactoryUtil;
+import com.liferay.portal.kernel.process.ClassPathUtil;
+import com.liferay.portal.kernel.process.ProcessCallable;
+import com.liferay.portal.kernel.process.ProcessException;
+import com.liferay.portal.kernel.process.ProcessExecutor;
+import com.liferay.portal.kernel.util.OSDetector;
+import com.liferay.portal.kernel.util.PropsKeys;
+import com.liferay.portal.kernel.util.ServerDetector;
+import com.liferay.portal.kernel.util.SystemEnv;
+import com.liferay.portal.kernel.util.Validator;
+import com.liferay.portal.log.Log4jLogFactoryImpl;
+import com.liferay.portal.util.PrefsPropsUtil;
+import com.liferay.portal.util.PropsUtil;
+import com.liferay.util.log4j.Log4JUtil;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Future;
+
+import javax.portlet.PortletPreferences;
+
+/**
+ * @author Alexander Chow
+ */
+public class ImageMagickImpl implements ImageMagick {
+
+ public static ImageMagickImpl getInstance() {
+ return _instance;
+ }
+
+ public void convert(List<String> arguments, boolean fork) throws Exception {
+ if (!isEnabled()) {
+ throw new IllegalStateException(
+ "Cannot call \"convert\" when ImageMagick is disabled");
+ }
+
+ if (fork) {
+ ProcessCallable<String[]> processCallable =
+ new ImageMagickProcessCallable(
+ ServerDetector.getServerId(),
+ PropsUtil.get(PropsKeys.LIFERAY_HOME),
+ Log4JUtil.getCustomLogSettings(), _globalSearchPath,
+ getResourceLimits(), arguments, true);
+
+ Future<String[]> future = ProcessExecutor.execute(
+ ClassPathUtil.getPortalClassPath(), processCallable);
+
+ future.get();
+ }
+ else {
+ LiferayConvertCmd.run(
+ _globalSearchPath, getResourceLimits(), arguments);
+ }
+ }
+
+ public String getGlobalSearchPath() throws Exception {
+ PortletPreferences preferences = PrefsPropsUtil.getPreferences();
+
+ String globalSearchPath = preferences.getValue(
+ PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, null);
+
+ if (Validator.isNotNull(globalSearchPath)) {
+ return globalSearchPath;
+ }
+
+ String filterName = null;
+
+ if (OSDetector.isApple()) {
+ filterName = "apple";
+ }
+ else if (OSDetector.isWindows()) {
+ filterName = "windows";
+ }
+ else {
+ filterName = "unix";
+ }
+
+ return PropsUtil.get(
+ PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, new Filter(filterName));
+ }
+
+ public Properties getResourceLimitsProperties() throws Exception {
+ Properties resourceLimitsProperties = PrefsPropsUtil.getProperties(
+ PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT, true);
+
+ if (resourceLimitsProperties.isEmpty()) {
+ resourceLimitsProperties = PropsUtil.getProperties(
+ PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT, true);
+ }
+
+ return resourceLimitsProperties;
+ }
+
+ public String[] identify(List<String> arguments, boolean fork)
+ throws Exception {
+
+ if (!isEnabled()) {
+ throw new IllegalStateException(
+ "Cannot call \"identify\" when ImageMagick is disabled");
+ }
+
+ if (fork) {
+ ProcessCallable<String[]> processCallable =
+ new ImageMagickProcessCallable(
+ ServerDetector.getServerId(),
+ PropsUtil.get(PropsKeys.LIFERAY_HOME),
+ Log4JUtil.getCustomLogSettings(), _globalSearchPath,
+ getResourceLimits(), arguments, false);
+
+ Future<String[]> future = ProcessExecutor.execute(
+ ClassPathUtil.getPortalClassPath(), processCallable);
+
+ return future.get();
+ }
+ else {
+ return LiferayIdentifyCmd.run(
+ _globalSearchPath, getResourceLimits(), arguments);
+ }
+ }
+
+ public boolean isEnabled() {
+ try {
+ return PrefsPropsUtil.getBoolean(PropsKeys.IMAGEMAGICK_ENABLED);
+ }
+ catch (Exception e) {
+ _log.warn(e, e);
+ }
+
+ return false;
+ }
+
+ public void reset() {
+ if (isEnabled()) {
+ try {
+ _globalSearchPath = getGlobalSearchPath();
+
+ _resourceLimitsProperties = getResourceLimitsProperties();
+ }
+ catch (Exception e) {
+ _log.warn(e, e);
+ }
+ }
+ }
+
+ protected LinkedList<String> getResourceLimits() {
+ LinkedList<String> resourceLimits = new LinkedList<String>();
+
+ if (_resourceLimitsProperties == null) {
+ return resourceLimits;
+ }
+
+ for (Object key : _resourceLimitsProperties.keySet()) {
+ String value = (String)_resourceLimitsProperties.get(key);
+
+ if (Validator.isNull(value)) {
+ continue;
+ }
+
+ resourceLimits.add("-limit");
+ resourceLimits.add((String)key);
+ resourceLimits.add(value);
+ }
+
+ return resourceLimits;
+ }
+
+ private static Log _log = LogFactoryUtil.getLog(ImageMagickImpl.class);
+
+ private static ImageMagickImpl _instance = new ImageMagickImpl();
+
+ private String _globalSearchPath;
+ private Properties _resourceLimitsProperties;
+
+ private static class ImageMagickProcessCallable
+ implements ProcessCallable<String[]> {
+
+ public ImageMagickProcessCallable(
+ String serverId, String liferayHome,
+ Map<String, String> customLogSettings, String globalSearchPath,
+ List<String> resourceLimits,
+ List<String> commandArguments, boolean convert) {
+
+ _serverId = serverId;
+ _liferayHome = liferayHome;
+ _customLogSettings = customLogSettings;
+ _globalSearchPath = globalSearchPath;
+ _commandArguments = commandArguments;
+ _resourceLimits = resourceLimits;
+ _convert = convert;
+ }
+
+ public String[] call() throws ProcessException {
+ Class<?> clazz = getClass();
+
+ ClassLoader classLoader = clazz.getClassLoader();
+
+ Properties systemProperties = System.getProperties();
+
+ SystemEnv.setProperties(systemProperties);
+
+ Log4JUtil.initLog4J(
+ _serverId, _liferayHome, classLoader, new Log4jLogFactoryImpl(),
+ _customLogSettings);
+
+ try {
+ if (_convert) {
+ LiferayConvertCmd.run(
+ _globalSearchPath, _resourceLimits, _commandArguments);
+ }
+ else {
+ return LiferayIdentifyCmd.run(
+ _globalSearchPath, _resourceLimits, _commandArguments);
+ }
+ }
+ catch (Exception e) {
+ throw new ProcessException(e);
+ }
+
+ return null;
+ }
+
+ private List<String> _commandArguments;
+ private boolean _convert;
+ private Map<String, String> _customLogSettings;
+ private String _globalSearchPath;
+ private String _liferayHome;
+ private List<String> _resourceLimits;
+ private String _serverId;
+
+ }
+
+}
View
107 portal-impl/src/com/liferay/portal/image/ImageToolImpl.java
@@ -49,8 +49,11 @@
import net.jmge.gif.Gif89Encoder;
+import org.im4java.core.IMOperation;
+
/**
* @author Brian Wing Shun Chan
+ * @author Alexander Chow
*/
public class ImageToolImpl implements ImageTool {
@@ -58,6 +61,58 @@ public static ImageTool getInstance() {
return _instance;
}
+ public RenderedImage convertCMYKtoRGB(
+ byte[] bytes, String type, boolean fork) {
+
+ if (!getImageMagickUtil().isEnabled()) {
+ return null;
+ }
+
+ File inputFile = _fileUtil.createTempFile(type);
+ File outputFile = _fileUtil.createTempFile(type);
+
+ try {
+ _fileUtil.write(inputFile, bytes);
+
+ IMOperation imOperation = new IMOperation();
+
+ imOperation.addRawArgs("-format", "%[colorspace]");
+ imOperation.addImage(inputFile.getPath());
+
+ String[] output = getImageMagickUtil().identify(
+ imOperation.getCmdArgs(), fork);
+
+ if ((output.length == 1) && output[0].equalsIgnoreCase("CMYK")) {
+ if (_log.isInfoEnabled()) {
+ _log.info("The image is in the CMYK colorspace");
+ }
+
+ imOperation = new IMOperation();
+
+ imOperation.addRawArgs("-colorspace", "RGB");
+ imOperation.addImage(inputFile.getPath());
+ imOperation.addImage(outputFile.getPath());
+
+ getImageMagickUtil().convert(imOperation.getCmdArgs(), fork);
+
+ bytes = _fileUtil.getBytes(outputFile);
+
+ return read(bytes, type);
+ }
+ }
+ catch (Exception e) {
+ if (_log.isErrorEnabled()) {
+ _log.error(e, e);
+ }
+ }
+ finally {
+ _fileUtil.delete(inputFile);
+ _fileUtil.delete(outputFile);
+ }
+
+ return null;
+ }
+
public BufferedImage convertImageType(BufferedImage sourceImage, int type) {
BufferedImage targetImage = new BufferedImage(
sourceImage.getWidth(), sourceImage.getHeight(), type);
@@ -122,8 +177,8 @@ public void encodeWBMP(RenderedImage renderedImage, OutputStream os)
os.write(0);
os.write(0);
- os.write(_toMultiByte(bufferedImage.getWidth()));
- os.write(_toMultiByte(bufferedImage.getHeight()));
+ os.write(toMultiByte(bufferedImage.getWidth()));
+ os.write(toMultiByte(bufferedImage.getHeight()));
DataBuffer dataBuffer = bufferedImage.getData().getDataBuffer();
@@ -169,17 +224,7 @@ public ImageBag read(byte[] bytes) {
if (codec.isFormatRecognized(bytes)) {
type = codec.getFormatName();
- ImageDecoder decoder = ImageCodec.createImageDecoder(
- type, new UnsyncByteArrayInputStream(bytes), null);
-
- try {
- renderedImage = decoder.decodeAsRenderedImage();
- }
- catch (IOException ioe) {
- if (_log.isDebugEnabled()) {
- _log.debug(type + ": " + ioe.getMessage());
- }
- }
+ renderedImage = read(bytes, type);
break;
}
@@ -344,7 +389,39 @@ else if (contentType.contains(TYPE_TIFF) ||
}
}
- private byte[] _toMultiByte(int intValue) {
+ protected ImageMagickImpl getImageMagickUtil() {
+ if (_imageMagickUtil == null) {
+ _imageMagickUtil = ImageMagickImpl.getInstance();
+
+ _imageMagickUtil.reset();
+ }
+
+ return _imageMagickUtil;
+ }
+
+ protected RenderedImage read(byte[] bytes, String type) {
+ RenderedImage renderedImage = null;
+
+ try {
+ if (type.equals(TYPE_JPEG)) {
+ type = "jpeg";
+ }
+
+ ImageDecoder decoder = ImageCodec.createImageDecoder(
+ type, new UnsyncByteArrayInputStream(bytes), null);
+
+ renderedImage = decoder.decodeAsRenderedImage();
+ }
+ catch (IOException ioe) {
+ if (_log.isDebugEnabled()) {
+ _log.debug(type + ": " + ioe.getMessage());
+ }
+ }
+
+ return renderedImage;
+ }
+
+ protected byte[] toMultiByte(int intValue) {
int numBits = 32;
int mask = 0x80000000;
@@ -375,4 +452,6 @@ else if (contentType.contains(TYPE_TIFF) ||
private static FileImpl _fileUtil = FileImpl.getInstance();
+ private static ImageMagickImpl _imageMagickUtil;
+
}
View
20 ...cumentlibrary/util/LiferayConvertCmd.java → ...feray/portal/image/LiferayConvertCmd.java
@@ -12,16 +12,14 @@
* details.
*/
-package com.liferay.portlet.documentlibrary.util;
+package com.liferay.portal.image;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.StringBundler;
-import com.liferay.portal.kernel.util.Validator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Properties;
import jodd.util.StringPool;
@@ -33,7 +31,7 @@
public class LiferayConvertCmd extends ConvertCmd {
public static void run(
- String globalSearchPath, Properties resourceLimitsProperties,
+ String globalSearchPath, List<String> resourceLimits,
List<String> commandArguments)
throws Exception {
@@ -42,19 +40,7 @@ public static void run(
LinkedList<String> arguments = new LinkedList<String>();
arguments.addAll(_instance.getCommand());
-
- for (Object key : resourceLimitsProperties.keySet()) {
- String value = (String)resourceLimitsProperties.get(key);
-
- if (Validator.isNull(value)) {
- continue;
- }
-
- arguments.add("-limit");
- arguments.add((String)key);
- arguments.add(value);
- }
-
+ arguments.addAll(resourceLimits);
arguments.addAll(commandArguments);
if (_log.isInfoEnabled()) {
View
77 portal-impl/src/com/liferay/portal/image/LiferayIdentifyCmd.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
+ *
+ * This library 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.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library 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.
+ */
+
+package com.liferay.portal.image;
+
+import com.liferay.portal.kernel.log.Log;
+import com.liferay.portal.kernel.log.LogFactoryUtil;
+import com.liferay.portal.kernel.util.StringBundler;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import jodd.util.StringPool;
+
+import org.im4java.core.IdentifyCmd;
+import org.im4java.process.ArrayListOutputConsumer;
+
+/**
+ * @author Alexander Chow
+ */
+public class LiferayIdentifyCmd extends IdentifyCmd {
+
+ public static String[] run(
+ String globalSearchPath, List<String> resourceLimits,
+ List<String> commandArguments)
+ throws Exception {
+
+ setGlobalSearchPath(globalSearchPath);
+
+ LinkedList<String> arguments = new LinkedList<String>();
+
+ arguments.addAll(_instance.getCommand());
+ arguments.addAll(resourceLimits);
+ arguments.addAll(commandArguments);
+
+ if (_log.isInfoEnabled()) {
+ StringBundler sb = new StringBundler(arguments.size() * 2);
+
+ for (String argument : arguments) {
+ sb.append(argument);
+ sb.append(StringPool.SPACE);
+ }
+
+ _log.info("Excecuting command '" + sb.toString() + "'");
+ }
+
+ ArrayListOutputConsumer outputConsumer = new ArrayListOutputConsumer();
+
+ _instance.setOutputConsumer(outputConsumer);
+ _instance.run(arguments);
+
+ List<String> outputList = outputConsumer.getOutput();
+
+ if (outputList != null) {
+ return outputList.toArray(new String[0]);
+ }
+ else {
+ return new String[0];
+ }
+ }
+
+ private static Log _log = LogFactoryUtil.getLog(LiferayIdentifyCmd.class);
+
+ private static LiferayIdentifyCmd _instance = new LiferayIdentifyCmd();
+
+}
View
4 portal-impl/src/com/liferay/portlet/admin/action/EditServerAction.java
@@ -28,6 +28,7 @@
import com.liferay.portal.kernel.cluster.ClusterLinkUtil;
import com.liferay.portal.kernel.cluster.ClusterRequest;
import com.liferay.portal.kernel.dao.shard.ShardUtil;
+import com.liferay.portal.kernel.image.ImageMagickUtil;
import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
import com.liferay.portal.kernel.io.unsync.UnsyncPrintWriter;
import com.liferay.portal.kernel.log.Log;
@@ -75,7 +76,6 @@
import com.liferay.portlet.ActionResponseImpl;
import com.liferay.portlet.admin.util.CleanUpPermissionsUtil;
import com.liferay.portlet.documentlibrary.util.DLPreviewableProcessor;
-import com.liferay.portlet.documentlibrary.util.PDFProcessorUtil;
import com.liferay.util.log4j.Log4JUtil;
import java.io.File;
@@ -499,7 +499,7 @@ protected void updateExternalServices(
preferences.store();
- PDFProcessorUtil.reset();
+ ImageMagickUtil.reset();
}
protected void updateFileUploads(
View
11 portal-impl/src/com/liferay/portlet/documentlibrary/util/ImageProcessorImpl.java
@@ -258,6 +258,17 @@ private void _generateImages(FileVersion fileVersion) {
return;
}
+ if (renderedImage.getColorModel().getNumComponents() == 4) {
+ RenderedImage convertedRenderedImage =
+ ImageToolUtil.convertCMYKtoRGB(
+ bytes, imageBag.getType(),
+ PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED);
+
+ if (convertedRenderedImage != null) {
+ renderedImage = convertedRenderedImage;
+ }
+ }
+
if (!_hasPreview(fileVersion)) {
_storePreviewImage(fileVersion, renderedImage);
}
View
122 portal-impl/src/com/liferay/portlet/documentlibrary/util/PDFProcessorImpl.java
@@ -14,7 +14,7 @@
package com.liferay.portlet.documentlibrary.util;
-import com.liferay.portal.kernel.configuration.Filter;
+import com.liferay.portal.kernel.image.ImageMagickUtil;
import com.liferay.portal.kernel.image.ImageToolUtil;
import com.liferay.portal.kernel.lar.PortletDataContext;
import com.liferay.portal.kernel.log.Log;
@@ -22,10 +22,6 @@
import com.liferay.portal.kernel.messaging.DestinationNames;
import com.liferay.portal.kernel.messaging.MessageBusException;
import com.liferay.portal.kernel.messaging.MessageBusUtil;
-import com.liferay.portal.kernel.process.ClassPathUtil;
-import com.liferay.portal.kernel.process.ProcessCallable;
-import com.liferay.portal.kernel.process.ProcessException;
-import com.liferay.portal.kernel.process.ProcessExecutor;
import com.liferay.portal.kernel.repository.model.FileEntry;
import com.liferay.portal.kernel.repository.model.FileVersion;
import com.liferay.portal.kernel.util.ContentTypes;
@@ -33,17 +29,11 @@
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.InstancePool;
import com.liferay.portal.kernel.util.MimeTypesUtil;
-import com.liferay.portal.kernel.util.OSDetector;
-import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.StreamUtil;
import com.liferay.portal.kernel.util.StringBundler;
-import com.liferay.portal.kernel.util.StringPool;
-import com.liferay.portal.kernel.util.SystemEnv;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.repository.liferayrepository.model.LiferayFileVersion;
-import com.liferay.portal.util.PrefsPropsUtil;
-import com.liferay.portal.util.PropsUtil;
import com.liferay.portal.util.PropsValues;
import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
import com.liferay.portlet.documentlibrary.store.DLStoreUtil;
@@ -57,17 +47,12 @@
import java.io.InputStream;
import java.util.Arrays;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Properties;
import java.util.Set;
import java.util.Vector;
-import java.util.concurrent.Future;
import javax.imageio.ImageIO;
-import javax.portlet.PortletPreferences;
-
import org.apache.commons.lang.time.StopWatch;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
@@ -92,32 +77,6 @@ public void generateImages(FileVersion fileVersion) throws Exception {
Initializer._initializedInstance._generateImages(fileVersion);
}
- public String getGlobalSearchPath() throws Exception {
- PortletPreferences preferences = PrefsPropsUtil.getPreferences();
-
- String globalSearchPath = preferences.getValue(
- PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, null);
-
- if (Validator.isNotNull(globalSearchPath)) {
- return globalSearchPath;
- }
-
- String filterName = null;
-
- if (OSDetector.isApple()) {
- filterName = "apple";
- }
- else if (OSDetector.isWindows()) {
- filterName = "windows";
- }
- else {
- filterName = "unix";
- }
-
- return PropsUtil.get(
- PropsKeys.IMAGEMAGICK_GLOBAL_SEARCH_PATH, new Filter(filterName));
- }
-
public InputStream getPreviewAsStream(FileVersion fileVersion, int index)
throws Exception {
@@ -144,18 +103,6 @@ public long getPreviewFileSize(FileVersion fileVersion, int index)
fileVersion, index);
}
- public Properties getResourceLimitsProperties() throws Exception {
- Properties resourceLimitsProperties = PrefsPropsUtil.getProperties(
- PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT, true);
-
- if (resourceLimitsProperties.isEmpty()) {
- resourceLimitsProperties = PropsUtil.getProperties(
- PropsKeys.IMAGEMAGICK_RESOURCE_LIMIT, true);
- }
-
- return resourceLimitsProperties;
- }
-
public InputStream getThumbnailAsStream(FileVersion fileVersion, int index)
throws Exception {
@@ -194,7 +141,7 @@ public boolean isDocumentSupported(String mimeType) {
}
public boolean isImageMagickEnabled() throws Exception {
- if (PrefsPropsUtil.getBoolean(PropsKeys.IMAGEMAGICK_ENABLED)) {
+ if (ImageMagickUtil.isEnabled()) {
return true;
}
@@ -244,14 +191,6 @@ public boolean isSupported(String mimeType) {
return false;
}
- public void reset() throws Exception {
- if (isImageMagickEnabled()) {
- _globalSearchPath = getGlobalSearchPath();
-
- _resourceLimitsProperties = getResourceLimitsProperties();
- }
- }
-
public void trigger(FileVersion fileVersion) {
Initializer._initializedInstance._queueGeneration(fileVersion);
}
@@ -338,7 +277,7 @@ protected void initialize() {
FileUtil.mkdirs(PREVIEW_TMP_PATH);
FileUtil.mkdirs(THUMBNAIL_TMP_PATH);
- reset();
+ ImageMagickUtil.reset();
}
catch (Exception e) {
_log.warn(e, e);
@@ -503,22 +442,9 @@ private void _generateImagesIM(
imOperation.addImage(getPreviewTempFilePath(tempFileId, -1));
}
- if (PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED) {
- ProcessCallable<String> processCallable =
- new ImageMagickProcessCallable(
- _globalSearchPath, _resourceLimitsProperties,
- imOperation.getCmdArgs());
-
- Future<String> future = ProcessExecutor.execute(
- ClassPathUtil.getPortalClassPath(), processCallable);
-
- future.get();
- }
- else {
- LiferayConvertCmd.run(
- _globalSearchPath, _resourceLimitsProperties,
- imOperation.getCmdArgs());
- }
+ ImageMagickUtil.convert(
+ imOperation.getCmdArgs(),
+ PropsValues.DL_FILE_ENTRY_PREVIEW_FORK_PROCESS_ENABLED);
// Store images
@@ -791,44 +717,8 @@ else if (DocumentConversionUtil.isEnabled()) {
}
private List<Long> _fileVersionIds = new Vector<Long>();
- private String _globalSearchPath;
- private Properties _resourceLimitsProperties;
private boolean _warned;
- private static class ImageMagickProcessCallable
- implements ProcessCallable<String> {
-
- public ImageMagickProcessCallable(
- String globalSearchPath, Properties resourceLimits,
- LinkedList<String> commandArguments) {
-
- _globalSearchPath = globalSearchPath;
- _commandArguments = commandArguments;
- _resourceLimits = resourceLimits;
- }
-
- public String call() throws ProcessException {
- Properties systemProperties = System.getProperties();
-
- SystemEnv.setProperties(systemProperties);
-
- try {
- LiferayConvertCmd.run(
- _globalSearchPath, _resourceLimits, _commandArguments);
- }
- catch (Exception e) {
- throw new ProcessException(e);
- }
-
- return StringPool.BLANK;
- }
-
- private LinkedList<String> _commandArguments;
- private String _globalSearchPath;
- private Properties _resourceLimits;
-
- }
-
private static class Initializer {
private static PDFProcessorImpl _initializedInstance;
View
39 portal-service/src/com/liferay/portal/kernel/image/ImageMagick.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
+ *
+ * This library 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.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library 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.
+ */
+
+package com.liferay.portal.kernel.image;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Alexander Chow
+ */
+public interface ImageMagick {
+
+ public void convert(List<String> arguments, boolean fork)
+ throws Exception;
+
+ public String getGlobalSearchPath() throws Exception;
+
+ public Properties getResourceLimitsProperties() throws Exception;
+
+ public String[] identify(List<String> arguments, boolean fork)
+ throws Exception;
+
+ public boolean isEnabled();
+
+ public void reset();
+
+}
View
107 portal-service/src/com/liferay/portal/kernel/image/ImageMagickUtil.java
@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
+ *
+ * This library 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.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This library 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.
+ */
+
+package com.liferay.portal.kernel.image;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * The ImageMagick utility class.
+ *
+ * @author Alexander Chow
+ */
+public class ImageMagickUtil {
+
+ /**
+ * Executes the <code>convert</code> command in ImageMagick.
+ *
+ * @param arguments the command arguments being passed to <code>convert
+ * <code>
+ * @param fork whether to fork the process
+ * @throws Exception if an unexpected error occurred while executing command
+ * @see <a href="http://www.imagemagick.org/script/convert.php">Convert
+ * documentation</a>
+ */
+ public static void convert(List<String> arguments, boolean fork)
+ throws Exception {
+
+ getImageMagick().convert(arguments, fork);
+ }
+
+ /**
+ * Returns the global search path configured for ImageMagick.
+ *
+ * @return the global search path
+ * @throws Exception if an unexpected error occurred
+ */
+ public static String getGlobalSearchPath() throws Exception {
+ return getImageMagick().getGlobalSearchPath();
+ }
+
+ public static ImageMagick getImageMagick() {
+ return _imageMagick;
+ }
+
+ /**
+ * Returns the cache and resource usage limits configured for ImageMagick.
+ *
+ * @return the resource limits
+ * @throws Exception if an unexpected error occurred
+ */
+ public static Properties getResourceLimitsProperties() throws Exception {
+ return getImageMagick().getResourceLimitsProperties();
+ }
+
+ /**
+ * Executes the <code>identify</code> command in ImageMagick.
+ *
+ * @param arguments the command arguments being passed to <code>identify
+ * </code>
+ * @param fork whether to fork the process
+ * @return the results of the <code>identify</code> call
+ * @throws Exception if an unexpected error occurred while executing command
+ * @see <a href="http://www.imagemagick.org/script/identify.php">Identify
+ * documentation</a>
+ */
+ public static String[] identify(List<String> arguments, boolean fork)
+ throws Exception {
+
+ return getImageMagick().identify(arguments, fork);
+ }
+
+ /**
+ * Returns <code>true</code> if ImageMagick is enabled.
+ *
+ * @return <code>true</code> if ImageMagick is enabled; <code>false</code>
+ * otherwise
+ */
+ public static boolean isEnabled() {
+ return getImageMagick().isEnabled();
+ }
+
+ /**
+ * Resets the global search path and resource limits for ImageMagick.
+ */
+ public static void reset() {
+ getImageMagick().reset();
+ }
+
+ public void setImageMagick(ImageMagick imageMagick) {
+ _imageMagick = imageMagick;
+ }
+
+ private static ImageMagick _imageMagick;
+
+}
View
24 portal-service/src/com/liferay/portal/kernel/image/ImageTool.java
@@ -23,6 +23,7 @@
/**
* @author Brian Wing Shun Chan
+ * @author Alexander Chow
*/
public interface ImageTool {
@@ -38,13 +39,16 @@
public static final String TYPE_TIFF = "tiff";
+ public RenderedImage convertCMYKtoRGB(
+ byte[] bytes, String type, boolean fork);
+
public BufferedImage convertImageType(BufferedImage sourceImage, int type);
public void encodeGIF(RenderedImage renderedImage, OutputStream os)
throws IOException;
public void encodeWBMP(RenderedImage renderedImage, OutputStream os)
- throws InterruptedException, IOException;
+ throws IOException;
public BufferedImage getBufferedImage(RenderedImage renderedImage);
@@ -55,26 +59,8 @@ public void encodeWBMP(RenderedImage renderedImage, OutputStream os)
public ImageBag read(File file) throws IOException;
- /**
- * Scales the image based on the given width with the height calculated to
- * preserve aspect ratio.
- *
- * @param renderedImage image to scale
- * @param width used as new width and to calculate for new height
- * @return scaled image
- */
public RenderedImage scale(RenderedImage renderedImage, int width);
- /**
- * Scales the image based on the maximum height and width given while
- * preserving the aspect ratio. If the image is already larger in both
- * dimensions, the image will not be scaled.
- *
- * @param renderedImage image to scale
- * @param maxHeight maximum height allowed for image
- * @param maxWidth maximum width allowed for image
- * @return scaled image
- */
public RenderedImage scale(
RenderedImage renderedImage, int maxHeight, int maxWidth);
View
108 portal-service/src/com/liferay/portal/kernel/image/ImageToolUtil.java
@@ -22,32 +22,93 @@
import java.io.OutputStream;
/**
+ * The Image utility class.
+ *
* @author Brian Wing Shun Chan
+ * @author Alexander Chow
*/
public class ImageToolUtil {
+ /**
+ * Converts a CMYK image to RGB using ImageMagick. This must be run against
+ * the original <code>byte[]</code> and not one extracted from a {@link
+ * java.awt.image.RenderedImage}. The latter may potentially have been
+ * already been read incorrectly.
+ *
+ * @param bytes the image to convert
+ * @param type the image type (e.g., "gif", "jpg", etc.)
+ * @param fork whether to fork the process
+ * @return the converted image or <code>null</code> if ImageMagick was
+ * disabled or if the conversion was not completed. The conversion
+ * may not complete if (1) the image was not in the CMYK colorspace
+ * to begin with or (2) there was an error in the conversion
+ * process.
+ */
+ public static RenderedImage convertCMYKtoRGB(
+ byte[] bytes, String type, boolean fork) {
+
+ return getImageTool().convertCMYKtoRGB(bytes, type, fork);
+ }
+
+ /**
+ * Converts an image from one image type to another.
+ *
+ * @param sourceImage the image to convert
+ * @param type the image type to convert to (e.g., "gif", "jpg", etc.)
+ * @return converted image
+ */
public static BufferedImage convertImageType(
BufferedImage sourceImage, int type) {
return getImageTool().convertImageType(sourceImage, type);
}
+ /**
+ * Encodes an image using the GIF format.
+ *
+ * @param renderedImage the image to encode
+ * @param os the stream to write to
+ * @throws IOException if an error occurred during writing
+ */
public static void encodeGIF(RenderedImage renderedImage, OutputStream os)
throws IOException {
getImageTool().encodeGIF(renderedImage, os);
}
+ /**
+ * Encodes an image using the WBMP format.
+ *
+ * @param renderedImage the image to encode
+ * @param os the stream to write to
+ * @throws IOException if an error occurred during writing
+ */
public static void encodeWBMP(RenderedImage renderedImage, OutputStream os)
- throws InterruptedException, IOException {
+ throws IOException {
getImageTool().encodeWBMP(renderedImage, os);
}
+ /**
+ * Returns a {@link java.awt.image.BufferedImage} from a given {@link
+ * java.awt.image.RenderedImage}.
+ *
+ * @param renderedImage the original image
+ * @return the converted image
+ */
public static BufferedImage getBufferedImage(RenderedImage renderedImage) {
return getImageTool().getBufferedImage(renderedImage);
}
+ /**
+ * Returns the <code>byte[]</code> from an image.
+ *
+ * @param renderedImage the image to read
+ * @param contentType the content type (e.g., "image/jpeg") or image type
+ * (e.g., "jpg") to use during encoding
+ * @return the encoded image
+ * @throws IOException if an error occurred during writing
+ */
public static byte[] getBytes(
RenderedImage renderedImage, String contentType)
throws IOException {
@@ -59,24 +120,69 @@ public static ImageTool getImageTool() {
return _imageTool;
}
+ /**
+ * Detects the image format and creates an {@link
+ * com.liferay.portal.kernel.image.ImageBag} containing the {@link
+ * java.awt.image.RenderedImage} and image type.
+ *
+ * @param bytes the bytes to read
+ * @return the {@link com.liferay.portal.kernel.image.ImageBag}
+ * @throws IOException if an error occurred during writing
+ */
public static ImageBag read(byte[] bytes) throws IOException {
return getImageTool().read(bytes);
}
+ /**
+ * Detects the image format and creates an {@link
+ * com.liferay.portal.kernel.image.ImageBag} containing the {@link
+ * java.awt.image.RenderedImage} and image type.
+ *
+ * @param file the file to read
+ * @return the {@link com.liferay.portal.kernel.image.ImageBag}
+ * @throws IOException if an error occurred during writing
+ */
public static ImageBag read(File file) throws IOException {
return getImageTool().read(file);
}
+ /**
+ * Scales the image based on the given width with the height calculated to
+ * preserve aspect ratio.
+ *
+ * @param renderedImage the image to scale
+ * @param width the new width; also used to calculate the new height
+ * @return the scaled image
+ */
public static RenderedImage scale(RenderedImage renderedImage, int width) {
return getImageTool().scale(renderedImage, width);
}
+ /**
+ * Scales the image based on the maximum height and width given while
+ * preserving the aspect ratio. If the image is already larger in both
+ * dimensions, the image will not be scaled.
+ *
+ * @param renderedImage the image to scale
+ * @param maxHeight the maximum height allowed for image
+ * @param maxWidth the maximum width allowed for image
+ * @return the scaled image
+ */
public static RenderedImage scale(
RenderedImage renderedImage, int maxHeight, int maxWidth) {
return getImageTool().scale(renderedImage, maxHeight, maxWidth);
}
+ /**
+ * Encodes an image using.
+ *
+ * @param renderedImage the image to encode
+ * @param contentType the content type (e.g., "image/jpeg") or image type
+ * (e.g., "jpg") to use during encoding
+ * @param os the stream to write to
+ * @throws IOException if an error occurred during writing
+ */
public static void write(
RenderedImage renderedImage, String contentType, OutputStream os)
throws IOException {
View
10 portal-service/src/com/liferay/portlet/documentlibrary/util/PDFProcessor.java
@@ -22,8 +22,6 @@
import java.io.InputStream;
-import java.util.Properties;
-
/**
* @author Sergio González
*/
@@ -41,8 +39,6 @@ public void exportGeneratedFiles(
public void generateImages(FileVersion fileVersion)
throws Exception;
- public String getGlobalSearchPath() throws Exception;
-
public InputStream getPreviewAsStream(FileVersion fileVersion, int index)
throws Exception;
@@ -51,8 +47,6 @@ public InputStream getPreviewAsStream(FileVersion fileVersion, int index)
public long getPreviewFileSize(FileVersion fileVersion, int index)
throws Exception;
- public Properties getResourceLimitsProperties() throws Exception;
-
public InputStream getThumbnailAsStream(FileVersion fileVersion, int index)
throws Exception;
@@ -70,12 +64,8 @@ public void importGeneratedFiles(
public boolean isDocumentSupported(String mimeType);
- public boolean isImageMagickEnabled() throws Exception;
-
public boolean isSupported(String mimeType);
- public void reset() throws Exception;
-
public void trigger(FileVersion fileVersion);
}
View
18 portal-service/src/com/liferay/portlet/documentlibrary/util/PDFProcessorUtil.java
@@ -18,8 +18,6 @@
import java.io.InputStream;
-import java.util.Properties;
-
/**
* @author Sergio González
*/
@@ -31,10 +29,6 @@ public static void generateImages(FileVersion fileVersion)
getPDFProcessor().generateImages(fileVersion);
}
- public static String getGlobalSearchPath() throws Exception {
- return getPDFProcessor().getGlobalSearchPath();
- }
-
public static PDFProcessor getPDFProcessor() {
return _pdfProcessor;
}
@@ -56,10 +50,6 @@ public static long getPreviewFileSize(FileVersion fileVersion, int index)
return getPDFProcessor().getPreviewFileSize(fileVersion, index);
}
- public static Properties getResourceLimitsProperties() throws Exception {
- return getPDFProcessor().getResourceLimitsProperties();
- }
-
public static InputStream getThumbnailAsStream(
FileVersion fileVersion, int index)
throws Exception {
@@ -85,18 +75,10 @@ public static boolean isDocumentSupported(String mimeType) {
return getPDFProcessor().isDocumentSupported(mimeType);
}
- public static boolean isImageMagickEnabled() throws Exception {
- return getPDFProcessor().isImageMagickEnabled();
- }
-
public static boolean isSupported(String mimeType) {
return getPDFProcessor().isSupported(mimeType);
}
- public static void reset() throws Exception {
- getPDFProcessor().reset();
- }
-
public static void trigger(FileVersion fileVersion) {
getPDFProcessor().trigger(fileVersion);
}
View
2  portal-web/docroot/html/portlet/admin/init.jsp
@@ -23,6 +23,7 @@ page import="com.liferay.portal.captcha.recaptcha.ReCaptchaImpl" %><%@
page import="com.liferay.portal.convert.ConvertProcess" %><%@
page import="com.liferay.portal.dao.shard.ManualShardSelector" %><%@
page import="com.liferay.portal.kernel.dao.shard.ShardUtil" %><%@
+page import="com.liferay.portal.kernel.image.ImageMagickUtil" %><%@
page import="com.liferay.portal.kernel.plugin.PluginPackage" %><%@
page import="com.liferay.portal.kernel.scripting.ScriptingUtil" %><%@
page import="com.liferay.portal.kernel.util.InstancePool" %><%@
@@ -30,7 +31,6 @@ page import="com.liferay.portal.util.PortalInstances" %><%@
page import="com.liferay.portlet.documentlibrary.model.DLFileEntry" %><%@
page import="com.liferay.portlet.documentlibrary.model.DLFileVersion" %><%@
page import="com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil" %><%@
-page import="com.liferay.portlet.documentlibrary.util.PDFProcessorUtil" %><%@
page import="com.liferay.portlet.expando.model.ExpandoBridge" %><%@
page import="com.liferay.portlet.expando.model.ExpandoColumnConstants" %>
View
6 portal-web/docroot/html/portlet/admin/server.jspf
@@ -548,14 +548,14 @@ numberFormat.setMinimumIntegerDigits(2);
<aui:fieldset>
<liferay-ui:panel-container extended="<%= true %>" id="adminExternalServicesPanelContainer" persistState="<%= true %>">
<liferay-ui:panel collapsible="<%= true %>" extended="<%= true %>" id="adminImageMagickConversionPanel" persistState="<%= true %>" title="enabling-imagemagick-provides-document-preview-functionality">
- <aui:input label="enabled" name="imageMagickEnabled" type="checkbox" value="<%= PrefsPropsUtil.getBoolean(PropsKeys.IMAGEMAGICK_ENABLED) %>" />
+ <aui:input label="enabled" name="imageMagickEnabled" type="checkbox" value="<%= ImageMagickUtil.isEnabled() %>" />
- <aui:input cssClass="lfr-input-text-container" label="path" name="imageMagickPath" type="text" value="<%= PDFProcessorUtil.getGlobalSearchPath() %>" />
+ <aui:input cssClass="lfr-input-text-container" label="path" name="imageMagickPath" type="text" value="<%= ImageMagickUtil.getGlobalSearchPath() %>" />
<aui:fieldset label="resource-limits">
<%
- Properties resourceLimitsProperties = PDFProcessorUtil.getResourceLimitsProperties();
+ Properties resourceLimitsProperties = ImageMagickUtil.getResourceLimitsProperties();
for (String label : _IMAGEMAGICK_RESOURCE_LIMIT_LABELS) {
String name = "imageMagickLimit" + StringUtil.upperCaseFirstLetter(label);
Something went wrong with that request. Please try again.