/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.ui.model.graphic;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.image.RenderedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.media.jai.OpImage;
import javax.media.jai.ROIShape;
import javax.media.jai.RenderedOp;
import org.weasis.core.api.image.op.ImageStatistics2Descriptor;
import org.weasis.core.api.image.op.ImageStatisticsDescriptor;
import org.weasis.core.api.image.util.MeasurableLayer;
import org.weasis.core.api.media.data.TagW;
import org.weasis.core.ui.model.utils.bean.MeasureItem;
import org.weasis.core.ui.model.utils.bean.Measurement;
public abstract class AbstractDragGraphicArea extends AbstractDragGraphic implements GraphicArea {
private static final long serialVersionUID = -3042328664891626708L;
public AbstractDragGraphicArea(Integer pointNumber) {
super(pointNumber);
}
public AbstractDragGraphicArea(AbstractDragGraphicArea graphic) {
super(graphic);
}
@Override
public Area getArea(AffineTransform transform) {
if (shape == null) {
return new Area();
} else {
Area area = super.getArea(transform);
area.add(new Area(shape)); // Add inside area for closed shape
return area;
}
}
@Override
public List<MeasureItem> getImageStatistics(MeasurableLayer layer, Boolean releaseEvent) {
if (layer != null) {
if (layer.hasContent() && isShapeValid()) {
ArrayList<MeasureItem> measVal = new ArrayList<>();
if (IMAGE_MIN.getComputed() || IMAGE_MAX.getComputed() || IMAGE_MEAN.getComputed()) {
Double[] min = null;
Double[] max = null;
Double[] mean = null;
Double[] stdv = null;
Double[] skew = null;
Double[] kurtosis = null;
if (releaseEvent && shape != null) {
RenderedImage image = layer.getSourceRenderedImage();
if (image == null) {
return null;
}
AffineTransform transform = layer.getShapeTransform();
Point offset = layer.getOffset();
if (offset != null) {
if (transform == null) {
transform = AffineTransform.getTranslateInstance(-offset.getX(), -offset.getY());
} else {
transform.translate(-offset.getX(), -offset.getY());
}
}
ROIShape roi;
if (transform != null) {
// Rescale ROI, if needed
roi = new ROIShape(transform.createTransformedShape(shape));
} else {
roi = new ROIShape(shape);
}
// Get padding values => exclude values
Double excludedMin = null;
Double excludedMax = null;
Integer paddingValue = (Integer) layer.getSourceTagValue(TagW.get("PixelPaddingValue")); //$NON-NLS-1$
Integer paddingLimit = (Integer) layer.getSourceTagValue(TagW.get("PixelPaddingRangeLimit")); //$NON-NLS-1$
if (paddingValue != null) {
if (paddingLimit == null) {
paddingLimit = paddingValue;
} else if (paddingLimit < paddingValue) {
int temp = paddingValue;
paddingValue = paddingLimit;
paddingLimit = temp;
}
excludedMin = paddingValue == null ? null : (double) paddingValue;
excludedMax = paddingLimit == null ? null : (double) paddingLimit;
}
RenderedOp dst =
ImageStatisticsDescriptor.create(image, roi, 1, 1, excludedMin, excludedMax, null);
// To ensure this image is not stored in tile cache
((OpImage) dst.getRendering()).setTileCache(null);
// For basic statistics, rescale values can be computed afterwards
double[][] extrema = (double[][]) dst.getProperty("statistics"); //$NON-NLS-1$
if (extrema == null || extrema.length < 1 || extrema[0].length < 1) {
return Collections.emptyList();
}
min = new Double[extrema[0].length];
max = new Double[extrema[0].length];
mean = new Double[extrema[0].length];
// LOGGER.error("Basic stats [ms]: {}", System.currentTimeMillis() - startTime);
// unit = pixelValue * rescale slope + rescale intercept
Double slopeVal = (Double) layer.getSourceTagValue(TagW.get("RescaleSlope")); //$NON-NLS-1$
Double interceptVal = (Double) layer.getSourceTagValue(TagW.get("RescaleIntercept")); //$NON-NLS-1$
double slope = slopeVal == null ? 1.0f : slopeVal.doubleValue();
double intercept = interceptVal == null ? 0.0f : interceptVal.doubleValue();
for (int i = 0; i < extrema[0].length; i++) {
min[i] = extrema[0][i] * slope + intercept;
max[i] = extrema[1][i] * slope + intercept;
mean[i] = extrema[2][i] * slope + intercept;
}
if (IMAGE_STD.getComputed() || IMAGE_SKEW.getComputed() || IMAGE_KURTOSIS.getComputed()) {
// startTime = System.currentTimeMillis();
// Required the mean value (not rescaled), slope and intercept to calculate correctly std,
// skew and kurtosis
dst = ImageStatistics2Descriptor.create(image, roi, 1, 1, extrema[2][0], excludedMin,
excludedMax, slope, intercept, null);
// To ensure this image is not stored in tile cache
((OpImage) dst.getRendering()).setTileCache(null);
double[][] extrema2 = (double[][]) dst.getProperty("statistics"); //$NON-NLS-1$
if (extrema != null && extrema.length > 0 && extrema[0].length > 0) {
stdv = new Double[extrema2[0].length];
skew = new Double[extrema2[0].length];
kurtosis = new Double[extrema2[0].length];
// LOGGER.info("Adv. stats [ms]: {}", System.currentTimeMillis() - startTime);
for (int i = 0; i < extrema2[0].length; i++) {
stdv[i] = extrema2[0][i];
skew[i] = extrema2[1][i];
kurtosis[i] = extrema2[2][i];
}
}
}
}
String unit = layer.getPixelValueUnit();
if (IMAGE_MIN.getComputed()) {
addMeasure(measVal, IMAGE_MIN, min, unit);
}
if (IMAGE_MAX.getComputed()) {
addMeasure(measVal, IMAGE_MAX, max, unit);
}
if (IMAGE_MEAN.getComputed()) {
addMeasure(measVal, IMAGE_MEAN, mean, unit);
}
if (IMAGE_STD.getComputed()) {
addMeasure(measVal, IMAGE_STD, stdv, unit);
}
if (IMAGE_SKEW.getComputed()) {
addMeasure(measVal, IMAGE_SKEW, skew, unit);
}
if (IMAGE_KURTOSIS.getComputed()) {
addMeasure(measVal, IMAGE_KURTOSIS, kurtosis, unit);
}
Double suv = (Double) layer.getSourceTagValue(TagW.SuvFactor);
if (Objects.nonNull(suv)) {
unit = "SUVbw"; //$NON-NLS-1$
if (IMAGE_MIN.getComputed()) {
measVal.add(
new MeasureItem(IMAGE_MIN, min == null || min[0] == null ? null : min[0] * suv, unit));
}
if (IMAGE_MAX.getComputed()) {
measVal.add(
new MeasureItem(IMAGE_MAX, max == null || max[0] == null ? null : max[0] * suv, unit));
}
if (IMAGE_MEAN.getComputed()) {
measVal.add(new MeasureItem(IMAGE_MEAN,
mean == null || mean[0] == null ? null : mean[0] * suv, unit));
}
}
}
return measVal;
}
}
return Collections.emptyList();
}
private static void addMeasure(ArrayList<MeasureItem> measVal, Measurement measure, Double[] val, String unit) {
if (val == null) {
measVal.add(new MeasureItem(measure, null, unit));
} else if (val.length == 1) {
measVal.add(new MeasureItem(measure, val[0], unit));
} else {
for (int i = 0; i < val.length; i++) {
measVal.add(new MeasureItem(measure, " " + (i + 1), val[i], unit)); //$NON-NLS-1$
}
}
}
}