001/* 002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 * 019 */ 020package org.nuxeo.ecm.platform.pictures.tiles.magick.tiler; 021 022import java.util.HashMap; 023import java.util.Map; 024 025import org.nuxeo.common.utils.Path; 026import org.nuxeo.ecm.core.api.NuxeoException; 027import org.nuxeo.ecm.platform.commandline.executor.api.CommandException; 028import org.nuxeo.ecm.platform.commandline.executor.api.CommandNotAvailable; 029import org.nuxeo.ecm.platform.picture.api.ImageInfo; 030import org.nuxeo.ecm.platform.picture.magick.utils.ImageCropperAndResizer; 031import org.nuxeo.ecm.platform.pictures.tiles.api.PictureTiles; 032import org.nuxeo.ecm.platform.pictures.tiles.api.PictureTilesImpl; 033import org.nuxeo.ecm.platform.pictures.tiles.helpers.StringMaker; 034import org.nuxeo.ecm.platform.pictures.tiles.tilers.PictureTiler; 035 036/** 037 * ImageMagic based Tiler Uses several ImageMagick command lines to extract a tile form a picture file 038 * 039 * @author tiry 040 */ 041public class MagickTiler implements PictureTiler { 042 043 /** @since 5.9.5. */ 044 public static final String CMYK_MAP_COMPONENTS = "cmyk"; 045 046 public boolean needsSync() { 047 return false; 048 } 049 050 public String getName() { 051 return "MagicTiler"; 052 } 053 054 static int[] computeCropCoords(ImageInfo input, int maxTiles, int tileWidth, int tileHeight, int xCenter, 055 int yCenter) { 056 int startX = 0; 057 int startY = 0; 058 int cropWidth = 0; 059 int cropHeight = 0; 060 int ntx = 0; 061 int nty = 0; 062 063 if (input.getWidth() > input.getHeight()) { 064 cropWidth = input.getWidth() / maxTiles; 065 if ((input.getWidth() % maxTiles) > 0) { 066 cropWidth += 1; 067 } 068 Double exactCropHeight = (new Double(tileHeight)) / tileWidth * cropWidth; 069 if (exactCropHeight - exactCropHeight.intValue() > 0) { 070 cropHeight = exactCropHeight.intValue() + 1; 071 } else { 072 cropHeight = exactCropHeight.intValue(); 073 } 074 ntx = maxTiles; 075 nty = input.getHeight() / cropHeight; 076 if ((input.getHeight() % cropHeight) > 0) { 077 nty += 1; 078 } 079 } else { 080 cropHeight = input.getHeight() / maxTiles; 081 if ((input.getHeight() % maxTiles) > 0) { 082 cropHeight += 1; 083 } 084 Double exactCropWidth = (new Double(tileWidth)) / tileHeight * cropHeight; 085 if (exactCropWidth - exactCropWidth.intValue() > 0) { 086 cropWidth = exactCropWidth.intValue() + 1; 087 } else { 088 cropWidth = exactCropWidth.intValue(); 089 } 090 nty = maxTiles; 091 ntx = input.getWidth() / cropWidth; 092 if ((input.getWidth() % cropWidth) > 0) { 093 ntx += 1; 094 } 095 } 096 097 startX = xCenter * cropWidth; 098 startY = yCenter * cropHeight; 099 100 double widthRatio = new Double(tileWidth) / cropWidth; 101 double heightRatio = new Double(tileHeight) / cropHeight; 102 103 if (xCenter == ntx - 1) { 104 cropWidth = input.getWidth() - (xCenter) * cropWidth; 105 tileWidth = (int) Math.round(cropWidth * widthRatio); 106 } 107 if (yCenter == nty - 1) { 108 cropHeight = input.getHeight() - (yCenter) * cropHeight; 109 tileHeight = (int) Math.round(cropHeight * heightRatio); 110 } 111 112 int[] result = { startX, startY, cropWidth, cropHeight, ntx, nty, tileWidth, tileHeight }; 113 114 return result; 115 } 116 117 public PictureTiles getTilesFromFile(ImageInfo input, String outputDirPath, int tileWidth, int tileHeight, 118 int maxTiles, int xCenter, int yCenter, long lastModificationTime, boolean fullGeneration) 119 { 120 121 int[] cropCoords = computeCropCoords(input, maxTiles, tileWidth, tileHeight, xCenter, yCenter); 122 123 String fileName = StringMaker.getTileFileName(xCenter, yCenter, lastModificationTime); 124 String outputFilePath = new Path(outputDirPath).append(fileName).toString(); 125 126 try { 127 String mapComponents = null; 128 if (CMYK_MAP_COMPONENTS.equalsIgnoreCase(input.getColorSpace())) { 129 mapComponents = CMYK_MAP_COMPONENTS; 130 } 131 132 ImageCropperAndResizer.cropAndResize(input.getFilePath(), outputFilePath, cropCoords[2], cropCoords[3], 133 cropCoords[0], cropCoords[1], cropCoords[6], cropCoords[7], mapComponents); 134 } catch (CommandNotAvailable | CommandException e) { 135 throw new NuxeoException(e); 136 } 137 138 Map<String, String> infoMap = new HashMap<String, String>(); 139 infoMap.put(PictureTilesImpl.TILE_OUTPUT_DIR_KEY, outputDirPath); 140 infoMap.put(PictureTilesImpl.X_TILES_KEY, Integer.toString(cropCoords[4])); 141 infoMap.put(PictureTilesImpl.Y_TILES_KEY, Integer.toString(cropCoords[5])); 142 143 return new PictureTilesImpl(infoMap); 144 } 145 146}