001/* 002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 * 021 */ 022package org.nuxeo.ecm.platform.pictures.tiles.magick.tiler; 023 024import java.util.HashMap; 025import java.util.Map; 026 027import org.nuxeo.common.utils.Path; 028import org.nuxeo.ecm.core.api.NuxeoException; 029import org.nuxeo.ecm.platform.commandline.executor.api.CommandException; 030import org.nuxeo.ecm.platform.commandline.executor.api.CommandNotAvailable; 031import org.nuxeo.ecm.platform.picture.api.ImageInfo; 032import org.nuxeo.ecm.platform.picture.magick.utils.ImageCropperAndResizer; 033import org.nuxeo.ecm.platform.pictures.tiles.api.PictureTiles; 034import org.nuxeo.ecm.platform.pictures.tiles.api.PictureTilesImpl; 035import org.nuxeo.ecm.platform.pictures.tiles.helpers.StringMaker; 036import org.nuxeo.ecm.platform.pictures.tiles.tilers.PictureTiler; 037 038/** 039 * ImageMagic based Tiler Uses several ImageMagick command lines to extract a tile form a picture file 040 * 041 * @author tiry 042 */ 043public class MagickTiler implements PictureTiler { 044 045 /** @since 5.9.5. */ 046 public static final String CMYK_MAP_COMPONENTS = "cmyk"; 047 048 public boolean needsSync() { 049 return false; 050 } 051 052 public String getName() { 053 return "MagicTiler"; 054 } 055 056 static int[] computeCropCoords(ImageInfo input, int maxTiles, int tileWidth, int tileHeight, int xCenter, 057 int yCenter) { 058 int startX = 0; 059 int startY = 0; 060 int cropWidth = 0; 061 int cropHeight = 0; 062 int ntx = 0; 063 int nty = 0; 064 065 if (input.getWidth() > input.getHeight()) { 066 cropWidth = input.getWidth() / maxTiles; 067 if ((input.getWidth() % maxTiles) > 0) { 068 cropWidth += 1; 069 } 070 Double exactCropHeight = (new Double(tileHeight)) / tileWidth * cropWidth; 071 if (exactCropHeight - exactCropHeight.intValue() > 0) { 072 cropHeight = exactCropHeight.intValue() + 1; 073 } else { 074 cropHeight = exactCropHeight.intValue(); 075 } 076 ntx = maxTiles; 077 nty = input.getHeight() / cropHeight; 078 if ((input.getHeight() % cropHeight) > 0) { 079 nty += 1; 080 } 081 } else { 082 cropHeight = input.getHeight() / maxTiles; 083 if ((input.getHeight() % maxTiles) > 0) { 084 cropHeight += 1; 085 } 086 Double exactCropWidth = (new Double(tileWidth)) / tileHeight * cropHeight; 087 if (exactCropWidth - exactCropWidth.intValue() > 0) { 088 cropWidth = exactCropWidth.intValue() + 1; 089 } else { 090 cropWidth = exactCropWidth.intValue(); 091 } 092 nty = maxTiles; 093 ntx = input.getWidth() / cropWidth; 094 if ((input.getWidth() % cropWidth) > 0) { 095 ntx += 1; 096 } 097 } 098 099 startX = xCenter * cropWidth; 100 startY = yCenter * cropHeight; 101 102 double widthRatio = new Double(tileWidth) / cropWidth; 103 double heightRatio = new Double(tileHeight) / cropHeight; 104 105 if (xCenter == ntx - 1) { 106 cropWidth = input.getWidth() - (xCenter) * cropWidth; 107 tileWidth = (int) Math.round(cropWidth * widthRatio); 108 } 109 if (yCenter == nty - 1) { 110 cropHeight = input.getHeight() - (yCenter) * cropHeight; 111 tileHeight = (int) Math.round(cropHeight * heightRatio); 112 } 113 114 int[] result = { startX, startY, cropWidth, cropHeight, ntx, nty, tileWidth, tileHeight }; 115 116 return result; 117 } 118 119 public PictureTiles getTilesFromFile(ImageInfo input, String outputDirPath, int tileWidth, int tileHeight, 120 int maxTiles, int xCenter, int yCenter, long lastModificationTime, boolean fullGeneration) 121 { 122 123 int[] cropCoords = computeCropCoords(input, maxTiles, tileWidth, tileHeight, xCenter, yCenter); 124 125 String fileName = StringMaker.getTileFileName(xCenter, yCenter, lastModificationTime); 126 String outputFilePath = new Path(outputDirPath).append(fileName).toString(); 127 128 try { 129 String mapComponents = null; 130 if (CMYK_MAP_COMPONENTS.equalsIgnoreCase(input.getColorSpace())) { 131 mapComponents = CMYK_MAP_COMPONENTS; 132 } 133 134 ImageCropperAndResizer.cropAndResize(input.getFilePath(), outputFilePath, cropCoords[2], cropCoords[3], 135 cropCoords[0], cropCoords[1], cropCoords[6], cropCoords[7], mapComponents); 136 } catch (CommandNotAvailable | CommandException e) { 137 throw new NuxeoException(e); 138 } 139 140 Map<String, String> infoMap = new HashMap<String, String>(); 141 infoMap.put(PictureTilesImpl.TILE_OUTPUT_DIR_KEY, outputDirPath); 142 infoMap.put(PictureTilesImpl.X_TILES_KEY, Integer.toString(cropCoords[4])); 143 infoMap.put(PictureTilesImpl.Y_TILES_KEY, Integer.toString(cropCoords[5])); 144 145 return new PictureTilesImpl(infoMap); 146 } 147 148}