Service class for images.

pull/10/head
Jens Pelzetter 2021-07-01 19:56:13 +02:00
parent 1bad56eafe
commit 6d850fb503
3 changed files with 259 additions and 0 deletions

View File

@ -27,7 +27,11 @@ import javax.persistence.JoinColumn;
import javax.persistence.Table; import javax.persistence.Table;
import com.arsdigita.cms.ui.assets.forms.ImageForm; import com.arsdigita.cms.ui.assets.forms.ImageForm;
import org.hibernate.envers.Audited; import org.hibernate.envers.Audited;
import org.librecms.ui.contentsections.assets.ImageCreateStep;
import org.librecms.ui.contentsections.assets.ImageEditStep;
import org.librecms.ui.contentsections.assets.MvcAssetEditKit;
import javax.persistence.OneToOne; import javax.persistence.OneToOne;
@ -48,6 +52,10 @@ import static org.librecms.assets.AssetConstants.*;
labelBundle = ASSETS_BUNDLE, labelBundle = ASSETS_BUNDLE,
descriptionKey = "image.description", descriptionKey = "image.description",
descriptionBundle = ASSETS_BUNDLE) descriptionBundle = ASSETS_BUNDLE)
@MvcAssetEditKit(
createStep = ImageCreateStep.class,
editStep = ImageEditStep.class
)
public class Image extends BinaryAsset implements Serializable { public class Image extends BinaryAsset implements Serializable {
private static final long serialVersionUID = -8095106228017573785L; private static final long serialVersionUID = -8095106228017573785L;

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.assets;
/**
* DTO for properties of an image.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ImageProperties {
/**
* The width of the image.
*/
private int width;
/**
* The height of the image
*/
private int height;
protected ImageProperties() {
}
public int getWidth() {
return width;
}
protected void setWidth(final int width) {
this.width = width;
}
public int getHeight() {
return height;
}
protected void setHeight(final int height) {
this.height = height;
}
}

View File

@ -0,0 +1,191 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.assets;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.core.UnexpectedErrorException;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.enterprise.context.Dependent;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
/**
* Utility class for working with images (JPEG, PNG, GIF).
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Dependent
public class ImageService {
private static final Logger LOGGER = LogManager.getLogger(
ImageService.class
);
public ImageProperties getImageProperties(final Image image) {
final InputStream inputStream = image.getDataAsInputStream();
return getImageProperties(inputStream);
}
public ImageProperties getImageProperties(final InputStream inputStream) {
final BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(inputStream);
} catch (IOException ex) {
throw new UnexpectedErrorException(ex);
}
final ImageProperties imageProperties = new ImageProperties();
imageProperties.setHeight(bufferedImage.getHeight());
imageProperties.setWidth(bufferedImage.getWidth());
return imageProperties;
}
public byte[] scaleImage(
final Image image, final int toWidth, final int toHeight
) {
final InputStream inputStream = image.getDataAsInputStream();
return scaleImage(inputStream, toWidth, toHeight);
}
public byte[] scaleImage(
final InputStream inputStream, final int toWidth, final int toHeight
) {
final BufferedImage bufferedImage;
final String imageFormat;
try {
final ImageInputStream imageInputStream = ImageIO
.createImageInputStream(inputStream);
final Iterator<ImageReader> readers = ImageIO
.getImageReaders(imageInputStream);
final ImageReader imageReader;
if (readers.hasNext()) {
imageReader = readers.next();
} else {
LOGGER.error(
"No image reader suitable image reader available");
throw new UnexpectedErrorException();
}
imageReader.setInput(imageInputStream);
bufferedImage = imageReader.read(0);
imageFormat = imageReader.getFormatName();
} catch (IOException ex) {
LOGGER.error("Failed to load image.");
LOGGER.error(ex);
throw new UnexpectedErrorException();
}
final java.awt.Image scaledImage = scaleImage(
bufferedImage, toWidth, toHeight
);
final ByteArrayOutputStream outputStream
= new ByteArrayOutputStream();
final BufferedImage bufferedScaledImage = new BufferedImage(
scaledImage.getWidth(null),
scaledImage.getHeight(null),
bufferedImage.getType());
bufferedScaledImage
.getGraphics()
.drawImage(scaledImage, 0, 0, null);
try {
ImageIO
.write(bufferedScaledImage, imageFormat, outputStream);
} catch (IOException ex) {
LOGGER.error("Failed to render scaled variant of image");
LOGGER.error(ex);
throw new UnexpectedErrorException(
"Failed to render scaled variant of image"
);
}
return outputStream.toByteArray();
}
private java.awt.Image scaleImage(
final BufferedImage image,
final float scaleToWidth,
final float scaleToHeight
) {
final float originalWidth = image.getWidth();
final float originalHeight = image.getHeight();
final float originalAspectRatio = originalWidth / originalHeight;
if (scaleToWidth > 0 && scaleToHeight > 0) {
//Check if parameters preserve aspectRatio. If not use the smaller
//scale factor.
final float scaleToAspectRatio = scaleToWidth / scaleToHeight;
if (Math.abs(scaleToAspectRatio - originalAspectRatio) < 0.009f) {
// Scale the image.
return image.getScaledInstance(Math.round(scaleToWidth),
Math.round(scaleToHeight),
java.awt.Image.SCALE_SMOOTH);
} else {
//Use the scale factor nearer to one for both dimensions
final float scaleFactorWidth = scaleToWidth / originalWidth;
final float scaleFactorHeight = scaleToHeight / originalHeight;
final float differenceWidth = Math.abs(scaleFactorWidth - 1);
final float differenceHeight = Math.abs(scaleFactorHeight - 1);
final float scaleFactor;
if (differenceWidth < differenceHeight) {
scaleFactor = scaleFactorWidth;
} else {
scaleFactor = scaleFactorHeight;
}
return scaleImage(image,
originalWidth * scaleFactor,
originalHeight * scaleFactor);
}
} else if (scaleToWidth > 0 && scaleToHeight <= 0) {
//Calculate the height to which to image is scaled based on the
//scale factor for the width
final float scaleFactor = scaleToWidth / originalWidth;
final float height = originalHeight * scaleFactor;
return scaleImage(image, scaleToWidth, height);
} else if (scaleToWidth <= 0 && scaleToHeight >= 0) {
//Calculate the width to which to image is scaled based on the
//scale factor for the height
final float scaleFactor = scaleToHeight / originalHeight;
final float width = originalWidth * scaleFactor;
return scaleImage(image, width, scaleToHeight);
} else {
//Return the image as is.
return image;
}
}
}