com.liferay.portal.image.SpriteProcessorImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of portal-impl Show documentation
Show all versions of portal-impl Show documentation
Contains implementation for the portal services.
/**
* Copyright (c) 2000-2013 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.image.ImageBag;
import com.liferay.portal.kernel.image.ImageToolUtil;
import com.liferay.portal.kernel.image.SpriteProcessor;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.security.pacl.DoPrivileged;
import com.liferay.portal.kernel.servlet.ServletContextUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.ContextPathUtil;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.kernel.util.JavaConstants;
import com.liferay.portal.kernel.util.PropertiesUtil;
import com.liferay.portal.kernel.util.SortedProperties;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.util.PropertyComparator;
import java.awt.Point;
import java.awt.Transparency;
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.awt.image.SampleModel;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.media.jai.LookupTableJAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.RasterFactory;
import javax.media.jai.TiledImage;
import javax.media.jai.operator.LookupDescriptor;
import javax.media.jai.operator.MosaicDescriptor;
import javax.media.jai.operator.TranslateDescriptor;
import javax.servlet.ServletContext;
/**
* @author Brian Wing Shun Chan
*/
@DoPrivileged
public class SpriteProcessorImpl implements SpriteProcessor {
@Override
public Properties generate(
ServletContext servletContext, List imageURLs,
String spriteRootDirName, String spriteFileName,
String spritePropertiesFileName, String rootPath, int maxHeight,
int maxWidth, int maxSize)
throws IOException {
if (imageURLs.size() < 1) {
return null;
}
Collections.sort(imageURLs, new PropertyComparator("path"));
File spriteRootDir = null;
if (Validator.isNull(spriteRootDirName)) {
File tempDir = (File)servletContext.getAttribute(
JavaConstants.JAVAX_SERVLET_CONTEXT_TEMPDIR);
spriteRootDir = new File(tempDir, SpriteProcessor.PATH);
}
else {
spriteRootDir = new File(spriteRootDirName);
}
spriteRootDir.mkdirs();
File spritePropertiesFile = new File(
spriteRootDir, spritePropertiesFileName);
File spritePropertiesParentFile = spritePropertiesFile.getParentFile();
spritePropertiesParentFile.mkdirs();
boolean build = false;
long lastModified = 0;
if (spritePropertiesFile.exists()) {
lastModified = spritePropertiesFile.lastModified();
URLConnection urlConnection = null;
for (URL imageURL : imageURLs) {
urlConnection = imageURL.openConnection();
if ((urlConnection != null) &&
(urlConnection.getLastModified() > lastModified)) {
build = true;
break;
}
}
}
else {
build = true;
}
if (!build) {
String spritePropertiesString = FileUtil.read(spritePropertiesFile);
if (Validator.isNull(spritePropertiesString)) {
return null;
}
else {
return PropertiesUtil.load(spritePropertiesString);
}
}
List renderedImages = new ArrayList();
Properties spriteProperties = new SortedProperties();
float x = 0;
float y = 0;
URLConnection urlConnection = null;
for (URL imageURL : imageURLs) {
urlConnection = imageURL.openConnection();
if ((urlConnection != null) &&
(urlConnection.getContentLength() > maxSize)) {
continue;
}
try {
ImageBag imageBag = ImageToolUtil.read(
urlConnection.getInputStream());
RenderedImage renderedImage = imageBag.getRenderedImage();
int height = renderedImage.getHeight();
int width = renderedImage.getWidth();
if ((height <= maxHeight) && (width <= maxWidth)) {
renderedImage = convert(renderedImage);
renderedImage = TranslateDescriptor.create(
renderedImage, x, y, null, null);
renderedImages.add(renderedImage);
String key = ServletContextUtil.getResourcePath(imageURL);
int pos = key.indexOf(rootPath);
if (pos == 0) {
key = key.substring(rootPath.length());
}
String contextPath = ContextPathUtil.getContextPath(
servletContext);
key = contextPath.concat(key);
String value = (int)y + "," + height + "," + width;
spriteProperties.setProperty(key, value);
y += renderedImage.getHeight();
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn("Unable to process " + imageURL);
}
if (_log.isDebugEnabled()) {
_log.debug(e, e);
}
}
}
if (renderedImages.size() <= 1) {
renderedImages.clear();
spriteProperties.clear();
}
else {
// PNG
RenderedImage renderedImage = MosaicDescriptor.create(
renderedImages.toArray(
new RenderedImage[renderedImages.size()]),
MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null,
null);
File spriteFile = new File(spriteRootDir, spriteFileName);
File spriteDir = spriteFile.getParentFile();
spriteDir.mkdirs();
ImageIO.write(renderedImage, "png", spriteFile);
if (lastModified > 0) {
spriteFile.setLastModified(lastModified);
}
}
FileUtil.write(
spritePropertiesFile, PropertiesUtil.toString(spriteProperties));
if (lastModified > 0) {
spritePropertiesFile.setLastModified(lastModified);
}
return spriteProperties;
}
protected RenderedImage convert(RenderedImage renderedImage)
throws Exception {
int height = renderedImage.getHeight();
int width = renderedImage.getWidth();
SampleModel sampleModel = renderedImage.getSampleModel();
ColorModel colorModel = renderedImage.getColorModel();
Raster raster = renderedImage.getData();
DataBuffer dataBuffer = raster.getDataBuffer();
if (colorModel instanceof IndexColorModel) {
IndexColorModel indexColorModel = (IndexColorModel)colorModel;
int mapSize = indexColorModel.getMapSize();
byte[][] data = new byte[4][mapSize];
indexColorModel.getReds(data[0]);
indexColorModel.getGreens(data[1]);
indexColorModel.getBlues(data[2]);
indexColorModel.getAlphas(data[3]);
LookupTableJAI lookupTableJAI = new LookupTableJAI(data);
renderedImage = LookupDescriptor.create(
renderedImage, lookupTableJAI, null);
}
else if (sampleModel.getNumBands() == 2) {
List bytesList = new ArrayList(
height * width * _NUM_OF_BANDS);
List tempBytesList = new ArrayList(_NUM_OF_BANDS);
for (int i = 0; i < dataBuffer.getSize(); i++) {
int mod = (i + 1) % 2;
int elemPos = i;
if (mod == 0) {
tempBytesList.add((byte)dataBuffer.getElem(elemPos - 1));
tempBytesList.add((byte)dataBuffer.getElem(elemPos - 1));
}
tempBytesList.add((byte)dataBuffer.getElem(elemPos));
if (mod == 0) {
Collections.reverse(tempBytesList);
bytesList.addAll(tempBytesList);
tempBytesList.clear();
}
}
byte[] data = ArrayUtil.toArray(
bytesList.toArray(new Byte[bytesList.size()]));
DataBuffer newDataBuffer = new DataBufferByte(data, data.length);
renderedImage = createRenderedImage(
renderedImage, height, width, newDataBuffer);
}
else if (colorModel.getTransparency() != Transparency.TRANSLUCENT) {
List bytesList = new ArrayList(
height * width * _NUM_OF_BANDS);
List tempBytesList = new ArrayList(_NUM_OF_BANDS);
for (int i = 0; i < dataBuffer.getSize(); i++) {
int mod = (i + 1) % 3;
int elemPos = i;
tempBytesList.add((byte)dataBuffer.getElem(elemPos));
if (mod == 0) {
tempBytesList.add((byte)255);
Collections.reverse(tempBytesList);
bytesList.addAll(tempBytesList);
tempBytesList.clear();
}
}
byte[] data = ArrayUtil.toArray(
bytesList.toArray(new Byte[bytesList.size()]));
DataBuffer newDataBuffer = new DataBufferByte(data, data.length);
renderedImage = createRenderedImage(
renderedImage, height, width, newDataBuffer);
}
return renderedImage;
}
protected RenderedImage createRenderedImage(
RenderedImage renderedImage, int height, int width,
DataBuffer dataBuffer) {
SampleModel sampleModel =
RasterFactory.createPixelInterleavedSampleModel(
DataBuffer.TYPE_BYTE, width, height, _NUM_OF_BANDS);
ColorModel colorModel = PlanarImage.createColorModel(sampleModel);
TiledImage tiledImage = new TiledImage(
0, 0, width, height, 0, 0, sampleModel, colorModel);
Raster raster = RasterFactory.createWritableRaster(
sampleModel, dataBuffer, new Point(0, 0));
tiledImage.setData(raster);
/*javax.media.jai.JAI.create(
"filestore", tiledImage, "test.png", "PNG");
printImage(renderedImage);
printImage(tiledImage);*/
return tiledImage;
}
protected void printImage(RenderedImage renderedImage) {
SampleModel sampleModel = renderedImage.getSampleModel();
int height = renderedImage.getHeight();
int width = renderedImage.getWidth();
int numOfBands = sampleModel.getNumBands();
int[] pixels = new int[height * width * numOfBands];
Raster raster = renderedImage.getData();
raster.getPixels(0, 0, width, height, pixels);
int offset = 0;
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
offset = (h * width * numOfBands) + (w * numOfBands);
System.out.print("[" + w + ", " + h + "] = ");
for (int b = 0; b < numOfBands; b++) {
System.out.print(pixels[offset + b] + " ");
}
}
System.out.println();
}
}
private static final int _NUM_OF_BANDS = 4;
private static Log _log = LogFactoryUtil.getLog(SpriteProcessorImpl.class);
}