/* * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Thibaud Arguillere */ package org.nuxeo.labs.images; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; import org.nuxeo.ecm.automation.core.Constants; import org.nuxeo.ecm.automation.core.annotations.Context; import org.nuxeo.ecm.automation.core.annotations.Operation; import org.nuxeo.ecm.automation.core.annotations.OperationMethod; import org.nuxeo.ecm.automation.core.annotations.Param; import org.nuxeo.ecm.automation.core.collectors.DocumentModelCollector; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.NuxeoException; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.impl.blob.FileBlob; import org.nuxeo.ecm.platform.picture.api.ImageInfo; import org.nuxeo.ecm.platform.picture.api.ImagingService; import org.nuxeo.ecm.platform.picture.api.PictureView; import org.nuxeo.ecm.platform.picture.api.PictureViewImpl; import org.nuxeo.runtime.api.Framework; /** * */ @Operation(id = ImageCropInViewsOp.ID, category = Constants.CAT_CONVERSION, label = "ImageCropInViewsOp", description = "") public class ImageCropInViewsOp { public static final String ID = "ImageCropInViewsOp"; @Context protected CoreSession session; @Param(name = "title", required = false) protected String title = ""; @Param(name = "top", required = false) protected long top = 0; @Param(name = "left", required = false) protected long left = 0; @Param(name = "width", required = false) protected long width = 0; @Param(name = "height", required = false) protected long height = 0; @Param(name = "pictureWidth", required = false) protected long pictureWidth = 0; @Param(name = "pictureHeight", required = false) protected long pictureHeight = 0; @Param(name = "targetFileName", required = false) protected String targetFileName = ""; @Param(name = "targetFileNameSuffix", required = false) protected String targetFileNameSuffix = ""; @OperationMethod(collector = DocumentModelCollector.class) public DocumentModel run(DocumentModel inDoc) throws IOException { // Possibly, nothing to do. if (width == 0 || height == 0) { return inDoc; } if (!inDoc.hasFacet("Picture")) { throw new NuxeoException( String.format( "The document (id:'%s') with title '%s' doesn't have the 'Picture' facet", inDoc.getId(), inDoc.getTitle())); } Blob pictureBlob = (Blob) inDoc.getPropertyValue("file:content"); // Scale the crop if (pictureWidth > 0 && pictureHeight > 0) { double coef = 0.0; int w = ((Long) inDoc.getPropertyValue("picture:info/width")).intValue(); int h = ((Long) inDoc.getPropertyValue("picture:info/height")).intValue(); if (w != (int) pictureWidth) { coef = (double) w / (double) pictureWidth; left *= coef; width *= coef; } if (h != (int) pictureHeight) { coef = (double) h / (double) pictureHeight; top *= coef; height *= coef; } } if (targetFileNameSuffix == null || targetFileNameSuffix.isEmpty()) { targetFileNameSuffix = "-crop" + top + "-" + left + "-" + width + "x" + height; } targetFileName = ConversionUtils.updateTargetFileName(pictureBlob, targetFileName, targetFileNameSuffix); Map<String, Serializable> params = new HashMap<String, Serializable>(); params.put("targetFilePath", targetFileName); params.put("top", "" + top); params.put("left", "" + left); params.put("width", "" + width); params.put("height", "" + height); // The "imageCropping" converter is defined in // OSGI-INF/extensions/conversions-contrib.xml Blob croppedBlob = ConversionUtils.convert("imageCropping", pictureBlob, params, targetFileName); croppedBlob.setMimeType(pictureBlob.getMimeType()); if (title == null || title.isEmpty()) { title = "Crop-" + top + "-" + left + "-" + width + "x" + height; } /* * MultiviewPicture mvp = inDoc.getAdapter(MultiviewPicture.class); * PictureView view = mvp.getView(title); if(view != null) { * mvp.removeView(title); } */ ImagingService imagingService = Framework.getService(ImagingService.class); ImageInfo info = imagingService.getImageInfo(croppedBlob); PictureView view = new PictureViewImpl(); view.setBlob(croppedBlob); view.setDescription(title); view.setFilename(croppedBlob.getFilename()); view.setHeight((int) height); view.setImageInfo(info); view.setTitle(title); view.setWidth((int) width); // mvp.addView(view); @SuppressWarnings("unchecked") List<Map<String, Object>> views = (List<Map<String, Object>>) inDoc.getPropertyValue("picture:views"); if (views != null) { int max = views.size(); int idxToDelete = -1; for (int i = 0; i < max; ++i) { Map<String, Object> map = views.get(i); if (map.get(PictureView.FIELD_TITLE).equals(title)) { idxToDelete = i; break; } } if (idxToDelete > -1) { views.remove(idxToDelete); } } views.add(myViewToMap(view)); inDoc.setPropertyValue("picture:views", (Serializable) views); inDoc = session.saveDocument(inDoc); return inDoc; } // 2015-03-14: workaround a bug in MultiviewPictureAdapter#viewToMap. // Will be fixed in the platform very soon, but need this to work for like // in 2 days. protected Map<String, Object> myViewToMap(PictureView view) { Map<String, Object> map = new HashMap<String, Object>(); map.put(PictureView.FIELD_TITLE, view.getTitle()); map.put(PictureView.FIELD_DESCRIPTION, view.getDescription()); map.put(PictureView.FIELD_TAG, view.getTag()); map.put(PictureView.FIELD_HEIGHT, view.getHeight()); map.put(PictureView.FIELD_WIDTH, view.getWidth()); map.put(PictureView.FIELD_FILENAME, view.getFilename()); Object o = view.getBlob(); Blob blob = null; if (o instanceof File) { blob = new FileBlob((File) o, "application/octet-stream"); } /* * else if (o instanceof InputStream) { blob = new * InputStreamBlob((InputStream) o, "application/octet-stream"); } */else if (o instanceof Blob) { blob = (Blob) o; } if (blob != null) { map.put(PictureView.FIELD_CONTENT, blob); } map.put(PictureView.FIELD_INFO, view.getImageInfo().toMap()); return map; } }