All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.portal.image.SpriteProcessorImpl Maven / Gradle / Ivy

There is a newer version: 7.0.0-nightly
Show newest version
/**
 * 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);

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy