/*
* (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.crop.ui;
import java.io.Serializable;
import java.util.Calendar;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
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.NuxeoPrincipal;
import org.nuxeo.ecm.platform.picture.api.PictureView;
import org.nuxeo.ecm.platform.picture.api.adapters.MultiviewPicture;
import org.nuxeo.ecm.platform.ui.web.api.NavigationContext;
/**
* Display "Crop image" UI in a fancybox. The bean sets up information about the
* picture and its size, to make it fit in the fancybox, while using a
* small/medium image (void using the original multi-mega bytes image).
* Possibly, the final width/height will be bigger than the image used, so the
* browser will scale it.
*
* When the user clicks "Crop" button, the crop itself is managed by the
* JavaScript not by this Bean (see
* resources/web/nuxeo.war/scripts/nuxeo-labs-image-cropper.js)
*
* @since 5.9.6
*/
@Name("imageCropHelper")
@Scope(ScopeType.EVENT)
public class ImageCropHelperBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final int kMAX_WIDTH = 1000;
private static final int kMAX_HEIGHT = 600;
private static final int kMIN_WIDTH = 300;
private static final int kMIN_HEIGHT = 200;
private static final Log log = LogFactory.getLog(ImageCropHelperBean.class);
@In(create = true, required = false)
protected transient CoreSession documentManager;
@In(create = true)
protected NavigationContext navigationContext;
@In(create = true, required = false)
protected transient FacesMessages facesMessages;
@In(create = true, required = false)
protected NuxeoPrincipal currentNuxeoPrincipal;
protected DocumentModel currentDocument = null;
protected long imageWidth = 0;
protected long imageHeight = 0;
protected String imageViewName = "";
protected long originalImageWidth = 0;
protected long originalImageHeight = 0;
protected double scaleH = 1.0;
protected double scaleV = 1.0;
@Create
public void initialize() throws NuxeoException {
try {
currentDocument = navigationContext.getCurrentDocument();
imageWidth = 0;
imageHeight = 0;
try {
originalImageWidth = ((Long) currentDocument.getPropertyValue("picture:info/width")).intValue();
originalImageHeight = ((Long) currentDocument.getPropertyValue("picture:info/height")).intValue();
} catch (Exception e) {
originalImageWidth = 0;
originalImageHeight = 0;
}
// Cf. images-service-contrib.xml
// We try the main views as pre-calculated by nuxeo: Small, Medium, Original
String [] viewNames = {"Small", "Medium", "Original"};
MultiviewPicture mvp = currentDocument.getAdapter(MultiviewPicture.class);
if(mvp != null) {
for(String name : viewNames) {
PictureView oneView = mvp.getView(name);
if(oneView != null) {
String title = oneView.getTitle();
String viewName = title + ":content";
long viewW = 0, viewH = 0;
viewW = oneView.getWidth();
viewH = oneView.getHeight();
if (originalImageWidth == 0 && title.toLowerCase().indexOf("original") == 0) {
originalImageWidth = viewW;
originalImageHeight = viewH;
}
if (viewW < kMAX_WIDTH) {
if (viewW > imageWidth) {
imageWidth = viewW;
imageHeight = viewH;
imageViewName = viewName;
}
}
}
}
// Either we have no views or none of them are < kMAX_WIDTH which is very, very unlikely. Result will be weird anyway.
if (imageWidth == 0) {
// We do have a problem
log.warn("No picture view found which is less than "
+ kMAX_WIDTH + "x" + kMAX_HEIGHT);
}
}
_updateDimensions();
} catch (NuxeoException e) {
log.error(e);
}
}
/*
* Check width/height and update them so that: - If they are smaller than
* kMAX_WIDTH/kMAX_HEIGHT, and original width/height are greater, it means
* we can resize the picture to kMAX_WIDTH/kMAX_HEIGHT. The picture used
* will then be scaled, but it will be more comfortable for the user.
*
* - If they are greater than kMAX_WIDTH/kMAX_HEIGHT, then picture is
* resized to the max. values.
*/
private void _updateDimensions() {
double coef = 0.0;
if (imageWidth == 0 || imageHeight == 0) {
return;
}
coef = ((double) kMAX_WIDTH / (double) imageWidth);
imageWidth = kMAX_WIDTH;
imageHeight *= coef;
if (imageHeight > kMAX_HEIGHT) {
coef = ((double) kMAX_HEIGHT / (double) imageHeight);
imageHeight = kMAX_HEIGHT;
imageWidth *= coef;
}
scaleH = 1.0;
if (originalImageWidth != (int) imageWidth) {
scaleH = (double) originalImageWidth / (double) imageWidth;
}
scaleV = 1.0;
if (originalImageHeight != (int) imageHeight) {
scaleV = (double) originalImageHeight / (double) imageHeight;
}
}
public String getImageViewURL(boolean inOriginalJpeg) {
//http://localhost:8080/nuxeo/nxpicsfile/default/1b5ef2d1-c152-4b84-904d-0ec7c2cf4510/Thumbnail:content/Thu%20Mar%2012%2016%3A51%3A49%20EDT%202015
String lastModification = "" + (((Calendar) currentDocument.getPropertyValue("dc:modified")).getTimeInMillis());
if(inOriginalJpeg) {
return "/nuxeo/nxpicsfile/default/" + currentDocument.getId() + "/OriginalJpeg:content/" + lastModification;
}
return "/nuxeo/nxpicsfile/default/" + currentDocument.getId() + "/" + imageViewName + "/" + lastModification;
}
public String getimageViewName() {
return imageViewName;
}
public double getScaleH() {
return scaleH;
}
public double getScaleV() {
return scaleV;
}
public long getImageWidth() {
return imageWidth;
}
public long getImageHeight() {
return imageHeight;
}
public long getImageBoxWidth() {
return imageWidth < kMIN_WIDTH ? kMIN_WIDTH : imageWidth;
}
public long getImageBoxHeight() {
return imageHeight < kMIN_HEIGHT ? kMIN_HEIGHT : imageHeight;
}
public long getOriginalImageWidth() {
return originalImageWidth;
}
public long getOriginalImageHeight() {
return originalImageHeight;
}
public long getMaxWidth() {
return kMAX_WIDTH;
}
public long getMaxHeigth() {
return kMAX_HEIGHT;
}
}